每个指令最短1字节,最长15字节。
经典定长指令
70 后面的立即数大于80往上跳 小于80往下跳
retf:改变同时改变CS和EIP
经典变长指令 ModR/M
0x88 MOV Eb,Gb G:通用寄存器 //第一个b说明了操作的大小是byte 例如 mov byte ptr ds:[ecx],al 第二个b 说明opcode查出来的寄存器是8位的。
0x89 MOV Ev,Gv E:寄存器/内存
0x8A MOV Gb,Eb b:字节
0x8B MOV Gv,Bv v:Word,doubleWord or quadWord
中间的Reg/Opcode决定了G位,Mod和R/M决定了E位,
mod 一共有4中情况
00 =》 [reg]
01 =》 [reg+disp8] 寄存器+8位偏移
10 =》 [reg+disp32] 寄存器+32位偏移
在表中 100 101不存在的是esp和ebp
分析 0x88 01
1:0x88 为变长指令 格式是: mov Eb,Gb
2:拆分01 00 000 001 mod=0 opcode为0 R/M为1
3:先确定G b表明了寄存器为8位,opcode决定G位 值为0 所以是al
4:确定E mod为0 查 表的上面部分 r/m为1 说明是ecx存放的内存地址
5:那么这个指令就是 mov byte ptr ds:[ecx],al
再次分析 0x89 01
1:0x88 为变长指令 格式是: mov Ev,Gv
2:在32位系统下,v是32位的 。其他分析过程与上面一样 所以这个指令是: mov dword ptr ds:[ecx],eax
7C92E45C 8801 mov byte ptr ds:[ecx],al
7C92E45E 8901 mov dword ptr ds:[ecx],eax
7C92E462 8A01 mov al,byte ptr ds:[ecx]
7C92E464 8B01 mov eax,dword ptr ds:[ecx]
SIB
注意这两个判断条件
base 就表示8个通用寄存器。
分析 88 84 48
-
88的指令格式:
0x88 MOV Eb,Gb =》b说明了是字节 mov byte ptr ds:[E],G
-
拆分84 10 000 100 中间3位是G位,G位为0,代表al
-
前面2位是2 最后三位是R/M值为4, 查表结果为[] []+disp32
-
这就说明了该指令后面还有一个SIB (数组的反汇编)
此时该指令的格式变为: mov byte ptr ds:[base+index*2scale+disp32],al // base 和index 都代表寄存器 scale代表2的多少次方
接着拆分SIB
- 01 001 000 scale:1 index:1 base:0
6. base就是8个通用寄存器 在这里是eax => 此时的指令为: mov byte ptr ds:[eax+index2scale+disp32],al
7. index 也是8个通用寄存器 在这里是1 所以就是ecx => 此时的指令为: mov byte ptr ds:[eax+ecx2scale+disp32],al
8. scale为1 那此时的指数就是1 => 此时的指令为: mov byte ptr ds:[eax+ecx*2+disp32],al
9. 这时候就指令就会从后面读取4字节的值 这个指令解析就完成了。
当index为100时,index被0替代,此时只有base有效
练习:分析89 2c 15
-
先看89 格式为:0x89 MOV Ev,Gv
-
拆分2c 00 101 100 mod=0 reg/opcode=5 R/M=4
-
因为是在32位平台下 reg/opcode=5 =》ebp而不是ch ,代表G位, 此时格式变为=》MOV E,ebp
-
查 mod=0 R/M=4=》 查出来[][] 说明此时指令后面还有sib 此时格式变为=》 mov dword ptr ds:xx,ebp
-
拆分15 00 010 101 => scale=0 index=010 base=101 => base查出来为[*] : 去手册table 2-3找
-
当base为101时:mod的值决定了格式
-
mod 为0 所以 格式变为:mov dword ptr ds:[scaled index +disp32],ebp
-
index=010 在寄存器顺序中是 edx=>mov dword ptr ds:[edx*2scale+disp32],ebp
-
scale=0 代表指数为0 2的0次方是1=>mov dword ptr ds:[edx*1+disp32],ebp =》mov dword ptr ds:[edx+disp32],ebp
-
最后从后面取4字节 该指令完成。
如何找到表2-3
打开白皮书,点击箭头处 往上翻 就能找到。
89 AC 15
如何查表
先查主表 A-2
带有Grp的 需要查a-6 后面的数字是1的话 就是查a6里面的第一组、
练习查表:80 65 08 ff
段前缀
在指令前加上段前缀,当前指令就会在相应的段里面执行。
以下为段前缀的默认值
最终项目:反汇编引擎。。。。待做