2025 SUCTF - Reverse 全题解
carbofish

2025 SUCTF Reverse Write UP

SU_APP

为什么我的安卓12跑不了这个app…,第一步刷机,降级安卓11,先patch一下so,去掉里面的一系列反调试

干掉签名检验

image-20250113121742079

干掉两个线程反调试

image-20250113123414422

image-20250113123407337

image-20250113123432476

image-20250113123441860

然后就可以 frida spawn 了,外层的 so 是一个加载器,先用 frida dump 出运行后的 so

dump so 脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var dump_so_func = function (soname, packageName) {
var module = Process.getModuleByName(soname);
var buffer = module.base.readByteArray(module.size);
console.log(`base: ${module.base}`);

const fileName = `/data/data/${packageName}/dump_so_${Date.now()}.so`;
const file = new File(fileName, "wb");
file.write(buffer);
file.flush();
file.close();

console.log(`[+] Saved ${soname} to file: ${fileName}`);
console.log(`[+] Bytecode size: ${module.size} bytes`);
};

function start_dump() {
var so_name = "libsuapp.so"
var package_name = "com.swdd.suapp"
dump_so_func(so_name, package_name)
}

dump 出来后发现前 128 个字节是坏的

image-20250113123639199

为了解决这个 我先尝试 dump 出 app 的整个内存,然后搜索 SUCTF{You_Find_Me}

dump memory 脚本
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
Java.perform(function() {
setTimeout(function() {

let allMemoryData = [];
let totalSize = 0;

const ranges = Process.enumerateRangesSync({
protection: '---',
coalesce: true
});

for (const range of ranges) {
try {
const current = range.base;
const size = range.size;
console.log(current, size)

const memoryData = Memory.readByteArray(current, size);
if (memoryData) {
allMemoryData.push(memoryData);
totalSize += size;
}
} catch {}
}

const finalBuffer = new ArrayBuffer(totalSize);
const finalArray = new Uint8Array(finalBuffer);
let offset = 0;

for (const data of allMemoryData) {
const tempArray = new Uint8Array(data);
finalArray.set(tempArray, offset);
offset += tempArray.length;
}

const timestamp = new Date().getTime();
const filename = `/data/data/com.swdd.suapp/memory_dump_${timestamp}.bin`;

const file = new File(filename, "wb");
file.write(finalBuffer);
file.flush();
file.close();
console.log(`[+] Saved ${finalBuffer.byteLength} bytes to ${filename}`);
}, 3000)
})

搜索到两个结果,其中一个结果只有前 64 个字节被抹了,接下来把这里未被覆盖的后64字节加上 apk 里的那个 so 加载器的前 64 个字节覆盖进dump出来的so,然后修复一下 so 就可以还原了

image-20250113123739248

找到主函数,简单重命名一下函数名和字段名后可以发现,这是利用了 libffi 库,根据 rc4 加密的前半步骤选取用于加密的函数,然后用 ffi_call 调用,一共有 256 种加密函数 每个加密函数有不同的参数个数,在调用前使用 j_ffi_prep_cif 预包装好参数

image-20250113124039881

image-20250113124120387

image-20250113124403520

由于加密过程和输入无关,可以用 frida 在五个参数运算完成后的位置 hook ,然后读出上面的 v20, v19, v18, v9, v8 这几个参数,再用 idapython 批量获取加密函数的伪代码,然后用脚本生成 z3 的约束条件去解

hook 运算步骤脚本
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
var inter = setInterval(() => {
try {
var proc = Process.findModuleByName("libsuapp.so")

// fake so
if (proc.size > 300000) return;

Interceptor.attach(proc.base.add(0x9D14), {
onEnter: function() {
var sp = this.context.sp
var v20 = sp.add(0x90).readU32()
var v19 = sp.add(0x8c).readU32()
var v18 = sp.add(0x88).readU32()
var v9 = sp.add(0x28).readU32()
var v8 = sp.add(0x24).readU32()
var v7 = sp.add(0x20).readU32()
var callFunc = sp.add(0x70).readPointer().sub(proc.base)
var callType = sp.add(0x14).readU32()

console.log(`${callFunc}-${callType}, ${v20}, ${v19}, ${v18}, ${v9}, ${v8}, ${v7}`)

// console.log(hexdump(proc.base.add(0x22868), { length: 128, ansi: true}))
}
})
clearInterval(inter)
console.log("Hooked!")
} catch {}
}, 10)

image-20250113124731425

得到运算步骤后生成 z3 约束条件

条件生成脚本
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
import re

with open("ezapp\\execute_route.txt", "r") as f:
data = f.read()
f.close()

with open("ezapp\\functions_pseudocode.txt", "r") as f:
fake_c_data = f.read()
f.close()

code_map = {}

for fake in fake_c_data.split("\n\n\n"):
if fake.strip() == "":
continue
addr = re.findall(r"// Function at (.*)", fake)[0]
code = re.findall(r"return (.*);", fake)[0]

code = code.replace("(unsigned int)", "")

code_map[addr] = code

# print(code)

func_map = {}

for line in data.split("\n"):
dts = line.split(', ')
func = dts[0].split("-")[0]
args = int(dts[0].split("-")[1])

if func not in func_map:
func_map[func] = True
# print(func)

v20 = dts[1]
v19 = dts[2]
v18 = dts[3]

v9 = dts[4]
v8 = dts[5]

code = code_map[func]

if args == 3:
code = code.replace("a1", v20)
code = code.replace("a2", v19)
code = code.replace("a3", v18)

code = code.replace("a4", f"flag[{v9}]")
code = code.replace("a5", f"flag[{v8}]")
elif args == 2:
code = code.replace("a1", v20)
code = code.replace("a2", v19)

code = code.replace("a3", f"flag[{v9}]")
code = code.replace("a4", f"flag[{v8}]")
elif args == 1:
code = code.replace("a1", v20)

code = code.replace("a2", f"flag[{v9}]")
code = code.replace("a3", f"flag[{v8}]")

print(f"flag[{v9}] = {code}")

'''
flag[11] = (197 + flag[11] + flag[15] + 209)
flag[25] = ((86 + flag[25]) ^ flag[4]) + 73
flag[6] = (148 ^ (131 + flag[6]) ^ flag[12]) + 158
flag[19] = (144 + flag[19] + flag[23] + 225)
flag[10] = (179 + flag[10] + flag[23] + 62)
flag[23] = (187 ^ 121 ^ flag[23] ^ flag[16]) + 180
flag[12] = (58 ^ (213 + flag[12] + flag[23])) + 174
flag[21] = (95 + flag[8] + flag[21])
flag[1] = (126 + flag[19] + flag[1])
flag[4] = ((219 + 9) ^ flag[4] ^ flag[17]) + 109
flag[22] = (60 + flag[18] + flag[22])
flag[14] = (109 + flag[14] + flag[30] + 238)
flag[18] = (72 ^ flag[20]) + flag[18]
flag[15] = (10 + 146 + flag[15] + flag[24] + 45)
flag[19] = (23 ^ flag[19] ^ flag[14]) + 51
flag[14] = (140 ^ (flag[14] + flag[20])) + 155
flag[21] = (89 ^ flag[21] ^ flag[13]) + 209
flag[21] = (187 + flag[21] + flag[19] + 168)
flag[8] = (47 + flag[8] + flag[22] + 229)
flag[4] = (159 ^ (flag[4] + flag[12])) + 248
flag[29] = (27 ^ (255 + flag[29] + flag[19])) + 137
flag[7] = (93 + flag[16] + flag[7])
flag[4] = (206 ^ (188 + flag[4]) ^ flag[12]) + 11
flag[8] = ((33 + flag[8]) ^ flag[7]) + 141
flag[24] = (178 + flag[11] + flag[24])
flag[13] = (35 + flag[8] + flag[13])
flag[19] = (215 + 230 + flag[19] + flag[23] + 169)
flag[5] = (201 + flag[27] + flag[5])
flag[28] = (107 + flag[19] + flag[28])
flag[26] = ((111 + 48) ^ flag[26] ^ flag[28]) + 196
flag[12] = (132 ^ flag[28]) + flag[12]
flag[0] = (163 ^ flag[3]) + flag[0]
flag[16] = (117 + flag[3] + flag[16])
flag[0] = (84 ^ flag[0] ^ flag[24]) + 217
flag[19] = (211 ^ (68 + flag[19]) ^ flag[29]) + 217
flag[24] = (29 + flag[13] + flag[24])
flag[14] = (228 + 117 + flag[14] + flag[28] + 37)
flag[9] = ((208 + 141 + flag[9]) ^ flag[22]) + 62
flag[30] = (202 + flag[30] + flag[27] + 90)
flag[20] = (0 ^ flag[8]) + flag[20]
flag[28] = (57 ^ (flag[28] + flag[1])) + 129
flag[15] = (210 + flag[28] + flag[15])
flag[14] = ((79 + 85 + flag[14]) ^ flag[10]) + 177
flag[17] = (123 + flag[23] + flag[17])
flag[30] = (146 + flag[30] + flag[18] + 255)
flag[25] = (84 + flag[25] + flag[1] + 120)
flag[20] = ((55 + 1 + flag[20]) ^ flag[15]) + 102
flag[6] = ((154 + flag[6]) ^ flag[23]) + 169
flag[5] = (15 ^ (flag[5] + flag[31])) + 104
flag[1] = (250 ^ flag[4]) + flag[1]
flag[18] = (255 + flag[18] + flag[8] + 177)
flag[15] = (249 + 101 + flag[15] + flag[21] + 168)
flag[0] = ((218 + 152) ^ (flag[0] + flag[30])) + 128
flag[5] = (94 + flag[18] + flag[5])
flag[9] = (98 ^ flag[0]) + flag[9]
flag[15] = (166 ^ (65 + flag[15] + flag[5])) + 46
flag[26] = (206 + flag[8] + flag[26])
flag[20] = (104 + flag[4] + flag[20])
flag[23] = (144 + flag[4] + flag[23])
flag[31] = (202 + flag[23] + flag[31])
flag[28] = (160 + flag[20] + flag[28])
flag[5] = (94 + 60 + flag[5] + flag[23] + 235)
flag[26] = (50 + flag[26] + flag[3] + 253)
flag[6] = ((149 + flag[6]) ^ flag[17]) + 19
flag[31] = (34 + flag[31] + flag[7] + 198)
flag[18] = (35 ^ flag[18] ^ flag[20]) + 249
flag[26] = (65 + flag[17] + flag[26])
flag[10] = (237 + flag[10] + flag[11] + 142)
flag[25] = (7 + 247 + flag[25] + flag[24] + 167)
flag[3] = (22 ^ flag[3] ^ flag[17]) + 190
flag[16] = (234 + flag[25] + flag[16])
flag[29] = (231 + 172 + flag[29] + flag[7] + 9)
flag[1] = (230 ^ flag[5]) + flag[1]
flag[2] = (51 + 152 + flag[2] + flag[4] + 55)
flag[17] = (252 + flag[17] + flag[3] + 161)
flag[17] = ((119 + flag[17]) ^ flag[11]) + 212
flag[30] = (88 ^ flag[30] ^ flag[9]) + 72
flag[8] = (30 + flag[8] + flag[10] + 38)
flag[19] = ((229 + flag[19]) ^ flag[14]) + 3
flag[5] = ((45 + 241) ^ (flag[5] + flag[18])) + 60
flag[25] = (197 + flag[25] + flag[14] + 244)
flag[30] = (241 + flag[30] + flag[18] + 231)
flag[8] = (138 ^ 226 ^ flag[8] ^ flag[31]) + 185
flag[18] = ((154 + 7 + flag[18]) ^ flag[9]) + 183
flag[2] = (138 ^ flag[17]) + flag[2]
flag[17] = (173 + flag[12] + flag[17])
flag[9] = ((111 + 86 + flag[9]) ^ flag[26]) + 151
flag[30] = (100 + 148 + flag[30] + flag[3] + 170)
flag[1] = (12 ^ flag[19]) + flag[1]
flag[30] = (215 + flag[12] + flag[30])
flag[20] = (151 ^ flag[25]) + flag[20]
flag[14] = (144 + flag[14] + flag[21] + 41)
flag[24] = (23 ^ (flag[24] + flag[12])) + 86
flag[0] = (168 ^ flag[29]) + flag[0]
flag[13] = (83 + flag[9] + flag[13])
flag[7] = (177 ^ (flag[7] + flag[4])) + 83
flag[14] = (146 ^ (flag[14] + flag[9])) + 173
flag[27] = (30 ^ (72 + flag[27] + flag[8])) + 2
flag[13] = (148 + flag[18] + flag[13])
flag[19] = (152 + flag[9] + flag[19])
flag[27] = (238 ^ (140 + flag[27] + flag[14])) + 50
flag[17] = (148 ^ flag[25]) + flag[17]
flag[8] = (77 ^ flag[20]) + flag[8]
flag[5] = (19 ^ (47 + flag[5] + flag[17])) + 238
flag[24] = (182 + flag[14] + flag[24])
flag[9] = (172 ^ (27 + flag[9]) ^ flag[31]) + 210
flag[6] = (211 ^ flag[2]) + flag[6]
flag[11] = (80 ^ flag[28]) + flag[11]
flag[13] = (12 ^ 33 ^ (flag[13] + flag[5])) + 61
flag[22] = (231 ^ (178 + flag[22] + flag[8])) + 197
flag[1] = (203 + flag[13] + flag[1])
flag[9] = (72 ^ (215 + flag[9] + flag[6])) + 116
flag[30] = (183 + flag[14] + flag[30])
flag[25] = (27 + 107 + flag[25] + flag[4] + 100)
flag[4] = (19 ^ (111 + flag[4]) ^ flag[16]) + 235
flag[5] = (220 ^ flag[15]) + flag[5]
flag[24] = ((60 + 163) ^ (flag[24] + flag[0])) + 164
flag[27] = ((99 + flag[27]) ^ flag[7]) + 25
flag[25] = (163 + flag[28] + flag[25])
flag[25] = (24 ^ (flag[25] + flag[4])) + 54
flag[10] = ((189 + 29 + flag[10]) ^ flag[16]) + 214
flag[5] = (13 + flag[5] + flag[21] + 160)
flag[30] = (92 ^ (208 + flag[30]) ^ flag[13]) + 189
flag[26] = (246 ^ flag[26] ^ flag[15]) + 93
flag[30] = ((59 + 0 + flag[30]) ^ flag[7]) + 72
flag[1] = (136 ^ (flag[1] + flag[9])) + 111
flag[25] = (65 ^ (flag[25] + flag[0])) + 98
flag[17] = (92 + flag[21] + flag[17])
flag[15] = (42 ^ (flag[15] + flag[17])) + 1
flag[31] = (183 ^ flag[4]) + flag[31]
flag[24] = (242 + flag[24] + flag[18] + 28)
flag[6] = (1 + flag[1] + flag[6])
flag[9] = (15 ^ 154 ^ (flag[9] + flag[10])) + 152
flag[8] = (55 ^ flag[2]) + flag[8]
flag[29] = (255 + 250 + flag[29] + flag[23] + 46)
flag[17] = (68 ^ (flag[17] + flag[22])) + 165
flag[8] = ((104 + 249 + flag[8]) ^ flag[5]) + 0
flag[0] = (53 + flag[0] + flag[24] + 224)
flag[17] = (222 ^ flag[1]) + flag[17]
flag[10] = ((82 + 98) ^ flag[10] ^ flag[2]) + 180
flag[14] = (128 ^ (166 + flag[14] + flag[1])) + 25
flag[0] = (165 ^ flag[29]) + flag[0]
flag[13] = (72 + flag[15] + flag[13])
flag[19] = (36 + flag[19] + flag[30] + 59)
flag[17] = (196 + flag[9] + flag[17])
flag[17] = (183 + 160 + flag[17] + flag[4] + 96)
flag[11] = (244 + flag[28] + flag[11])
flag[29] = (87 + flag[29] + flag[30] + 189)
flag[19] = (99 + 149 + flag[19] + flag[0] + 162)
flag[6] = (177 + flag[3] + flag[6])
flag[25] = (103 ^ (flag[25] + flag[30])) + 162
flag[29] = (148 + flag[29] + flag[13] + 8)
flag[14] = ((241 + flag[14]) ^ flag[15]) + 17
flag[7] = (139 + flag[23] + flag[7])
flag[30] = (152 + flag[9] + flag[30])
flag[23] = (113 + flag[23] + flag[4] + 54)
flag[9] = ((89 + flag[9]) ^ flag[12]) + 79
flag[19] = (39 + 230 + flag[19] + flag[27] + 189)
flag[23] = ((37 + 51 + flag[23]) ^ flag[24]) + 147
flag[1] = (196 + 252 + flag[1] + flag[4] + 224)
flag[20] = (67 + flag[2] + flag[20])
flag[8] = (43 ^ flag[13]) + flag[8]
flag[6] = (137 ^ 30 ^ (flag[6] + flag[7])) + 54
flag[3] = (74 ^ flag[22]) + flag[3]
flag[28] = (110 + flag[17] + flag[28])
flag[20] = ((178 + 197 + flag[20]) ^ flag[9]) + 141
flag[7] = (142 ^ (flag[7] + flag[10])) + 230
flag[25] = (82 ^ flag[25] ^ flag[2]) + 242
flag[23] = (191 ^ flag[23] ^ flag[7]) + 201
flag[11] = (137 + flag[11] + flag[18] + 34)
flag[8] = (49 + 173 + flag[8] + flag[5] + 117)
flag[23] = (172 + 111 + flag[23] + flag[22] + 235)
flag[10] = (250 + flag[20] + flag[10])
flag[27] = (131 + 12 + flag[27] + flag[16] + 38)
flag[28] = (179 + flag[28] + flag[19] + 115)
flag[23] = (108 + flag[27] + flag[23])
flag[9] = (121 ^ 144 ^ (flag[9] + flag[26])) + 23
flag[22] = ((213 + 23 + flag[22]) ^ flag[31]) + 108
flag[0] = ((140 + 168) ^ (flag[0] + flag[30])) + 85
flag[19] = ((125 + 83) ^ (flag[19] + flag[27])) + 129
flag[19] = (9 + flag[28] + flag[19])
flag[13] = (228 + flag[13] + flag[13] + 182)
flag[2] = (105 + flag[8] + flag[2])
flag[30] = (40 ^ flag[10]) + flag[30]
flag[28] = (146 ^ (flag[28] + flag[23])) + 143
flag[18] = ((201 + 238 + flag[18]) ^ flag[12]) + 211
flag[19] = (78 + 148 + flag[19] + flag[25] + 110)
flag[18] = (57 + flag[27] + flag[18])
flag[14] = (180 + flag[15] + flag[14])
flag[25] = ((177 + flag[25]) ^ flag[31]) + 104
flag[18] = (46 ^ (172 + flag[18]) ^ flag[27]) + 100
flag[14] = (255 ^ flag[14] ^ flag[29]) + 61
flag[8] = (226 + flag[8] + flag[14] + 103)
flag[29] = ((188 + 12) ^ (flag[29] + flag[1])) + 164
flag[5] = (229 ^ flag[18]) + flag[5]
flag[2] = (8 + flag[2] + flag[3] + 184)
flag[20] = (45 + flag[23] + flag[20])
flag[6] = (230 ^ flag[6] ^ flag[9]) + 243
flag[4] = (174 + flag[4] + flag[11] + 101)
flag[11] = (68 + 19 + flag[11] + flag[15] + 124)
flag[11] = (48 + flag[4] + flag[11])
flag[4] = ((111 + 60 + flag[4]) ^ flag[3]) + 172
flag[25] = (192 ^ (99 + flag[25] + flag[21])) + 128
flag[3] = ((167 + 163 + flag[3]) ^ flag[20]) + 48
flag[22] = ((28 + 24 + flag[22]) ^ flag[19]) + 160
flag[22] = (68 + 189 + flag[22] + flag[29] + 51)
flag[0] = (80 + flag[4] + flag[0])
flag[29] = (117 + flag[29] + flag[16] + 142)
flag[29] = (141 + flag[29] + flag[10] + 137)
flag[8] = (175 ^ flag[8] ^ flag[0]) + 126
flag[15] = (7 ^ flag[25]) + flag[15]
flag[2] = ((105 + 65 + flag[2]) ^ flag[18]) + 60
flag[4] = (96 ^ (flag[4] + flag[15])) + 47
flag[1] = (85 ^ flag[27]) + flag[1]
flag[11] = (81 + 183 + flag[11] + flag[18] + 177)
flag[28] = ((228 + flag[28]) ^ flag[20]) + 254
flag[23] = (50 ^ (1 + flag[23]) ^ flag[23]) + 57
flag[24] = (1 + flag[26] + flag[24])
flag[28] = (10 ^ (55 + flag[28] + flag[15])) + 134
flag[14] = (98 + flag[14] + flag[26] + 165)
flag[5] = (215 ^ (flag[5] + flag[31])) + 225
flag[0] = (86 + flag[25] + flag[0])
flag[0] = ((101 + 53) ^ (flag[0] + flag[26])) + 207
flag[31] = (152 ^ flag[30]) + flag[31]
flag[20] = ((65 + flag[20]) ^ flag[2]) + 69
flag[25] = (194 ^ (flag[25] + flag[6])) + 105
flag[19] = (65 ^ flag[14]) + flag[19]
flag[11] = (29 ^ flag[8]) + flag[11]
flag[27] = (175 ^ flag[16]) + flag[27]
flag[8] = (254 + flag[8] + flag[10] + 215)
flag[0] = (201 ^ flag[0]) + flag[0]
flag[18] = (68 + flag[30] + flag[18])
flag[29] = ((60 + flag[29]) ^ flag[18]) + 101
flag[2] = (190 + flag[21] + flag[2])
flag[11] = (128 ^ flag[11] ^ flag[2]) + 38
flag[2] = (195 + flag[3] + flag[2])
flag[8] = ((222 + flag[8]) ^ flag[1]) + 210
flag[17] = (109 + flag[17] + flag[13] + 90)
flag[28] = (143 + flag[7] + flag[28])
flag[4] = (247 ^ (152 + flag[4]) ^ flag[22]) + 249
flag[22] = ((233 + flag[22]) ^ flag[10]) + 163
flag[15] = (132 ^ flag[7]) + flag[15]
flag[29] = (172 + flag[6] + flag[29])
flag[19] = ((123 + flag[19]) ^ flag[19]) + 225
flag[0] = (152 + flag[0] + flag[28] + 34)
flag[10] = (68 + flag[23] + flag[10])
flag[23] = (130 + flag[23] + flag[24] + 17)
flag[22] = (141 + 137 + flag[22] + flag[30] + 254)
flag[8] = (71 + 74 + flag[8] + flag[5] + 232)
flag[9] = (118 ^ (flag[9] + flag[13])) + 115
flag[13] = (241 + flag[13] + flag[5] + 101)
flag[6] = ((73 + 142) ^ (flag[6] + flag[17])) + 217
flag[18] = (202 + flag[18] + flag[10] + 222)
flag[9] = (226 + flag[9] + flag[26] + 8)
flag[2] = (7 + flag[10] + flag[2])
flag[21] = (114 + flag[13] + flag[21])
'''
获取伪代码的 idapython 脚本
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
import idaapi
import idautils
import idc

def get_pseudocode(func_addr):
try:
decompilation = idaapi.decompile(func_addr)
if decompilation:
return str(decompilation)
else:
return None
except idaapi.DecompilationFailure:
print(f"[!] Failed to decompile function at {hex(func_addr)}")
return None

func_addresses = [
0xc7b4,
0xcc38,
0xb8f0,
0xa900,
0xac10,
0xb798,
0xca0c,
0xa6cc,
0xb6c0,
0xccec,
0xa2b0,
0xe180,
0xd900,
0xae5c,
0xae9c,
0xdd98,
0xb01c,
0xd668,
0xbdb0,
0xcbd0,
0xb11c,
0xd2f8,
0xd244,
0xbf0c,
0xab38,
0xbb30,
0xdcd8,
0xb4c0,
0xcaf4,
0xa840,
0xdaf0,
0xaf68,
0xd75c,
0xd0f8,
0xb970,
0xb3f4,
0xbdfc,
0xbabc,
0xb2f4,
0xa264,
0xc4cc,
0xcf60,
0xc7f4,
0xe100,
0xad50,
0xcb28,
0xa224,
0xda18,
0xb9fc,
0xceac,
0xce60,
0xbcf0,
0xb0a8,
0xba48,
0xbea4,
0xca80,
0xcc78,
0xa43c,
0xa64c,
0xc2f4,
0xb5c0,
0xc6d8,
0xb480,
0xafa8,
0xdc64,
0xc54c,
0xdb8c,
0xde98,
0xd404,
0xaa50,
0xbf40,
0xd834,
0xbed8,
0xc498,
0xa7c0,
0xbd24,
0xb758,
0xc240,
0xcf20,
0xc68c,
0xc5d8,
0xd6a8,
0xc74c,
0xbc18,
0xbbe4,
0xc400,
0xcfa0,
0xd510,
0xded8,
0xbb64,
0xc0e8,
0xd02c,
0xccb8,
0xc1f4,
0xadd0,
0xc598,
0xc44c,
0xc174,
0xb70c,
0xb0dc,
0xad90,
0xb58c,
0xcdec,
0xd6dc,
0xc380,
0xda64,
0xd590,
0xb328,
0xbc64,
0xddd8,
0xe098,
0xd7a8,
0xd190,
0xc074,
0xc9d8,
0xb8b0,
0xbcb0,
0xe064,
0xcac0,
0xc60c,
0xe140,
0xd61c,
0xdc18,
0xd98c,
0xb434,
0xc9a4,
0xb168,
0xcd20,
0xbd64,
0xcb9c,
0xc0b4,
0xad1c,
0xc8d8,
0xdb58,
0xe024,
0xd338,
0xa4e4,
0xc780,
0xba7c,
0xcc04,
0xcfec,
0xd2ac,
0xa8b4,
0xac5c,
0xab04,
0xcd6c,
0xe1b4,
0xbff4,
0xbb98,
0xc134,
0xde64,
0xa9e8,
0xb634,
0xd144,
0xbfb4,
0xa47c,
0xca40,
0xa2f0,
0xdf24,
0xdbcc
]

output_file = "functions_pseudocode.txt"

with open(output_file, "w", encoding="utf-8") as f:
for func_addr in func_addresses:
if not idc.get_func_name(func_addr):
print(f"[!] No function found at {hex(func_addr)}")
continue

print(f"[+] Processing function at {hex(func_addr)}")
pseudocode = get_pseudocode(func_addr)
if pseudocode:
f.write(f"// Function at {hex(func_addr)}\n")
f.write(f"{pseudocode}\n\n")
else:
f.write(f"// Failed to decompile function at {hex(func_addr)}\n\n")

print(f"[+] Pseudocode saved to {output_file}")
z3 脚本
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
from z3 import *

s = Solver()

flag = [BitVec(f"f_{_}", 16) for _ in range(32)]

for i in range(32):
s.add(And(flag[i] >= 0, flag[i] <= 255))

s.add(flag[0] == ord('S'))
s.add(flag[1] == ord('U'))
s.add(flag[2] == ord('C'))
s.add(flag[3] == ord('T'))
s.add(flag[4] == ord('F'))

mw = [0x000D7765, 0x00011EBD, 0x00032D12, 0x00013778, 0x0008A428, 0x0000B592, 0x0003FA57, 0x00001616, 0x0003659E, 0x0002483A, 0x00002882, 0x000508F4, 0x00000BAD, 0x00027920, 0x0000F821, 0x00019F83, 0x00000F97, 0x00033904, 0x000170D5, 0x0000016C, 0x0000CF5D, 0x000280D2, 0x000A8ADE, 0x00009EAA, 0x00009DAB, 0x0001F45E, 0x00003214, 0x000052FA, 0x0006D57A, 0x000460ED, 0x000124FF, 0x00013936]

flag[11] = (197 + flag[11] + flag[15] + 209)
flag[25] = ((86 + flag[25]) ^ flag[4]) + 73
flag[6] = (148 ^ (131 + flag[6]) ^ flag[12]) + 158
flag[19] = (144 + flag[19] + flag[23] + 225)
flag[10] = (179 + flag[10] + flag[23] + 62)
flag[23] = (187 ^ 121 ^ flag[23] ^ flag[16]) + 180
flag[12] = (58 ^ (213 + flag[12] + flag[23])) + 174
flag[21] = (95 + flag[8] + flag[21])
flag[1] = (126 + flag[19] + flag[1])
flag[4] = ((219 + 9) ^ flag[4] ^ flag[17]) + 109
flag[22] = (60 + flag[18] + flag[22])
flag[14] = (109 + flag[14] + flag[30] + 238)
flag[18] = (72 ^ flag[20]) + flag[18]
flag[15] = (10 + 146 + flag[15] + flag[24] + 45)
flag[19] = (23 ^ flag[19] ^ flag[14]) + 51
flag[14] = (140 ^ (flag[14] + flag[20])) + 155
flag[21] = (89 ^ flag[21] ^ flag[13]) + 209
flag[21] = (187 + flag[21] + flag[19] + 168)
flag[8] = (47 + flag[8] + flag[22] + 229)
flag[4] = (159 ^ (flag[4] + flag[12])) + 248
flag[29] = (27 ^ (255 + flag[29] + flag[19])) + 137
flag[7] = (93 + flag[16] + flag[7])
flag[4] = (206 ^ (188 + flag[4]) ^ flag[12]) + 11
flag[8] = ((33 + flag[8]) ^ flag[7]) + 141
flag[24] = (178 + flag[11] + flag[24])
flag[13] = (35 + flag[8] + flag[13])
flag[19] = (215 + 230 + flag[19] + flag[23] + 169)
flag[5] = (201 + flag[27] + flag[5])
flag[28] = (107 + flag[19] + flag[28])
flag[26] = ((111 + 48) ^ flag[26] ^ flag[28]) + 196
flag[12] = (132 ^ flag[28]) + flag[12]
flag[0] = (163 ^ flag[3]) + flag[0]
flag[16] = (117 + flag[3] + flag[16])
flag[0] = (84 ^ flag[0] ^ flag[24]) + 217
flag[19] = (211 ^ (68 + flag[19]) ^ flag[29]) + 217
flag[24] = (29 + flag[13] + flag[24])
flag[14] = (228 + 117 + flag[14] + flag[28] + 37)
flag[9] = ((208 + 141 + flag[9]) ^ flag[22]) + 62
flag[30] = (202 + flag[30] + flag[27] + 90)
flag[20] = (0 ^ flag[8]) + flag[20]
flag[28] = (57 ^ (flag[28] + flag[1])) + 129
flag[15] = (210 + flag[28] + flag[15])
flag[14] = ((79 + 85 + flag[14]) ^ flag[10]) + 177
flag[17] = (123 + flag[23] + flag[17])
flag[30] = (146 + flag[30] + flag[18] + 255)
flag[25] = (84 + flag[25] + flag[1] + 120)
flag[20] = ((55 + 1 + flag[20]) ^ flag[15]) + 102
flag[6] = ((154 + flag[6]) ^ flag[23]) + 169
flag[5] = (15 ^ (flag[5] + flag[31])) + 104
flag[1] = (250 ^ flag[4]) + flag[1]
flag[18] = (255 + flag[18] + flag[8] + 177)
flag[15] = (249 + 101 + flag[15] + flag[21] + 168)
flag[0] = ((218 + 152) ^ (flag[0] + flag[30])) + 128
flag[5] = (94 + flag[18] + flag[5])
flag[9] = (98 ^ flag[0]) + flag[9]
flag[15] = (166 ^ (65 + flag[15] + flag[5])) + 46
flag[26] = (206 + flag[8] + flag[26])
flag[20] = (104 + flag[4] + flag[20])
flag[23] = (144 + flag[4] + flag[23])
flag[31] = (202 + flag[23] + flag[31])
flag[28] = (160 + flag[20] + flag[28])
flag[5] = (94 + 60 + flag[5] + flag[23] + 235)
flag[26] = (50 + flag[26] + flag[3] + 253)
flag[6] = ((149 + flag[6]) ^ flag[17]) + 19
flag[31] = (34 + flag[31] + flag[7] + 198)
flag[18] = (35 ^ flag[18] ^ flag[20]) + 249
flag[26] = (65 + flag[17] + flag[26])
flag[10] = (237 + flag[10] + flag[11] + 142)
flag[25] = (7 + 247 + flag[25] + flag[24] + 167)
flag[3] = (22 ^ flag[3] ^ flag[17]) + 190
flag[16] = (234 + flag[25] + flag[16])
flag[29] = (231 + 172 + flag[29] + flag[7] + 9)
flag[1] = (230 ^ flag[5]) + flag[1]
flag[2] = (51 + 152 + flag[2] + flag[4] + 55)
flag[17] = (252 + flag[17] + flag[3] + 161)
flag[17] = ((119 + flag[17]) ^ flag[11]) + 212
flag[30] = (88 ^ flag[30] ^ flag[9]) + 72
flag[8] = (30 + flag[8] + flag[10] + 38)
flag[19] = ((229 + flag[19]) ^ flag[14]) + 3
flag[5] = ((45 + 241) ^ (flag[5] + flag[18])) + 60
flag[25] = (197 + flag[25] + flag[14] + 244)
flag[30] = (241 + flag[30] + flag[18] + 231)
flag[8] = (138 ^ 226 ^ flag[8] ^ flag[31]) + 185
flag[18] = ((154 + 7 + flag[18]) ^ flag[9]) + 183
flag[2] = (138 ^ flag[17]) + flag[2]
flag[17] = (173 + flag[12] + flag[17])
flag[9] = ((111 + 86 + flag[9]) ^ flag[26]) + 151
flag[30] = (100 + 148 + flag[30] + flag[3] + 170)
flag[1] = (12 ^ flag[19]) + flag[1]
flag[30] = (215 + flag[12] + flag[30])
flag[20] = (151 ^ flag[25]) + flag[20]
flag[14] = (144 + flag[14] + flag[21] + 41)
flag[24] = (23 ^ (flag[24] + flag[12])) + 86
flag[0] = (168 ^ flag[29]) + flag[0]
flag[13] = (83 + flag[9] + flag[13])
flag[7] = (177 ^ (flag[7] + flag[4])) + 83
flag[14] = (146 ^ (flag[14] + flag[9])) + 173
flag[27] = (30 ^ (72 + flag[27] + flag[8])) + 2
flag[13] = (148 + flag[18] + flag[13])
flag[19] = (152 + flag[9] + flag[19])
flag[27] = (238 ^ (140 + flag[27] + flag[14])) + 50
flag[17] = (148 ^ flag[25]) + flag[17]
flag[8] = (77 ^ flag[20]) + flag[8]
flag[5] = (19 ^ (47 + flag[5] + flag[17])) + 238
flag[24] = (182 + flag[14] + flag[24])
flag[9] = (172 ^ (27 + flag[9]) ^ flag[31]) + 210
flag[6] = (211 ^ flag[2]) + flag[6]
flag[11] = (80 ^ flag[28]) + flag[11]
flag[13] = (12 ^ 33 ^ (flag[13] + flag[5])) + 61
flag[22] = (231 ^ (178 + flag[22] + flag[8])) + 197
flag[1] = (203 + flag[13] + flag[1])
flag[9] = (72 ^ (215 + flag[9] + flag[6])) + 116
flag[30] = (183 + flag[14] + flag[30])
flag[25] = (27 + 107 + flag[25] + flag[4] + 100)
flag[4] = (19 ^ (111 + flag[4]) ^ flag[16]) + 235
flag[5] = (220 ^ flag[15]) + flag[5]
flag[24] = ((60 + 163) ^ (flag[24] + flag[0])) + 164
flag[27] = ((99 + flag[27]) ^ flag[7]) + 25
flag[25] = (163 + flag[28] + flag[25])
flag[25] = (24 ^ (flag[25] + flag[4])) + 54
flag[10] = ((189 + 29 + flag[10]) ^ flag[16]) + 214
flag[5] = (13 + flag[5] + flag[21] + 160)
flag[30] = (92 ^ (208 + flag[30]) ^ flag[13]) + 189
flag[26] = (246 ^ flag[26] ^ flag[15]) + 93
flag[30] = ((59 + 0 + flag[30]) ^ flag[7]) + 72
flag[1] = (136 ^ (flag[1] + flag[9])) + 111
flag[25] = (65 ^ (flag[25] + flag[0])) + 98
flag[17] = (92 + flag[21] + flag[17])
flag[15] = (42 ^ (flag[15] + flag[17])) + 1
flag[31] = (183 ^ flag[4]) + flag[31]
flag[24] = (242 + flag[24] + flag[18] + 28)
flag[6] = (1 + flag[1] + flag[6])
flag[9] = (15 ^ 154 ^ (flag[9] + flag[10])) + 152
flag[8] = (55 ^ flag[2]) + flag[8]
flag[29] = (255 + 250 + flag[29] + flag[23] + 46)
flag[17] = (68 ^ (flag[17] + flag[22])) + 165
flag[8] = ((104 + 249 + flag[8]) ^ flag[5]) + 0
flag[0] = (53 + flag[0] + flag[24] + 224)
flag[17] = (222 ^ flag[1]) + flag[17]
flag[10] = ((82 + 98) ^ flag[10] ^ flag[2]) + 180
flag[14] = (128 ^ (166 + flag[14] + flag[1])) + 25
flag[0] = (165 ^ flag[29]) + flag[0]
flag[13] = (72 + flag[15] + flag[13])
flag[19] = (36 + flag[19] + flag[30] + 59)
flag[17] = (196 + flag[9] + flag[17])
flag[17] = (183 + 160 + flag[17] + flag[4] + 96)
flag[11] = (244 + flag[28] + flag[11])
flag[29] = (87 + flag[29] + flag[30] + 189)
flag[19] = (99 + 149 + flag[19] + flag[0] + 162)
flag[6] = (177 + flag[3] + flag[6])
flag[25] = (103 ^ (flag[25] + flag[30])) + 162
flag[29] = (148 + flag[29] + flag[13] + 8)
flag[14] = ((241 + flag[14]) ^ flag[15]) + 17
flag[7] = (139 + flag[23] + flag[7])
flag[30] = (152 + flag[9] + flag[30])
flag[23] = (113 + flag[23] + flag[4] + 54)
flag[9] = ((89 + flag[9]) ^ flag[12]) + 79
flag[19] = (39 + 230 + flag[19] + flag[27] + 189)
flag[23] = ((37 + 51 + flag[23]) ^ flag[24]) + 147
flag[1] = (196 + 252 + flag[1] + flag[4] + 224)
flag[20] = (67 + flag[2] + flag[20])
flag[8] = (43 ^ flag[13]) + flag[8]
flag[6] = (137 ^ 30 ^ (flag[6] + flag[7])) + 54
flag[3] = (74 ^ flag[22]) + flag[3]
flag[28] = (110 + flag[17] + flag[28])
flag[20] = ((178 + 197 + flag[20]) ^ flag[9]) + 141
flag[7] = (142 ^ (flag[7] + flag[10])) + 230
flag[25] = (82 ^ flag[25] ^ flag[2]) + 242
flag[23] = (191 ^ flag[23] ^ flag[7]) + 201
flag[11] = (137 + flag[11] + flag[18] + 34)
flag[8] = (49 + 173 + flag[8] + flag[5] + 117)
flag[23] = (172 + 111 + flag[23] + flag[22] + 235)
flag[10] = (250 + flag[20] + flag[10])
flag[27] = (131 + 12 + flag[27] + flag[16] + 38)
flag[28] = (179 + flag[28] + flag[19] + 115)
flag[23] = (108 + flag[27] + flag[23])
flag[9] = (121 ^ 144 ^ (flag[9] + flag[26])) + 23
flag[22] = ((213 + 23 + flag[22]) ^ flag[31]) + 108
flag[0] = ((140 + 168) ^ (flag[0] + flag[30])) + 85
flag[19] = ((125 + 83) ^ (flag[19] + flag[27])) + 129
flag[19] = (9 + flag[28] + flag[19])
flag[13] = (228 + flag[13] + flag[13] + 182)
flag[2] = (105 + flag[8] + flag[2])
flag[30] = (40 ^ flag[10]) + flag[30]
flag[28] = (146 ^ (flag[28] + flag[23])) + 143
flag[18] = ((201 + 238 + flag[18]) ^ flag[12]) + 211
flag[19] = (78 + 148 + flag[19] + flag[25] + 110)
flag[18] = (57 + flag[27] + flag[18])
flag[14] = (180 + flag[15] + flag[14])
flag[25] = ((177 + flag[25]) ^ flag[31]) + 104
flag[18] = (46 ^ (172 + flag[18]) ^ flag[27]) + 100
flag[14] = (255 ^ flag[14] ^ flag[29]) + 61
flag[8] = (226 + flag[8] + flag[14] + 103)
flag[29] = ((188 + 12) ^ (flag[29] + flag[1])) + 164
flag[5] = (229 ^ flag[18]) + flag[5]
flag[2] = (8 + flag[2] + flag[3] + 184)
flag[20] = (45 + flag[23] + flag[20])
flag[6] = (230 ^ flag[6] ^ flag[9]) + 243
flag[4] = (174 + flag[4] + flag[11] + 101)
flag[11] = (68 + 19 + flag[11] + flag[15] + 124)
flag[11] = (48 + flag[4] + flag[11])
flag[4] = ((111 + 60 + flag[4]) ^ flag[3]) + 172
flag[25] = (192 ^ (99 + flag[25] + flag[21])) + 128
flag[3] = ((167 + 163 + flag[3]) ^ flag[20]) + 48
flag[22] = ((28 + 24 + flag[22]) ^ flag[19]) + 160
flag[22] = (68 + 189 + flag[22] + flag[29] + 51)
flag[0] = (80 + flag[4] + flag[0])
flag[29] = (117 + flag[29] + flag[16] + 142)
flag[29] = (141 + flag[29] + flag[10] + 137)
flag[8] = (175 ^ flag[8] ^ flag[0]) + 126
flag[15] = (7 ^ flag[25]) + flag[15]
flag[2] = ((105 + 65 + flag[2]) ^ flag[18]) + 60
flag[4] = (96 ^ (flag[4] + flag[15])) + 47
flag[1] = (85 ^ flag[27]) + flag[1]
flag[11] = (81 + 183 + flag[11] + flag[18] + 177)
flag[28] = ((228 + flag[28]) ^ flag[20]) + 254
flag[23] = (50 ^ (1 + flag[23]) ^ flag[23]) + 57
flag[24] = (1 + flag[26] + flag[24])
flag[28] = (10 ^ (55 + flag[28] + flag[15])) + 134
flag[14] = (98 + flag[14] + flag[26] + 165)
flag[5] = (215 ^ (flag[5] + flag[31])) + 225
flag[0] = (86 + flag[25] + flag[0])
flag[0] = ((101 + 53) ^ (flag[0] + flag[26])) + 207
flag[31] = (152 ^ flag[30]) + flag[31]
flag[20] = ((65 + flag[20]) ^ flag[2]) + 69
flag[25] = (194 ^ (flag[25] + flag[6])) + 105
flag[19] = (65 ^ flag[14]) + flag[19]
flag[11] = (29 ^ flag[8]) + flag[11]
flag[27] = (175 ^ flag[16]) + flag[27]
flag[8] = (254 + flag[8] + flag[10] + 215)
flag[0] = (201 ^ flag[0]) + flag[0]
flag[18] = (68 + flag[30] + flag[18])
flag[29] = ((60 + flag[29]) ^ flag[18]) + 101
flag[2] = (190 + flag[21] + flag[2])
flag[11] = (128 ^ flag[11] ^ flag[2]) + 38
flag[2] = (195 + flag[3] + flag[2])
flag[8] = ((222 + flag[8]) ^ flag[1]) + 210
flag[17] = (109 + flag[17] + flag[13] + 90)
flag[28] = (143 + flag[7] + flag[28])
flag[4] = (247 ^ (152 + flag[4]) ^ flag[22]) + 249
flag[22] = ((233 + flag[22]) ^ flag[10]) + 163
flag[15] = (132 ^ flag[7]) + flag[15]
flag[29] = (172 + flag[6] + flag[29])
flag[19] = ((123 + flag[19]) ^ flag[19]) + 225
flag[0] = (152 + flag[0] + flag[28] + 34)
flag[10] = (68 + flag[23] + flag[10])
flag[23] = (130 + flag[23] + flag[24] + 17)
flag[22] = (141 + 137 + flag[22] + flag[30] + 254)
flag[8] = (71 + 74 + flag[8] + flag[5] + 232)
flag[9] = (118 ^ (flag[9] + flag[13])) + 115
flag[13] = (241 + flag[13] + flag[5] + 101)
flag[6] = ((73 + 142) ^ (flag[6] + flag[17])) + 217
flag[18] = (202 + flag[18] + flag[10] + 222)
flag[9] = (226 + flag[9] + flag[26] + 8)
flag[2] = (7 + flag[10] + flag[2])
flag[21] = (114 + flag[13] + flag[21])

for i in range(32):
s.add(flag[i] == mw[i])

solutions = []

while s.check() == sat:
model = s.model()
solution = [0] * 32
for d in model.decls():
solution[int(d.name().split("_")[1])] = model[d].as_long()
print(bytes(solution).decode())

s.add(Or([flag[i] != solution[i] for i in range(32)]))

# SUCTF{Y0u_Ar3_Andr0id_M4st3r!!!}

SU_Harmony

简单一元二次方程

到手后提取出 abc 和 libentry.so,ark层没啥东西,就是调用so

image-20250113125321445

RegisterEntryModule 下找到注册函数调用,然后找到 check 函数注册位置

image-20250113125422031

有点混淆,但是问题不大,不是很影响

关键是这里,把输入的内容拼成 int 后传进去加密,然后和结果数字表比较

image-20250113125514559

加密函数关键都在头部,是个高精度操作,总结起来就是

image-20250113125606652

然后用一元二次求根公式就行了

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
import math
from Crypto.Util.number import long_to_bytes

dt = [
999272289930604998,
1332475531266467542,
1074388003071116830,
1419324015697459326,
978270870200633520,
369789474534896558,
344214162681978048,
2213954953857181622
]

# 2 * (x * x + 2 * x - 3) = dt

# print(math.sqrt(999272289930605002))

for x in dt:
c = (2 * x) + 3
delta = 4 + 4 * c
delta = math.sqrt(delta)
sol = (-2 + delta) / 2
sol = int(sol)
print(long_to_bytes(sol)[::-1].decode(), end="")
# SUCTF{Ma7h_WorldIs_S0_B3aut1ful}

SU_minesweeper

又是一个 z3 题,题目把输入的内容两两拼接成 uint8 存进数组

image-20250113130040726

然后这个字符对应集和标准hex是不一样的,是 abcdef0123456789

一共 50 个 uint8,拆成 400 位,20 * 20 的矩阵

然后这个函数按照 wtMap 来判断以 [i][j] 为中心的 3 * 3 网格内 1 的数量是否等于 wtMap 里的值

image-20250113130130467

这个函数就是在提取 第 i 行的 j 位

image-20250113130300507

然后就可以用 z3 去解了

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

a = [0x03, 0x04, 0xFF, 0xFF, 0xFF, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0x04, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0x04, 0x06, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x05, 0x06, 0x04, 0xFF, 0x05, 0xFF, 0x04, 0x07, 0xFF, 0x08, 0xFF, 0x06, 0xFF, 0xFF, 0x06, 0x06, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0x03, 0xFF, 0x05, 0x06, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x05, 0x04, 0x05, 0x07, 0x06, 0xFF, 0xFF, 0x04, 0xFF, 0x02, 0x01, 0xFF, 0xFF, 0xFF, 0x03, 0x04, 0xFF, 0xFF, 0x05, 0x04, 0x03, 0xFF, 0xFF, 0x07, 0x04, 0x03, 0xFF, 0xFF, 0x01, 0x01, 0xFF, 0xFF, 0x04, 0x03, 0xFF, 0x02, 0xFF, 0x04, 0x03, 0xFF, 0xFF, 0x02, 0xFF, 0x05, 0x04, 0xFF, 0xFF, 0x02, 0x02, 0xFF, 0xFF, 0x04, 0xFF, 0x04, 0xFF, 0x03, 0x05, 0x06, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0x01, 0x04, 0xFF, 0xFF, 0x07, 0x05, 0xFF, 0xFF, 0x03, 0x03, 0x02, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0x05, 0x07, 0xFF, 0x03, 0x02, 0x04, 0x04, 0xFF, 0x07, 0x05, 0x04, 0x03, 0xFF, 0xFF, 0x04, 0xFF, 0x02, 0x04, 0x05, 0xFF, 0xFF, 0x06, 0x05, 0x04, 0xFF, 0x02, 0xFF, 0xFF, 0x07, 0x04, 0xFF, 0xFF, 0x03, 0xFF, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x03, 0x02, 0x02, 0xFF, 0xFF, 0x02, 0x04, 0x03, 0x05, 0xFF, 0xFF, 0x05, 0xFF, 0x04, 0xFF, 0x06, 0xFF, 0xFF, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x03, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0xFF, 0x06, 0x06, 0xFF, 0x07, 0x06, 0x04, 0xFF, 0x04, 0x03, 0xFF, 0x04, 0x03, 0x05, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x06, 0x07, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x05, 0xFF, 0x05, 0xFF, 0xFF, 0x06, 0x07, 0x07, 0xFF, 0x05, 0x06, 0x06, 0xFF, 0xFF, 0x02, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0xFF, 0xFF, 0x07, 0x07, 0x06, 0xFF, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x03, 0x05, 0xFF, 0x07, 0xFF, 0x05, 0xFF, 0x06, 0xFF, 0x05, 0xFF, 0xFF, 0x07, 0x08, 0xFF, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x05, 0x03, 0xFF, 0x04, 0x05, 0x05, 0x03, 0xFF, 0xFF, 0x06, 0x05, 0x05, 0x06, 0xFF, 0x06, 0x05, 0x02, 0x04, 0x03, 0x04, 0xFF, 0xFF, 0x03, 0x04, 0x04, 0x06, 0x05, 0xFF, 0x03, 0xFF, 0x05, 0x05, 0x05, 0xFF, 0xFF, 0x05, 0xFF, 0xFF, 0x04, 0xFF, 0xFF, 0x04, 0xFF, 0x07, 0x07, 0x08, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0xFF, 0xFF, 0xFF, 0x04, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x03]

bit_matrix = [[BitVec(f"x_{i}_{j}", 32) for j in range(20)] for i in range(20)]

s = Solver()

for i in range(20):
for j in range(20):
if a[20 * i + j] != 0xFF:
tmp_i = i
tmp_j = j
addTmp_expr = []
for k1 in range(-1, 2, 1):
for k2 in range(-1, 2, 1):
new_i = tmp_i + k1
new_j = tmp_j + k2

if new_i >= 0 and new_i <= 19 and new_j >= 0 and new_j <= 19:
addTmp_expr.append(bit_matrix[new_i][new_j])

s.add(Sum(addTmp_expr) == a[20 * i + j])

for i in range(20):
for j in range(20):
s.add(Or(bit_matrix[i][j] == 0, bit_matrix[i][j] == 1))

solutions = []
while s.check() == sat:
model = s.model()
# 提取当前解
solution = [[model.evaluate(bit_matrix[i][j]).as_long() for j in range(20)] for i in range(20)]
solutions.append(solution)

for i in range(20):
for j in range(20):
if a[20 * i + j] != 0xFF:
tmp_i = i
tmp_j = j
addTmp = 0
for k1 in range(-1, 2, 1):
for k2 in range(-1, 2, 1):
new_i = tmp_i + k1
new_j = tmp_j + k2

if new_i >= 0 and new_i <= 19 and new_j >= 0 and new_j <= 19:
addTmp = addTmp + solution[new_i][new_j]
print(addTmp, a[20 * i + j])
if addTmp != a[20 * i + j]:
exit()

print(solution)

block = []
for i in range(20):
for j in range(20):
block.append(bit_matrix[i][j] == solution[i][j])
s.add(Not(And(block)))

print("Done")

for idx, solution in enumerate(solutions):
print(f"Solution {idx + 1}:")
for row in solution:
print(row)
print()

我在写脚本的时候为了方便比特位是顺序过去的,但是上面的提取比特函数是有 “端序” 的,得到答案矩阵后每次截取 8 位需要逆转一下才是正确答案

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
solution = [[1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1], [0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1], [1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1], [0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1], [1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0], [1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0], [1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1], [0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0], [1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1], [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1], [1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], [0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0], [1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1], [0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0]]

def recovery(dt):
if dt <= 5:
return chr(dt + 97)
else:
return chr(dt + 42)

newSol = [0] * 400
result = ""

for i in range(20):
for j in range(20):
newSol[i * 20 + j] = solution[i][j]

for i in range(0, 400, 8):
dt = newSol[i: i + 8][::-1]
dt = [str(_) for _ in dt]
dt = "".join(dt)
dt = int(dt, 2)

part1 = (dt >> 4) & 0xF
part2 = dt & 0xF

part1 = recovery(part1)
part2 = recovery(part2)

result += part1 + part2

print(result)

# f57503596fb80f955fa5cad3cb282aa18ac62922a1981ea7b53b07a30709b508f3176601154250d509b7bee0f2170b898617
# SUCTF{d661b98e4241de7423ef2d953098329d}

SU_BBRE

我好像选了个笨办法。。。把所有汇编转换成 asm,然后 nasm + gcc 编译再用 ida 看

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
section .data
format db "please input your flag:", 0
a19s db "%19s", 0
aS db "%s", 0
aSuctf db "suctf", 0
s db "hhh,you find me:", 0
aCongratulate db "congratulate!!!", 0

section .bss
src resb 100


extern printf
extern __isoc99_scanf
extern puts
extern exit
extern strcpy

section .text
global _start
_start:
lea ecx, [esp + 4]
and esp, 0FFFFFFF0h
push dword [ecx - 4]
push ebp
mov ebp, esp
push ecx
sub esp, 74h
sub esp, 0Ch
push format
call printf
add esp, 10h
sub esp, 8
lea eax, [ebp - 6Ch]
push eax
push a19s
call __isoc99_scanf
add esp, 10h
sub esp, 0Ch
lea eax, [ebp - 6Ch]
push eax
call function2
add esp, 10h
sub esp, 0Ch
lea eax, [ebp - 6Ch]
push eax
call function0
add esp, 10h
mov eax, 0
mov ecx, [ebp-4]
leave
lea esp, [ecx-4]
ret

function1:
push ebp
mov ebp, esp
sub esp, 28h
mov dword [ebp-1Fh], 4D626D41h
mov dword [ebp-1Bh], 294E4953h
mov byte [ebp-17h], 28h ; '('
sub esp, 0Ch
push s ; "hhh,you find me:"
call puts
add esp, 10h
sub esp, 8
lea eax, [ebp-16h]
push eax
push aS ; "%s"
call __isoc99_scanf
add esp, 10h
mov dword [ebp-0Ch], 0
jmp short loc_4022B5

loc_402282:
lea edx, [ebp-16h]
mov eax, [ebp-0Ch]
add eax, edx
movzx eax, byte [eax]
movsx eax, al
sub eax, [ebp-0Ch]
mov edx, eax
lea ecx, [ebp-1Fh]
mov eax, [ebp-0Ch]
add eax, ecx
movzx eax, byte [eax]
movsx eax, al
cmp edx, eax
jz short loc_4022B1
sub esp, 0Ch
push 0 ; status
call exit

loc_4022B1:
add dword [ebp-0Ch], 1

loc_4022B5:
cmp dword [ebp-0Ch], 8
jle short loc_402282
sub esp, 0Ch
push aCongratulate ; "congratulate!!!"
call puts
add esp, 10h
sub esp, 0Ch
push 0 ; status
call exit

function0:
push ebp
mov ebp, esp
sub esp, 18h
sub esp, 8
push dword [ebp+8] ; src
lea eax, [ebp-0Ch]
push eax ; dest
call strcpy
add esp, 10h
mov eax, 0
leave
retn

function2:
push ebp
mov ebp, esp
sub esp, 28h
mov dword [ebp-1Ch], 65575A2Fh
mov dword [ebp-18h], 0CD698F14h
mov dword [ebp-14h], 551A2993h
mov dword [ebp-10h], 5EE44018h
push 10h
push dword [ebp+8]
push 5
push aSuctf ; "suctf"
call function5
add esp, 10h
mov dword [ebp-0Ch], 0
jmp short loc_402364

loc_402333:
mov edx, [ebp-0Ch]
mov eax, [ebp+8]
add eax, edx
movzx eax, byte [eax]
movsx eax, al
movzx edx, al
lea ecx, [ebp-1Ch]
mov eax, [ebp-0Ch]
add eax, ecx
movzx eax, byte [eax]
movzx eax, al
cmp edx, eax
jz short loc_402360
sub esp, 0Ch
push 0 ; status
call exit

loc_402360:
add dword [ebp-0Ch], 1

loc_402364:
cmp dword [ebp-0Ch], 0Fh
jle short loc_402333
nop
nop
leave
retn

function3:
push ebp
mov ebp, esp
sub esp, 10h
mov dword [ebp-8h], 0
mov dword [ebp-4h], 0
jmp short loc_402395

loc_402384:
mov edx, [ebp-4h]
mov eax, [ebp+10h]
add eax, edx
mov edx, [ebp-4h]
mov [eax], dl
add dword [ebp-4h], 1

loc_402395:
cmp dword [ebp-4h], 0FFh
jle short loc_402384
mov dword [ebp-4h], 0
jmp short loc_402416

loc_4023A7:
mov edx, [ebp-4h]
mov eax, [ebp+10h]
add eax, edx
movzx eax, byte [eax]
movzx edx, al
mov eax, [ebp-8h]
lea ecx, [edx+eax]
mov eax, [ebp-4h]
cdq
idiv dword [ebp+0Ch]
mov eax, edx
mov edx, eax
mov eax, [ebp+8h]
add eax, edx
movzx eax, byte [eax]
movzx eax, al
add eax, ecx
cdq
shr edx, 18h
add eax, edx
movzx eax, al
sub eax, edx
mov [ebp-8h], eax
mov edx, [ebp-4h]
mov eax, [ebp+10h]
add eax, edx
movzx eax, byte [eax]
mov [ebp-9h], al
mov edx, [ebp-8h]
mov eax, [ebp+10h]
add eax, edx
mov ecx, [ebp-4h]
mov edx, [ebp+10h]
add edx, ecx
movzx eax, byte [eax]
mov [edx], al
mov edx, [ebp-8h]
mov eax, [ebp+10h]
add edx, eax
movzx eax, byte [ebp-9h]
mov [edx], al
add dword [ebp-4h], 1

loc_402416:
cmp dword [ebp-4h], 0FFh
jle short loc_4023A7
nop
nop
leave
retn

function4:
push ebp
mov ebp, esp
sub esp, 20h
mov dword [ebp-4], 0
mov dword [ebp-8], 0
mov dword [ebp-0Ch], 0
jmp loc_4024F6

loc_402443:
mov eax, [ebp-4]
add eax, 1
cdq
shr edx, 18h
add eax, edx
movzx eax, al
sub eax, edx
mov [ebp-4], eax
mov edx, [ebp-4]
mov eax, [ebp+8]
add eax, edx
movzx eax, byte [eax]
movzx edx, al
mov eax, [ebp-8]
add eax, edx
cdq
shr edx, 18h
add eax, edx
movzx eax, al
sub eax, edx
mov [ebp-8], eax
mov edx, [ebp-4]
mov eax, [ebp+8]
add eax, edx
movzx eax, byte [eax]
mov [ebp-0Dh], al
mov edx, [ebp-8]
mov eax, [ebp+8]
add eax, edx
mov ecx, [ebp-4]
mov edx, [ebp+8]
add edx, ecx
movzx eax, byte [eax]
mov [edx], al
mov edx, [ebp-8]
mov eax, [ebp+8]
add edx, eax
movzx eax, byte [ebp-0Dh]
mov [edx], al
mov edx, [ebp-4]
mov eax, [ebp+8]
add eax, edx
movzx edx, byte [eax]
mov ecx, [ebp-8]
mov eax, [ebp+8]
add eax, ecx
movzx eax, byte [eax]
add eax, edx
movzx edx, al
mov eax, [ebp+8]
add eax, edx
movzx eax, byte [eax]
movzx eax, al
mov [ebp-14h], eax
mov edx, [ebp-0Ch]
mov eax, [ebp+0Ch]
add eax, edx
movzx eax, byte [eax]
mov edx, eax
mov eax, [ebp-14h]
mov ecx, edx
xor ecx, eax
mov edx, [ebp-0Ch]
mov eax, [ebp+0Ch]
add eax, edx
mov edx, ecx
mov [eax], dl
add dword [ebp-0Ch], 1

loc_4024F6:
mov eax, [ebp-0Ch]
cmp eax, [ebp+10h]
jl loc_402443
nop
nop
leave
retn

function5:
push ebp
mov ebp, esp
sub esp, 100h
lea eax, [ebp-100h]
push eax
push dword [ebp+0Ch]
push dword [ebp+8]
call function3
add esp, 0Ch
push dword [ebp+14h]
push dword [ebp+10h]
lea eax, [ebp-100h]
push eax
call function4
add esp, 0Ch
nop
leave
retn

image-20250113135658130

一个简单 rc4

image-20250113135713468

然后有一个隐藏的函数

image-20250113135744183

这里有一个栈溢出漏洞,RC4中也只加密16个字符,所以可以猜测是主函数中输入 20 个字符,末尾 4 个用来栈溢出,ret 到 function1,触发隐藏内容

image-20250113135757528

rc4解出来是 We1com3ToReWorld

function1 的地址是 0x0040223D,转换成字符串就是 ="@

function1 解出来是 AndPWNT00

拼接一下就是 We1com3ToReWorld="@AndPWNT00SUCTF{We1com3ToReWorld="@AndPWNT00}

SU_ezlua

题目应该是魔改了 luac 的文件结构,我选择直接外部导入 liblua.so,然后调用里面的 luaU_dump 来 dump 一份 luac 修改代码来源 Sink

image-20250113154655497

然后修改下 Makefile 参数,编译出 liblua.so,之后使用 frida 载入,调用 luaL_dumpfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var luac = Module.load("/mnt/d/CTF/scripts/frida/liblua.so")
var func_ptr = luac.findExportByName("luaL_dumpfile")
var dumpLua = new NativeFunction(func_ptr, "int", ["pointer", "pointer"]);
var output = Memory.allocUtf8String("/mnt/d/CTF/scripts/frida/dump.luac")

Memory.protect(ptr(luac.base), luac.size, 'rwx');

var module = Process.getModuleByName("lua")
Interceptor.attach(module.base.add(0x1CB70), {
onEnter: function(args) {
console.log("Hooked! Dumping...")
this.L_object = args[0]
},
onLeave: function() {
console.log(this.L_object, output)
dumpLua(this.L_object, output)
}
})

没有魔改字节码 unluac 反编译得到

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
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
local L0_1, L1_1

function L0_1(A0_2)
local L1_2, L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2, L13_2, L14_2, L15_2
L2_2 = ""
L1_2 = "0123456789abcdef"
L6_2 = 1
L7_2 = string
L7_2 = L7_2.len
L8_2 = A0_2
L7_2 = L7_2(L8_2)
L8_2 = 1
for L9_2 = L6_2, L7_2, L8_2 do
L10_2 = string
L10_2 = L10_2.byte
L11_2 = A0_2
L12_2 = L9_2
L10_2 = L10_2(L11_2, L12_2)
L3_2 = L10_2
L10_2 = And
L11_2 = Shr
L12_2 = L3_2
L13_2 = 4
L11_2 = L11_2(L12_2, L13_2)
L12_2 = 15
L10_2 = L10_2(L11_2, L12_2)
L4_2 = L10_2
L10_2 = And
L11_2 = L3_2
L12_2 = 15
L10_2 = L10_2(L11_2, L12_2)
L5_2 = L10_2
L10_2 = L2_2
L11_2 = string
L11_2 = L11_2.sub
L12_2 = L1_2
L13_2 = L4_2 + 1
L14_2 = L4_2 + 1
L11_2 = L11_2(L12_2, L13_2, L14_2)
L12_2 = string
L12_2 = L12_2.sub
L13_2 = L1_2
L14_2 = L5_2 + 1
L15_2 = L5_2 + 1
L12_2 = L12_2(L13_2, L14_2, L15_2)
L2_2 = L10_2 .. L11_2 .. L12_2
end
return L2_2
end

hex = L0_1

function L0_1(A0_2)
local L1_2, L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2
L1_2 = string
L1_2 = L1_2.char
L2_2 = And
L3_2 = A0_2
L4_2 = 255
L2_2 = L2_2(L3_2, L4_2)
L3_2 = And
L4_2 = Shr
L5_2 = A0_2
L6_2 = 8
L4_2 = L4_2(L5_2, L6_2)
L5_2 = 255
L3_2 = L3_2(L4_2, L5_2)
L4_2 = And
L5_2 = Shr
L6_2 = A0_2
L7_2 = 16
L5_2 = L5_2(L6_2, L7_2)
L6_2 = 255
L4_2 = L4_2(L5_2, L6_2)
L5_2 = And
L6_2 = Shr
L7_2 = A0_2
L8_2 = 24
L6_2 = L6_2(L7_2, L8_2)
L7_2 = 255
L5_2, L6_2, L7_2, L8_2 = L5_2(L6_2, L7_2)
return L1_2(L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2)
end

from_uint = L0_1

function L0_1(A0_2, A1_2)
local L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2
if A1_2 == nil then
A1_2 = 1
end
L2_2 = string
L2_2 = L2_2.byte
L3_2 = A0_2
L4_2 = A1_2
L2_2 = L2_2(L3_2, L4_2)
L3_2 = Or
L4_2 = L2_2
L5_2 = Shl
L6_2 = string
L6_2 = L6_2.byte
L7_2 = A0_2
L8_2 = A1_2 + 1
L6_2 = L6_2(L7_2, L8_2)
L7_2 = 8
L5_2, L6_2, L7_2, L8_2 = L5_2(L6_2, L7_2)
L3_2 = L3_2(L4_2, L5_2, L6_2, L7_2, L8_2)
L2_2 = L3_2
L3_2 = Or
L4_2 = L2_2
L5_2 = Shl
L6_2 = string
L6_2 = L6_2.byte
L7_2 = A0_2
L8_2 = A1_2 + 2
L6_2 = L6_2(L7_2, L8_2)
L7_2 = 16
L5_2, L6_2, L7_2, L8_2 = L5_2(L6_2, L7_2)
L3_2 = L3_2(L4_2, L5_2, L6_2, L7_2, L8_2)
L2_2 = L3_2
L3_2 = Or
L4_2 = L2_2
L5_2 = Shl
L6_2 = string
L6_2 = L6_2.byte
L7_2 = A0_2
L8_2 = A1_2 + 3
L6_2 = L6_2(L7_2, L8_2)
L7_2 = 24
L5_2, L6_2, L7_2, L8_2 = L5_2(L6_2, L7_2)
L3_2 = L3_2(L4_2, L5_2, L6_2, L7_2, L8_2)
L2_2 = L3_2
return L2_2
end

to_uint = L0_1

function L0_1(A0_2, A1_2)
local L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2, L13_2
L6_2 = string
L6_2 = L6_2.len
L7_2 = A1_2
L6_2 = L6_2(L7_2)
L4_2 = L6_2
L6_2 = 0
L7_2 = 255
L8_2 = 1
for L9_2 = L6_2, L7_2, L8_2 do
A0_2[L9_2] = L9_2
end
L3_2 = 0
L6_2 = 0
L7_2 = 255
L8_2 = 1
for L9_2 = L6_2, L7_2, L8_2 do
L10_2 = A0_2[L9_2]
L10_2 = L3_2 + L10_2
L11_2 = string
L11_2 = L11_2.byte
L12_2 = A1_2
L13_2 = L9_2 % L4_2
L13_2 = L13_2 + 1
L11_2 = L11_2(L12_2, L13_2)
L10_2 = L10_2 + L11_2
L3_2 = L10_2 % 256
L5_2 = A0_2[L9_2]
L10_2 = A0_2[L3_2]
A0_2[L9_2] = L10_2
A0_2[L3_2] = L5_2
end
end

rc4init = L0_1

function L0_1(A0_2, A1_2)
local L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2, L13_2, L14_2, L15_2, L16_2
L7_2 = ""
L2_2 = 0
L3_2 = 0
L8_2 = 0
L9_2 = string
L9_2 = L9_2.len
L10_2 = A1_2
L9_2 = L9_2(L10_2)
L9_2 = L9_2 - 1
L10_2 = 1
for L11_2 = L8_2, L9_2, L10_2 do
L12_2 = L2_2 + 1
L2_2 = L12_2 % 256
L12_2 = A0_2[L2_2]
L12_2 = L3_2 + L12_2
L3_2 = L12_2 % 256
L5_2 = A0_2[L2_2]
L12_2 = A0_2[L3_2]
A0_2[L2_2] = L12_2
A0_2[L3_2] = L5_2
L12_2 = Xor
L13_2 = string
L13_2 = L13_2.byte
L14_2 = A1_2
L15_2 = L11_2 + 1
L13_2 = L13_2(L14_2, L15_2)
L14_2 = And
L15_2 = A0_2[L2_2]
L16_2 = A0_2[L3_2]
L15_2 = L15_2 - L16_2
L16_2 = 255
L14_2 = L14_2(L15_2, L16_2)
L14_2 = A0_2[L14_2]
L12_2 = L12_2(L13_2, L14_2)
L6_2 = L12_2
L12_2 = L7_2
L13_2 = string
L13_2 = L13_2.char
L14_2 = L6_2
L13_2 = L13_2(L14_2)
L7_2 = L12_2 .. L13_2
L12_2 = L3_2 + L6_2
L3_2 = L12_2 % 256
end
return L7_2
end

rc4crypt = L0_1

function L0_1(A0_2, A1_2)
local L2_2, L3_2, L4_2, L5_2
L3_2 = {}
L2_2 = L3_2
L3_2 = rc4init
L4_2 = L2_2
L5_2 = A1_2
L3_2(L4_2, L5_2)
L3_2 = rc4crypt
L4_2 = L2_2
L5_2 = A0_2
return L3_2(L4_2, L5_2)
end

rc4 = L0_1

function L0_1()
local L0_2, L1_2
L0_2 = print
L1_2 = "wrong"
L0_2(L1_2)
L0_2 = os
L0_2 = L0_2.exit
L1_2 = 0
L0_2(L1_2)
end

fail = L0_1

function L0_1(A0_2, A1_2, A2_2)
local L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2, L13_2, L14_2, L15_2, L16_2, L17_2, L18_2, L19_2
L10_2 = to_uint
L11_2 = A2_2
L12_2 = 1
L10_2 = L10_2(L11_2, L12_2)
L6_2 = L10_2
L10_2 = to_uint
L11_2 = A2_2
L12_2 = 5
L10_2 = L10_2(L11_2, L12_2)
L7_2 = L10_2
L10_2 = to_uint
L11_2 = A2_2
L12_2 = 9
L10_2 = L10_2(L11_2, L12_2)
L8_2 = L10_2
L10_2 = to_uint
L11_2 = A2_2
L12_2 = 13
L10_2 = L10_2(L11_2, L12_2)
L9_2 = L10_2
L4_2 = 305419896
L5_2 = 0
L10_2 = 1
L11_2 = 32
L12_2 = 1
for L13_2 = L10_2, L11_2, L12_2 do
L14_2 = to_uint
L15_2 = rc4
L16_2 = from_uint
L17_2 = L4_2
L16_2 = L16_2(L17_2)
L17_2 = A2_2
L15_2, L16_2, L17_2, L18_2, L19_2 = L15_2(L16_2, L17_2)
L14_2 = L14_2(L15_2, L16_2, L17_2, L18_2, L19_2)
L4_2 = L14_2
L14_2 = And
L15_2 = L5_2 + L4_2
L16_2 = 4294967295
L14_2 = L14_2(L15_2, L16_2)
L5_2 = L14_2
L14_2 = And
L15_2 = Xor
L16_2 = Xor
L17_2 = Shl
L18_2 = A1_2
L19_2 = 4
L17_2 = L17_2(L18_2, L19_2)
L17_2 = L17_2 + L6_2
L18_2 = A1_2 + L5_2
L16_2 = L16_2(L17_2, L18_2)
L17_2 = Shr
L18_2 = A1_2
L19_2 = 5
L17_2 = L17_2(L18_2, L19_2)
L17_2 = L17_2 + L7_2
L15_2 = L15_2(L16_2, L17_2)
L15_2 = A0_2 + L15_2
L16_2 = 4294967295
L14_2 = L14_2(L15_2, L16_2)
A0_2 = L14_2
L14_2 = And
L15_2 = Xor
L16_2 = Xor
L17_2 = Shl
L18_2 = A0_2
L19_2 = 4
L17_2 = L17_2(L18_2, L19_2)
L17_2 = L17_2 + L8_2
L18_2 = A0_2 + L5_2
L16_2 = L16_2(L17_2, L18_2)
L17_2 = Shr
L18_2 = A0_2
L19_2 = 5
L17_2 = L17_2(L18_2, L19_2)
L17_2 = L17_2 + L9_2
L15_2 = L15_2(L16_2, L17_2)
L15_2 = A1_2 + L15_2
L16_2 = 4294967295
L14_2 = L14_2(L15_2, L16_2)
A1_2 = L14_2
end
L10_2 = A0_2
L11_2 = A1_2
return L10_2, L11_2
end

encrypt = L0_1

function L0_1(A0_2)
local L1_2, L2_2, L3_2, L4_2, L5_2, L6_2, L7_2, L8_2, L9_2, L10_2, L11_2, L12_2, L13_2
L2_2 = ""
L3_2 = "thisshouldbeakey"
L6_2 = rc4
L7_2 = A0_2
L8_2 = L3_2
L6_2 = L6_2(L7_2, L8_2)
A0_2 = L6_2
L6_2 = 0
L7_2 = 3
L8_2 = 1
for L9_2 = L6_2, L7_2, L8_2 do
L10_2 = to_uint
L11_2 = A0_2
L12_2 = 8 * L9_2
L12_2 = 1 + L12_2
L10_2 = L10_2(L11_2, L12_2)
L4_2 = L10_2
L10_2 = to_uint
L11_2 = A0_2
L12_2 = 8 * L9_2
L12_2 = 1 + L12_2
L12_2 = L12_2 + 4
L10_2 = L10_2(L11_2, L12_2)
L5_2 = L10_2
L10_2 = encrypt
L11_2 = L4_2
L12_2 = L5_2
L13_2 = L3_2
L10_2, L11_2 = L10_2(L11_2, L12_2, L13_2)
L5_2 = L11_2
L4_2 = L10_2
L10_2 = L2_2
L11_2 = from_uint
L12_2 = L4_2
L11_2 = L11_2(L12_2)
L12_2 = from_uint
L13_2 = L5_2
L12_2 = L12_2(L13_2)
L2_2 = L10_2 .. L11_2 .. L12_2
end
L6_2 = hex
L7_2 = L2_2
L6_2 = L6_2(L7_2)
L2_2 = L6_2
L6_2 = L2_2 == "ac0c0027f0e4032acf7bd2c37b252a933091a06aeebc072c980fa62c24f486c6"
return L6_2
end

check = L0_1

function L0_1()
local L0_2, L1_2, L2_2, L3_2, L4_2, L5_2
L0_2 = print
L1_2 = "input flag: "
L0_2(L1_2)
L0_2 = io
L0_2 = L0_2.read
L0_2 = L0_2()
L1_2 = string
L1_2 = L1_2.len
L2_2 = L0_2
L1_2 = L1_2(L2_2)
if L1_2 ~= 39 then
L1_2 = fail
L1_2()
end
L1_2 = string
L1_2 = L1_2.sub
L2_2 = L0_2
L3_2 = 1
L4_2 = 6
L1_2 = L1_2(L2_2, L3_2, L4_2)
if L1_2 ~= "SUCTF{" then
L1_2 = fail
L1_2()
end
L1_2 = string
L1_2 = L1_2.sub
L2_2 = L0_2
L3_2 = 39
L1_2 = L1_2(L2_2, L3_2)
if L1_2 ~= "}" then
L1_2 = fail
L1_2()
end
L1_2 = check
L2_2 = string
L2_2 = L2_2.sub
L3_2 = L0_2
L4_2 = 7
L5_2 = 38
L2_2, L3_2, L4_2, L5_2 = L2_2(L3_2, L4_2, L5_2)
L1_2 = L1_2(L2_2, L3_2, L4_2, L5_2)
if L1_2 then
L1_2 = print
L2_2 = "correct"
L1_2(L2_2)
else
L1_2 = fail
L1_2()
end
end

main = L0_1
L0_1 = main
L0_1()

可以 patch 一下 lua,使他能进入控制台状态或者执行其他 lua 脚本

image-20250113155209749

之后通过修改反编译出的 lua 脚本一步步理顺逻辑可以得到这是一个魔改 RC4 + Tea,其中 lua 的 str 转 byte 功能也被魔改了

image-20250113155354941

RC4 的魔改点在 原文异或完成后又对 j 进行了加减

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void encRC4(unsigned char *key, uint8 *data2, int length) {
int n, i, j, R, tmp;

init_sbox(key);

i = j = 0;

for (n = 0; n < length; n++) {
i = (i + 1) % 256;
j = (j + sbox[i]) % 256;

tmp = sbox[i];
sbox[i] = sbox[j];
sbox[j] = tmp;

R = sbox[(sbox[i] - sbox[j]) & 0xFF];

data2[n] ^= R;

j = (j + (data2[n])) % 256;
}
}

我写了一个 dfs 来根据 sbox 爆破出原文

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
#include <cstdio>
#include "defs.h"
#include "stdint.h"
#include "stdlib.h"

unsigned char sbox[257] = {0};
#define size 256

void init_sbox(unsigned char *key) {
unsigned int i, j, k;
int tmp;

for (i = 0; i < size; i++) {
sbox[i] = i;
}

j = k = 0;
for (i = 0; i < size; i++) {
tmp = sbox[i];
j = (j + tmp + key[k % 16]) % size;
sbox[i] = sbox[j];
sbox[j] = tmp;
k += 1;
}

// uint8 bbox[256] = {
// 189, 86, 91, 245, 11, 56, 53, 171, 196, 29, 20, 249, 160, 54, 81, 224, 14, 181, 33, 38, 82, 78, 61, 52, 51, 177, 40, 39, 217, 115, 182, 227, 222, 71, 247, 173, 72, 242, 234, 107, 150, 9, 136, 166, 197, 155, 13, 164, 132, 159, 118, 180, 190, 149, 10, 167, 67, 105, 252, 88, 148, 120, 119, 172, 230, 128, 114, 1, 62, 146, 121, 193, 77, 68, 2, 122, 207, 64, 112, 195, 170, 135, 103, 100, 97, 99, 28, 123, 101, 178, 84, 16, 238, 212, 96, 98, 130, 111, 139, 124, 129, 35, 168, 169, 165, 110, 235, 147, 34, 237, 3, 174, 26, 131, 244, 127, 209, 226, 49, 175, 90, 246, 144, 134, 106, 23, 255, 179, 202, 17, 248, 85, 186, 19, 31, 210, 70, 216, 109, 176, 204, 48, 63, 73, 58, 253, 133, 47, 162, 15, 87, 194, 223, 154, 36, 161, 59, 203, 143, 22, 42, 236, 188, 5, 45, 163, 69, 225, 199, 104, 27, 241, 185, 200, 239, 214, 25, 220, 219, 211, 221, 57, 43, 184, 74, 30, 117, 32, 231, 4, 208, 125, 157, 6, 137, 8, 215, 243, 37, 218, 93, 83, 126, 250, 41, 191, 80, 108, 66, 55, 24, 254, 141, 12, 251, 75, 229, 65, 0, 89, 21, 50, 153, 76, 113, 140, 7, 46, 44, 228, 142, 187, 151, 79, 206, 183, 102, 240, 158, 138, 95, 201, 145, 92, 94, 152, 233, 18, 192, 232, 156, 116, 205, 60, 213, 198
// };
// for (int i = 0; i < 256; ++i) {
// sbox[i] = bbox[i];
// }

}

uint32 encInt(unsigned char *key, uint32 data) {
int n, i, j, R, tmp;

init_sbox(key);

uint32 orig = data;
uint8 *data2 = (uint8 *) (&orig);

i = j = 0;

// printf("\n");

for (n = 0; n < 4; n++) {
i = (i + 1) % 256;
j = (j + sbox[i]) % 256;

tmp = sbox[i];
sbox[i] = sbox[j];
sbox[j] = tmp;

R = sbox[(sbox[i] - sbox[j]) & 0xFF];

// printf("%c ", data2[n]);
data2[n] ^= n;
data2[n] += 35;

// printf("%d %d ", data2[n], R);

data2[n] ^= R;

// printf("%d\n", data2[n]);

j = (j + (data2[n])) % 256;
}

for (int k = 0; k < 4; ++k) {
data2[k] ^= k;
data2[k] += 35;
}

return orig;
}

void encRC4(unsigned char *key, uint8 *data2, int length) {
int n, i, j, R, tmp;

init_sbox(key);

i = j = 0;

for (n = 0; n < length; n++) {
i = (i + 1) % 256;
j = (j + sbox[i]) % 256;

tmp = sbox[i];
sbox[i] = sbox[j];
sbox[j] = tmp;

R = sbox[(sbox[i] - sbox[j]) & 0xFF];

data2[n] ^= R;

j = (j + (data2[n])) % 256;
}
}

uint32 deltas[32] = {};

void decrypt(uint32_t *v, uint32_t *k)
{
uint32_t v0 = v[0], v1 = v[1], i;
uint32_t delta = 0x12345678;
uint32_t sum = 0;

for (int j = 0; j < 32; ++j) {
delta = encInt((uint8 *) k, delta);
sum += delta;
deltas[j] = sum;
}

uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++)
{
sum = deltas[31 - i];
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
}
v[0] = v0;
v[1] = v1;
}

void encrypt(uint32_t *v, uint32_t *k)
{
// b0808b64 8e5f6941
// 3805d30c 12e4b5ed

uint32_t v0 = v[0], v1 = v[1], sum = 0, i;
// printf("%x %x\n", v0, v1);
uint32_t delta = 0x12345678;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++)
{
// printf("%u ", delta);
delta = encInt((uint8 *) k, delta);

// printf("%d - %u\n", i, delta);

sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}
v[0] = v0;
v[1] = v1;
}

int8* encrypt_func() {
char *mw = (char *) malloc(32);
strncpy(mw, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 32);

int8 keys[16];

strncpy(keys, "thisshouldbeakey", 16);

for (int i = 0; i < 16; ++i) {
keys[i] ^= i;
keys[i] += 35;
}

for (int i = 0; i < 32; ++i) {
mw[i] ^= i;
mw[i] += 35;
}

// rc4 前面
printf("Before RC4:\n");
for (int i = 0; i < 32; ++i) {
printf("%02x", (uint8) mw[i]);
}

printf("\n");

printf("After RC4:\n");
encRC4((uint8 *) keys, (uint8 *) mw, 32);

// 未异或+35之前
for (int i = 0; i < 32; ++i) {
printf("%02x", (uint8) mw[i]);
}

printf("\n");

printf("Before string.byte:\n");
for (int i = 0; i < 32; ++i) {
mw[i] ^= i;
mw[i] += 35;

printf("%02x", (uint8) mw[i]);
}

printf("\n");

uint32 *uptr = (uint32 *) mw;

for (int i = 0; i < 8; i += 2) {
encrypt(uptr + i, (uint32 *) keys);
}

for (int i = 0; i < 32; ++i) {
// uint8 dt = mw[i];
mw[i] ^= i;
mw[i] += 35;
printf("%02x", (uint8) mw[i]);
}
printf("\n");

return mw;

}

void printHex(void *ptr, size_t length) {
for (int i = 0; i < length; ++i) {
printf("%02x", ((uint8 *) ptr)[i]);
}
printf("\n");
}

uint8 crack[32] = {};

bool crackRC4(uint8 *keys, uint8 *enced, int idx) {
if (idx == 32) {
uint8 enc_test[32] = {0};
memcpy(enc_test, crack, 32);
encRC4(keys, enc_test, 32);

if (memcmp(enc_test, enced, 32) != 0) return false;

for (int i = 0; i < 32; ++i) {
crack[i] -= 35;
crack[i] ^= i;
}
return true;
}
for (int i = 0; i < 256; ++i) {
uint8 to_encrypt[32] = {0};

for (int j = 0; j < 32; ++j) {
if (j < idx) to_encrypt[j] = crack[j];
else to_encrypt[j] = i;
}

encRC4(keys, to_encrypt, 32);

if (to_encrypt[idx] == enced[idx]) {
crack[idx] = i;
return crackRC4(keys, enced, idx + 1);
}
}
}

void decrypt_func() {
uint8 encrypted_data[32] = {
0xac,0x0c,0x00,0x27,0xf0,0xe4,0x03,0x2a,0xcf,0x7b,0xd2,0xc3,0x7b,0x25,0x2a,0x93,0x30,0x91,0xa0,0x6a,0xee,0xbc,0x07,0x2c,0x98,0x0f,0xa6,0x2c,0x24,0xf4,0x86,0xc6
};

uint32 original_data[8] = {};

// 转换 hex lua代码里面 hex 转 int 也用了 char -> byte
for (int i = 0; i < 32; ++i) {
encrypted_data[i] -= 35;
encrypted_data[i] ^= i;
}

memcpy(original_data, encrypted_data, 32);

// 操作 key, 也是 char -> byte 的问题
int8 keys[16];
strncpy(keys, "thisshouldbeakey", 16);

for (int i = 0; i < 16; ++i) {
keys[i] ^= i;
keys[i] += 35;
}

uint32 *enc_ptr = (uint32 *) encrypted_data;

// 反向解密 tea
for (int i = 0; i < 8; i += 2) {
decrypt(enc_ptr + i, (uint32 *) keys);
}

// 由于这里还有一次 char -> byte, 所以还得操作一次
uint8 toDecryptData[32] = {};
for (int i = 0; i < 32; ++i) {
toDecryptData[i] = (uint8)((encrypted_data[i] - 35) ^ i);
}

// 校验
for (int i = 0; i < 8; i += 2) {
encrypt(enc_ptr + i, (uint32 *) keys);
if (original_data[i] != enc_ptr[i] || original_data[i + 1] != enc_ptr[i + 1]) {
printf("failed!");
}
}

printf("Try decrypt rc4: ");
printHex(toDecryptData, 32);

if (crackRC4((uint8 *) keys, toDecryptData, 0)) {
printf("Success! ");
for (int i = 0; i < 32; ++i) {
printf("%c", crack[i]);
}
}
printf("\n");
}

int main() {
decrypt_func();
return 0;
}

// SUCTF{341528c2bde511efade200155d8503ef}

SU_vm_master

先找到运算函数

1
2
3
4
5
6
7
8
9
num_operates = {
0x6a5e: "^",
0x6a78: ">>",
0x6a6a: "<<",
0x6a46: "&",
0x6a52: "|",
0x6a3a: "-",
0x6a30: "+"
}

然后用 qiling 框架 hook 这些地方,获取运算逻辑

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
from qiling import *
from qiling.const import QL_VERBOSE
from ctypes import c_uint32

num_operates = {
0x6A68: "^",
0x6A84: ">>",
0x6A76: "<<",
0x6A50: "&",
0x6A5C: "|",
0x6A44: "-",
0x6A38: "+"
}

operators = ""

def hook_call(ql: Qiling):
global operators
pc = ql.arch.regs.arch_pc
op = num_operates[pc - program_base]
num1 = ql.arch.regs.read("rsi")
num2 = ql.arch.regs.read("rdx")
val = ql.arch.regs.read("rax")
operators += f"{num1:#x} {op} {num2:#x} = {val:#x}\n"

ql = Qiling(["./vm_master"], "/home/carbo/rootfs/x8664_linux_glibc2.39/", verbose=QL_VERBOSE.OFF, profile="linux.ql", multithread=True)

program_base = ql.loader.images[0].base

for addr in num_operates.keys():
ql.hook_address(hook_call, program_base + addr)

ql.run()

with open("operators.txt", "w") as f:
f.write(operators)

观察运算操作,可以发现是一个魔改 SM4,还有一个奇怪的移位操作,还有 SM4 中32轮次的加密 本来是 大端读 大端存,这题是小端的,然后还会异或上一个 0xdeadbeef

1
2
3
4
5
while (i < 32)
{
ulbuf[i + 4] = ulbuf[i] ^ sm4Lt(ulbuf[i + 1] ^ ulbuf[i + 2] ^ ulbuf[i + 3] ^ sk[i]) ^ 0xdeadbeef;
i++;
}

image-20250113175542755

这里可以发现本来读出来的密钥是 emos 0x736f6d65,换完端序变成 esom,也就是这样换序

1
2
3
uint32 wtfRotate(uint32 a) {
return BYTEn(a, 3) << 24 | BYTEn(a, 0) << 16 | BYTEn(a, 1) << 8 | BYTEn(a, 2);
}

IV是 0x6e696874656d6f730x646f6f67746f6e67

image

后16位异或上上一次加密的结果,然后 dump 出 RK 来写解密脚本

解密脚本
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
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
/*
* SM4 Encryption alogrithm (SMS4 algorithm)
* GM/T 0002-2012 Chinese National Standard ref:http://www.oscca.gov.cn/
* thanks to Xyssl
* thnaks and refers to http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html
* author:goldboar
* email:goldboar@163.com
* 2012-4-20
*/
#define SM4_ENCRYPT 1
#define SM4_DECRYPT 0

typedef unsigned char uint8;
typedef unsigned int uint32;

/**
* \brief SM4 context structure
*/
typedef struct
{
int mode; /*!< encrypt/decrypt */
uint32 sk[32]; /*!< SM4 subkeys */
} sm4_context;

/**
* \brief SM4 key schedule (128-bit, encryption)
*
* \param ctx SM4 context to be initialized
* \param key 16-byte secret key
*/
void sm4_setkey_enc(sm4_context *ctx, uint8 key[16]);

/**
* \brief SM4 key schedule (128-bit, decryption)
*
* \param ctx SM4 context to be initialized
* \param key 16-byte secret key
*/
void sm4_setkey_dec(sm4_context *ctx, uint8 key[16]);

/**
* \brief SM4-ECB block encryption/decryption
* \param ctx SM4 context
* \param mode SM4_ENCRYPT or SM4_DECRYPT
* \param length length of the input data
* \param input input block
* \param output output block
*/
void sm4_crypt_ecb(sm4_context *ctx,
int mode,
int length,
uint8 *input,
uint8 *output);

/**
* \brief SM4-CBC buffer encryption/decryption
* \param ctx SM4 context
* \param mode SM4_ENCRYPT or SM4_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
void sm4_crypt_cbc(sm4_context *ctx,
int mode,
int length,
uint8 iv[16],
uint8 *input,
uint8 *output);

#include <string.h>
#include <stdio.h>
#include <time.h>
#include "defs.h"
#include "ctype.h"

/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n, b, i) \
{ \
(n) = ((uint32)(b)[(i)] << 24) | ((uint32)(b)[(i) + 1] << 16) | ((uint32)(b)[(i) + 2] << 8) | ((uint32)(b)[(i) + 3]); \
}
#endif

#ifndef GET_UINT32_LE
#define GET_UINT32_LE(n, b, i) \
{ \
(n) = ((uint32)(b)[(i) + 3] << 24) | ((uint32)(b)[(i) + 2] << 16) | ((uint32)(b)[(i) + 1] << 8) | ((uint32)(b)[(i)]); \
}
#endif

#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n, b, i) \
{ \
(b)[(i)] = (uint8)((n) >> 24); \
(b)[(i) + 1] = (uint8)((n) >> 16); \
(b)[(i) + 2] = (uint8)((n) >> 8); \
(b)[(i) + 3] = (uint8)((n)); \
}
#endif

#ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n, b, i) \
{ \
(b)[(i) + 3] = (uint8)((n) >> 24); \
(b)[(i) + 2] = (uint8)((n) >> 16); \
(b)[(i) + 1] = (uint8)((n) >> 8); \
(b)[(i)] = (uint8)((n)); \
}
#endif

/*
*rotate shift left marco definition
*
*/
#define SHL(x, n) (((x) & 0xFFFFFFFF) << n)
#define SHR(x, n) (((x) & 0xFFFFFFFF) >> n)

#define ROTL(x, n) (SHL((x), n) | ((x) >> (32 - n)))
#define ROTR(x, n) (SHR((x), n) | ((x) << (32 - n)))

#define SWAP(a, b) \
{ \
uint32 t = a; \
a = b; \
b = t; \
t = 0; \
}

/*
* Expanded SM4 S-boxes
/* Sbox table: 8bits input convert to 8 bits output*/

static const uint8 SboxTable[16][16] = {
{0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05},
{0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99},
{0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62},
{0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6},
{0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8},
{0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35},
{0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87},
{0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e},
{0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1},
{0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3},
{0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f},
{0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51},
{0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8},
{0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0},
{0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84},
{0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48}
};

/* System parameter */
static const uint32 FK[4] = {0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc};

/* fixed parameter */
static const uint32 CK[32] = {
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
};

/*
* private function:
* look up in SboxTable and get the related value.
* args: [in] inch: 0x00~0xFF (8 bits unsigned value).
*/
static uint8 sm4Sbox(uint8 inch)
{
uint8 *pTable = (uint8 *)SboxTable;
uint8 retVal = (uint8)(pTable[inch]);
return retVal;
}

void printHex_withSpace(char *name, void *ptr, int len);
void hexdump(char *name, const void *data, size_t size);

/*
* private F(Lt) function:
* "T algorithm" == "L algorithm" + "t algorithm".
* args: [in] a: a is a 32 bits unsigned value;
* return: c: c is calculated with line algorithm "L" and nonline algorithm "t"
*/
static uint32 sm4Lt(uint32 ka)
{
uint32 bb = 0;
uint32 c = 0;

uint8 a[4];
uint8 b[4];

PUT_UINT32_BE(ka, a, 0)

b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);

GET_UINT32_BE(bb, b, 0)

c = bb ^ (ROTL(bb, 2)) ^ (ROTL(bb, 10)) ^ (ROTL(bb, 18)) ^ (ROTL(bb, 24));
return c;
}

/*
* private F function:
* Calculating and getting encryption/decryption contents.
* args: [in] x0: original contents;
* args: [in] x1: original contents;
* args: [in] x2: original contents;
* args: [in] x3: original contents;
* args: [in] rk: encryption/decryption key;
* return the contents of encryption/decryption contents.
*/
static uint32 sm4F(uint32 x0, uint32 x1, uint32 x2, uint32 x3, uint32 rk)
{
return (x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk));
}

/* private function:
* Calculating round encryption key.
* args: [in] a: a is a 32 bits unsigned value;
* return: sk[i]: i{0,1,2,3,...31}.
*/
static uint32 sm4CalciRK(uint32 ka)
{
uint32 bb = 0;
uint32 rk = 0;

uint8 a[4];
uint8 b[4];

PUT_UINT32_BE(ka, a, 0)

b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);

GET_UINT32_BE(bb, b, 0)

rk = bb ^ (ROTL(bb, 13)) ^ (ROTL(bb, 23));

return rk;
}

static void sm4_setkey(uint32 SK[32], uint8 key[16])
{
uint32 MK[4];
uint32 k[36];
uint32 i = 0;

GET_UINT32_BE(MK[0], key, 0);
GET_UINT32_BE(MK[1], key, 4);
GET_UINT32_BE(MK[2], key, 8);
GET_UINT32_BE(MK[3], key, 12);

k[0] = MK[0] ^ FK[0];
k[1] = MK[1] ^ FK[1];
k[2] = MK[2] ^ FK[2];
k[3] = MK[3] ^ FK[3];

for (; i < 32; i++)
{
k[i + 4] = k[i] ^ (sm4CalciRK(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ CK[i]));
SK[i] = k[i + 4];
}
}

/*
* SM4 standard one round processing
*
*/
static void sm4_one_round(uint32 sk[32],
uint8 input[16],
uint8 output[16])
{
uint32 i = 0;
uint32 ulbuf[36];

memset(ulbuf, 0, sizeof(ulbuf));
GET_UINT32_LE(ulbuf[0], input, 0)
GET_UINT32_LE(ulbuf[1], input, 4)
GET_UINT32_LE(ulbuf[2], input, 8)
GET_UINT32_LE(ulbuf[3], input, 12)

while (i < 32)
{

ulbuf[i + 4] = ulbuf[i] ^ sm4Lt(ulbuf[i + 1] ^ ulbuf[i + 2] ^ ulbuf[i + 3] ^ sk[i]) ^ 0xdeadbeef;
i++;
}

PUT_UINT32_LE(ulbuf[35], output, 0);
PUT_UINT32_LE(ulbuf[34], output, 4);
PUT_UINT32_LE(ulbuf[33], output, 8);
PUT_UINT32_LE(ulbuf[32], output, 12);
}

/*
* SM4 key schedule (128-bit, encryption)
*/
void sm4_setkey_enc(sm4_context *ctx, uint8 key[16])
{
ctx->mode = SM4_ENCRYPT;
sm4_setkey(ctx->sk, key);
}

/*
* SM4 key schedule (128-bit, decryption)
*/
void sm4_setkey_dec(sm4_context *ctx, uint8 key[16])
{
int i;
ctx->mode = SM4_ENCRYPT;
sm4_setkey(ctx->sk, key);
for (i = 0; i < 16; i++)
{
SWAP(ctx->sk[i], ctx->sk[31 - i]);
}
}

/*
* SM4-ECB block encryption/decryption
*/

void sm4_crypt_ecb(sm4_context *ctx,
int mode,
int length,
uint8 *input,
uint8 *output)
{
while (length > 0)
{
sm4_one_round(ctx->sk, input, output);
input += 16;
output += 16;
length -= 16;
}
}

/*
* SM4-CBC buffer encryption/decryption
*/
void sm4_crypt_cbc(sm4_context *ctx,
int mode,
int length,
uint8 iv[16],
uint8 *input,
uint8 *output)
{
int i;
uint8 temp[16];

if (mode == SM4_ENCRYPT)
{
while (length > 0)
{
for (i = 0; i < 16; i++)
output[i] = (uint8)(input[i] ^ iv[i]);

sm4_one_round(ctx->sk, output, output);
memcpy(iv, output, 16);

input += 16;
output += 16;
length -= 16;
}
}
else /* SM4_DECRYPT */
{
while (length > 0)
{
memcpy(temp, input, 16);
sm4_one_round(ctx->sk, input, output);

for (i = 0; i < 16; i++)
output[i] = (uint8)(output[i] ^ iv[i]);

memcpy(iv, temp, 16);

input += 16;
output += 16;
length -= 16;
}
}
}

void printHex(char *name, void *ptr, int len)
{
printf("%s", name);
for (size_t i = 0; i < len; i++)
printf("%02x", ((uint8 *)ptr)[i]);
printf("\n");
}

void printHex_withSpace(char *name, void *ptr, int len)
{
printf("%s\n", name);
for (size_t i = 0; i < len * 4; i++)
printf("%02x ", ((uint8 *)ptr)[i]);
printf("\n");
}

void hexdump(char *name, const void *data, size_t size) {
const unsigned char *byte_data = (const unsigned char *)data;
size_t i, j;

printf("%s\n", name);

for (i = 0; i < size; i += 16) {
// 打印偏移地址
printf("%08zx ", i);

// 打印十六进制数据
for (j = 0; j < 16; ++j) {
if (i + j < size) {
printf("%02x ", byte_data[i + j]);
} else {
printf(" "); // 不足部分用空格填充
}

// 在每8字节后添加一个额外的空格
if (j == 7) {
printf(" ");
}
}

printf(" |");

// 打印ASCII字符
for (j = 0; j < 16; ++j) {
if (i + j < size) {
unsigned char ch = byte_data[i + j];
printf("%c", isprint(ch) ? ch : '.');
} else {
printf(" ");
}
}

printf("|\n");
}
}

uint32 wtfRotate(uint32 a) {
return BYTEn(a, 3) << 24 | BYTEn(a, 0) << 16 | BYTEn(a, 1) << 8 | BYTEn(a, 2);
}

int main()
{
unsigned int RK[32] = {
0xD82A4100, 0x086FDB9C, 0x54729EE3, 0x642D1011, 0x9730EF5F, 0xB85C0651, 0xBA8D1C0D, 0x0849E21D,
0xC94DFAB0, 0x25EFA522, 0x5AC0EB10, 0x4BCFEBA7, 0x41905F52, 0x5C7CC60E, 0x278DD7C6, 0x9A350413,
0xD70ABA28, 0xBC153002, 0xC1E22407, 0xD856CD4D, 0xD155AF6F, 0xECBC0A53, 0xF41DAB0D, 0x6332E744,
0x58B84CEB, 0xBBEC0444, 0x79393283, 0x2509498E, 0x5CE96C70, 0xD5058E68, 0xACF4C9A3, 0x08A8E93E
};

// reverse RK
for (int i = 0; i < 16; ++i) {
uint32 tmp = RK[31 - i];
RK[31 - i] = RK[i];
RK[i] = tmp;
}

unsigned int encryptedData[8] = {
0x50BCA8F0, 0xCEF73AD9, 0x77EA2849, 0xB017B433, 0xADA5B98E, 0x2FDE72D2, 0x4CF27246, 0x3834416D
};

unsigned int round2[8] = {};
memcpy(round2, encryptedData, 32);


for (int i = 0; i < 8; ++i) {
encryptedData[i] = wtfRotate(encryptedData[i]);
}

uint32 output[8] = {};

sm4_context ctx;
memcpy(ctx.sk, RK, 32 * 4);
ctx.mode = SM4_DECRYPT;

printHex("Input: ", encryptedData, 32);

sm4_crypt_ecb(&ctx, SM4_DECRYPT, 32, (uint8 *) encryptedData, (uint8 *) output);

printHex("Output: ", output, 32);

for (int i = 0; i < 8; ++i) {
output[i] = wtfRotate(output[i]);
}

auto *p1 = (uint64 *) (output + 4);
auto *p2 = (uint64 *) round2;

for (int i = 0; i < 2; ++i) {
*p1++ ^= *p2++;
}

auto *ptr = (uint64 *) output;

// iv
*ptr ^= 0x6e696874656d6f73;
*(ptr + 1) ^= 0x646f6f67746f6e67;

auto *dt = (uint8 *) output;

for (int i = 0; i < 32; ++i) {
printf("%c", dt[i]);
}

return 0;
}

// Input: bca8f050f73ad9ceea28497717b433b0a5b98eadde72d22ff272464c34416d38
// Output: 085d11015a5d440d58585012585e5354dfccc961c20aefadd94b714321d70589
// b2ed053c767f41709dc1605c8c346c69
// SUCTF{b2ed053c767f41709dc1605c8c346c69}

SU_mapmap2 (赛后)

ida 反编译大函数很慢。。。赛后发现 BN 可以反

这是一题搜索题

就是这个函数很大,结果 BN 秒出

image-20250114180142847

反编译成 IL 是最容易写脚本的

image-20250114180355011

简单分析一下就是一开始生成一个 (树图),因为我不知道怎么描述这个,姑且叫他树图

graph

类似于这样一个结构,然后输入的每一位字符拆成高四位和第四位作为map的下标去取,从 rax_2 对应的那个 map 开始一直取到 rax_800,路径就是 flag

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
import re

codes = open("source.c", "r").read().split("\n")

parms = {}
selected = None

for code in codes:
if code.startswith("void*"):
# 初始化 map
name = re.findall(" (.*) =", code)[0].strip()
parms[name] = dict()
elif code.startswith("var"):
# 变量赋值
name = re.findall("(.*) =", code)[0].strip()
value = int(re.findall("= (.*);", code)[0].strip(), 16)
parms[name] = value
elif code.startswith("int64_t*"):
# 获取子字典
name = re.findall("int64_t\\* (.*) =", code)[0].strip()
args = re.findall(r"map_index\((.*), &(.*)\);", code)[0]
target = parms[args[1]]
if target not in parms[args[0]]:
parms[args[0]][target] = dict()
parms[name] = parms[args[0]][target]
elif code.startswith("*unordered_map_index"):
# 赋值
args = re.findall(r"unordered_map_index\((.*), &(.*)\) = (.*);", code)[0]
target = parms[args[1]]
parms[args[0]][target] = args[2]

walked = {}

def search(cur, paths):
if cur == "rax_800":
print(len(paths), paths)
return True
target = parms[cur]
for k1 in target.keys():
for k2 in target[k1].keys():
goto = target[k1][k2]
if not walked.get(goto, False):
val = k1 << 4 | k2
v0 = val - 97
if v0 > 0x16 or v0 < 0:
continue
new_path = paths + chr(val)
# print(goto, new_path)
walked[goto] = True
result = search(goto, new_path)
walked[goto] = False
walked["rax_2"] = True
search("rax_2", "")

# ddssaassddddssddssssaassaawwwwwwaassssssssssddssssssddwwddddssssddssssddwwwwddssddwwddssddwwwwwwwwwwaawwaawwddwwaaaawwwwddwwddssddddddssaassaassddssddwwddwwwwwwwwwwwwddssssssssssddddssssssddwwwwwwddssddssaassssddssssaaaawwwwaassssaawwaassssssddddssssddssssssaassdddddd

# SUCTF{8b587367b99e5e2fcbdb6598da14b9bc}

其中 source.c 就是从 bn 里拉下来的 反编译后的 IL

下载地址:https://s3.carbo.ink/img/2025/01/6903cc2dc509469c01bfa2f6938c9526.c

 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
总字数 54k 访客数 访问量