自写反汇编引擎(一)——Intel指令编码

自写反汇编引擎(一)——Intel指令编码


资料:
1.Intel指令手册
2.打造自己的反汇编引擎——Intel指令编码学习报告(https://wenku.baidu.com/view/8557a44d2b160b4e767fcf0d.html)
3.****核心原理(49.IA-32)

写在文章前的一些话:这篇文章是我编写完反汇编引擎后的有感而发,也是一种整理总结并将自己的经验分享出来。相信很多学习逆向的朋友与我一样,都会有那么一段时间去编写一个反汇编引擎以巩固自己对于机器语言与汇编语言的学习,而事实也证明这样确实能加强我们的能力。学习反汇编引擎的编写是十分有意义的,同时也是十分枯燥的,所以在此我还要说一点,那就是希望大家不要抱以一种“反正市面上已经有了许多很完善的反汇编工具”的态度来学习,因为那样你是往往不能坚持下来的。我们学习的目的不是为了学习而学习,而是去弥补自己的不足,从无到有的过程,而这样的过程有何尝不是一种对自己的锻炼?所以,加油吧!

在正式开始编写反汇编引擎之前,也是最重要的一点,那就是需要大家先学会查询IA-32指令,这是最重要的一点,如果连这一步都不会,那整个过程将无从下手。

一、IA-32指令

1、IA-32指令指IA-32(Intel Architecture 32位)系列CPU使用的指令。

2、IA-32指令的格式由6部分组成:
自写反汇编引擎(一)——Intel指令编码
自写反汇编引擎(一)——Intel指令编码
ModR/M = Mod + Reg/Opcode + R/M;
SIB = Scale + Index + Base

二、分析结构

(一) 指令前缀

可选项,对特定的操作码的补充说明

  • 段寄改写与分支前缀:
2E     CS 
36     SS 
3E     DS 
26     ES 
64     FS 
65     GS 
2E     分支未实现 
3E     分支实现
- 操作数大小改写前缀 : 
F0    Lock 
F2    REPNE/REPNZ (cmps,scas) 
F3     REP    (movs,ins outs,lods,stos) 
REPE/REPZ                (cmps,scas)
- 地址大小改写前缀 : 
66     改变操作数大小
- 重复与锁前缀 : 
67     改变寻址方式

(二) 操作码

用来实际表示的指令,长度为1~3字节,种类有寄存器、内存地址、常量。

(三) ModR/M

可选项,辅助说明操作码的操作数(操作数的个数、种类【寄存器】、地址、常量)
自写反汇编引擎(一)——Intel指令编码
ModR/M有一个字节(8位)长度,分为三个长度(如上图)
EX:ModR/M = F4,二进制为11110100,ModR/M拆分 = 11/110/100(Mod:11,Reg:110,R/M:100)

(四) SIB

可选项,辅助说明ModR/M,当操作码为地址时需要与操作数一起使用。
自写反汇编引擎(一)——Intel指令编码
SIB有一个字节(8位)长度,分为三个长度(如上图)
EX:SIB = C4,二进制为11000100,SIB拆分 = 11/110/100(Scale:11,Index:000,Base:100)

(五) 位移

可选项,操作码为位移时,用来表示位移操作

(六) 立即数

可选项,操作码的操作数为常量时,该常量为立即数

三、Intel指令查询

对指令的解析需要用到Intel手册手动查询

1、解析1条长度为1的字节指令

41	inc ecx

自写反汇编引擎(一)——Intel指令编码
注:i64表示不在64位模式中,o64表示只在64位模式中,所以操作码40~47在32位作INC,64位作REX前缀

2、操作数形态

68 80A44000		push 0040A480

自写反汇编引擎(一)——Intel指令编码
由此得出68对应的指令为 push Iz ,其中Iz表示操作数的 类型。大写I表示寻址方法(立即数),z表示操作数类型(4字节)。

3、ModR/M

8BC1	mov  eax,ecx

自写反汇编引擎(一)——Intel指令编码

 8B	MOV Gv,Ev

小写字母为大小32位4字节操作数,大写字母E表示寄存器或内存地址形式,大写字母G表示只能是寄存器形式(注意当操作数的形式为E或G时,操作码后一定存在ModR/M选项)
自写反汇编引擎(一)——Intel指令编码
在ModR/M表中查询C1分别在E区域和G区域中查找,找到32位的ECX和EAX

4、Group

Group指令将操作码与ModR/M组合起来,能较好的扩展操作码映射。

83C3  12    add  ebx,12

自写反汇编引擎(一)——Intel指令编码

83    Grp1 Ev,Ib

操作数中含有E,其后紧随的是1字节的ModR/M,而Group后也跟随ModR/M,所以综合查询。(ModR/M = 11/000/011)
自写反汇编引擎(一)——Intel指令编码
根据Grp1查询Group表中对应的1位置和Reg:000定位到指令AD

再根据C3找到E区域为EBX,那么所有指令都查询完了

5、前缀

66:81FE  4578	 cmp  SI,7845

自写反汇编引擎(一)——Intel指令编码
查询到“66”表示操作数的前缀,表示“将32位大小的操作数识别为16位大小”,所以查询“66”后1字节“81”
自写反汇编引擎(一)——Intel指令编码
接下查询(Grp1A Ex,Iz),得出CMP SI,7845

6、双字节操作码

双字节操作码的第一个字节恒为0F,也就是说在查询时找到了0F就需要到双字节表继续查询下一位字节的操作码,而操作码映射的方式和单字节是一样的。
自写反汇编引擎(一)——Intel指令编码
7、位移值和立即数

在查询ModR/M表时我们会看到“disp32”的结果,它代表32位大小的位移值,而立即数也是区别于E和G 的。

C705  00FA4000  02315000  MOV [0040FA00],053102

8、SIB

SIB的查询方式与ModR/M类似,用(Scale,Index,Base)辅助寻址,在SIB表中查询(ModR/M表中带有【–】【–】)

以上就是对于IA-32指令最基本的解析,只有熟练掌握这些结构才能正真开始编写反汇编引擎,我将在下一篇文章中具体来分享我的思路,希望能对大家有所帮助。