文章总结: 本文通过一道CTF逆向题目,详细解析了函数HOOK技术如何使异或加密失效的反调试手法。文章揭示了程序通过VirtualProtect修改内存权限,利用ReadProcessMemory/WriteProcessMemory动态替换关键数据,并最终发现真实加密算法为魔改XXTEA。关键发现包括HOOK点定位、内存修改分析流程,并提供了完整的动态调试方法和Python解密脚本,成功获取flag。 综合评分: 85 文章分类: CTF,逆向分析,红队,漏洞分析,WEB安全
CTF逆向陷阱:函数HOOK让异或算法瞬间失效,手把手教你揪出真flag
原创
小话安全 小话安全
小话安全
2026年5月14日 00:17 山东
在小说阅读器读本章
去阅读
在CTF逆向中,异或(XOR) 算法简单到几乎“有手就行”——找到key和密文,一行Python脚本就能爆flag。
但如果出题人偷偷用了函数HOOK呢?
你在IDA里提取的key是假的,密文是错的,甚至比较函数都被替换了。
VirtualProtect、ReadProcessMemory、WriteProcessMemory
特别是当这三个“危险函数”联手登场时,静态分析直接沦为废铁。
本文通过一道真实CTF题目,带你彻底搞懂这种XOR + HOOK的反调试与反静态分析手法。
打开程序看到了三个危险函数
分析主程序
设置断点进行调试
根据题目要求输入flag,长度是40
将我们的输入改成00 00 00 以获取第一个异或的数值
执行完第一次异或后0变成了s,因此异或的变量为0x73
导出加密后数据和密钥
编写脚本解密
我们发现这个flag是错误的,为什么错误呢,我们看最开始的那几个危险函数。
各步骤行为分析
VirtualProtect(lpAddress, 0x1000, 0x40, &flOldProtect)
0x40=PAGE_EXECUTE_READWRITE- 将目标内存页(很可能是
.text代码段或.data数据段)设置为可读可写可执行,暂时解除写保护。 - 目的是为了后续能够改写内存中的指令或数据。
ReadProcessMemory(hProcess, lpBaseAddress, Buffer, 8, NULL)
- 从自身进程(
hProcess通常是GetCurrentProcess())中读取lpBaseAddress处的 8字节 内容,保存到Buffer。 - 这8字节原本是指令或原始数据,先备份起来,以便后续恢复(或用于校验)。
VWriteProcessMemory(hProcess, (LPVOID)lpBaseAddress, &v13, 8, NULL)
- 将局部变量
v13的8字节内容写入到lpBaseAddress处。 - 这就是HOOK的核心:用新数据覆盖原位置。
- 如果
lpBaseAddress指向代码段,则相当于动态修改指令(比如把xor eax, eax改成mov eax, 1)。 - 如果指向数据段(如
key或enc数组),则直接替换全局变量。
VirtualProtect(lpAddress, 0x1000, flOldProtect, &flOldProtect)
- 恢复内存页的原始属性(通常是
PAGE_READONLY或PAGE_EXECUTE_READ)。 - 目的是隐藏修改痕迹,让静态分析或后续的内存扫描难以察觉。
V13是a1,找到a1
查看函数的交叉引用
strcpy(LibFileName, "User32.dll");strcpy(ProcName, "MessageBoxA");hProcess = GetCurrentProcess();ModuleHandleW = GetModuleHandleW(0i64);hModule = LoadLibraryA(LibFileName);if (!hModule) exit(0);ProcAddress = GetProcAddress(hModule, ProcName);
- 准备目标DLL名
User32.dll和函数名MessageBoxA。 - 获取当前进程句柄(用于后续
ReadProcessMemory/WriteProcessMemory)。 ModuleHandleW= 当前进程的基址(EXE的基址)。- 加载
User32.dll并获取MessageBoxA的真实地址(ProcAddress)。
也就是程序在弹窗提示正确或错误时执行了别的函数
分析执行的函数,对之前的加密进行了反向操作,获取到了输入数据的值
分析加密函数,这是一个魔改的XXTEA
设置断点导出加密后的数据和密钥
用AI编写解密脚本获得flag
import struct
def bytes_to_uint32_le(data): """将字节数组(小端序)转换为32位无符号整数列表""" n = len(data) // 4 return [struct.unpack('<I', data[i*4:(i+1)*4])[0] for i in range(n)]
def uint32_to_bytes_le(v): """将32位无符号整数列表转换为小端序字节数组""" return b''.join(struct.pack('<I', x) for x in v)
def xxtea_decrypt(v, key): """ XXTEA解密 v: 32位无符号整数列表(密文) key: 4个32位无符号整数列表(密钥) 返回解密后的整数列表 """ n = len(v) if n < 2: return v # 长度至少为2,否则无需处理
delta = 0x11451981 #注意值会变 rounds = 6 + 52 // n # 初始sum = rounds * delta,并保证32位无符号 total_sum = (rounds * delta) & 0xFFFFFFFF y = v[0] while rounds > 0: # 每轮的sum用于计算e e = (total_sum >> 2) & 3 for p in range(n-1, 0, -1): z = v[p-1] # MX宏的计算,所有运算均在32位无符号范围内 mx = (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((total_sum ^ y) + (key[(p & 3) ^ e] ^ z)) v[p] = (v[p] - mx) & 0xFFFFFFFF y = v[p] z = v[n-1] mx = (((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((total_sum ^ y) + (key[(0 & 3) ^ e] ^ z)) v[0] = (v[0] - mx) & 0xFFFFFFFF y = v[0] total_sum = (total_sum - delta) & 0xFFFFFFFF rounds -= 1 return v
def main(): # 密文字节数组 //IDA动态调试导出 a = [ 0xE4, 0xE7, 0xFE, 0xE3, 0x17, 0x1C, 0xDE, 0x32, 0xE6, 0xB8, 0x68, 0x40, 0x40, 0xD8, 0x72, 0xFA, 0x88, 0x14, 0xE1, 0x85, 0xCD, 0x81, 0xAA, 0xDE, 0x1D, 0xE8, 0x92, 0x41, 0xB8, 0x1E, 0x5E, 0xCF, 0xCE, 0x49, 0x27, 0x22, 0x39, 0x7D, 0x50, 0xDA ] # 密钥字节数组 b = [ 0x48, 0x65, 0x31, 0x6C, 0x30, 0x4E, 0x73, 0x53, 0x21, 0x11, 0x45, 0x14, 0x19, 0x19, 0x81, 0x00 ]
# 转换为小端序32位整数 cipher_int = bytes_to_uint32_le(bytes(a)) key_int = bytes_to_uint32_le(bytes(b))
# 解密 plain_int = xxtea_decrypt(cipher_int, key_int)
# 转换回字节 plain_bytes = uint32_to_bytes_le(plain_int)
# 尝试解码为UTF-8文本(如失败则显示十六进制) try: print(plain_bytes.decode('utf-8')) except UnicodeDecodeError: print("解密结果(十六进制):", plain_bytes.hex())
if __name__ == "__main__": main()
NSSCTF{C0ngr@tulat1ons!H0Ok_bY_1t_s3lf!}
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:小话安全 小话安全 小话安全《CTF逆向陷阱:函数HOOK让异或算法瞬间失效,手把手教你揪出真flag》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论