告别枯燥理论用5个CTFshow逆向真题带你玩转Python反编译与Base变种当你面对一个未知的Python可执行文件或字节码时是否感到无从下手本文将带你通过5个CTFshow逆向真题系统掌握Python逆向的核心技能。从工具链使用到编码变种分析我们不仅解决具体题目更构建可复用的解题工具箱。1. Python逆向基础工具链逆向Python程序的第一步是获取可读的源代码。根据程序打包方式不同我们需要使用不同的工具链。1.1 PyInstaller打包程序逆向对于PyInstaller打包的.exe文件推荐使用pyinstxtractor工具python pyinstxtractor.py target.exe执行后会生成一个目录其中包含提取的.pyc文件。关键点查找名称与原始脚本相近的.pyc文件注意PYZ-00.pyz.extracted目录可能包含依赖库1.2 .pyc文件反编译获取.pyc后可以使用以下工具进行反编译工具名称特点适用场景uncompyle6支持Python 3.7-3.8大多数现代.pyc文件decompyle3Python 3.9支持新版Python编译的字节码pycdc支持多种版本兼容性较好但可能出错典型使用方式uncompyle6 -o output.py target.pyc提示如果反编译失败尝试先用python -m py_compile重新生成.pyc文件2. Base编码变种识别与逆向CTF中常见的Base编码变种包括换表、移位等操作。掌握这些变种的识别与逆向是解题关键。2.1 Base64换表识别标准Base64使用A-Za-z0-9/作为码表。换表变种的识别方法查找代码中的字符串常量特别是64个字符的组合观察编码函数中是否有类似base64.b64encode的操作检查是否有自定义的索引映射逻辑例如在签退题目中码表被修改为c_charset string.ascii_uppercase string.ascii_lowercase string.digits ()2.2 字符移位处理许多题目会在Base编码后增加字符移位操作。常见移位类型ROT系列固定位移如ROT13凯撒密码字母表循环位移异或运算与固定值或位置相关值异或逆向移位的关键是找到位移规律。例如签退题目中的rend函数def rend(s): def encodeCh(ch): f lambda x: chr(((ord(ch) - x) 2) % 26 x) if ch.islower(): return f(97) if ch.isupper(): return f(65) return ch return .join([encodeCh(c) for c in s])对应的逆向函数应为def rend_reverse(s): decoded [] for c in s: if c.islower(): decoded_char chr((ord(c) - 97 - 2) % 26 97) elif c.isupper(): decoded_char chr((ord(c) - 65 - 2) % 26 65) else: decoded_char c decoded.append(decoded_char) return .join(decoded)3. Base58与异变种分析Base58是比特币地址常用的编码方式与Base64相比去除了易混淆字符。3.1 标准Base58特征标准Base58码表123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz识别要点码表长度为58通常包含大小写字母和数字去除了0/O/I/l等易混淆字符3.2 异或变种处理在来一个派森题目中Base58编码后还进行了逐字符异或tmp [] for i in range(len(temp)): tmp.append(chr(ord(temp[i]) ^ i))逆向时需要先异或再Base58解码check [A,5,q,O,g,q,d,\x7f,[,\x7f,s,{,G,A,x,,D,,K,c,-,c, ,G,,,|,x,},J,h,\\,l] temp [] for i in range(len(check)): temp.append(chr(ord(check[i]) ^ i))4. RC4加密算法逆向RC4是CTF中常见的流加密算法识别和逆向有一定技巧。4.1 RC4算法特征典型RC4实现包含两个阶段KSA密钥调度算法初始化S盒PRGA伪随机生成算法生成密钥流识别特征256字节的S盒初始化嵌套循环结构字节交换操作4.2 高强度RC4变种在屏幕裂开了题目中RC4的KSA阶段被重复执行99999次for hit_count in range(99999): j 0 for i in range(256): j (s[i]jk[i])%256 s[i],s[j] s[j],s[i]逆向时需要完整模拟这一过程不能简化。5. 实战解题工具箱综合上述技术我们构建一个Python逆向解题工具箱5.1 常用工具列表反编译工具pyinstxtractor解包PyInstalleruncompyle6/decompyle3反编译.pycpycdas查看字节码编码工具CyberChef在线编码转换base64/binasciiPython标准库hashlib哈希计算调试工具x64dbg/x32dbg动态调试IDA Pro/Ghidra静态分析5.2 实用代码片段Base64换表解码模板import base64 custom_b64 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789() std_b64 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/ def custom_b64decode(s): trans str.maketrans(custom_b64, std_b64) return base64.b64decode(s.translate(trans))RC4解密模板def rc4_decrypt(data, key): S list(range(256)) j 0 # KSA for i in range(256): j (j S[i] key[i % len(key)]) % 256 S[i], S[j] S[j], S[i] # PRGA i j 0 result [] for char in data: i (i 1) % 256 j (j S[i]) % 256 S[i], S[j] S[j], S[i] result.append(char ^ S[(S[i] S[j]) % 256]) return bytes(result)在实际CTF比赛中Python逆向题目往往结合多种技术。例如先需要反编译获取源码然后分析自定义的编码算法最后编写逆向脚本。掌握这些核心技能后你会发现Python逆向其实充满乐趣。