IA-32指令解析详解

0x00 前言

这段时间忙于考试,信息论和最优化,还有算法分析,有点让人头大。期间花了几天看SEH机制,能明白个大概,但是对于VC++对于SHE的包装似乎还是不是很明白,发现逆向工程核心原理对于这段写的太简单,至于加密与解密则是模棱两可,软件加密技术内幕倒是详解了,可是太老了,代码又是汇编写的总是编译不通过。真是让人难受!本来想写一篇SEH详解,但是基于以上原因暂时搁置。这两天看了逆向核心原理关于IA-32指令解析的内容,发现还是挺有意思,遂记录下来。

0x01 何谓IA-32的指令解析

其实很简单,就是把汇编的机器码解析成汇编语言的过程。下图显示了机器码和汇编代码的关系。

0x02 解析所需知识点

  1. 汇编指令的格式

汇编指令有六部分构成,如下图:

Prefix----指令前缀(可选项)

Opand----操作指令(必选项)

Mod R/M---操作数辅助说明(可选项)

SIB----Mod R/M辅助说明(可选项,但是出现Mod R/M 这个必须有)

Displacement---操作数作为内存地址时用来表示位移(可选项)

Immediate ----表示操作数为立即数(可选项)

2.重要字段简单说明

1)指令前缀prefix大小为一个字节,用来辅助说明指令的具体功能,可选项

例如:66:81FE 4746 CMP SI,474红色字体就是指令前缀,后面跟一个:。

2)操作指令opand,这个没啥好说的,必选项,大小为1到3字节,通常为一个字节,多字节后面会有说明.例如:66:81FE 4746 CMP SI,474

3)Mod R/M 大小为一个字节,由三部分组成,分别为 Mod(字节前两位),Reg(字节中间三位),R/M(字节后三位)。Mod R/M的主要功能就是说明操作数的寻址方式,包括寄存器选择,内存操作数的偏移等等。例如:66:81FE 4746 CMP SI,474

4)SIB,大小为一个字节,也是用来辅助操作数寻址的,一般用于辅助Mod R/M,当出现基址加变址寻址或者基址寻址时要用到。898424  50020000 Mov [ESP+250],EAX.

3. 为了能够顺利解析IA-32的机器码,我们应该下载Intel的开发手册,然后打印出有关指令解析的图表。下载网址为:http://www.intel.com/products/processor/manuals

选择第一个最完整的下载,如下图:

下面是我总结的应该打印的页码数:

table 2-2 32-bit Addressing forms with the ModR/M Byte, page 510

table 2-3 32-bit Addressing forms with the SIB Bytes, page 511

APPENDIX A ,page 487

A.2.1 Codes for Addressing Method

A.2.2 Code for Operand Type

Table A-2 .one –byte Opcode Maps

Table A-3.two-bytes Opcode Maps

pages :2519-2530

Table A-6 Opcode Extension for one-and Two Opcodes by Group Number

pages:2535-2537

0x03 指令解析步骤

1) 操作码映射

首先我们解析一个长度为一的操作码,对应的表是Table A-2 .one –byte Opcode Maps

指令:41,将指令拆成4和1,4对应表的行向量,1对应表列向量,如下图:

由上图可知41对应的指令为INC ECX,我们可以使用od来印证正确性。如下图:

至于为什么用寄存器ECX,是因为IA-32默认使用32位寄存器。

2) 操作数的使用

指令68 A0B44000,我们先拆分68为6和8还是使用表Table A-2 .one –byte Opcode Maps

来查找操作指令。如下图:

上图可知是push指令,操作数的寻址方式有Iz规定,我们接下来来使用code for Addressing Method和表code for opcode type 来查看具体信息,第一个大写字符I规定了寻址方式,在code for Addressing Method查找对应含义,如下图:

表示这是一个立即数。第二个小写字符z在表code for opcode type 中查找,如下图:

z表示使用的字符大小为字或者双字,由于是在32位系统中默认使用双字(使用单字的情况是使用前缀来说明),故这里是个双字,Iz一起就是表明使用双字立即数,表明指令68 A0B44000中A0B44000就是使用的双字立即数。完整的指令翻译过来就是:

Push 0004B4A0(注意汇编中的数据存储),我们也来使用od验证一下。如下图:

3) 带有Mod R/M的指令

上面两个指令都很简单,除了操作码就是操作数本身,下面来解析带有Mod R/M的指令,现在来看指令89C1。先解析89如下图:

上图可知指令是OR指令,两个操作数的说明分别是Ev和Gv,这两个使用表A.2.1 Codes for Addressing Method和表A.2.2 Code for Operand Type来查看。Ev的查询结果如下图:

这里应该主义的是,E中已经说明了要使用通用寄存器或者内存操作数,并且要使用Mod R/M来进行辅助说明,所以在操作码89后的C1就是ModR/M,Ev统一起来就是可以使用双子寄存器操作数或者双子内存操作数,具体的要使用ModR/M字段来辅助说明。我们把ModR/M字段的内容c1(1100,0001)拆成三部分:Mod:11,Reg:000,R/M:001,下面根据这个信息来查询表table 2-2 32-bit Addressing forms with the ModR/M Byte,如下图:

使用三个字段分别找到Ev对应的寄存器是ECX,Gv使用的寄存器是EAX,因此完整指令应该为89C1 OR ECX,EAX,用od验证如下图:

4) 带有Group指令解析

Group指令与ModR/M结合使用。Group给指令带来了更为丰富的变化,也是的指令解析更为复杂。例如:83C3 12,先解析83,如下图:

上图可以看出该指令带group指令。对于group指令我们还需查询表Table A-6 Opcode Extension for one-and Two Opcodes by Group Number。我们使用ModR/M(C3=1100,0011)的第二个字段Reg(000)来查询,如下图:

对应的指令为ADD,结合来看指令大致为ADD Ev,Ib,再根据ModR/M字段值C3得出指令为ADD EBX,12。

5) 指令前缀的使用

指令前缀主要来辅助说明操作码的,比如前缀66就会规定指令为16位形式。前缀的形式一般都是:前缀:操作码(这里是显示形式,其实在od中编写不用写符号:但是显示会出现符号:)。

接下来来示范解析带有前缀的指令 66:81FE 3412。前缀66的信息查询也是在表

Table A-2 .one –byte Opcode Maps(单字节操作码查询表)中如下图:

上图表示操作码的size位16位,接下来继续解析81,如下图:

说明还要使用ModR/M(FE=1111,1110)的字段Reg(111)表Table A-6 Opcode Extension for one-and Two Opcodes by Group Number来查询Group信息。如下图:

因此指令的形式是CMP Ev,Ib,由于前缀规定使用16位操作数,所以指令解析为:

66:81FE 3412 CMP SI,1234(指令为16位的)。

6) 双字节操作码的解析

双字节操作码很好分辨,指令的第一个字节为0F,指令映射参考表Table A-3.two-bytes Opcode Maps。接下来我们来解析指令0F85 FA1F0000。先解析0F,查询表Table A-2 .one –byte Opcode Maps可得下图:

可知这是一个双字节操作数,其实双操作数的第一个字节都是0F,再来查询85,我们使用表Table A-3.two-bytes Opcode Maps。如下图:

由上图可知这是一个条件跳转指令,而且是长跳转,JCC +NE/NZ=JNE指令。Long型表明跳转地址为四个字节。这里还需特别注意的是:机器码0F85 FA1F0000的四个字节是相对地址,要正确解析出指令还需算出实际的跳转地址。公式为:实际地址=当前地址+指令大小+相对地址。我们用OD实际的运算一下:选定当前的地址是010073ee,则解析后的实际跳转地址=010073ee+6(指令大小为五个字节)+00001FFA= 01008EEE,所以完整的指令解析为:

JNZ 01008EEE。如下图:

7) 同时含有位移值和立即数的情况

例如指令:C705 00CF4000 01000100

首先解析C7,如下图:

这是一个含有group的指令,ModR/M为05(0000,0101),其中Reg值为:000,根据Reg值查询group表,如下图:

由此可见指令的形式为MOV  Ev,Iz,Ev表示使用ModR/M规定的寄存器双字或者内存双字。Iz表示立即数双字。下面使用ModR/M来确定具体的寻址方式,查询ModR/M表,如下图:

因此第一个操作数使用的32位内存操作数,默认的段寄存器是DS,第二个操作数是立即数。完整解析指令为:Mov DWORD DS:[40CF00],10001.

8) 使用SIB的情况

SIB也是用来辅助寻址的,主要针对基址寻址和基址加变址寻址。

那如何来判断指令是否使用了SIB呢?

且看指令8B0C01 ,先解析8B,如下图:

指令形式为MOV Gv,Ev。Gv表示ModR/M规定的双字寄存器数,Ev表示使用ModR/M规定的双子寄存器数或者双字内存数。接下俩解析ModR/M,字段值为0C(00001100),查询ModR/M表可得下图:

由上图可得指令的基本结构为MOV ECX,[Reg.A+Reg.B]。对于这种结构的寻址方式就要用到SIB辅助寻址,指令中的SIB=01,拆成三个字段scale=00,Index=000,base=001,查询表table 2-3 32-bit Addressing forms with the SIB Bytes如下图:

因此完整的解析指令为:8B0C01 MOV ECX,DWORD PTR DS:[ECX,EAX],使用OD验证一下,如下图:

以上就是解析IA-32机器码时会遇到的所有情况,掌握了这些解析机器码不成问题。

0x04 感想

IA-32指令解析本身不是很难,只要多多练习就能提高。还有就是解析是碰到内存操作数最好还是使用PTR说明符,虽然有些情况下可以不适用,但是OD默认的情况是碰到内存操作数就是用PTR。这点需要注意。

IA-32指令解析详解的更多相关文章

  1. SSI指令使用详解(转)

    什么是 SHTML使用SSI(Server Side Include)的html文件扩展名,SSI(Server Side Include),通常称为“服务器端嵌入”或者叫“服务器端包含”,是一种类似 ...

  2. MySQL-5.5.32 配置文件优化详解

    目录 MySQL-5.5.32 配置文件优化详解 一.配置文件说明 2.my-medium.cnf 3.my-large.cnf 4.my-huge.cnf 5.my-innodb-heavy-4G. ...

  3. ng-repeat指令使用详解

    ng-repeat指令使用详解 link: function(scope,element,attr) scope.$index: if(scope.$last == true){} attr['mng ...

  4. Java中String的intern方法,javap&cfr.jar反编译,javap反编译后二进制指令代码详解,Java8常量池的位置

    一个例子 public class TestString{ public static void main(String[] args){ String a = "a"; Stri ...

  5. android Json解析详解

    JSON的定义: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语 言的支持),从而可以在不同平台间进行数 ...

  6. android Json解析详解(详细代码)

    JSON的定义: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据 ...

  7. Spring IoC componet-scan 节点解析详解

    前言 我们在了解 Spring 容器的扩展功能 (ApplicationContext) 之前,先介绍下 context:componet-scan 标签的解析过程,其作用很大是注解能生效的关键所在. ...

  8. vue自定义指令VNode详解(转)

    1.自定义指令钩子函数 Vue.directive('my-directive', {bind: function () {// 做绑定的准备工作// 比如添加事件监听器,或是其他只需要执行一次的复杂 ...

  9. AngularJS指令的详解

    指令作为AngularJS中最为重要的部分,所以这个框架本身也是自带了比较多的的指令,但是在开发中,这些指令通常不能满足我们的需要,所以我们也是需要自定义一些指令的.指令是我们用来扩展浏览器能力的技术 ...

随机推荐

  1. jenkins+svn 自动化上线

    一.环境: [root@bimvm01 ~]# cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core) [root@bimvm01 ~ ...

  2. SqlServer下一些实用的sql语句收集

    清理数据库日志 USE [master] ALTER DATABASE [表名] SET RECOVERY SIMPLE WITH NO_WAIT ALTER DATABASE [表名] SET RE ...

  3. mysql安装过程以及遇到问题的解决方法

    因为工作原因,配备了新电脑,需要装mysql,今天给大家分享一下安装的过程以及遇到的问题(在此仅介绍压缩包解压方式的安装) 1.准备mysql的压缩包(我使用的是5.7经典版本) 2.配置环境变量,这 ...

  4. SimpleDateFormat 和 Calendar 对于时间的处理

    import java.text.SimpleDateFormat;import java.util.Date;public class test { public static void main( ...

  5. pytorch入门2.1构建回归模型初体验(模型构建)

    pytorch入门2.x构建回归模型系列: pytorch入门2.0构建回归模型初体验(数据生成) pytorch入门2.1构建回归模型初体验(模型构建) pytorch入门2.2构建回归模型初体验( ...

  6. 使用VBS实现SSH远程登录并自动执行命令

    set ws=createobject("wscript.shell")ws.run "Putty所在路径\putty.exe -ssh -pw 你的密码 用户名@192 ...

  7. TensorFlow从0到1之TensorFlow超参数及其调整(24)

    正如你目前所看到的,神经网络的性能非常依赖超参数.因此,了解这些参数如何影响网络变得至关重要. 常见的超参数是学习率.正则化器.正则化系数.隐藏层的维数.初始权重值,甚至选择什么样的优化器优化权重和偏 ...

  8. java中工厂模式

    最近在项目中使用了工厂模式来重构下之前的代码,在这里做个小结. 工厂模式最主要的特点是每次新增一个产品的时候,都需要新增一个新的工厂,这样在对于新的产品做扩展的时候,减少对客户端代码的修改. 我在项目 ...

  9. IP地址和端口

    IP地址是网络中计算机的唯一标识.没有IP地址,计算机无法接入互联网. IPv4地址32bit,用点分十进制表示,如202.38.64.3 IPv6地址128bit,用冒号分割十六进制表示,如2001 ...

  10. for, for in, for of, map, forEach 循环的区别:

    for, for in,  for of, map, forEach 循环的区别: for  遍历数组: //对象遍历数组 var arr = [ {Monday: '星期一', Tuesday: ' ...