装载与汇编
装载



汇编
两种语法风格
| 功能 / 场景 | Intel 汇编格式 | AT&T 汇编格式 |
|---|---|---|
| 立即数传送到寄存器 | mov eax, 8 |
movl $8, %eax |
| 带十六进制立即数的传送 | mov ebx, 0ffffh |
movl $0xffff, %ebx |
| 触发系统调用(中断) | int 80h |
int $0x80 |
| 内存数据传送到寄存器 | mov eax, [ecx] |
movl (%ecx), %eax |
| 函数 / 过程(sum 示例) | sum: push ebp mov ebp, esp mov eax, [ebp+12] add eax, [ebp+8] pop ebp retn |
sum: pushl %ebp movl %esp, %ebp movl 12(%ebp), %eax addl 8(%ebp), %eax popl %ebp ret |
寄存器与数据类型
寄存器
| 寄存器 | 位数 | 主要功能 | 特殊用途 | 子寄存器关系 |
|---|---|---|---|---|
| RAX | 64-bit | 函数返回值、算术运算 | 系统调用号(Syscall) | RAX → EAX → AX → AH/AL |
| EAX | 32-bit | 累加器、算术运算主存器 | 乘法/除法结果存储 | EAX → AX → AH/AL |
| AX | 16-bit | 字乘法/字除法/字I/O | - | AX → AH(高8位)/AL(低8位) |
| AL | 8-bit | 字节乘法/字节除法/字节I/O 十进制运算 | BCD运算 | AX的低字节 |
| AH | 8-bit | 字节乘法/字节除法 | - | AX的高字节 |
| RBX | 64-bit | 通用数据存储 | 内存寻址基址 | RBX → EBX → BX → BH/BL |
| EBX | 32-bit | 内存寻址基址 | - | EBX → BX → BH/BL |
| BX | 16-bit | 内存指针 | 段寄存器(DS)的默认基址 | BX → BH(高8位)/BL(低8位) |
| RCX | 64-bit | 循环计数器 | REP前缀指令计数 | RCX → ECX → CX → CH/CL |
| ECX | 32-bit | 循环计数器 | - | ECX → CX → CH/CL |
| CX | 16-bit | 串操作/循环控制 | - | CX → CH(高8位)/CL(低8位) |
| CL | 8-bit | 移位/旋转计数器 | 位操作指令 | CX的低字节 |
| RDX | 64-bit | I/O指针、数据存储 | 除法余数存储 | RDX → EDX → DX → DH/DL |
| EDX | 32-bit | 字乘法/字除法 间接I/O | 除法余数 | EDX → DX → DH/DL |
| DX | 16-bit | 端口地址指针 | - | DX → DH(高8位)/DL(低8位) |
| RSI | 64-bit | 内存源指针 | 串操作源地址 | RSI → ESI → SI |
| ESI | 32-bit | 内存源指针 | LODS/MOVS等指令 | ESI → SI |
| SI | 16-bit | 串操作源指针 | DS段偏移 | - |
| RDI | 64-bit | 内存目的指针 | 串操作目的地址 | RDI → EDI → DI |
| EDI | 32-bit | 内存目的指针 | STOS/MOVS等指令 | EDI → DI |
| DI | 16-bit | 串操作目的指针 | ES段偏移 | - |
| RBP | 64-bit | 栈基指针 | 访问栈帧参数/局部变量 | RBP → EBP → BP |
| EBP | 32-bit | 栈基指针 | 函数栈帧基准 | EBP → BP |
| BP | 16-bit | 栈数据访问指针 | SS段偏移 | - |
| RSP | 64-bit | 栈顶指针 | 当前栈顶位置 | RSP → ESP → SP |
| ESP | 32-bit | 栈顶指针 | PUSH/POP操作 | ESP → SP |
| SP | 16-bit | 栈顶指针 | - | - |
| RIP | 64-bit | 指令指针 | 存放下一条指令地址 | RIP → EIP → IP |
| EIP | 32-bit | 指令指针 | 控制程序执行流程 | EIP → IP |
| IP | 16-bit | 指令指针 | 实模式下使用 | - |
关键补充说明:
寄存器层级关系:
- 64位寄存器 (R开头):
RAX,RBX,RCX,RDX,RSI,RDI,RBP,RSP,RIP - 32位寄存器 (E开头):
EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP,EIP - 16位寄存器:
AX,BX,CX,DX,SI,DI,BP,SP,IP - 8位寄存器:
AH/AL,BH/BL,CH/CL,DH/DL
Pwn/逆向中的核心寄存器:
- RIP/EIP:控制程序执行流(劫持核心目标)
- RSP/ESP:栈指针(缓冲区溢出关键)
- RBP/EBP:栈帧基准(定位局部变量/参数)
- RAX/EAX:存储系统调用号和函数返回值
特殊功能寄存器:
- 段寄存器:CS(代码段), DS(数据段), SS(堆栈段), ES/FS/GS(附加段)
- 标志寄存器:EFLAGS/RFLAGS(存储状态标志如ZF/CF/SF等)
寄存器使用场景:
#函数调用示例 |
64位与32位差异:
- 64位新增寄存器:R8-R15
- 调用约定变更:64位使用RCX/RDX/R8/R9传参
- 内存寻址范围扩大:64位支持48位虚拟地址空间
栈帧:
一个栈帧就是保存一个函数的状态,简单来说就是一个函数所需要的栈空间.
rsp(栈顶寄存器) /esp(栈指针寄存器)永远指向栈帧的栈顶,rbp(栈基寄存器)/ebp(扩展基址指针寄存器)则永远指向栈帧的栈底,rip(程序计数寄存器)/eip(指令指针寄存器)指向当前栈栈帧执行的命令。
栈从高地址向低地址开辟内存空间,所以低地址的是栈顶,而栈底的第一个栈帧在这里存放着我们的主函数的父函数,所以main函数并不是最栈顶的函数,main上面还会在编译过程中有一些库函数,但是他们并不会产生栈帧,因为栈先进后出的特性,所以当在main函数中需要调用其他函数时,就开辟一个新的函数栈帧,并存储上一个栈的栈底,当调用结束时,将现在的栈帧弹出,恢复到原来的main函数继续执行完main函数。

数据类型
整数常量
表达方式:
| 进制 | 前缀 | 示例 | 汇编表示 |
|---|---|---|---|
| 十进制 | 无 | 12345 |
mov eax, 12345 |
| 十六进制 | 0x |
0xDEADBEEF |
mov ebx, 0xDEADBEEF |
| 八进制 | 0 |
0755 |
mov ecx, 0755 |
| 二进制 | 0b |
0b10101010 |
mov dl, 0b10101010 |
内存存储(小端序):
int num = 0x12345678; // 32位整数 |
浮点数常量
IEEE 754标准:
| 类型 | 总位数 | 符号位 | 指数位 | 尾数位 | 范围 | 示例 |
|---|---|---|---|---|---|---|
| float | 32-bit | 1 bit | 8 bits | 23 bits | ±3.4e38 | 3.14f |
| double | 64-bit | 1 bit | 11 bits | 52 bits | ±1.7e308 | 2.71828 |
内存布局(float示例):
float pi = 3.14159; // 十六进制: 0x40490FD0 |
字符串常量
内存表示:
char *str = "Hello Pwn!"; |
汇编定义:
section .data |
标志位
·进位标志CF(Carry Flag):
进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高 位产生了一个进位或借位,那么,其值为1,否则其值为0。
·奇偶标志PF(Parity Flag):
奇偶标志PF用于反映运算结果中“1”的个数的奇偶性。如果“1”的个数为偶数,则PF的值为1,否则其值为0。
·辅助进位标志AF(Auxiliary Carry Flag):
在发生下列情况时,辅助进位标志AF的值被置为1,否则其值为0(在字操作时,发生低字节向高字节进位或借位时;在字节操作时,发生低4位向高4位进位或借位时)。
·零标志ZF(ZeroFlag):
零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。在判断运算结果是否为0时,可使用此标志位。
·符号标志SF(Sign Flag):
符号标志SF用来反映运算结果的符号位,它与运算结果的最高位相同。在微机系统中,有符号数采用码表示法,所以,SF也就反映运算结果的正负号。运算结果为正数时,SF的值为0,否则其值为1。
·溢出标志OF(Overflow Flag):
溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。
汇编指令
常用指令表
| 指令类型 | 指令 | 语法 | 功能描述 | 标志位影响 | Pwn应用场景 |
|---|---|---|---|---|---|
| 数据传送 | MOV |
MOV 目标, 源 |
将源操作数复制到目标 | 无影响 | 构造ROP链、寄存器控制 |
LEA |
LEA 目标, [内存] |
加载有效地址(不访问内存) | 无影响 | 计算地址绕过ASLR | |
| 算术运算 | ADD |
ADD 目标, 源 |
目标 = 目标 + 源 | CF,OF,SF,ZF | 整数溢出漏洞利用 |
SUB |
SUB 目标, 源 |
目标 = 目标 - 源 | CF,OF,SF,ZF | 内存地址计算 | |
INC |
INC 目标 |
目标 = 目标 + 1 | OF,SF,ZF | 计数器修改 | |
DEC |
DEC 目标 |
目标 = 目标 - 1 | OF,SF,ZF | 循环控制 | |
| 逻辑运算 | AND |
AND 目标, 源 |
目标 = 目标 & 源 | CF=0,OF=0,SF,ZF | 位掩码操作 |
OR |
OR 目标, 源 |
目标 = 目标 | 源 | CF=0,OF=0,SF,ZF | 位设置 | |
XOR |
XOR 目标, 源 |
目标 = 目标 ^ 源 | CF=0,OF=0,SF,ZF | 清零寄存器(XOR EAX, EAX) |
|
NOT |
NOT 目标 |
目标 = ~目标 | 无影响 | 位翻转 | |
| 控制转移 | CALL |
CALL 地址 |
1. 压入返回地址 2. 跳转到目标地址 | 无影响 | 函数调用劫持 |
RET |
RET [n] |
1. 弹出返回地址 2. 跳转到该地址 3. 可选栈调整 | 无影响 | 栈溢出利用 | |
JMP |
JMP 地址 |
无条件跳转 | 无影响 | 程序流劫持 | |
| 比较测试 | CMP |
CMP 操作数1, 操作数2 |
设置标志位(操作数1 - 操作数2) | CF,OF,SF,ZF | 条件分支漏洞利用 |
TEST |
TEST 操作数1, 操作数2 |
设置标志位(操作数1 & 操作数2) | CF=0,OF=0,SF,ZF | 权限检查绕过 | |
| 栈操作 | PUSH |
PUSH 源 |
1. ESP -= 4/8 2. [ESP] = 源 | 无影响 | 栈帧构造 |
POP |
POP 目标 |
1. 目标 = [ESP] 2. ESP += 4/8 | 无影响 | ROP gadget利用 | |
| 系统调用 | INT |
INT n |
触发软件中断 | 影响所有 | 系统调用利用 |
SYSCALL |
SYSCALL |
快速系统调用 | 影响所有 | 现代漏洞利用 |
关键指令深度解析
MOV vs LEA
; MOV - 内存访问 |
Pwn应用:LEA常用于计算地址偏移,绕过ASLR
CMP与条件跳转
cmp eax, 100 ; 比较eax和100 |
标志位关系:
| 跳转指令 | 含义 | 检查标志 |
|---|---|---|
JE/JZ |
相等/零 | ZF=1 |
JNE/JNZ |
不等/非零 | ZF=0 |
JG/JNLE |
大于 | ZF=0且SF=OF |
JL/JNGE |
小于 | SF≠OF |
CALL-RET 机制
call func: ; 相当于 |
漏洞利用:缓冲区溢出覆盖返回地址
栈操作指令
; 函数序言 |
Pwn意义:栈帧结构是缓冲区溢出的基础
TEST指令妙用
test eax, eax ; 检查eax是否为0 |
汇编与高级语言的对应关系
C 语言与汇编(x86-64)的简单映射示例:
int add(int a, int b) { |
; add函数 |
第一二章 前言-汇编的概念:http://fynote.com/s/3251
第三章 寄存器:http://fynote.com/s/3269
第四章 汇编程序:http://fynote.com/s/3315
第五章 汇编指令:http://fynote.com/s/3354
