本文最后更新于 343 天前,其中的信息可能已经过时,如有错误可以直接在文章下留言
这一题和 NewStarCTF 2023 Week2 PZthon 的步骤几乎一模一样,只是 pycdc 反编译后的 python 源码不一样,这类题目的什么是.pyc 文件、byte 数组等知识已经在 NewStarCTF 2023 这题里面详细说明了,建议先看那一篇,在这篇文章就不多说了。用 IDA 打开压缩包给的.exe 文件,Shift+F12 看 Strings window,一样有星期、月份还有 26 个大小写字母,如图,有 python 的痕迹
直接用 pyinstxtractor 工具解包,解包后的文件夹里有一个如图 ezpyc.pyc 文件,如图。
然后用 pycdc 和在线网站都反编译,发现 pycdc 会少一些代码。以下为 python 源码
| def custom_b64encode(b): |
| old_table = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' |
| new_table = old_table[::-1] |
| import base64 |
| b = base64.b64encode(b) |
| table = dict(zip(old_table, new_table)) |
| b = list(b) |
| for i in range(len(b)): |
| b[i] = table[b[i]] |
| return bytes(b) |
| print('Welcome to GZHU CTF') |
| print('This is a ....... Program') |
| print('Maybe you should use PE tools to check what am I') |
| a = input() |
| flag = '' |
| key = 'gzhu' |
| encrypted = '' |
| for i in range(len(flag)): |
| encrypted += str(ord(flag[i]) ^ ord(key[i % 4])) |
| encrypted += ' ' |
| encrypted = custom_b64encode(encrypted.encode()) |
| encrypted = b'zt/Nzd/G387H383H38zfx8ffz9/Kyd/Kyt/G38zP38fL38zI383L38vL38vfxs7fysrfycffxt/IyN/I38vN383M38zK38jM38ff' |
一个” 空变量 “flag 经过种种操作便可以得到 encrypted,所以我们通过已知的变量 encrypted 反推可以得到 flag。encrypted 最后一步经过自定义函数 custom_b64encode 得到最终的变量 encrypted,所以我们首先分析这个函数。
| old_table = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' |
| new_table = old_table[::-1] |
| |
| b = base64.b64encode(b) |
| |
| table = dict(zip(old_table, new_table)) |
| |
| b = list(b) |
| |
| for i in range(len(b)): |
| b[i] = table[b[i]] |
| |
| return bytes(b) |
上面代码的意思比如,在 b 中的字符’A’,经过函数处理后变成了’/’,我们就可以写一个脚本还原一下,逻辑应该不难理解。
| import base64 |
| encrypted = b'zt/Nzd/G387H383H38zfx8ffz9/Kyd/Kyt/G38zP38fL38zI383L38vL38vfxs7fysrfycffxt/IyN/I38vN383M38zK38jM38ff' |
| def custom_b64encode(b): |
| old_table = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' |
| new_table = old_table[::-1] |
| table = dict(zip(old_table, new_table)) |
| b = list(b) |
| for i in range(len(b)): |
| b[i] = table[b[i]] |
| b=bytes(b) |
| return base64.b64decode(b) |
| print(custom_b64encode(encrypted)) |
| |
| data=custom_b64encode(encrypted) |
| data=data.decode() |
| data=data.split(' ') |
| key= 'gzhu' |
| flag='' |
| for i in range(len(data)-1): |
| flag+=chr(int(data[i])^ord(key[i%4])) |
| print(flag) |
| |
异或那里直接再异或一次就好了,数据处理的时候唯一要注意的就是字节串里面每个数字后面都是加了空格的,所 flag 就是 flag {y0u_Mak3_pYc!_1n7o_pY!}