逆向工程基础:x86/x64汇编基础、PE/ELF文件格式解析、常用逆向工具介绍
各位同学,欢迎来到逆向工程的第一课。说实话,逆向分析这活儿,看着挺酷,但入门确实有点门槛。不过别怕,咱们一步步来。今天要聊的三个东西——汇编、文件格式、工具——是逆向的三大支柱。我个人习惯把这三点比作「语言、地图和武器」。你想想看,不懂语言怎么读代码?没地图怎么找关键函数?没武器怎么调试?好,咱们开整。
x86/x64汇编基础:从寄存器到指令
汇编语言,说白了就是CPU能直接听懂的话。x86是32位时代的王者,x64是64位时代的霸主。两者兼容,但细节上差异不小。
寄存器:CPU的临时记事本
x86有8个通用寄存器:EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP。每个32位。到了x64,扩展成了RAX、RBX……一共16个,每个64位。嗯,这里要注意:x64下,低32位还能用EAX访问,但高32位是独立的。
我遇到过不少新手,一上来就记寄存器名字,记到崩溃。其实不用。你只要记住几个关键角色:
- EAX/RAX:累加器,函数返回值通常放这儿。
- EBP/RBP:基址指针,指向当前栈帧的底部。
- ESP/RSP:栈指针,指向栈顶。这俩是调试时的命根子。
- EIP/RIP:指令指针,指向下一条要执行的指令。逆向时你盯着它看就行。
常用指令:别被吓到
汇编指令看着多,其实常用的就那几十条。我列几个你一定会遇到的:
| 指令 | 作用 | 例子 |
|---|---|---|
| MOV | 数据传送 | MOV EAX, 0x1234 |
| PUSH/POP | 压栈/出栈 | PUSH EAX; POP EBX |
| CALL/RET | 调用函数/返回 | CALL 0x401000 |
| JMP/Jcc | 无条件/条件跳转 | JMP 0x401200; JE 0x401300 |
| LEA | 取有效地址 | LEA EAX, [EBP-0x4] |
为什么会这样?因为程序本质上就是数据搬运+跳转。你只要看懂数据怎么流、控制怎么跳,逆向就成功了一半。
PE/ELF文件格式解析:可执行文件的骨架
PE是Windows的格式,ELF是Linux的格式。两者结构不同,但核心思想一样:告诉操作系统「我的代码在哪儿、数据在哪儿、入口在哪儿」。
PE文件格式:Windows下的标准
PE文件的结构,我习惯从DOS头开始看。DOS头里有个e_lfanew字段,指向真正的PE签名。签名之后是文件头、可选头、节表。嗯,这里要注意:可选头其实不是可选的,它包含了程序入口点、镜像基址、节对齐等关键信息。
节表定义了各个节(.text、.data、.rdata等)的虚拟地址、文件偏移、大小和属性。逆向时,我经常先看节表,判断代码段和数据段的位置。
// 一个简单的PE解析示例(伪代码)
DOS_HEADER *dos = (DOS_HEADER *)file_base;
PE_HEADER *pe = (PE_HEADER *)(file_base + dos->e_lfanew);
IMAGE_OPTIONAL_HEADER *opt = &pe->OptionalHeader;
printf("Entry Point: 0x%X\n", opt->AddressOfEntryPoint);
printf("Image Base: 0x%X\n", opt->ImageBase);
// 遍历节表
for (int i = 0; i < pe->FileHeader.NumberOfSections; i++) {
SECTION_HEADER *sec = &opt->Sections[i];
printf("Section: %s, VA: 0x%X, Size: 0x%X\n", sec->Name, sec->VirtualAddress, sec->SizeOfRawData);
}
ELF文件格式:Linux下的优雅设计
ELF的结构比PE更简洁。文件头(Ehdr)直接告诉你这是32位还是64位、入口点、节头表偏移。节头表(Shdr)描述每个节的信息。程序头表(Phdr)描述段(Segment)信息,用于加载。
我个人觉得ELF的设计更「干净」。没有DOS头那些历史包袱,结构紧凑。逆向ELF时,我一般先看节头表,找.text和.rodata节。前者是代码,后者是只读数据(比如字符串)。
常用逆向工具:IDA Pro、Ghidra、x64dbg
工具是逆向工程师的武器。选对工具,事半功倍。我个人的工具箱里,这三样是常驻的。
IDA Pro:静态分析的王者
IDA Pro,业内公认的静态分析神器。它的反编译功能(F5)能把汇编转成类C代码,极大降低分析门槛。我刚开始用IDA时,最震撼的就是按一下F5,一堆汇编变成了清晰的逻辑判断。
IDA的交叉引用(Xref)功能也很强。你选中一个函数,它能列出所有调用它的地方。这在分析恶意软件的控制流时特别有用。
不过IDA Pro是收费的,而且价格不菲。如果你预算有限,可以先用免费版(IDA Free),功能少一些,但基础分析够用。
Ghidra:开源界的黑马
Ghidra是美国NSA开源的逆向工具,功能直逼IDA Pro。它的反编译引擎很成熟,支持多种架构(x86、ARM、MIPS等)。而且,Ghidra是免费的!
我建议新手从Ghidra入手。它的界面可能不如IDA直观,但胜在功能全、更新快。而且,Ghidra的脚本功能(Python/Java)很强大,可以批量分析样本。
我记得有一次分析一个变种样本,IDA的签名库没识别出来,但Ghidra的自动分析直接匹配到了已知的恶意代码模式。嗯,从那以后我两个工具都开着。
x64dbg:动态调试的利器
静态分析只能看代码,动态调试才能看行为。x64dbg是Windows下最流行的开源调试器,支持x86和x64。它的界面简洁,功能实用:断点、单步、内存查看、寄存器编辑……该有的都有。
我调试恶意软件时,习惯先在入口点下断点,然后单步跟踪。遇到反调试代码(比如IsDebuggerPresent),我会手动修改寄存器或跳过它。x64dbg的「Run to User Code」功能也很实用,能快速跳过系统加载代码,直接进入程序逻辑。
好了,这一章的内容就这么多。逆向工程的基础,说白了就是「看懂汇编、摸清格式、用好工具」。这三样练熟了,后面的课程你会轻松很多。下一章,咱们聊聊如何用这些基础去分析一个真实的恶意样本。到时候,我会拿一个我实际分析过的案例来演示。敬请期待!