news 2026/4/15 14:59:21

【攻防世界】reverse | BABYRE 详细题解 WP

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【攻防世界】reverse | BABYRE 详细题解 WP

【攻防世界】reverse | BABYRE 详细题解 WP

下载附件

main函数伪代码:

int __fastcall main(int argc, const char **argv, const char **envp) { char s[24]; // [rsp+0h] [rbp-20h] BYREF int v5; // [rsp+18h] [rbp-8h] int i; // [rsp+1Ch] [rbp-4h] for ( i = 0; i <= 181; ++i ) judge[i] ^= 0xCu; printf("Please input flag:"); __isoc99_scanf("%20s", s); v5 = strlen(s); if ( v5 == 14 && (*(unsigned int (__fastcall **)(char *))judge)(s) ) puts("Right!"); else puts("Wrong!"); return 0; }

exp:

defsolve():# 1. 提取原始judge数组(确保十六进制字符串无换行/空格)judge_raw=bytes.fromhex("594485E9448571D4CA49EC6ACA49ED61""CA49EE6FCA49EF68CA49E873CA49E967""CA49EA3BCA49EB68CA49E437CA49E55A""CA49E66CCA49E737CA49E062CA49E17C""CB49F00C0C0C0CE7248749F0446FDCC4""8749D4440DDC8759F0446FC6448759D4""440DC603BA1E8741F03DC6841C8F49F0""0D8F71F00172DECB49F00C0C0C0CE725""8749F0446FDCC48749D4440DDC03BA1C""8749F0449403BA4809EC34CE780BB40C""0C0C0CE7038F49F00D8F71F00172DDB4""0D0C0C0C51CF")# 2. 异或解密(密钥0xC)KEY=0xCjudge_decrypted=bytes([b^KEYforbinjudge_raw])print("=== 解密后的机器码(十六进制)===")print(judge_decrypted.hex())print("\n=== 反汇编指令与字符提取 ===")# 3. 反汇编配置(64位x86)try:fromcapstoneimportCs,CS_ARCH_X86,CS_MODE_64 md=Cs(CS_ARCH_X86,CS_MODE_64)md.detail=True# 启用详细指令解析(必须开启,否则无法获取操作数细节)exceptImportError:print("错误:未安装capstone库,请执行pip3 install capstone")return""# 4. 提取目标字符的核心逻辑target_chars=[None]*14# 初始化14位flag的列表forinsninmd.disasm(judge_decrypted,0x600B00):# 打印反汇编指令(便于调试)print(f"0x{insn.address:08x}:{insn.mnemonic:<6}{insn.op_str}")# 匹配目标指令:cmp byte ptr [rdi + 偏移], 立即数ifinsn.mnemonic=="cmp":# 检查操作数数量和类型(确保是内存操作数 vs 立即数)iflen(insn.operands)==2:op1=insn.operands[0]# 第一个操作数:内存地址 [rdi + 偏移]op2=insn.operands[1]# 第二个操作数:立即数 imm8# 筛选条件1:op1是内存操作数,且基址为RDI(寄存器编号13,对应capstone的X86_REG_RDI)ifop1.type==1andop1.mem.base==13:# 1=CS_OP_MEM,13=X86_REG_RDI# 筛选条件2:op2是立即数,且大小为8位(1字节)ifop2.type==2andop2.size==1:# 2=CS_OP_IMM# 提取偏移量(rdi + offset)offset=op1.mem.disp# 筛选条件3:偏移量在0-13之间(flag长度为14)if0<=offset<14:target_char=chr(op2.value.imm)# 立即数转ASCII字符target_chars[offset]=target_charprint(f" → 匹配成功:偏移{offset},字符'{target_char}'(0x{op2.value.imm:02x})")# 5. 过滤空值并拼接flag(防止指令顺序混乱导致的空值)flag="".join([cforcintarget_charsifcisnotNone])# 验证flag长度iflen(flag)!=14:print(f"\n警告:提取到的字符长度为{len(flag)},预期14位")else:print(f"\n=== 提取完成 ===")returnflagif__name__=="__main__":flag=solve()# print(f"正确flag:{flag}")defsolve_final():# 1. 从反汇编指令中提取的14个预存常量C[i](十六进制)C=[0x66,0x6d,0x63,0x64,0x7f,0x6b,0x37,0x64,0x3b,0x56,0x60,0x3b,0x6e,0x70]# 2. 计算每个位置的flag字符:s[i] = C[i] ^ iflag=[]foriinrange(14):char_code=C[i]^i flag_char=chr(char_code)flag.append(flag_char)print(f"索引{i}:0x{C[i]:02x}^ 0x{i:02x}= 0x{char_code:02x}→ '{flag_char}'")# 3. 拼接flagfinal_flag="".join(flag)returnfinal_flagif__name__=="__main__":print("=== flag计算过程 ===")final_flag=solve_final()print("\n=== 最终结果 ===")print(f"正确flag:{final_flag}")

运行 exp 脚本:

flag{n1c3_j0b}

【攻防世界】reverse | BABYRE 详细题解 WP 原理深度解析:

【CTF 逆向实战】攻防世界 BABYRE 详细解题指南:从异或解密到逻辑逆向

在 CTF 逆向工程中,一类经典题型是通过数据加密隐藏验证逻辑,再通过函数指针动态调用执行验证。这类题目不仅考察逆向工程师对汇编指令的理解,更考验对程序执行流程的整体把握。本文以攻防世界 “reverse BABYRE” 为例,从程序逻辑拆解到 flag 推导,完整还原解题过程,并提炼同类题目的通用解法,帮助读者掌握 “数据加密 + 函数指针” 类逆向题的核心破解思路。

一、题目初步分析

1.1 程序核心逻辑拆解

通过反编译得到的main函数伪代码如下,我们以此为起点梳理程序执行流程:

int__fastcallmain(intargc,constchar**argv,constchar**envp){chars[24];// 存储输入的flagintv5;// 输入字符串长度inti;// 循环变量// 阶段1:对judge数组进行异或预处理for(i=0;i<=181;++i)judge[i]^=0xCu;// 阶段2:读取输入printf("Please input flag:");__isoc99_scanf("%20s",s);// 阶段3:验证条件v5=strlen(s);if(v5==14&&(*(unsignedint(__fastcall**)(char*))judge)(s))puts("Right!");// 验证通过elseputs("Wrong!");// 验证失败return0;}

核心结论

  • 程序先对judge数组(共 182 字节)逐字节异或0xC(关键预处理);
  • 输入的 flag 长度必须为 14,否则直接失败;
  • judge数组被强制转换为函数指针,传入输入字符串s后,返回非 0 值则验证通过。

1.2 关键数据定位

  • judge数组:存储在.data段(地址0x600B00),原始数据为加密后的字节序列,异或0xC后变为可执行机器码;
  • 函数调用约定:64 位程序采用fastcall,第一个参数(输入字符串s)通过RDI寄存器传递,返回值存于RAX

二、解密 judge 数组

judge数组是解题核心,其原始数据通过异或0xC隐藏了真实逻辑,第一步需还原其内容。

2.1 提取原始数据

从题目中获取judge数组的原始十六进制数据(共 182 字节):

judge_raw=bytes.fromhex("594485E9448571D4CA49EC6ACA49ED61""CA49EE6FCA49EF68CA49E873CA49E967""CA49EA3BCA49EB68CA49E437CA49E55A""CA49E66CCA49E737CA49E062CA49E17C""CB49F00C0C0C0CE7248749F0446FDCC4""8749D4440DDC8759F0446FC6448759D4""440DC603BA1E8741F03DC6841C8F49F0""0D8F71F00172DECB49F00C0C0C0CE725""8749F0446FDCC48749D4440DDC03BA1C""8749F0449403BA4809EC34CE780BB40C""0C0C0CE7038F49F00D8F71F00172DDB4""0D0C0C0C51CF")

2.2 异或解密实现

通过 Python 对原始数据逐字节异或0xC,还原机器码:

KEY=0xCjudge_decrypted=bytes([b^KEYforbinjudge_raw])

解密后的前 20 字节为:554889e548897dd8c645e066c645e16d,这是典型的 64 位函数开头(push rbp; mov rbp, rsp)。

三、机器码反汇编与逻辑分析

解密后的judge数组是可执行机器码,需通过反汇编分析其验证逻辑。

3.1 反汇编工具与配置

使用 Capstone 反汇编库(需先安装:pip install capstone):

fromcapstoneimportCs,CS_ARCH_X86,CS_MODE_64 md=Cs(CS_ARCH_X86,CS_MODE_64)md.detail=True# 启用详细指令解析forinsninmd.disasm(judge_decrypted,0x600B00):print(f"0x{insn.address:08x}:{insn.mnemonic}{insn.op_str}")

3.2 核心逻辑拆解

反汇编后,机器码的验证逻辑分为两个关键阶段:

阶段 1:输入字符串预处理(异或操作)
0x600B49: mov eax, dword ptr [rbp - 4] ; eax = 索引i(0-13) 0x600B63: movzx edx, byte ptr [rdx] ; edx = 输入字符s[i] 0x600B66: mov ecx, dword ptr [rbp - 4] ; ecx = i 0x600B69: xor edx, ecx ; edx = s[i] ^ i(核心预处理) 0x600B6D: add dword ptr [rbp - 4], 1 ; i++ 0x600B71: cmp dword ptr [rbp - 4], 0xd ; 循环14次(0xd=13)

动作:将输入的 14 个字符s[i]与各自索引i(0-13)逐字节异或,结果存入临时缓冲区。

阶段 2:与预存常量比较
0x600B08: mov byte ptr [rbp - 0x20], 0x66 ; 栈上存储常量C[0]=0x66 0x600B0C: mov byte ptr [rbp - 0x1f], 0x6d ; 栈上存储常量C[1]=0x6d ...(共14个常量,存储在rbp-0x20到rbp-0x11) 0x600B95: movzx eax, byte ptr [rbp + rax - 0x20] ; eax = 常量C[i] 0x600B9A: cmp dl, al ; 比较异或结果与C[i] 0x600B9C: je 0x600BA5 ; 匹配则继续,否则返回失败 0x600BAF: mov eax, 1 ; 全部匹配返回成功

动作:将预处理后的结果与栈上预存的 14 个常量逐字节比较,全部匹配则验证通过。

3.3 关键公式推导

从上述逻辑可直接推导出 flag 计算方式:

输入字符s[i] ^ 索引i = 预存常量C[i] → s[i] = C[i] ^ i (i∈0-13)

四、flag 计算与验证

4.1 提取预存常量 C [i]

从反汇编的mov指令中提取 14 个常量:

C=[0x66,0x6d,0x63,0x64,0x7f,0x6b,0x37,0x64,0x3b,0x56,0x60,0x3b,0x6e,0x70]

4.2 计算 flag

根据公式s[i] = C[i] ^ i编写脚本:

defsolve_final():C=[0x66,0x6d,0x63,0x64,0x7f,0x6b,0x37,0x64,0x3b,0x56,0x60,0x3b,0x6e,0x70]flag=[]foriinrange(14):char_code=C[i]^i flag.append(chr(char_code))return"".join(flag)print("flag:",solve_final())# 输出:flag{n1c3_j0b}

五、核心原理深度分析

5.1 题目设计精髓

  1. 数据与代码混淆

    通过异或0xC将可执行机器码隐藏在judge数组中,避免静态分析直接暴露逻辑。

  2. 动态验证逻辑

    将数组强制转换为函数指针调用,使验证逻辑脱离静态反编译的直接视野,增加分析难度。

  3. 预处理 + 比较的双层验证

    输入字符需先经过索引异或处理,再与预存常量比较,而非直接匹配,增加逆向复杂度。

5.2 逆向破解核心思路

  1. 识别数据加密方式

    main函数的循环操作(judge[i] ^= 0xC)定位解密密钥,还原原始机器码。

  2. 理解函数指针调用

    明确 64 位fastcall调用约定(参数通过RDI传递),定位输入数据在汇编中的存储位置(RDI指向输入字符串)。

  3. 拆解验证逻辑层次

    区分 “输入预处理” 和 “结果比较” 两个阶段,提取关键计算公式(如本文的异或关系)。

六、同类题目举一反三

面对 “数据加密 + 函数指针” 类逆向题,可遵循以下通用框架:

6.1 解题步骤模板

  1. 静态分析主函数
    • 定位数据预处理逻辑(异或、移位、Base64 等);
    • 明确输入限制(长度、格式等);
    • 标记关键数据(如本题的judge数组)和函数调用。
  2. 解密隐藏数据
    • 根据预处理逻辑还原数据(异或密钥、解密算法等);
    • 判断数据类型(字符串 / 机器码 / 其他结构)。
  3. 反汇编与逻辑提取
    • 对机器码反汇编,梳理执行流程;
    • 重点关注条件判断(cmp/test)、循环逻辑和返回值设置(mov eax, x);
    • 提取输入与目标数据的关系(如公式、算法)。
  4. 编写脚本计算 flag
    • 根据逻辑关系逆向推导输入(如本文的C[i] ^ i);
    • 验证结果(输入程序测试或动态调试确认)。

6.2 实战技巧

  • 动态调试辅助:若静态分析困难,可通过 GDB 在函数指针调用处下断点,跟踪输入数据的处理过程;
  • 工具选择:IDA/Ghidra 用于静态反汇编,Capstone 用于批量提取指令,Python 用于快速实现逆向计算;
  • 逻辑简化:复杂验证逻辑往往可提炼为数学公式(异或、加减、查表等),避免陷入指令细节。

七、总结

本题通过 “异或解密机器码→反汇编分析逻辑→推导计算公式” 的步骤,最终破解 flag。核心在于从汇编指令中提炼出 “输入字符与索引异或” 的关键逻辑,而非机械地提取比较指令。

在 CTF 逆向中,工具是辅助,理解程序执行的本质才是核心。面对同类题目,只要抓住 “数据解密→逻辑拆解→公式推导” 的主线,就能快速突破层层包装,高效解出 flag。

最终 flagflag{n1c3_j0b}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 14:57:45

Excalidraw绘图技巧:如何画出专业级系统架构图

Excalidraw绘图技巧&#xff1a;如何画出专业级系统架构图 在一次跨时区的远程架构评审会上&#xff0c;团队成员盯着屏幕上那张“完美对齐、像素精准”的Visio图沉默良久——没人敢动一笔。直到有人提议&#xff1a;“要不我们换到Excalidraw试试&#xff1f;”几分钟后&#…

作者头像 李华
网站建设 2026/4/15 14:58:18

Open-AutoGLM安装报错合集(从Python环境到CUDA依赖的终极解决方案)

第一章&#xff1a;Open-AutoGLM 常见问题手册概述 本手册旨在为开发者、系统管理员及技术爱好者提供一份关于 Open-AutoGLM 框架的权威性问题排查与解决方案指南。Open-AutoGLM 是一个开源的自动化通用语言模型集成框架&#xff0c;支持多源模型接入、任务编排与智能调度。由于…

作者头像 李华
网站建设 2026/4/15 14:58:16

Open-AutoGLM导出效率提升10倍的秘密:资深架构师不愿公开的7个命令参数

第一章&#xff1a;Open-AutoGLM导出效率革命的背景与意义在人工智能模型快速迭代的背景下&#xff0c;大语言模型&#xff08;LLM&#xff09;的应用场景日益广泛&#xff0c;对模型导出效率的要求也显著提升。传统的模型导出流程通常涉及复杂的中间格式转换、手动优化配置以及…

作者头像 李华
网站建设 2026/4/14 18:15:52

【Open-AutoGLM避坑指南】:8类用户踩过的坑,第5个90%新手都会中招

第一章&#xff1a;Open-AutoGLM核心机制解析Open-AutoGLM 是一个面向自动化自然语言理解任务的开源大语言模型框架&#xff0c;其核心设计融合了图神经网络&#xff08;GNN&#xff09;与生成式语言模型&#xff08;GLM&#xff09;的双重优势&#xff0c;实现对复杂语义结构的…

作者头像 李华
网站建设 2026/4/15 11:36:58

为什么你的手势识别总延迟?Open-AutoGLM缩放参数调优指南

第一章&#xff1a;为什么你的手势识别总延迟&#xff1f;手势识别系统在智能设备、AR/VR 和人机交互中扮演着关键角色&#xff0c;但许多开发者常遇到响应延迟的问题。延迟不仅影响用户体验&#xff0c;还可能导致误识别或操作失效。根本原因通常隐藏在数据处理流程的多个环节…

作者头像 李华
网站建设 2026/4/15 12:17:37

针对3D打印微针鳍式MLCP散热方案的技术解析

&#x1f393;作者简介&#xff1a;科技自媒体优质创作者 &#x1f310;个人主页&#xff1a;莱歌数字-CSDN博客 &#x1f48c;公众号&#xff1a;莱歌数字 &#x1f4f1;个人微信&#xff1a;yanshanYH 211、985硕士&#xff0c;职场15年 从事结构设计、热设计、售前、产品设…

作者头像 李华