纸翼 · 加载中
4119 words
21 minutes
汇编笔记(部分)

一、x86基础寄存器(逆向工程核心基础)#

x86架构的寄存器是指令操作的核心载体,逆向中需精准掌握寄存器的用途、分类及数据流向,32位x86核心寄存器分为以下几类:

1. 通用寄存器(数据操作核心)#

通用寄存器用于存储数据、地址、参数等,32位寄存器可拆分为16位/8位子寄存器(如EAX→AX→AH/AL),逆向中需关注子寄存器的操作(如单字节/双字节数据处理)。

32位寄存器16位子寄存器8位子寄存器核心用途(逆向场景)
EAXAXAH/AL累加器:算术运算、函数返回值(Windows API返回值默认存EAX)、系统调用号
EBXBXBH/BL基址寄存器:全局变量指针、内存基址(如PEB/TEB偏移计算)
ECXCXCH/CL计数器:循环计数(REP指令)、Fastcall/Thiscall参数传递(第1参数/this指针)
EDXDXDH/DL数据寄存器:大数运算(除法余数、64位数据高32位)、Fastcall第2参数
ESISISIL源变址寄存器:字符串操作(MOVS/LODS)源地址、数据拷贝源指针
EDIDIDIL目的变址寄存器:字符串操作(MOVS/STOS)目的地址、数据拷贝目的指针
EBPBPBPL基址指针:栈帧基址(逆向中通过EBP偏移定位局部变量/参数)
ESPSPSPL栈指针:始终指向栈顶(逆向中跟踪栈帧变化、栈平衡)

逆向关键

  • EAX是逆向中最常关注的寄存器(函数返回值、运算结果、系统调用号);
  • EBP/ESP是栈帧分析的核心,通过EBP+偏移定位参数,EBP-偏移定位局部变量;
  • ESI/EDI是字符串/内存操作的专属寄存器,REP指令依赖这两个寄存器+ECX(长度)。

2. 段寄存器(内存寻址辅助)#

段寄存器在保护模式下用于定位内存段,逆向中需重点关注FS寄存器(关联TEB/PEB):

寄存器核心用途(逆向场景)
CS代码段:指向当前执行指令的代码段(.text段)
DS数据段:指向全局数据段(.data/.rdata)
SS栈段:指向栈段(栈帧所在内存区域)
ES/FS/GS附加段:FS在Windows中指向TEB(线程环境块),是反调试分析的核心

3. 指令指针寄存器(执行流核心)#

寄存器32位名称核心用途(逆向场景)
IPEIP指令指针:指向当前即将执行的指令地址(逆向中跟踪执行流、断点设置核心)

逆向关键:EIP无法直接修改(仅能通过JMP/CALL/RET/INT等指令间接修改),是控制流分析的核心。

4. 标志寄存器(状态判断核心)#

标志寄存器(EFLAGS)存储指令执行后的状态,是条件跳转(Jcc)、条件移动(CMOVcc)的判断依据,核心标志位如下:

标志位缩写名称含义
ZF零标志运算结果为0则置1,否则置0(JE/JNE的判断依据)
SF符号标志运算结果最高位为1(负数)则置1,否则置0(JG/JL的判断依据)
CF进位标志无符号运算产生进位/借位则置1(JA/JB/ADC/SBB的判断依据)
OF溢出标志有符号运算溢出则置1(JO/JNO/JG/JL的判断依据)
PF奇偶标志运算结果低8位中1的个数为偶数则置1(位运算/字节操作辅助判断)
IF中断标志控制CPU是否响应可屏蔽中断(反调试中可能通过CLI/STI修改)

二、汇编基本结构(x86实模式/保护模式)#

x86汇编程序的核心结构分为段定义数据段代码段栈段三大部分,逆向中需重点关注内存布局与指令执行流:

1. 段结构(保护模式下)#

; 典型NASM格式结构
section .data ; 数据段:只读/可读写常量(全局变量、字符串、常量)
msg db "hello",0x00
num dd 123 ; 4字节整型常量
section .bss ; 未初始化数据段:逆向中常为全局未初始化变量
buf resb 100 ; 预留100字节缓冲区
section .text ; 代码段:指令执行区,逆向核心分析区域
global _start ; 入口点(Linux)/ main(Windows)
_start:
; 指令执行流
mov eax, 1 ; sys_exit调用
int 0x80 ; 系统调用

2. 逆向视角的结构要点#

  • 数据段(.data/.rdata):逆向中通过常量、字符串定位功能(如错误提示、密钥);
  • 代码段(.text):指令的机器码与汇编对应,是反汇编、动态调试的核心;
  • 栈段(stack):运行时动态分配,存储局部变量、函数调用上下文,逆向中需跟踪栈帧变化。

三、核心指令体系(逆向高频指令)#

1. 数据传输指令(逆向最基础、最高频)#

数据传输指令负责在寄存器、内存、立即数间移动数据,逆向中需关注数据流向(如参数传递、加密数据搬运)。

指令格式功能逆向场景
MOVMOV reg, mem/imm/reg数据移动(不影响标志位)变量赋值、参数传递
LEALEA reg, mem加载有效地址(计算地址)数组索引、指针运算
PUSH/POPPUSH reg/mem; POP reg入栈/出栈函数调用、栈帧构建
XCHGXCHG reg, reg/mem交换数据加密算法、寄存器暂存
CMOVccCMOVZ reg, mem条件移动(依标志位)无分支条件判断(反调试)
MOVSX/MOVZXMOVSX reg, reg8/16符号/零扩展移动整型类型转换(如char→int)

逆向示例

lea eax, [ebp+var_4] ; 计算局部变量var_4的地址(而非取值)
movsx ebx, byte ptr [eax] ; 单字节符号扩展为4字节(处理负数)

2. 算数运算指令(逆向中加密/校验/数值计算核心)#

指令格式功能影响标志位
ADD/SUBADD reg, mem/imm加减运算ZF/SF/CF/OF/AF/PF
MUL/IMULIMUL reg, mem/imm无符号/有符号乘法CF/OF(MUL)
DIV/IDIVDIV reg无符号/有符号除法无(商→AX,余数→DX)
INC/DECINC reg自增/自减(不影响CF)ZF/SF/OF/AF/PF
NEGNEG reg取反(等价于0 - reg)同SUB
ADC/SBBADC reg, imm带进位/借位加减同ADD/SUB

逆向关键

  • IMUL/DIV常出现在加密算法(如RC4、AES)的数值计算;
  • ADC/SBB用于大数运算(如64位以上整数加减,逆向中关注CF标志);
  • INC/DEC不影响CF,需注意与ADD reg,1的区别(后者影响CF)。

3. 位操作指令(逆向中加密/压缩/硬件交互核心)#

指令格式功能影响标志位
AND/OR/XORXOR reg, mem/imm按位与/或/异或ZF/SF/PF(CF/OF=0)
NOTNOT reg按位取反
SHL/SHRSHL reg, imm逻辑左移/右移(空位补0)CF/ZF/SF/OF/PF
SAL/SARSAR reg, imm算术左移/右移(SAR补符号位)同SHL/SHR
ROL/RORROL reg, imm循环左移/右移(进位参与循环)同SHL
BT/BTC/BTRBT reg, imm位测试/测试并取反/测试并复位CF(目标位值)

逆向示例

xor eax, eax ; 快速清零寄存器(比mov eax,0更高效)
shl ebx, 3 ; 等价于ebx *= 8(逆向中识别乘除优化)
bt ecx, 7 ; 测试ecx第7位是否为1(结果存CF)

4. 逻辑比较指令(控制流分支的基础)#

比较指令本质是“减法但不保存结果,仅更新标志位”,逆向中需结合标志位分析分支条件。

指令格式功能影响标志位
CMPCMP reg, mem/imm比较(reg - mem/imm)同SUB
TESTTEST reg, mem/imm按位与(仅更新标志位)同AND
SCASSCASB/SCASW/SCASD串比较(AL/AX/EAX - [EDI])同CMP

逆向关键

  • TEST eax, eax:快速判断eax是否为0(等价于CMP eax,0,更高效);
  • CMP后紧跟Jcc(条件跳转),是逆向中分析分支逻辑的核心;
  • SCAS常用于字符串长度计算、内存数据校验(如缓冲区对比)。

5. 控制转移指令(逆向中分析执行流的核心)#

控制转移指令改变EIP(指令指针),分为无条件跳转条件跳转函数调用/返回三类:

(1)无条件转移#

指令功能逆向场景
JMP无条件跳转分支、循环、壳的跳转
CALL调用函数(PUSH EIP+JMP)函数调用、API调用
RET/RETN函数返回(POP EIP)函数结束、栈平衡

(2)条件跳转(Jcc)#

基于标志寄存器的组合判断,是逆向中分析逻辑的核心:

指令别名条件标志位组合典型逆向场景
JEJZ相等/零ZF=1字符串比较结束、循环终止
JNEJNZ不等/非零ZF=0循环继续、条件分支
JGJNLE有符号大于SF=OF 且 ZF=0数值范围判断(如x>10)
JGEJNL有符号大于等于SF=OF数值判断(x≥0)
JLJNGE有符号小于SF≠OF数值判断(x<5)
JLEJNG有符号小于等于SF≠OF 或 ZF=1数值判断(x≤0)
JAJNBE无符号高于CF=0 且 ZF=0地址/长度比较(如buf_len>100)
JAEJNB无符号高于等于CF=0地址判断(ptr≥0x400000)
JBJNAE无符号低于CF=1长度判断(len<256)
JBEJNA无符号低于等于CF=1 或 ZF=1长度判断(len≤512)
JS-结果为负SF=1负数处理、符号校验
JNS-结果非负SF=0正数判断
JO-溢出OF=1溢出异常检测、数值越界
JNO-无溢出OF=0正常数值运算
JC-有进位CF=1大数运算、校验和计算
JNC-无进位CF=0大数运算正常分支

6. 栈操作指令(逆向中栈帧分析核心)#

栈是x86逆向的核心(函数调用、局部变量、参数传递均依赖栈),栈操作指令需结合栈帧结构分析:

指令格式功能逆向注意点
PUSHPUSH reg/mem/imm栈顶指针ESP-4,数据入栈逆向中跟踪栈内容变化
POPPOP reg栈顶数据出栈,ESP+4注意POP后寄存器值变化
PUSHA/POPA-所有通用寄存器入栈/出栈保护现场(壳/调试器常用)
ENTER/LEAVEENTER imm16, imm8构建/销毁栈帧(等价于PUSH EBP; MOV EBP,ESP; SUB ESP,imm)函数入口/出口快速识别

逆向核心:栈的生长方向为高地址→低地址,ESP始终指向栈顶,EBP为栈帧基址(逆向中通过EBP偏移定位参数/局部变量)。

7. 字符串操作指令(逆向中字符串处理/内存拷贝核心)#

字符串指令通过ESI(源地址)、EDI(目的地址)、ECX(长度)、EAX(比较值)配合,批量处理内存数据,逆向中常出现在字符串拷贝、加密、校验场景:

指令格式功能逆向场景
MOVSMOVSB/MOVSW/MOVSD串拷贝([ESI]→[EDI])内存拷贝、数据搬运
LODSLODSB/LODSW/LODSD串加载([ESI]→AL/AX/EAX)读取字符串/数据块
STOSSTOSB/STOSW/STOSD串存储(AL/AX/EAX→[EDI])内存填充(如memset)
REPREP MOVSB重复执行(ECX≠0)批量拷贝(如strcpy)
REPE/REPNEREPE SCASB相等/不等时重复字符串比较(如strcmp)

逆向示例

; 等价于memset(edi, 0, ecx)
xor eax, eax ; 填充值为0
rep stosb ; 重复将AL写入[EDI],ECX次,EDI自动递增

四、TEB/PEB与反调试技术(逆向核心对抗场景)#

TEB(线程环境块)、PEB(进程环境块)是Windows系统中存储进程/线程信息的核心结构,反调试技术常通过读取这些结构中的标志位检测调试器。

1. 核心结构关系#

  • PEB:位于进程地址空间(32位:0x7FFDF000),存储进程基本信息(如是否调试、模块列表);
  • TEB:每个线程独有(32位:FS:[0]指向TEB),TEB偏移0x30指向PEB;
  • 关键偏移(32位Windows):
    TEB + 0x30 → PEB
    PEB + 0x02 → BeingDebugged(1字节,调试时为1)
    PEB + 0x68 → Ldr(模块加载器)
    PEB + 0x10 → ProcessHeap(进程堆)

2. 基于TEB/PEB的反调试方法(逆向需识别)#

反调试方式汇编实现逆向识别要点
检测BeingDebugged标志mov eax, fs:[0x30]
mov al, [eax+0x02]
test al, al
jnz Debugged
跟踪FS:[0x30]访问,检查PEB+0x02
检测PEB堆标志mov eax, fs:[0x30]
mov eax, [eax+0x10]
test dword ptr [eax+0x14], 0x40
访问ProcessHeap+0x14(HeapFlags)
检测调试端口(PEB+0xBC)mov eax, fs:[0x30]
cmp dword ptr [eax+0xBC], 0
jne Debugged
PEB+0xBC为调试端口,非0则调试

3. 逆向应对思路#

  • 动态调试:修改BeingDebugged标志为0,或Hook相关内存访问;
  • 静态分析:识别FS:[0x30]、PEB偏移访问指令,定位反调试分支。

五、函数调用与栈帧(逆向中函数分析核心)#

1. 函数的标准汇编结构(32位x86,以Stdcall为例)#

一个完整的函数在汇编层面分为函数序言函数体函数尾声三部分,逆向中可通过这三部分快速识别函数边界:

函数阶段典型汇编指令核心作用逆向识别特征
函数序言(Prologue)push ebp
mov ebp, esp
sub esp, n
push ebx/esi/edi(可选)
1. 保存旧栈帧基址(EBP)
2. 建立新栈帧(EBP=ESP)
3. 分配局部变量空间(ESP-n)
4. 保护非易失性寄存器(EBX/ESI/EDI)
函数开头固定出现push ebp + mov ebp, esp,是识别函数入口的核心特征
函数体(Body)各类业务指令(运算、分支、调用子函数等)实现函数核心逻辑包含业务相关的指令流,如参数访问(EBP+8/12)、局部变量访问(EBP-4/8)、子函数CALL等
函数尾声(Epilogue)pop ebx/esi/edi(可选)
mov esp, ebp
pop ebp
retn n(Stdcall)/ ret(Cdecl)
1. 恢复非易失性寄存器
2. 销毁栈帧(ESP=EBP)
3. 恢复旧EBP
4. 函数返回并平衡栈
函数结尾固定出现mov esp, ebp + pop ebp + ret/retn,是识别函数出口的核心特征

逆向示例:标准函数结构汇编代码

; 函数:int Add(int a, int b) (Stdcall调用约定)
Add:
; 函数序言
push ebp ; 保存旧EBP
mov ebp, esp ; 建立新栈帧
sub esp, 0x4 ; 分配1个局部变量(4字节)空间
push esi ; 保护非易失性寄存器ESI
; 函数体
mov eax, [ebp+8] ; 读取参数a(EBP+8为第一个参数)
mov esi, [ebp+12] ; 读取参数b(EBP+12为第二个参数)
add eax, esi ; a + b,结果存EAX(返回值)
mov [ebp-4], eax ; 临时存入局部变量(可选)
; 函数尾声
pop esi ; 恢复ESI
mov esp, ebp ; 销毁局部变量空间(ESP回到EBP)
pop ebp ; 恢复旧EBP
retn 0x8 ; 返回,平衡栈(参数a+b共8字节,Stdcall由被调用者平衡)

2. 函数嵌套堆栈结构(32位x86)#

以“函数A调用函数B,B有2个局部变量、2个参数”为例,栈帧结构(高地址→低地址):

函数A的栈帧
函数B的局部变量2
函数B的局部变量1
上一层的ebp
返回地址
参数1
参数2
函数B的栈顶(ESP)

3. 函数调用约定(逆向中识别参数传递/栈平衡)#

调用约定决定参数传递顺序、栈平衡责任、寄存器使用,是逆向中还原函数原型的关键:

调用约定参数传递顺序栈平衡责任寄存器使用典型场景
Cdecl右→左调用者C/C++默认、可变参数函数(printf)
Stdcall右→左被调用者Windows API(如MessageBoxA)
Fastcall右→左被调用者ECX(第1参数)、EDX(第2参数)快速调用(编译器优化)
Thiscall右→左被调用者ECX=this指针C++类成员函数
Syscall寄存器内核EAX(系统调用号)、EBX/ECX/EDX(参数)Windows内核系统调用(如NtReadFile)

逆向识别要点

  • Cdecl:函数返回后调用者执行ADD ESP, n平衡栈;
  • Stdcall:函数返回时执行RETN n(n为参数总字节数);
  • Fastcall:优先看ECX/EDX是否传递参数;
  • Thiscall:C++代码中ECX在函数开头赋值,大概率为this指针。

六、标志寄存器的高级用法(逆向中分析分支/运算)#

1. 高级应用场景#

  • 无分支条件判断:通过CMOVcc/SETcc指令替代Jcc,减少分支(反调试/壳常用):
    ; 等价于if (eax == 0) ebx = 1; else ebx = 2;
    xor ecx, ecx
    cmp eax, 0
    mov ecx, 2
    cmovz ecx, 1 ; ZF=1时,ecx=1
    mov ebx, ecx
  • 大数运算校验:ADC/SBB结合CF标志实现64位以上整数运算,逆向中需跟踪CF的传递;
  • 溢出检测:JO指令捕获有符号运算溢出(如int32超出范围),逆向中识别异常处理逻辑;
  • 反调试混淆:故意修改标志位(如CLI/STI修改IF标志),干扰调试器跟踪。

七、逆向工程核心技巧总结#

  1. 指令流分析:从入口点开始,跟踪EIP变化,结合Jcc/Call/Ret分析执行流;
  2. 栈帧还原:通过EBP偏移定位参数(EBP+8开始)、局部变量(EBP-4开始),还原函数原型;
  3. 标志位跟踪:CMP/TEST后紧跟Jcc,需先分析标志位组合,再判断分支逻辑;
  4. 反调试识别:关注FS:[0x30](TEB)、PEB偏移访问、标志位异常修改指令;
  5. 调用约定还原:通过栈平衡指令(ADD ESP/RETN n)、寄存器使用(ECX/EDX)识别调用约定。
汇编笔记(部分)
https://blog.huangzy.xyz/posts/汇编笔记基础部分/
Author
纸翼
Published at
2025-12-23
License
CC BY-NC-SA 4.0

Some information may be outdated