4.3.3 操作码和字节序
x86使用小端字节序,即高位数放在低字节. 0x42 00 00 00 实际为0x42 在cpu中 127.0.0.1 表示为0x0100007F, 在网络数据中使用大端存储: 0x7F000001
4.3.4 操作数有三种类型
1.立即数
2.寄存器:eax
3.内存地址:[eax]
4.3.5 寄存器:
1.通用寄存器: EAX,ECX,EDX,EBX ESI,EDI,ESP,EBP
2.段寄存器: CS, SS , DS, ES, FS, GS
3.标志寄存器:ELAGS
4.指令指针:EIP
注解:乘法和除法只能使用EAX和EDX
标志寄存器 CF: 当目标操作数太大或太小是被置位,否则清零
TF: 用于调试, 当他置位时, x86处理器每次只执行一条命令
EIP:控制了eip 就控制了cpu, 通常攻击者先使攻击代码进入内存, 然后改变eip的值指向那段代码,从而攻击系统
4.3.6 简单指令
lea 是"load effective address"的简称,将一个内存地址赋值给目的操作数
lea eax,[ebx+8] 将ebp+8的值赋给eax.与其相对应的mov eax,[ebx+8] 是将ebx+8指向的内存地址的数据给eax.
而mov eax,ebx+8是不成立的, 因为在指令中除表示内存地址时(即带[])是不允许算数运算的.
lea指令还可以用来算数运算 例如:lea ebx,[eax*5+5] 等价于ebx = (eax+1)*5 用四条指令实现: inc eax, mov cx,5;mul ecx; mov ebx,eax;
算术运算:
sub destination,value . sub指令会修改zf 和 cf. 当目标操作数比value小时,cf被置位
mul指令: mul value指 将eax*value 将结果高32位放入edx中, 低32位放入eax
div指令: div value指 将edx作为高32位,eax作为低32位 然后除以 value,得到的结果 商放入eax, 余数放在ed x中
4.3.7 栈:相关的操作指令: pop push enter call leave ret
函数调用:
1.push 或者寄存器传参
2.call addr 调用,包含两个操作:1.将addr写入eip,2.将下一条质量入栈
3.push ebp 将ebp 放入内存..
4.move ebp,esp sub esp,0xxx 将原来的栈底作为栈顶,然后开辟栈空间
5.push ebx esi edi,保存现场
6.执行函数代码
7.回复现场
8.mov esp,ebp 关闭栈针
9.ret 返回 将[ebp+4]的数据放入eip
10.add esp,0xXX 平衡堆栈
4.3.8 条件指令 test和 cmp
test与and指令功能一样, 但并不会修改操作数, 只观察zf标志位 经常用来检查一个寄存器是否为0 test eax ,eax
cmp与sub指令一样.但只设置标志位. zf 和cf
cmp dst,src zf cf
dst<src 0 1
dst=src 1 0
dst>src 0 0