1 抽象层次
硬件
微指令
机器码
低级语言
高级语言
解释型语言
2 逆向工程
x86 intel IA-32
可参考《汇编语言的编程艺术》
3 x86体系结构
- 中央处理器 CPU
- 内存 RAM
-
IO 硬盘 键盘鼠标 显示器
image.png
3.1 内存
数据 数据节 静态值
代码 CPU要执行的指令
堆 动态内存 在程序执行过程中动态的分配和释放
栈 保存局部变量和参数,控制程序流程
3.2 指令
3.3 操作码和字节序
x86采用小端字节序 0x42在内存为42 00 00 00
网络数据 采用 大端字节序
3.4 操作数
- 立即数 就是固定的数 如0x42
- 寄存器 如ecx
- 内存地址 [eax]
3.5 寄存器
通用寄存器
EAX
标志寄存器
ZF 当结果为0时,ZF=1
CF 当目标操作数存不下结果时(过大或过小),CF=1
SF 结果为负 SF=1, 对于算术运算,当运算结果的最高位为1时,SF位也会 被置1
TF 用于调试,当TF=1时,x86架构处理器每次只执行一条指令
可参考《Intel 64 and IA-32架构软件开发者手册》
EIP
保存着下一条要执行的指令在内存中的地址
简单指令
mov指令
mov eax,ebx
mov eax,0x42
mov eax,[0x4037C4]
mov eax,[ebx]
mov eax,[ebx+esi*4]
lea指令(load effective address)
lea destination,source
lea eax,[ebx+8] ;将ebx+8的值赋值给eax
该指令可用于计算表达式
lea ebx,[eax*5+5];等价于ebx=eax*5+5
算术运算
add destination,value
sub destination,value 若结果为0,ZF=1,或value > destination,CF=1
add eax,ebx
sub eax,0x10
inc edx
dec ecx
mul value 将eax乘以value,EDX存结果的高32位,EAX存结果的低32位
div value EDX:EAX除以value,EDX存高32位,EAX存低32位,商存储在EAX中,余数存储在EDX中
imul 和 idiv是它们有有符号数的版本
xor eax,eax 将EAX快速置0
移位操作符
shr destination,count 右移位
shl destination,count 左移位
移出的目的操作数边界上位会先移动到CF标志位上,在移位中,用填充新的位
ror destination,count 右循环移位 用移出的位填充另一端空出的位
rol destination,count 左循环移位
shl eax,n 相当eax=eax*2^n
在加密和压缩函数中会大量使用
xor,or,and,shl,shr,ror,rol这样的指令
nop指令
这条指令什么也不做,操作码为0x90,可用于填充代码
栈
先入先出的数据结构
EBP 栈基址
ESP 指向栈顶的指针
栈在内存中是自顶向下的 底在上,顶在下
相关指令有 push,pop,call,leave,enter,ret
pusha,pushad将所有的寄存器压入栈
popa,popad弹出栈
3.8 条件指令
test 同and指令但不会修改操作数 test eax,eax用于测试eax是否为0,为0为ZF=1
cmp 比较指令 同sub指令,但不改变操作数
3.9 分支指令
jmp location 无条件跳转
3.10 重复指令
用于操作数组
movsx
cmpsx
stosx
scasx
其中x可以是b,w,d,分别代码字节(8位),字(16位),双字(32位)
相关的寄存器
ESI 源索引寄存器
EDI 目的索引寄存器
ECX 用作计数
这些指令需要与前缀指令配合使用
举例
rep movsb 等价于C语言中memcpy函数
movsb将ESI指向的字节移动到EDI指向的地址,若DF=0,则ESI和EDI加1,若DF=1,则同时减1,直到ECX为0
repz cmpsb 等价于C语言中的memcmp函数
cmpsb会逐一比较ESI和EDI指向的字节,并设置标志位,直到ECX=0(比较到头了)或者ZF=0(ESI和EDI指向的数据不一致)
repne scasb 从一串字节中检索一个值,这个值由AL给出,将ESI指向的值与AL逐一作比较,直到找到该字节或ECX=0
3.11 C语言主函数和偏移
3.12
若遇到不认识的指令可参考
可在intel官网上查询
4 小结
实践出真知