1. 本质 (First Principles)
- ISA (Instruction Set Architecture):软硬件的契约 (Contract)。
- 它是软件眼中的硬件(Hardware as seen by Software)。
- 核心矛盾:在代码密度(存储空间)、硬件复杂度(解码速度)和编译器易用性之间寻找平衡。
2. 寻址方式:黑客的瑞士军刀 (Addressing Modes)
指令如何找到操作数?这决定了你如何访问内存。
| 方式 | 汇编示例 (类MIPS) | 有效地址 (EA) | 安全/逆向意义 |
|---|---|---|---|
| 立即数 | addi $1, $2, 100 | 硬编码常数,Shellcode 中用于消除 NULL 字节或设置系统调用号。 | |
| 寄存器 | add $1, $2, $3 | 最快,无访存。Shellcode 也就是在寄存器间倒腾数据。 | |
| 基址/偏移 | lw $1, 100($2) | 核心! 访问结构体成员、局部变量(基于 $fp/$sp)。栈溢出就是覆盖了栈帧中基于 $sp 偏移的返回地址。 | |
| PC相对 | beq $1, $2, label | 位置无关代码 (PIC) 的基础。Shellcode 常用它来动态获取当前地址(GetPC),绕过 ASLR。 | |
| 变址 | (x86常见) [EAX + EBX*4] | 数组访问。利用数组越界(Out-of-bound)进行任意地址读写。 |
核心公式 (必背)
- :你要跳去的目标地址(Label)。
- :当前这条
beq/bne指令的地址。- PC + 4 是因为一条指令占 32 bit,也就是 4 byte
- :机器码中存储的 16 位立即数
- 注意地址是十六进制的,不能直接除 4
3. CISC vs. RISC:架构哲学的对撞
- CISC (Complex, e.g., x86):
- 哲学:硬件包办一切。提供复杂的指令(如
memcpy对应的串操作),代码密度高。 - 代价:硬件解码器极其复杂,流水线难以优化。
- 隐喻:单体应用 (Monolith)。功能全,但臃肿。
- 哲学:硬件包办一切。提供复杂的指令(如
- RISC (Reduced, e.g., MIPS, RISC-V, ARM):
- 哲学:二八定律。只提供最常用的 20% 简单指令,复杂操作交给编译器组合。
- 特征:Load/Store 架构(只有加载/存储指令能访问内存,运算必须在寄存器)、定长指令、流水线友好。
- 隐喻:微服务 (Microservices)。原子化,组合灵活,高性能。
4. 关联链接
- Shellcode编写:如何利用 PC 相对寻址编写通用的 Shellcode?
- 栈溢出原理:理解
$sp和$fp在函数调用栈帧中的偏移关系。