CTF 逆向实战:从 WriteUp 到自动化分析——以 DASCTF 2022 赛题 RC4 魔改与自修改代码为例

📅 2026/7/12 3:00:47
CTF 逆向实战:从 WriteUp 到自动化分析——以 DASCTF 2022 赛题 RC4 魔改与自修改代码为例
CTF 逆向实战从 WriteUp 到自动化分析——以 DASCTF 2022 赛题 RC4 魔改与自修改代码为例逆向工程在网络安全竞赛中一直占据重要地位而自动化分析技术则是提升逆向效率的关键。本文将以 DASCTF 2022 春季赛中的Re easyre赛题为案例深入探讨如何从WriteUp解读过渡到自动化脚本开发重点分析RC4算法魔改与自修改代码的对抗技术。1. 赛题背景与技术要点Re easyre是一道典型的中级逆向题目结合了自修改代码(SMC)和RC4算法魔改两大技术难点。题目要求参赛者识别并处理自修改代码的干扰逆向分析魔改版RC4算法编写IDAPython脚本实现自动化反混淆还原解密逻辑并获取flag与常规逆向题不同本题的挑战在于程序运行时会动态修改自身的代码段这使得静态分析工具如IDA Pro难以直接获取可读的反汇编结果。同时题目对标准RC4算法进行了多处修改增加了算法识别的难度。2. 自修改代码的识别与对抗自修改代码(Self-Modifying Code)是恶意软件和CTF题目中常见的技术通过运行时修改指令来干扰静态分析。在本题中IDA静态分析显示大量无法解析的代码区域.text:00401000 db 0E8h .text:00401001 db 1Fh .text:00401002 db 0 .text:00401003 db 0 .text:00401004 db 0 .text:00401005 db 83h动态调试对抗策略设置内存断点在代码段(.text)设置写入断点捕获修改行为分段分析在代码解密后暂停执行进行静态分析指令修复使用IDAPython脚本重新定义代码关键调试步骤在0x401000处设置硬件执行断点运行到断点后单步跟踪观察代码解密过程3. RC4算法识别与魔改分析通过动态调试可以定位到加密函数对比标准RC4实现发现以下魔改点标准RC4本题魔改固定初始化S盒动态生成S盒简单交换操作加入算术运算直接异或输出输出前进行位移和加法关键魔改代码片段for ( i 0; i v3; i ) byte_492A60[i] (LOBYTE(key_stream[i]) ^ *(_BYTE *)(i a1)) 71;算法还原步骤识别KSA(密钥调度算法)修改点分析PRGA(伪随机生成算法)的额外运算跟踪密钥流生成过程4. IDAPython自动化分析实战针对自修改代码我们开发了自动化分析脚本import idaapi def repair_code(start_ea, end_ea): ea start_ea while ea end_ea: idaapi.create_insn(ea) # 创建指令 insn idaapi.insn_t() length idaapi.decode_insn(insn, ea) ea length print(代码修复完成) # 应用范围0x401000到0x425000 repair_code(0x401000, 0x425000)该脚本实现了自动识别代码边界重建指令流修复交叉引用5. 完整解密流程还原基于逆向分析结果我们还原出完整的解密流程初始化阶段读取密钥123456生成魔改S盒加密流程void modified_rc4(uint8_t *key, int key_len, uint8_t *data, int data_len) { // 魔改KSA for(int i0; i256; i) { S[i] (S[i] 66) % 256; S[i] S[j] - 33; S[i] ^ 2; S[j] 5 * (S[i] 66); } // 魔改PRGA for(int i0; idata_len; i) { data[i] (data[i] ^ key_stream[i]) 71; } }验证逻辑比较解密结果与硬编码值通过则输出Right6. 自动化解密脚本开发结合分析结果我们编写了完整的解密脚本def rc4_init(key): S list(range(256)) j 0 for i in range(256): j (j S[i] key[i % len(key)]) % 256 # 魔改点1 S[i] (S[i] 66) % 256 S[i] S[j] - 33 S[i] ^ 2 S[j] 5 * (S[i] 66) S[j] S[i] - 10 S[j] S[i] S[i] - 18 # 标准交换 S[i], S[j] S[j], S[i] return S def decrypt(data, key): S rc4_init(key) out [] i j 0 for byte in data: i (i 1) % 256 j (j S[i]) % 256 S[i], S[j] S[j], S[i] out_byte (byte - 71) ^ S[(S[i] S[j]) % 256] out.append(out_byte) return bytes(out) enc_data [...] key b123456 print(decrypt(enc_data, key))7. 经验总结与技巧分享通过本题我们总结了以下逆向工程经验动态分析优先对于SMC题目先动态调试获取运行时代码算法特征识别注意RC4的256字节S盒和交换操作特征脚本化思维将重复操作转化为IDAPython脚本版本对比法对比标准算法快速定位魔改点实际调试中发现的一个有趣现象是程序在解密自身代码后会立即擦除解密密钥这种反调试技巧可以通过内存断点有效对抗。