Ezre
加密部分
加密逻辑很简单,没什么好说的
a = list('QKEMK{7JB5_i5_W3SllD_3z_W3}')
b = 'ISCTF'
for i in range(len(a)):
v7 = ord(a[i])
if 'A' <= chr(v7) <= 'Z':
v7 = (v7 - ord(b[i%5])) % 26 + ord('A')
a[i] = chr(v7)
print(''.join(a))
ISCTF{7HI5_i5_R3AllY_3z_R3}
你知道elf文件吗
使用ubuntu24运行,报错
看这个报错猜测只能在较低版本linux下运行,使用ubuntu20运行
《回忆安魂曲》--第二章:当记忆被割裂
ida反编译不了,所有函数都爆红,但是看汇编并没有花指令,汇编很正常,果断开始调试
先随便输入,直到进入check函数
注意到每一个函数都有一个很明显的特点,就是先把子函数存入寄存器,然后再一个一个调用
直接F4进入第一个子函数
检测输入长度为36位,重新开始调试,随便输入36位字符串
在右边的寄存器栏可以看到输入的字符串存在堆中
一路F8,直到看到enc函数,看名字是加密函数,F7步入看逻辑
发现key,继续调试
发现变量ans,继续调试
第一轮循环中,运行到这里
fun3:
分析:第1行将轮数[rbp-58h]存入eax,第3行将对应轮数的key即[rbp - 45h]存入eax,第4行将轮数和key相加,第7行将和与[rbp-46h]的内容异或
fun1:
注意到,在enc的子函数fun1中[rbp-46h]被赋值过
分析:第1行将轮数存入eax,第2行轮数加102,第3行可以观察到是输入的flag与al异或,第4行异或82,后面的汇编很简单就不分析了
fun2:
发现结果仍然不对,看fun2,发现这里第1行还加了个6
按照这样循环
最后在这里比较
还原加密逻辑
flag = ''
key = ''
for i in range(len(flag)):
ret1 = i + 102
ret1 ^= flag[i]
ret1 ^= 82
ret2 = i + ord(key[i])
ans = (ret1 & 0xff) + 6 ^ ret2
解密脚本
ans = [
234, 12, 26, 17, 246, 44, 29, 62, 23, 53,
49, 41, 244, 57, 57, 211, 195, 45, 0, 16,
48, 61, 204, 0, 211, 192, 75, 198, 17, 199,
41, 62, 186, 96, 144, 52
]
key = 'i_can_reverse_but_i_can_not_have_you'
for i in range(36):
enc1 = ((ans[i] ^ i + ord(key[i])) - 6) & 0xff
enc2 = enc1 ^ 82 ^ i + 102
print(chr(enc2),end='')
《回忆安魂曲》--第三章:逃不出的黑墙
30*30迷宫,上下左右对应lvoe
,起点为P,终点为E
maze = list('###############################P#...............#...#.......#.#####.###.#####.#.###.#####.#.....#...#.#.....#...#.#...#.#####.#.###.#.#######.#.#.###.#C..#.#.#...#.#...#...#.#.#...#.#.#.#.#.###.#.#.#.###.#.#.#.#.#.#.#.#...#...#.#.......#.#.#.###.#.###.#####.#########.###.#...#...#.....#.#.......#...#.#.#####.#####.#.#.#####.###.#...#...#...#...#...#...#.#...#.###.#.###.#.#######.#.#.#.#.#...#.#.#...#.#...#...#...#.#.###.#.#.#####.#.#.#.#######.###.#...#.....#...#.#.#...#.....#.#########.#####.#.###.#.###.#.#.....#.#...#...#...#...#.#.#.#.#.#.#.###.#.#####.###.#.#.#...#.#...#.#...#...#...#...#.#.###.###.#.#####.#.###.###.#.#...#.#.#.......#.#...#.#...#.#####.#.#######.#.#####.#.###.#...#.#.......#.#...#...#.#..E#.#.#.#.#######.###.#.#####.#.#.#...#.............#.....#.#.#.###############.#######.#.#.#.........#...#...#.....#...#.#.#######.#.#.#####.#.#######.#.......#...#.......#.........')
for i in range(len(maze)):
if maze[i] == '#':
maze[i] = 1
elif maze[i] == '.':
maze[i] == 0
elif maze[i] == 'E':
maze[i] = 2
visited = [0] * (30 * 30) # 记录访问过的点
def BFS(maze, x, y):
queue = [(x, y, '')] # 设置队列
while queue:
x, y, path = queue.pop(0)
if 30 > x >= 0 and 30 > y >= 0 and visited[x * 30 + y] != 1 and maze[x * 30 + y] != 1:
visited[x * 30 + y] = 1
queue.append((x - 1, y, path + 'l'))
queue.append((x, y - 1, path + 'v'))
queue.append((x + 1, y, path + 'o'))
queue.append((x, y + 1, path + 'e'))
else:
continue
if maze[x * 30 + y] == 2: # 终点
return path
flag = BFS(maze, 1, 1) # 起点坐标,行/列
print(flag)
然后MD5加密一下就行
py不好,会被ban
python编译的exe文件,先用pyinstxtractor.py解包,然后在解包的文件夹里面发现了main.pyc文件,用DIE查成分,发现是用3.12版本编译的,这就用不了uncompyle6了,用pycdc也反编译不完全,只好用pycdas解出pyc字节码
[Code]
File Name: main.py
Object Name: <module>
Qualified Name: <module>
Arg Count: 0
Pos Only Arg Count: 0
KW Only Arg Count: 0
Stack Size: 2
Flags: 0x00000000
[Names]
'verify'
'main'
'__name__'
[Locals+Names]
[Constants]
[Code]
File Name: main.py
Object Name: verify
Qualified Name: verify
Arg Count: 3
Pos Only Arg Count: 0
KW Only Arg Count: 0
Stack Size: 9
Flags: 0x00000003 (CO_OPTIMIZED | CO_NEWLOCALS)
[Names]
'range'
'reverse'
'len'
[Locals+Names]
'o0000'
'len2'
'language2'
'enc'
'i'
'ii'
'iii'
'iiii'
[Constants]
None
(
25
85
88
62
105
93
110
124
1
97
46
47
75
5
116
48
2
25
)
1
False
True
[Disassembly]
0 RESUME 0
2 BUILD_LIST 0
4 LOAD_CONST 1: (25, 85, 88, 62, 105, 93, 110, 124, 1, 97, 46, 47, 75, 5, 116, 48, 2, 25)
6 LIST_EXTEND 1
8 STORE_FAST 3: enc
10 LOAD_GLOBAL 1: NULL + range
20 LOAD_FAST 1: len2
22 LOAD_CONST 2: 1
24 BINARY_OP 10 (-)
28 CALL 1
36 GET_ITER
38 FOR_ITER 19 (to 78)
42 STORE_FAST 4: i
44 LOAD_FAST 0: o0000
46 LOAD_FAST 4: i
48 BINARY_SUBSCR
52 LOAD_FAST 0: o0000
54 LOAD_FAST 4: i
56 LOAD_CONST 2: 1
58 BINARY_OP 0 (+)
62 BINARY_SUBSCR
66 BINARY_OP 12 (^)
70 LOAD_FAST 0: o0000
72 LOAD_FAST 4: i
74 STORE_SUBSCR
78 JUMP_BACKWARD 21 (to 38)
80 END_FOR
82 LOAD_FAST 0: o0000
84 LOAD_ATTR 3: reverse
104 CALL 0
112 POP_TOP
114 LOAD_GLOBAL 1: NULL + range
124 LOAD_FAST 1: len2
126 LOAD_CONST 2: 1
128 BINARY_OP 10 (-)
132 CALL 1
140 GET_ITER
142 FOR_ITER 19 (to 182)
146 STORE_FAST 5: ii
148 LOAD_FAST 0: o0000
150 LOAD_FAST 5: ii
152 BINARY_SUBSCR
156 LOAD_FAST 0: o0000
158 LOAD_FAST 5: ii
160 LOAD_CONST 2: 1
162 BINARY_OP 0 (+)
166 BINARY_SUBSCR
170 BINARY_OP 12 (^)
174 LOAD_FAST 0: o0000
176 LOAD_FAST 5: ii
178 STORE_SUBSCR
182 JUMP_BACKWARD 21 (to 142)
184 END_FOR
186 LOAD_GLOBAL 1: NULL + range
196 LOAD_FAST 1: len2
198 CALL 1
206 GET_ITER
208 FOR_ITER 30 (to 270)
212 STORE_FAST 6: iii
214 LOAD_FAST 0: o0000
216 LOAD_FAST 6: iii
218 COPY 2
220 COPY 2
222 BINARY_SUBSCR
226 LOAD_FAST 2: language2
228 LOAD_FAST 6: iii
230 LOAD_GLOBAL 5: NULL + len
240 LOAD_FAST 2: language2
242 CALL 1
250 BINARY_OP 6 (%)
254 BINARY_SUBSCR
258 BINARY_OP 25 (^=)
262 SWAP 3
264 SWAP 2
266 STORE_SUBSCR
270 JUMP_BACKWARD 32 (to 208)
272 END_FOR
274 LOAD_GLOBAL 1: NULL + range
284 LOAD_FAST 1: len2
286 CALL 1
294 GET_ITER
296 FOR_ITER 15 (to 328)
300 STORE_FAST 7: iiii
302 LOAD_FAST 0: o0000
304 LOAD_FAST 7: iiii
306 BINARY_SUBSCR
310 LOAD_FAST 3: enc
312 LOAD_FAST 7: iiii
314 BINARY_SUBSCR
318 COMPARE_OP 55 (!=)
322 POP_JUMP_IF_TRUE 1 (to 326)
324 JUMP_BACKWARD 15 (to 296)
326 POP_TOP
328 RETURN_CONST 3: False
330 END_FOR
332 RETURN_CONST 4: True
[Code]
File Name: main.py
Object Name: main
Qualified Name: main
Arg Count: 0
Pos Only Arg Count: 0
KW Only Arg Count: 0
Stack Size: 6
Flags: 0x00000003 (CO_OPTIMIZED | CO_NEWLOCALS)
[Names]
'print'
'input'
'len'
'ord'
'verify'
[Locals+Names]
'language'
'OO000'
'language1'
'OOO00'
'len1'
'itemm'
'item'
[Constants]
None
'Y0u k0nw what is the best language in the world???'
''
'is_.py_not_py'
'goOo0od!!!'
'So,th3n???'
True
'very goOo0od!!!'
'What a pity!!!T_T'
'NoOo0o!!!T_T'
[Disassembly]
0 RESUME 0
2 LOAD_GLOBAL 1: NULL + print
12 LOAD_CONST 1: 'Y0u k0nw what is the best language in the world???'
14 CALL 1
22 POP_TOP
24 LOAD_GLOBAL 3: NULL + input
34 CALL 0
42 STORE_FAST 0: language
44 BUILD_LIST 0
46 STORE_FAST 1: OO000
48 BUILD_LIST 0
50 STORE_FAST 2: language1
52 LOAD_CONST 2: ''
54 STORE_FAST 3: OOO00
56 LOAD_FAST 0: language
58 LOAD_CONST 3: 'is_.py_not_py'
60 COMPARE_OP 40 (==)
64 POP_JUMP_IF_FALSE 130 (to 326)
66 LOAD_GLOBAL 1: NULL + print
76 LOAD_CONST 4: 'goOo0od!!!'
78 CALL 1
86 POP_TOP
88 LOAD_GLOBAL 1: NULL + print
98 LOAD_CONST 5: 'So,th3n???'
100 CALL 1
108 POP_TOP
110 LOAD_GLOBAL 3: NULL + input
120 CALL 0
128 STORE_FAST 3: OOO00
130 LOAD_GLOBAL 5: NULL + len
140 LOAD_FAST 3: OOO00
142 CALL 1
150 STORE_FAST 4: len1
152 LOAD_FAST 0: language
154 GET_ITER
156 LOAD_FAST_AND_CLEAR 5: itemm
158 SWAP 2
160 BUILD_LIST 0
162 SWAP 2
164 FOR_ITER 13 (to 192)
168 STORE_FAST 5: itemm
170 LOAD_GLOBAL 7: NULL + ord
180 LOAD_FAST 5: itemm
182 CALL 1
190 LIST_APPEND 2
192 JUMP_BACKWARD 15 (to 164)
194 END_FOR
196 STORE_FAST 2: language1
198 STORE_FAST 5: itemm
200 LOAD_FAST 3: OOO00
202 GET_ITER
204 LOAD_FAST_AND_CLEAR 6: item
206 SWAP 2
208 BUILD_LIST 0
210 SWAP 2
212 FOR_ITER 13 (to 240)
216 STORE_FAST 6: item
218 LOAD_GLOBAL 7: NULL + ord
228 LOAD_FAST 6: item
230 CALL 1
238 LIST_APPEND 2
240 JUMP_BACKWARD 15 (to 212)
242 END_FOR
244 STORE_FAST 1: OO000
246 STORE_FAST 6: item
248 LOAD_GLOBAL 9: NULL + verify
258 LOAD_FAST 1: OO000
260 LOAD_FAST 4: len1
262 LOAD_FAST 2: language1
264 CALL 3
272 LOAD_CONST 6: True
274 IS_OP 0 (is)
276 POP_JUMP_IF_FALSE 12 (to 302)
278 LOAD_GLOBAL 1: NULL + print
288 LOAD_CONST 7: 'very goOo0od!!!'
290 CALL 1
298 POP_TOP
300 RETURN_CONST 0: None
302 LOAD_GLOBAL 1: NULL + print
312 LOAD_CONST 8: 'What a pity!!!T_T'
314 CALL 1
322 POP_TOP
324 RETURN_CONST 0: None
326 LOAD_GLOBAL 1: NULL + print
336 LOAD_CONST 9: 'NoOo0o!!!T_T'
338 CALL 1
346 POP_TOP
348 RETURN_CONST 0: None
350 SWAP 2
352 POP_TOP
354 SWAP 2
356 STORE_FAST 5: itemm
358 RERAISE 0
360 SWAP 2
362 POP_TOP
364 SWAP 2
366 STORE_FAST 6: item
368 RERAISE 0
'__main__'
None
[Disassembly]
0 RESUME 0
2 LOAD_CONST 0: <CODE> verify
4 MAKE_FUNCTION 0
6 STORE_NAME 0: verify
8 LOAD_CONST 1: <CODE> main
10 MAKE_FUNCTION 0
12 STORE_NAME 1: main
14 LOAD_NAME 2: __name__
16 LOAD_CONST 2: '__main__'
18 COMPARE_OP 40 (==)
22 POP_JUMP_IF_FALSE 8 (to 40)
24 PUSH_NULL
26 LOAD_NAME 1: main
28 CALL 0
36 POP_TOP
38 RETURN_CONST 3: None
40 RETURN_CONST 3: None
手k出加密逻辑
def verify(o0000, len2, language2):
enc = [25, 85, 88, 62, 105, 93, 110, 124, 1, 97, 46, 47, 75, 5, 116, 48, 2, 25]
for i in range(len2 - 1):
o0000[i] = o0000[i] ^ o0000[i + 1]
o0000.reverse()
for ii in range(len2 - 1):
o0000[ii] = o0000[ii] ^ o0000[ii + 1]
for iii in range(len(o0000)):
o0000[iii] = o0000[iii] ^ ord(language2[iii % len(language2)])
for iiii in range(len(o0000)):
if o0000[iiii] != enc[iiii]:
return False
return True
def main():
print("Y0u k0nw what is the best language in the world???")
language = input()
OO000 = []
language1 = []
OOO00 = ""
if language == "is_.py_not_py":
print("goOo0od!!!")
print("So,th3n???")
OOO00 = input()
len1 = len(OOO00)
for itemm in language:
language1.append(ord(itemm))
for item in OOO00:
OO000.append(ord(item))
if verify(OO000, len1, language1):
print("very goOo0od!!!")
else:
print("What a pity!!!T_T")
else:
print("NoOo0o!!!T_T")
if __name__ == "__main__":
main()
解密脚本:
enc = [25, 85, 88, 62, 105, 93, 110, 124, 1, 97, 46, 47, 75, 5, 116, 48, 2, 25]
lg = 'is_.py_not_py'
lg = [ord(i)for i in lg]
for i in range(len(enc)):
enc[i] ^= lg[i%len(lg)]
ret1 = enc[-1]
for i in range(len(enc)-1,-1,-1):
enc[i-1] ^= enc[i]
enc[-1] = ret1
enc.reverse()
ret2 = enc[-1]
for i in range(len(enc)-1,-1,-1):
enc[i - 1] ^= enc[i]
enc[-1] = ret2
print(''.join([chr(i)for i in enc]))
Y0u_r3@l1y_knOw_py
找啊找
DIE查壳,UPX壳,提示modified,用010editor打开检查upx特征码
四个都被改成APK了,改回UPX,工具脱壳成功
ida反编译
加密逻辑非常简单,只需要注意一个地方。对27行的unk_40040交叉引用,会跳到另一个函数func,这里对unk_40040重新赋值
先大小写转换,然后所有值异或57,写脚本逆向
enc = [
0x50, 0x4A, 0x5A, 0x4D, 0x5F, 0x42, 0x7E, 0x76, 0x76, 0x5D,
0x18, 0x18, 0x08, 0x4A, 0x56, 0x66, 0x60, 0x56, 0x4C, 0x66,
0x5F, 0x08, 0x57, 0x5D, 0x66, 0x08, 0x6D, 0x66, 0x54, 0x79,
0x50, 0x57, 0x18, 0x18, 0x79, 0x44
]
for i in range(len(enc)):
enc[i] ^= 57
if enc[i] > 96 and enc[i] <= 122:
enc[i] -= 32
elif enc[i] > 64 and enc[i] <= 90:
enc[i] += 32
print(''.join([chr(i)for i in enc]))
ISCTF{gooD!!1SO_yOU_F1ND_1t_M@IN!!@}