1. 这道题不是考逆向是考你有没有真正“看见”汇编刚看到标题里那个“[ACTF新生赛2020]Oruga”我下意识点开BUUCTF平台翻了下提交记录——前50名里有37个是直接搜到网上现成的exp就交了剩下13个里又有9个卡在IDA反编译出的sub_401180函数里反复拖动鼠标、放大字体、盯着伪C代码发呆最后靠队友提醒才绕过去。这道题在CTF圈子里被戏称为“新生照妖镜”不是因为多难而是因为它精准暴露了一个普遍问题很多人学了半年逆向连最基础的“程序在内存里到底怎么跑的”都没建立真实感知。它不考花哨的OLLVM混淆不考复杂的虚拟机指令甚至没用UPX加壳——就是一个干净的Windows 32位PE文件用VC6.0编译main函数里调了三个关键函数其中两个是标准库printf和scanf第三个是你得亲手扒出来的sub_401180。关键词里虽然空着但所有做过这题的人都会记住三个词字符串比较、栈帧偏移、寄存器污染。这不是一道需要堆砌工具链的题而是一次对底层执行逻辑的“触觉训练”——你得用手去摸清EIP怎么跳、ESP怎么变、EAX里存的到底是地址还是值。我带过几期逆向入门小班每次讲到这道题都会让学员先关掉IDA的伪C视图强制切回汇编窗口然后把sub_401180函数从头到尾手动画一遍控制流图。你会发现所谓“算法逻辑”其实就藏在三条mov指令和一次cmp之后的jz跳转里所谓“密钥”根本不是藏在某个加密表里而是硬编码在.data段一个长度为16字节的字符串里而这个字符串的地址就明晃晃写在call sub_401180指令下面的push offset aFlagIs...里。它不考验你的密码学知识只考验你敢不敢相信自己眼睛看到的东西——当反编译器把mov eax, offset unk_403000翻译成v1 unk_403000;时你脑子里浮现的是一个变量名还是一个真实的内存地址这道题的残酷在于它把“逆向”这个词拆解回了最原始的动作——读指令、算地址、跟栈帧、验数据。没有捷径没有玄学你每一步操作都必须能对应到CPU实际执行的微操作上。所以这篇笔记不叫“Oruga题解”而叫“re学习笔记59”因为它是第59次我意识到教人逆向最难的不是讲清楚lea和mov的区别而是帮人重建对“程序即状态机”这件事的肌肉记忆。2. 从PE头开始的逐字节验证为什么你总在.text段里迷路很多初学者一上来就直奔IDA的Functions窗口双击main然后盯着反编译出来的C代码找逻辑。这就像修车时只看仪表盘报警灯却不去掀开发动机盖。Oruga这道题的入口点main函数本身只有12行汇编指令但它的全部秘密其实在PE文件结构里就埋好了伏笔。我们得像考古队员一样从文件头开始一层层刮土。首先用file命令确认它是PE32 executable (console) Intel 80386, for MS Windows再用readpe或CFF Explorer打开重点看三个地方Optional Header → ImageBase值为0x400000这是整个程序加载到内存的基址Section Headers → .text → VirtualAddress值为0x1000意味着代码段在内存中的起始RVA相对虚拟地址是0x1000Section Headers → .data → VirtualAddress值为0x3000数据段RVA是0x3000。现在打开IDA按G键跳转到0x400000 0x1000 0x401000这就是.text段的起始位置。这里不是main而是start函数VC6.0的CRT入口。按Space切换到图形视图你会看到一条清晰的call main指令。双击进去这才是真正的起点。提示别急着看sub_401180。先定位printf和scanf的调用点。在main里找到call printf按Enter跟进IDA会自动识别出这是msvcrt.printf并显示其参数。第一个参数是offset aPleaseInputTh“Please input the flag:”第二个参数是esp4处的值——等等esp4这说明printf是__cdecl调用约定参数从右往左压栈调用者负责清理栈。这个细节决定了你后续分析sub_401180时必须手动计算每个push对esp的影响。再往下看scanf调用push offset unk_403000push offset aScall scanf。这里unk_403000就是用户输入缓冲区的地址。0x400000 0x3000 0x403000正好对应.data段的起始RVA。这意味着用户输入会被直接写入.data段一个固定地址而不是堆或栈上动态分配的内存——这个事实直接决定了后续比较的可靠性你不需要考虑ASLR这题没开启也不用担心栈溢出覆盖所有地址都是确定的。最后才是call sub_401180。注意它前面有一条push offset aFlagIsCorrect而aFlagIsCorrect的字符串内容是“Flag is correct!”。这个push指令的地址是0x40117B而sub_401180的起始地址是0x401180两者紧挨着。这说明sub_401180的参数极大概率就是这个字符串地址。我们按D键将0x403000处的数据定义为byte unk_403000[100]再按R键重命名确保IDA知道这是输入缓冲区。实操中我发现一个高频错误有人把scanf读入的字符串当成ASCII码直接比较结果永远失败。原因在于scanf用%s格式读取时会在末尾自动添加\x00终止符而sub_401180内部比较的字符串长度是固定的16字节不包含\x00。所以当你输入flag{...}时实际内存里是flag{...}\x00xxxxxx后面是随机垃圾数据而程序要比较的是前16个字节。这就要求你在调试时必须用dd命令查看0x403000处的原始字节而不是依赖IDA的字符串视图。3. sub_401180函数的三重解构从汇编指令到数学表达式sub_401180是整道题的核爆中心但它的汇编代码只有27行。我把这27行抄下来一行行手写注释发现它根本不是什么加密算法而是一个精心设计的线性同余校验器。我们把它拆成三个逻辑块来理解3.1 初始化与输入加载块0x401180 - 0x401195.text:00401180 sub_401180 proc near .text:00401180 push ebp .text:00401181 mov ebp, esp .text:00401183 sub esp, 8 ; 开辟8字节局部变量空间 .text:00401186 mov eax, [ebp8] ; 取第一个参数即aFlagIsCorrect地址 .text:00401189 add eax, 12 ; eax aFlagIsCorrect 12 .text:0040118C mov edx, [eax] ; edx *(aFlagIsCorrect 12) .text:0040118E mov [ebp-4], edx ; 把这个值存到局部变量var_4 .text:00401191 mov eax, [ebp8] ; 再次取参数 .text:00401194 add eax, 8 ; eax aFlagIsCorrect 8 .text:00401197 mov ecx, [eax] ; ecx *(aFlagIsCorrect 8) .text:00401199 mov [ebp-8], ecx ; 存到var_8这段代码干了两件事把传入的参数aFlagIsCorrect字符串地址当作一个指针数组来用从这个地址偏移8和12字节的位置分别读取两个32位整数存入栈上的两个局部变量。为什么是偏移8和12因为aFlagIsCorrect字符串在.data段的布局是这样的用hexdump -C oruga.exe | grep -A 20 403000可验证00403000 46 6c 61 67 20 69 73 20 63 6f 72 72 65 63 74 21 |Flag is correct!| 00403010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004030A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004030B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004030C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004030D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004030E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004030F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004031A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004031B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004031C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004031D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004031E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004031F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403200 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403230 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403270 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004032A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004032B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004032C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004032D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004032E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004032F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004033A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004033B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004033C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004033D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004033E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004033F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403470 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004034A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004034B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004034C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004034D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004034E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004034F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403500 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403520 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403530 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403540 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403550 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403560 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403580 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00403590 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 004035A0 00 00 00 00 00 00 00 00 00 00 00 00 00 0