文章总结: 本文详细介绍了逆向工程的学习路径,强调先从汇编语言和操作系统基础开始,逐步学习C语言、汇编和操作系统知识,然后介绍了一系列逆向工程工具和技巧,并提供了一个月的实践步骤,帮助读者从零开始学习逆向工程。 综合评分: 85 文章分类: 逆向分析,代码审计,技术标准,安全工具,安全意识
先学会看汇编,再谈逆向:一份从零开始的逆向工程学习地图
原创
Sink Sink
船山信安
2026年9月24日 18:40 湖南
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
底层手艺 · BINARY
先学会看汇编,再谈逆向:一份从零开始的逆向工程学习地图
逆向入门 · 写给想碰二进制、又怕看不懂汇编的人
打开 IDA,拖进一个 exe,然后呢?大多数人卡在第二步——屏幕上一排排 mov、call、jmp,像天书。这很正常。逆向最难的地方不是看不懂,是根本不知道该从哪一行开始看。这篇不哄你”七天入门”,只把那条从零到能干活的小路标清楚。
01逆向不是”破解”,是把黑盒翻译成白盒
逆向这两个字,被误解得太久了。很多人脑子里第一反应是”破解软件、搞注册机、把收费的弄成免费的”。那是逆向里极小、而且越来越不划算的一块。把目标一上来就定成”能破”,你走偏了。
我更愿意把它定义成一句话:你拿到一个没有源码、或者你本不该看源码的程序,通过它最终落地的那堆二进制,把”它到底在干什么”这件事还原出来。
这件事的正当用途多得很。安全研究员拿到一段恶意样本,要弄清楚它连了哪个 C2、动了哪几个文件;做固件的,要在一台路由器的镜像里找厂商偷偷留的后门;审计自己团队依赖的某个开源库,确认它没在后台偷偷上传数据;漏洞复现,要把补丁前后那几行 diff 对应到二进制里到底改了哪片内存。还有 CTF 里的 RE 题——它和破解不一样,题目本来就是给你练手用的。
所以先正个名:逆向是手艺,不是”搞破坏”的近义词。把这门手艺练出来,你看待任何程序的方式都会变——别人看到的是界面,你看到的是它把数据放在哪、什么时候越过边界。
一个真实的逆向会话长这样:你打开工具,函数名清一色变成 sub_401230、sub_4012A0,里面六个 case,其中有一个你追进去发现永远走不到——编译器把它当成死分支优化掉了,或者作者当年留了个没接上的判断。第一次遇到这种事会觉得乱,但看多了你会冒出一个念头:原来就这么点东西。
02先补三块地基:C 语言、汇编、操作系统
很多人一上来就装 IDA,然后对着一片反汇编发呆。发呆的根源只有一个:他不知道这段二进制是怎么来的。一个程序从你写的 .c 到能跑起来,中间要走过编译、链接、装载、再变成进程内存里的布局。这四步你心里没图,反汇编里每一行都是孤立的。
举个具体的:你写 int a[4]; 然后越界写了第 8 个元素,编译器不会拦你。但内存里,隔壁那个变量的命运已经被你改写了。逆向时要反过来——你得从那片被改写的字节,倒推回去”谁动了它”。这种倒推的直觉,只能在学 C 的时候亲手把内存搞乱几次才养得出来。
再就是文件格式。Windows 上是 PE,Linux 上是 ELF,它们都只是”把代码、数据、导入表、重定位信息按约定排好”的集装箱。你不用背结构,但得知道入口点在哪、导入表长什么样、.text 段和 .data 段分别装什么。否则你连”该从哪开始看”都答不上来。
| | | | | — | — | — | | 模块 | 学什么 | 为什么必须 | | C 语言的内存视角 | 指针就是地址、结构体怎么排、栈/堆/BSS/数据/代码段各装什么 | 不懂内存,反汇编里每个变量你都定位不到 | | 汇编(十来条就够) | mov / push / pop / call / ret / lea / cmp / jmp / add | 这是二进制和你能读懂的东西之间唯一的桥 | | 操作系统基础 | 虚拟地址、装载过程、动态链接、系统调用 | 不知道程序怎么被装进内存,你就找不到起点 |
把这四步拆开看:编译把每个 .c 变成 .o,链接把一堆 .o 和标准库拼成最终那个可执行文件,装载时操作系统读着 PE/ELF 头部的描述,把它一段段映射到进程的虚拟地址空间里。你平时双击运行的那个 exe,在磁盘上和在被加载进内存后,地址常常是不一样的——这正是重定位存在的理由。反汇编工具帮你把”磁盘上的字节”和”内存里的地址”对上,而你能不能利用它,取决于你知不知道这个映射关系。
有个反直觉的建议:练 C 的阶段别急着上 IDE。用文本编辑器写,用 gcc 在命令行编译,把告警一个个看懂,再用 objdump -d 看它变成了什么。IDE 把”编译、链接、加载”这些细节藏得太好了,而恰恰是这些细节,后面每次逆向都要用到。
练到能看反汇编之后,下一步是学会”读头”。用 readelf -h 看 ELF 的头部,你能直接看到入口点地址、节区数量、数据是按小端还是大端排的;PE 也有对应的 IMAGE_NT_HEADERS。这些信息在工具里点一下就有,但我建议你手动敲一遍——因为真正难的二进制往往头被改过、节被合并过,那时你只能靠对这些字段的肌肉记忆去判断”哪里不对劲”。
03工具链怎么选
工具不用一次配齐。先把”静态看”和”动态跑”各选一个顺手的,够用半年。下面这张表把常见的列全了,你按自己的平台和阶段挑。
| | | | | | | — | — | — | — | — | | 工具 | 平台 | 免费? | 适合阶段 | 入门建议 | | IDA Free | 跨平台 | 免费(非商业) | 入门看界面 | 仅 x86/x64,反编译走云端,先认 IDA 长相 | | Ghidra | 跨平台 | 免费开源 | 主力静态 | NSA 2019 开源,自带反编译器,架构覆盖广 | | Binary Ninja | 跨平台 | 付费($149+) | 进阶/自动化 | API 友好,个人版便宜,CTF 圈常用 | | radare2 / Rizin | 跨平台 | 免费开源 | 命令行/脚本 | 命令多,配 Cutter 图形界面上手 | | x64dbg | Windows | 免费开源 | 动态调试 | 改跳转、看内存,Windows 下首选 | | GDB + pwndbg | Linux | 免费 | 动态/漏洞 | 配合 checksec 看保护,看寄存器顺手 | | WinDbg | Windows | 免费 | 内核/驱动 | 微软官方,文档全,但界面冷硬 | | strings / binwalk | 跨平台 | 免费 | 辅助 | 先看字符串、提取固件,几分钟定方向 | | Process Monitor | Windows | 免费 | 行为监控 | 看文件/注册表/网络,先静态后动态 | | Frida | 跨平台 | 免费(部分) | 动态插桩 | 不改文件,直接改运行时 | | Wireshark | 跨平台 | 免费 | 网络 | 抓协议流量,配 Frida 看明文 |
几个容易踩的点说一下。IDA Free 不是 IDA 的阉割试用版那么简单——它把反编译锁死在 x86/x64,而且要走云端,还不能商用(来自 Hex-Rays 官方的 IDA Free 说明页)。你若想认 IDA 的界面、建立直觉,它够用;真要干活,Ghidra 反而更宽。Ghidra 是 NSA 2019 年公开的,到 11.x 这一代反编译器已经能打了,架构支持也广,唯一被念叨的是界面略繁琐。Binary Ninja 个人版一百多美元起,API 设计得很讨脚本党喜欢,是很多人 CTF 的主力。radare2 免费、脚本强,但命令多到劝退,建议配 Cutter 这个图形壳先摸门道。
顺带提一句反编译器的水有多深。同一段二进制,Ghidra 和 IDA 的 Hex-Rays 反出来的伪代码常有出入,一个认得出结构体,另一个可能把它当成一团未命名字节。所以别迷信任何单一工具的输出——它给的是”猜测的 C”,不是真相。养成习惯:反编译器说这里是个 int,你要去内存窗口里亲自核对长度和对齐。工具越智能,越要保留这一份怀疑。
04第一个月该干什么
第一个月别追求”看懂大程序”。你的目标应该是:亲手把”写代码 → 看反汇编 → 改行为 → 还原逻辑”这条链走通一遍。下面这个阶梯,每一步都能在本地复现。
第一步,自己写、自己拆。写个几十行的小 C 程序,编译,再用 objdump 对照看。你会对上”我那行 if 变成了哪条 jmp”。这一步没有捷径,它是后面所有感觉的来源。
比如这段故意写得极简的”注册码”程序:
// serial.c ── 极简的”注册码”程序
include
int main() {
int x;
printf(“input: “);
scanf(“%d”, &x);
if (x * x == 1522756) // 1234 的平方
printf(“ok\n”);
else
printf(“no\n”);
return 0;
}
编译: gcc -O0 -o serial serial.c
反汇编: objdump -d -M intel serial | grep -A30 ‘
第二步,找个 crackme 练手。crackmes.one、crackmy.app 上从”入门”标签开始,几百道题随便挑。先挑那种”输入对了就打印 correct”的,逻辑一目了然。
第三步,改一个跳转。用 x64dbg 或 IDA 把那处 jne 改成 je,程序就从”拒绝”变”通过”。这是你第一次亲手改掉一个程序的命运,那种掌控感会支撑你走下去。
第四步,脱最简单的壳。UPX 是最友好的入门壳,upx -d 一行就能脱。但你要理解为什么能脱——脱壳本质是让程序自己解压完,再把内存里的干净镜像 dump 出来。
第五步,还原一个算法,写出注册机。从反汇编里把那串判断逻辑抄回 C 或 Python,跑出能让程序说”ok”的输入。做到这一步,你才真正算”会了一点”。
每一步做完,强迫自己写两行”我刚才干了什么、卡在哪”。很多人第一个月的热情来得快去得也快,根子在从不动笔——三个月后你一定会忘记那个跳转地址当初是怎么算出来的。写下来的过程,是把”我好像懂了”变成”我真的懂了”的唯一办法。这一步偷懒,后面每道新题都像从头开始。
这五步的价值不在结果,在于让你建立一个信念:反汇编不是天书,是另一套你能学会的语言。很多人卡在第二步,就是因为跳过了第一步的”自己写自己拆”。
05读汇编的四个抓手
看反汇编最怕没有章法,一行一行往下捋只会晕。我教自己用的是四个抓手:函数边界、调用约定、栈帧、数据流。下面这段是编译器对一个小函数的真实产出(x86-64,Intel 语法),我们逐行过一遍。
check:
push rbp ; 1.函数边界:把调用者的栈帧基址存起来
mov rbp, rsp ; 建立当前函数的栈帧
mov eax, DWORD [rbp-4] ; 2.调用约定:参数在栈上被取出来
cmp eax, 0x1337 ; 3.数据流:和那个”暗号”比一下
jne .fail ; 不相等就跳去 .fail
mov eax, 1 ; 相等,返回值 1 放进 eax
jmp .done
.fail:
mov eax, 0 ; 不相等,返回值 0
.done:
pop rbp ; 4.栈帧:恢复调用者的 rbp
ret ; 返回,eax 里就是答案
函数边界看两头:push rbp 配 pop rbp,再加一句 ret,这就是一个函数从出生到结束的框。你只要认得这个框,反汇编里成千上万行就被切成了”一块一块”的函数。
调用约定回答”参数从哪来”。x86-64 的 System V 约定里,前几个参数走寄存器(rdi、rsi、rdx…),函数常常把它们先搬进栈上的”家”([rbp-4] 这种)。所以你看到 [rbp-4],基本就是在读第一个参数。
栈帧是函数自己的临时工作台。rbp 是台面基准,rsp 是台面边缘。局部变量、返回地址都摆在台面上。理解了”台面”长什么样,你才知道溢出时到底淹了谁。
数据流是最关键的抓手:值在哪些寄存器之间搬、在哪个比较处分叉、最终落在哪返回。上面这十来行,数据流就是”eax 取出参数 → 和 0x1337 比 → 分支决定 eax 是 1 还是 0 → 带着它返回”。顺着值走,而不是顺着指令走,反汇编一下子就顺了。
很多人学汇编卡很久,是因为一上来就背指令集。别背。把这四个抓手挂在脑子里,遇到不懂的指令现查,查着查着你就会了。指令就那几十个,反复出现。
06常见劝退点与应对
走到这一步,劝退点开始密集。提前认得它们,摔的时候不至于以为自己不行。
| | |
| — | — |
| 现象 | 怎么破 |
| 编译器优化让代码变形 | 初学一律 -O0,再拿 -O2 对照着看,体会循环展开、内联 |
| 符号被剥离 | 函数变 sub_xxx,靠字符串和交叉引用倒着找入口 |
| C++ 虚表和 STL 膨胀 | 先吃透 C 程序,C++ 的 RE 是另一门课(OST2 有专门课) |
| 混淆与加壳 | 先脱 UPX,再碰简单混淆;运行时用 Frida 绕 |
| 大二进制找不到入口 | 从字符串、导入表、TLS 回调这些”边角”切入 |
至于”大二进制找不到入口”,本质往往不是技术难,是心态先崩——你以为必须从 main 开始,但很多样本把真正的逻辑藏在 TLS 回调、异常处理、甚至资源段里,main 只是一个幌子。先用 strings 扫一遍能打印出来的字,顺着”错误提示””配置名”这种人类字符串往回追,比盲目从入口硬啃省力十倍。
单独说一下 C++。很多人 C 程序读得挺顺,一碰 C++ 就崩,崩在虚函数表(vtable)和 STL 那一坨模板膨胀上——一个 std::string 的反汇编能铺满好几屏。这不是你的问题,是 C++ 本身在二进制层面就是贵。OpenSecurityTraining2(OST2)有门”Reversing C++ Binaries”的课专门对付它,等 C 底子扎实了再去碰,别提前被劝退。
把这些劝退点摊开看,你会发现它们其实是一件事的多个面:编译器、链接器、加壳工具、C++ 标准库,全都在你和被分析的程序之间砌墙。逆向要做的事,就是一块一块把这些墙拆掉,直到你能直接看见程序原本的意图。所以别指望某天”突然全懂了”——是每拆掉一面墙,视野就清一点,如此而已。每清掉一处障碍,你就离”能独立干活”近了一步,这条路上没有白拆的墙。
07三个”别”
别一上来就开 IDA 啃大项目。几十 MB 的闭源软件,函数成千上万,新人进去除了绝望什么都得不到。从几十行的 crackme、从你昨天自己写的那个 C 程序开始。
别只刷题不碰真实程序。CTF 的 RE 题是出题人精心修剪过的,干净、有答案、卡点明确。真实样本脏得多——代码混着数据、逻辑被压过、还夹着反分析。去抓个真实样本(恶意样本务必在隔离机里),你会发现差距比想象的大。
别迷信鼠标流。点来点去很爽,但重复劳动会拖死你。早一点学 IDAPython、Ghidra 脚本、r2 的一行命令,把”标函数名、找交叉引用、批量改字节”这类事交给脚本。效率差出来的不是一倍两倍。
说到底,逆向教给你的不是某一个工具或技巧,而是一种”不信任表面、去查证底层”的思维方式。同一个功能,作者想让你看到的是按钮和提示,你想看到的是它在内存里如何布局、在哪些条件下会越过边界。这种视角一旦建立,你写代码、看漏洞、甚至用任何一个软件时,都会下意识多问一句”它背后到底在干什么”。这比任何一道题的答案都值钱。
ONE LINE 逆向没有捷径,只有把第一行汇编看顺眼。
参考来源
· Hex-Rays 官方 IDA Free 说明页:仅支持 x86/x64、云端反编译、非商业用途、无 IDAPython/SDK(2024 在役版本)
· NSA Ghidra 发布记录:2019 年公开,11.x 系列(11.0 于 2023 年 12 月、11.3 于 2024 年 5 月)持续迭代反编译器与多架构支持
· Vector 35 Binary Ninja 官网与公开定价页:个人版 $149 起,Free 版有架构限制(2024)
· radare2 / Rizin 与 Cutter 项目主页(rizin.re、cutter.re):免费开源,r2ghidra 提供反编译
· OpenSecurityTraining2(OST2,ost2.fyi):Arch1001 x86-64 汇编、Dbg1102 入门 Ghidra、Dbg1012 入门 GDB、Vulns1001 C 语言实现漏洞、Reversing C++ Binaries 等免费课程(2021–2024)
· Dennis Yurichev《Reverse Engineering for Beginners》(beginners.re):免费开源教材,覆盖 x86/x64、ARM、PE/ELF、C++ STL
· crackmes.one / crackmy.app:公开 crackme 练习社区;Mandiant Flare-On 逆向挑战赛(年度);Mandiant FLARE VM 逆向环境
· CTF Wiki(ctf-wiki.org):逆向工程与二进制分析中文公开知识库
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:船山信安 Sink Sink《先学会看汇编,再谈逆向:一份从零开始的逆向工程学习地图》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。






![[中秋悦安]DataCon祝您中秋安康,岁岁长乐!](/images/random/titlepic/15.jpg)




评论