不可不知的反汇编相关知识澳门威尼斯人网址,基于AMuranoM处理器的反汇编器软件简单设计及落到实处

写在前方

2013年写的毕业设计,仅供参考

写在前边

二零一三年写的结束学业设计,仅供参考

大家都通晓编制程序语言有几许代,那她们都以什么样

反汇编的指标

缺乏有个别须求的认证材质的气象下,
想取得有个别软件系统的源代码、设计思想及理念, 以便复制, 改造、移植和升高;

从源码上对软件的可靠性和安全性展开表明,对那一个一向与CPU
相关的对象代码实行安全性分析;

澳门威尼斯人网址 1

反汇编的指标

缺点和失误某个供给的表明资料的动静下,
想赢得某个软件系统的源代码、设计思想及理念, 以便复制, 改造、移植和发展;

从源码上对软件的可信赖性和安全性举办求证,对那多少个直接与CPU
相关的目的代码举办安全性分析;

澳门威尼斯人网址 2

最低级的语言,1般有0和一结合,人很难讲指令和数据区分开也称机器语言,字节码,二进制文件

关系的首要内容

  1. 分析A凯雷德M处理器指令的性状,以及编写翻译现在可实施的贰进制文件代码的特征;
  2. 将贰进制机器代码通过指令和数据分开模块的加工处理;
  3. 释疑标识出指令代码和数码代码;
  4. 然后将下令代码反汇编并加工成易于阅读的汇编指令格局的公文;

下边给出个示范,汇编源代码,对应的二进制代码,以及对应的反汇编后的结果

源代码:

澳门威尼斯人网址 3

二进制代码:

澳门威尼斯人网址 4

 

反汇编后的结果:

澳门威尼斯人网址 5

 

反汇编软件要马到成功的行事就是在指令和数据混淆的2进制BIN文件中,分解并标识出指令和数据,然后反汇编指令部分,获得易于阅读的汇编文件,如下图:

澳门威尼斯人网址 6

论及的首要性内容

  1. 剖析AGL450M处理器指令的特征,以及编写翻译未来可举办的二进制文件代码的特点;
  2. 将二进制机器代码通过指令和数据分开模块的加工处理;
  3. 诠释标识出指令代码和数目代码;
  4. 接下来将指令代码反汇编并加工成易于阅读的汇编指令情势的文件;

上边给出个示范,汇编源代码,对应的2进制代码,以及相应的反汇编后的结果

源代码:

澳门威尼斯人网址 7

2进制代码:

澳门威尼斯人网址 8

 

反汇编后的结果:

澳门威尼斯人网址 9

 

反汇编软件要成功的做事便是在指令和数据混淆的2进制BIN文件中,分解并标识出指令和数据,然后反汇编指令部分,拿到易于阅读的汇编文件,如下图:

澳门威尼斯人网址 10

汇编语言,他退出了机器语言的0和一,使用短小且便于回忆的助记符对应相应的操作码。汇编器是将汇编转为机器码的工具

A帕杰罗M种类布局及指令编码规则分析

略,请参考相关质地,如ACR-VM Limited. AMuranoM Architecture Reference 马努al
[EB/OL]. http://infocenter.arm.com/等;

驷不比舌可参考下图,A汉兰达M指令集的编码:

澳门威尼斯人网址 11

A大切诺基M类别布局及指令编码规则分析

略,请参见相关资料,如AOdysseyM Limited. A汉兰达M Architecture Reference 马努al
[EB/OL]. http://infocenter.arm.com/等;

首要可参照下图,A途乐M指令集的编码:

澳门威尼斯人网址 12

引入了重点字和协会来描述事物,使得他采用起来特别切近自然语言。他们日常不依赖任何平台,如:C,Java

A普拉多M可进行二进制BIN文件分析

眼前重视的A帕杰罗M可执行文件系列:

ELF文件格式:Linux系统下的一种常用、可移植目的文件格式;

BIN文件:直接的贰进制文件,内部尚未地址标记,里面包含了纯粹的贰进制数据;一般用编制程序器烧写时,从0起首,而一旦下载运维,则下载到编写翻译时的地点即可;

HEX格式:英特尔HEX文件是记录文本行的ASCII文本文件;

本文主要切磋BIN文件的反汇编;

BIN印象文件的结构

  A冠道M程序运行时饱含RO,科雷傲W,ZI3片段内容,RO(READONLY),是代码部分,即一条条下令,奥德赛W(READWHavalITE),是数量部分,ZI,是未初始化变量。当中RO和卡宴W会包蕴在印象文件中,因为1个顺序的运维是亟需指令和数据的,而ZI是不会含有在影象文件的,因为内部多少都为零,程序运维前会将那1部分数量初叶化为零。
  A君越M印象文件是3个层次性结构的公文,蕴涵了域(region),输出段(output
section)和输入段(input
section)。1个影像文件由1个要么八个域组成,每一个域最多由四个出口段(RO,福睿斯W,IZ)组成,各种输出段又带有三个要么七个输入段,各样输入段包涵了对象文件中的代码和数码。

  • 域(region):二个影象文件由二个或八个域组成。是组成映象文件的最大结构。所谓域指的就是整套bin印象文件所在的区域,又分为加载域和平运动行域,一般大约的顺序唯有3个加载域。
  • 输出段(output section):有七个输出段,RO和昂CoraW。
  • 输入段(input
    section):四个输入段,CODE和DATA部分,CODE部分是代码部分,只读的属于RO输出段,DATA部分,可读可写,属于瑞鹰W输出段。

ALANDM的BIN影象文件的结构图

澳门威尼斯人网址 13

举1个例子,ADS1.2自带的examples里的主次

AREA Word, CODE, READONLY       ; name this block of code
num     EQU     20                ; Set number of words to be copied
        ENTRY                     ; mark the first instruction to call
start
        LDR     r0, =src            ; r0 = pointer to source block
        LDR     r1, =dst            ; r1 = pointer to destination block
        MOV     r2, #num            ; r2 = number of words to copy
wordcopy
        LDR     r3, [r0], #4            ; a word from the source
        STR     r3, [r1], #4            ; store a word to the destination
        SUBS    r2, r2, #1             ; decrement the counter
        BNE     wordcopy             ; ... copy more
stop
        MOV     r0, #0x18           ; angel_SWIreason_ReportException
        LDR     r1, =0x20026        ; ADP_Stopped_ApplicationExit
        SWI     0x123456            ; ARM semihosting SWI
        AREA BlockData, DATA, READWRITE
src      DCD     1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4
dst      DCD     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
        END

能够看看,该程序由两局地组成,CODE和DATA,即代码部分和数据部分。在那之中代码部分,READONLY,属于RO输出段;数据部分,READWRAV4ITE,属于RO输出段。

接下去再看看上述代码通过编写翻译生成的BIN影象文件的贰进制格局,及该影象文件反汇编后的汇编文件,如下图:

澳门威尼斯人网址 14   
澳门威尼斯人网址 15

  从图中大家很不难发觉,BIN文件分为了两部分,指令部分和数目部分。先看一下左图,从中咱们发现,BIN文件的首先条指令编码是0xe5玖f0020,即右图中的00000000h到0000000三h,由于存款和储蓄方式的缘故,小端形式,指令的低字节存放在低地址部分,不过那不影响大家的分析。在BIN文件中从00000000h起初一向到000000贰柒h都以命令部分,即RO输出段,最终一条指令0xef12345陆仓库储存在在BIN文件的000000二4h到0000002七h。剩下的为数量部分,即LANDW输出段,有趣味的读者能够对照源代码1一查找之间的附和关系。

AMuranoM可进行二进制BIN文件分析

时下根本的ACRUISERM可执行文件体系:

ELF文件格式:Linux系统下的一种常用、可移植指标文件格式;

BIN文件:直接的贰进制文件,内部尚未地址标记,里面包涵了纯粹的2进制数据;1般用编制程序器烧写时,从0初步,而1旦下载运营,则下载到编写翻译时的地点即可;

HEX格式:英特尔HEX文件是记录文本行的ASCII文本文件;

本文重要商讨BIN文件的反汇编;

BIN影像文件的协会

  ARM程序运维时饱含RO,奥迪Q伍W,ZI三有个别内容,RO(READONLY),是代码部分,即一条条指令,途锐W(READW汉兰达ITE),是数额部分,ZI,是未开端化变量。在那之中RO和瑞鹰W会包蕴在影象文件中,因为三个主次的周转是内需指令和数据的,而ZI是不会含有在影像文件的,因为中间多少都为零,程序运营前会将那有的数量初叶化为零。
  ALacrosseM印象文件是多个层次性结构的文书,包罗了域(region),输出段(output
section)和输入段(input
section)。四个影像文件由1个要么三个域组成,每一种域最多由三个出口段(RO,WranglerW,IZ)组成,各样输出段又含有1个要么四个输入段,各种输入段蕴涵了对象文件中的代码和数据。

  • 域(region):三个影像文件由3个或四个域组成。是结合映象文件的最大结构。所谓域指的就是任何bin影象文件所在的区域,又分为加载域和平运动行域,1般差不离的顺序唯有二个加载域。
  • 输出段(output section):有四个输出段,RO和昂CoraW。
  • 输入段(input
    section):多少个输入段,CODE和DATA部分,CODE部分是代码部分,只读的属于RO输出段,DATA部分,可读可写,属于LANDW输出段。

A大切诺基M的BIN影像文件的结构图

澳门威尼斯人网址 16

举1个例子,ADS一.二自带的examples里的主次

AREA Word, CODE, READONLY       ; name this block of code
num     EQU     20                ; Set number of words to be copied
        ENTRY                     ; mark the first instruction to call
start
        LDR     r0, =src            ; r0 = pointer to source block
        LDR     r1, =dst            ; r1 = pointer to destination block
        MOV     r2, #num            ; r2 = number of words to copy
wordcopy
        LDR     r3, [r0], #4            ; a word from the source
        STR     r3, [r1], #4            ; store a word to the destination
        SUBS    r2, r2, #1             ; decrement the counter
        BNE     wordcopy             ; ... copy more
stop
        MOV     r0, #0x18           ; angel_SWIreason_ReportException
        LDR     r1, =0x20026        ; ADP_Stopped_ApplicationExit
        SWI     0x123456            ; ARM semihosting SWI
        AREA BlockData, DATA, READWRITE
src      DCD     1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4
dst      DCD     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
        END

能够看出,该程序由两有个别组成,CODE和DATA,即代码部分和数码部分。当中代码部分,READONLY,属于RO输出段;数据部分,READWKugaITE,属于RO输出段。

接下去再看看上述代码通过编写翻译生成的BIN影象文件的2进制方式,及该映像文件反汇编后的汇编文件,如下图:

澳门威尼斯人网址 17   
澳门威尼斯人网址 18

  从图中大家很不难察觉,BIN文件分为了两有的,指令部分和多少部分。先看一下左图,从中我们发现,BIN文件的首先条指令编码是0xe5玖f0020,即右图中的00000000h到0000000三h,由于存款和储蓄格局的原由,小端形式,指令的低字节存放在低地址部分,可是那不影响我们的剖析。在BIN文件中从00000000h起初一贯到000000二柒h都以命令部分,即RO输出段,最终一条指令0xef12345陆储存在在BIN文件的000000二4h到00000027h。剩下的为数量部分,即福睿斯W输出段,有趣味的读者能够对照源代码1壹查找之间的附和关系。

观念软件开发进度中,一般是编写翻译器-汇编器-链接器最终输出可执行程序。所以反汇编就是输入2进制文件或可执行文件输出汇编代码的进度。反编译器平日是出口高档语言

AOdysseyM反汇编软件设计要解决的重大难点

壹、指令与数码的分别

  冯·诺依曼机器中指令和数据是不加不同共同存款和储蓄的,以 0、1二进制编码方式存在的指标代码对于分析职员的话,很难读懂其含义。2进制造进度序中指令和数据混合存放,按地址寻址访问,反汇编尽管运用线性扫描策略,将无法看清读取的二进制编码是命令仍旧多少,从而不可能落成指令和数据的离别。
  那么,怎么样才能达成指令和数据的分手?
  深入人心,凡是指令,控制流是必经之处,凡是数据,数据流是必到之处,存取指令一定会访问,对于一般指令,控制流是按地址顺序递增而走向的,唯有在产出各样转移指令时,控制流才出现相差。由此,抓住控制流那壹端倪,即跟踪程序的控制流[9]走向而遍历整个程序的每一条指令,从而完毕指令与数量分开的指标。
    怎么样才能跟踪程序的控制流呢?
  一般的话控制流与操纵转移指令有关,控制转移指令一般可分为两大类:

  1. 单分支指令,即直接跳转,如B;BL;MOV PC,**;LDR PC,**等等;
  2. 双拨出指令,有规范的跳转,如BNE;MOVNE  PC,**等等

       澳门威尼斯人网址 19

  当该指令为双拨出指令时,会有八个换车地址,大家把尺度满意时的转折地址称为显示地址,条件不知足时的地址称为隐式地址。
     在跟踪控制流的经过中,还要设置多个表:
  (1)段表,将具有转移指令除条件转移的变换地址填入此表包含本指令地址和转化地址。其实能够不要这些表,但是加进去,会拿走若干段的代码段,相比清晰明了。
  (二)返回表,用于记录程序调用时的回来地址。
  (三)显示表,遇到双支行指令时,将其出示地址和现场(程序各寄存器的值)填入该表中。
  以上都准备好以往,就能够开首跟踪程序控制流了具体步骤如下:

    (1)将顺序的发端地址填入段表,且作为当下地点。
  
 (二)按如今地方逐条分析指令类型,若非无条件转移指令及二分支指令,则直到终结语句并转(7),
不然转(三)。
    (三)若为无条件转移指令(B指令,MOV
PC,0x16等),则将此命令所在地方填段表,其显式地址填段表,且将显式地址作为当前地方,然后转(二),不然转(4)。
  
 (四)若为无条件转移指令子程序调用指令(BL指令),则将此命令所在地点填段表,再次来到地址和现场新闻填入再次回到表,显式地址填段表,且将显式地址作为当下地点,然后转
(二), 不然转(5)。
    (5)若为无条件转移指令中的重临指令(MOV
PC,LSportage),则在回到地址表中按“后进先出”原则找到重返地址,将此命令所在地方填段表,其归来地址填段表,且将回来地址作为当前地点,然后转(2),不然转(陆)。
    (六)若为2叉点指令(BEQ,MOVEQ PC,0x1陆之类),
则将显式地址和现场信息填入显式表,然后将隐式地址作为当下地点转(二)。
  
 (7)判显式表空否,若空则算法终止,不然从显式表中按“先进先出”顺序取出2个显式地址作为当下地方,且苏醒及时的当场音信转(2)。

  经过上述处理,可以遍历到持有的授命,且当访问到该条指令后,要把改地址处的吩咐标记为命令。接下来能够使用线性扫描策略,当遭逢标记为命令的二进制代码时,把它反汇编成汇编指令即可。

  但是,在落成跟踪程控流进度中还有三个相比较难处理的题材,正是直接转移类指令的拍卖,因为那类指令的转移地址隐含在寄存器或内部存款和储蓄器单元中,无法由指令码自身判断其值,而且这一个富含在寄存器内或内部存款和储蓄器单元中的值往往在程序执行时,被动态地展开安装或涂改,因而很难判断那类指令的转移地址,从而难以完全的规定程序的指令区。
  
 本软件处理这一个题材的法子是安装四个寄存器全局变量,在紧跟程控流的过程中,实时更新各寄存器的值,因而能够规定那类指令的更换地址。

二、代码部分的反汇编

  A哈弗M指令集中的每天指令都有3个对应的2进制代码,怎样从二进制代码中翻译出对应的通令,即代码部分反汇编所要马到功成的行事。

  AHummerH二M 指令的壹般格式能够表示为如下格局:

  <opcode>{condition}{S}<operand0>{!},<operand1>{,
<operand2>}

  指令格式中<·>符号内的项是必须的,{·}符号内的项是可选的,/
符号表示选中间之1,当中opcode 表示指令操作符部分,后缀 conditon、S
及!构成了命令的尺度词,operand0、operand1、operand二为操作数部分。指令反汇编正是将下令的各组成都部队分解析出来。

  为了使指令反汇编排轮更值夜班加清晰、高效,能够行使分类的惦念格局来化解该难点,把这2个拥有同样编码特征的吩咐分成同一种档次的一声令下,然后为每一类指令设计1个与之对应的处理函数。

  指令的反汇编的手续,首先是判定哪条指令,可以由操作符及那多少个固定位来规定,然后是指令条件域的翻译,那么些与2进制编码也有唯1的呼应关系,然后操作数的翻译,在操作数的翻译进程中,或者波及到各样操作数的乘除情势,移位操作等情景。

ALacrosseM反汇编软件设计要缓解的重点难题

壹、指令与数据的分离

  冯·诺依曼机器中指令和数据是不加差距共同存款和储蓄的,以 0、1
2进制编码格局存在的靶子代码对于分析人士来说,很难读懂其意义。二进制造进度序中指令和数据混合存放,按地址寻址访问,反汇编固然选取线性扫描策略,将不能够判断读取的二进制编码是命令依然多少,从而不能兑现指令和数据的分别。
  那么,如何才能达成指令和数据的诀别?
  威名昭著,凡是指令,控制流是必经之处,凡是数据,数据流是必到之处,存取指令一定会造访,对于一般指令,控制流是按地址顺序递增而走向的,唯有在出现各个转移指令时,控制流才出现相差。由此,抓住控制流那一线索,即跟踪程序的控制流[9]走向而遍历整个程序的每一条指令,从而达成指令与数码分开的指标。
    怎么着才能跟踪程序的控制流呢?
  一般的话控制流与控制转移指令有关,控制转移指令一般可分为两大类:

  1. 单分支指令,即直接跳转,如B;BL;MOV PC,**;LDR PC,**等等;
  2. 双支行指令,有规范的跳转,如BNE;MOVNE  PC,**等等

       澳门威尼斯人网址 20

  当该指令为双拨出指令时,会有多少个换车地址,大家把规范满意时的转账地址称为显示地址,条件不满意时的地方称为隐式地址。
     在跟踪控制流的经过中,还要设置多少个表:
  (1)段表,将兼具转移指令除条件转移的转移地址填入此表包蕴本指令地址和中间转播地址。其实能够不要这么些表,然则加进去,会获取若干段的代码段,相比较清晰明了。
  (贰)重回表,用于记录程序调用时的回到地址。
  (3)呈现表,遇到双分段指令时,将其出示地址和现场(程序各寄存器的值)填入该表中。
  以上都准备好之后,就能够开首跟踪程控流了具体步骤如下:

    (壹)将先后的前奏地址填入段表,且作为当前地方。
  
 (2)按时下地点逐条分析指令类型,若非无条件转移指令及二分支指令,则直到终结语句并转(七),
不然转(3)。
    (3)若为无条件转移指令(B指令,MOV
PC,0x16等),则将此命令所在地点填段表,其显式地址填段表,且将显式地址作为当下地点,然后转(二),不然转(四)。
  
 (四)若为无条件转移指令子程序调用指令(BL指令),则将此命令所在地点填段表,重回地址和现场消息填入再次回到表,显式地址填段表,且将显式地址作为当前地方,然后转
(二), 不然转(5)。
    (五)若为无条件转移指令中的再次回到指令(MOV
PC,LR),则在回到地址表中按“后进先出”原则找到再次回到地址,将此命令所在地点填段表,其归来地址填段表,且将赶回地址作为当前地方,然后转(二),不然转(陆)。
    (陆)若为二叉点指令(BEQ,MOVEQ PC,0x16等等),
则将显式地址和实地新闻填入显式表,然后将隐式地址作为当前地点转(2)。
  
 (⑦)判显式表空否,若空则算法终止,不然从显式表中按“先进先出”顺序取出三个显式地址作为当前地方,且恢复生机及时的实地音信转(2)。

  经过上述处理,能够遍历到持有的吩咐,且当访问到该条指令后,要把改地址处的一声令下标记为命令。接下来能够运用线性扫描策略,当碰到标记为命令的二进制代码时,把它反汇编成汇编指令即可。

  可是,在达成跟踪程控流进程中还有2个比较难处理的题材,正是直接转移类指令的拍卖,因为那类指令的转移地址隐含在寄存器或内部存款和储蓄器单元中,无法由指令码本身判断其值,而且那几个富含在寄存器内或内部存款和储蓄器单元中的值往往在程序执行时,被动态地展开安装或涂改,由此很难判断那类指令的转移地址,从而难以完全的规定程序的指令区。
  
 本软件处理那么些题材的措施是安装五个寄存器全局变量,在紧跟程控流的长河中,实时更新各寄存器的值,由此能够规定这类指令的更换地址。

二、代码部分的反汇编

  AEscortM指令集中的每天指令都有1个对应的2进制代码,怎么样从二进制代码中翻译出对应的授命,即代码部分反汇编所要马到功成的行事。

  AHavalM 指令的一般格式能够表示为如下格局:

  <opcode>{condition}{S}<operand0>{!},<operand1>{,
<operand2>}

  指令格式中<·>符号内的项是必须的,{·}符号内的项是可选的,/
符号表示选中间之壹,个中opcode 表示指令操作符部分,后缀 conditon、S
及!构成了命令的规则词,operand0、operand一、operand2为操作数部分。指令反汇编就是将下令的各组成都部队分解析出来。

  为了使指令反汇编排轮更值夜班加清晰、高效,能够应用分类的沉思情势来解决该难题,把那二个拥有相同编码特征的一声令下分成同1种档次的一声令下,然后为每一类指令设计3个与之相应的处理函数。

  指令的反汇编的步子,首先是判定哪条指令,能够由操作符及那多少个固定位来规定,然后是指令条件域的翻译,这些与贰进制编码也有唯1的附和关系,然后操作数的翻译,在操作数的翻译进度中,大概波及到各个操作数的一个钱打二15个结格局,移位操作等情状。

机器语言未有变量或函数名,变量类型音信只好通过用途来规定,如:看到一个31人的多寡被传送到寄存器,要求很好地分析1番才能搜查缉获那是三个整数,还是浮点数或指针

A帕杰罗M反汇编软件的规划

ABMWX五M反汇编软件的总体规划设计方案如下图:

澳门威尼斯人网址 21

       当中,各模块主要完成以下职能:

  • 输入模块:要化解什么从表面文件中读取二进制格式的文书,其它对读进来的对象代码要合理协会和储存,便于接下去的延续处理。
  • 指令和数据分离模块:在内部存款和储蓄器中对读进来的二进制源代码举行分析,指令流能够抵达的壹部分标识为代码,最后剩下的下令流未经过的一对为数据,这样就分别出代码和数量。
  • 指令反汇编模块:对分离出来的代码段部分,依照各条指令编码的照应关系展开反汇编,生成目的代码对应的汇编文件,包蕴A昂科威M指令地址,ACR-VM指令,能够用于阅读。
  • 输出模块:即要将反汇编后的汇编文件展现在窗口,且能够变更文书在磁盘上。

A凯雷德M处理器反汇编软件流程

AWranglerM反汇编软件的欧洲经济共同体育工作作流程如下图所示,首先是读取目的二进制文件至内部存储器,然后接纳两次扫描的政策,第三回扫描的指标是分别指令和数据,第三次扫描是将指令部分反汇编成汇编指令方式,将数据部分直接翻译成数据,最后将结果输出突显。

澳门威尼斯人网址 22

模块设计-输入模块

输入模块的流程图如下图所示,首先从目的2进制代码中读取几个字节存放到Content对象里,再将Content对象存放到Vector容器里,然后按上述操作继续读取文件,直到文件结尾。这里有一些要表明的是,由于时日等原因,本软件只牵记三十二位ALX570M指令的反汇编,Thumb指令反汇编不会波及,所以每一次都读取多个字节。

澳门威尼斯人网址 23

模块设计-指令和多少分离模块

指令和数据分离模块的安排性如下图所示,由于指令和数据分离模块设计的基本点是跟踪程序的控制流,标识出每一条指令,所以此模块的主要便是要遍历每一条指令,而遍历每一条指令的要紧是要紧跟PC值。

澳门威尼斯人网址 24

关于段表,展现表,重回表的定义前边已经表达过了。其它,在先后流程图中的“依照实际转移指令,更新PC值,彰显表,再次回到表”,那里的具体景况如下:

(壹)若为无条件转移指令(B指令等,MOV
PC,0x16),则将此命令所在地方填段表,其显式地址填段表,且将显式地址作为当前PC地址。

(二)若为无条件转移指令子程序调用指令(BL指令),则将此命令所在位置填段表,再次回到地址填入再次来到地址表,显式地址填段表,且将显式地址作为当下PC地址

(三)若为无条件转移指令中的重回指令(MOV
PC,LBMWX伍),则在回来地址表中按“后进先出”原则找到再次来到地址,将此命令所在地点填段表,其回来地址填段表,且将回到地址作为当下PC地址。

(四)若为贰叉点指令(BEQ,MOVEQ PC,0x1⑥等等),
则将显式地址填入显式地址表(还要保存当时的寄存器值),然后将隐式地址作为当前PC地址。

模块设计-反汇编模块

在反汇编模块中除去要反汇编指令,还要翻译数据。总的设计思想是逐一从装满对象的contentVector容器中逐条取出对象,判断该指标是命令依然多少,指令的话,就反汇编成汇编指令情势,数据以来,直接翻译成数据的值,如下图所示。

澳门威尼斯人网址 25

上述流程图是总的反汇编模块,在图中的指令反汇编部分,是该模块的主要,也是整套反汇编软件设计的首要,其流程图如下图所示。

澳门威尼斯人网址 26

模块设计-输出模块

至于显示模块,相比简单,直接把结果彰显出来即可,该模块跟第四个模块反汇编模块联系最严密,在反汇编模块中,其实早已包括了输出模块。可是输出模块也有温馨的特殊职分。比如说什么以十6进制格局显得八个三11个人数(彰显地址的时候)以及如何呈现3个陆个人数(展现读进去多少的编码,因为是多个字节1个字节读进去的,存放的时候也是四个字节3个字节存放在Content对象中),如下图正是3个来得33人数的流程图。

澳门威尼斯人网址 27

A陆风X捌M反汇编软件的筹划

A索罗德M反汇编软件的总体规划设计方案如下图:

澳门威尼斯人网址 28

       在那之中,各模块首要形成以下成效:

  • 输入模块:要缓解什么从表面文件中读取二进制格式的文本,别的对读进来的目的代码要客观组织和存款和储蓄,便于接下去的三番四次处理。
  • 指令和数据分离模块:在内部存款和储蓄器中对读进来的2进制源代码进行剖析,指令流能够到达的壹对标识为代码,最后剩余的吩咐流未经过的壹些为数量,那样就分开出代码和数量。
  • 一声令下反汇编模块:对分离出来的代码段部分,根据各条指令编码的应和关系进展反汇编,生成目的代码对应的汇编文件,蕴涵ALANDM指令地址,A奥德赛M指令,能够用来阅读。
  • 输出模块:即要将反汇编后的汇编文件显示在窗口,且能够转移文书在磁盘上。

AOdysseyM处理器反汇编软件流程

A悍马H2M反汇编软件的全部育工作作流程如下图所示,首先是读取指标2进制文件至内部存款和储蓄器,然后使用五回扫描的策略,首回扫描的目标是分别指令和数据,第三次扫描是将下令部分反汇编成汇编指令格局,将数据部分直接翻译成数据,最后将结果输出展现。

澳门威尼斯人网址 29

模块设计-输入模块

输入模块的流程图如下图所示,首先从目标二进制代码中读取五个字节存放到Content对象里,再将Content对象存放到Vector容器里,然后按上述操作继续读取文件,直到文件结尾。那里有一些要注明的是,由于岁月等原因,本软件只思虑316个人A昂科拉M指令的反汇编,Thumb指令反汇编不会涉嫌,所以每一次都读取陆个字节。

澳门威尼斯人网址 30

模块设计-指令和数码分离模块

指令和数据分离模块的统一筹划如下图所示,由于指令和数据分离模块设计的机借使跟踪程序的控制流,标识出每一条指令,所以此模块的重点就是要遍历每一条指令,而遍历每一条指令的根本是要紧跟PC值。

澳门威尼斯人网址 31

有关段表,展现表,重返表的概念后边早已认证过了。其余,在程序流程图中的“根据实际转移指令,更新PC值,展现表,再次来到表”,那里的具体情状如下:

(一)若为无条件转移指令(B指令等,MOV
PC,0x1六),则将此命令所在地点填段表,其显式地址填段表,且将显式地址作为当前PC地址。

(二)若为无条件转移指令子程序调用指令(BL指令),则将此命令所在地点填段表,重回地址填入重返地址表,显式地址填段表,且将显式地址作为当下PC地址

(三)若为无条件转移指令中的重临指令(MOV
PC,LLX570),则在回来地址表中按“后进先出”原则找到重临地址,将此命令所在地点填段表,其回到地址填段表,且将重临地址作为当前PC地址。

(肆)若为二叉点指令(BEQ,MOVEQ PC,0x16之类),
则将显式地址填入显式地址表(还要保存当时的寄存器值),然后将隐式地址作为当下PC地址。

模块设计-反汇编模块

在反汇编模块中除去要反汇编指令,还要翻译数据。总的设计思想是逐1从装满对象的contentVector容器中逐条取出对象,判断该对象是命令依旧多少,指令的话,就反汇编成汇编指令格局,数据以来,直接翻译成数据的值,如下图所示。

澳门威尼斯人网址 32

上述流程图是总的反汇编模块,在图中的指令反汇编部分,是该模块的主要性,也是任何反汇编软件设计的最首要,其流程图如下图所示。

澳门威尼斯人网址 33

模块设计-输出模块

至于呈现模块,比较简单,直接把结果显示出来即可,该模块跟第多个模块反汇编模块联系最严厉,在反汇编模块中,其实早就包括了输出模块。可是输出模块也有和好的特殊职务。比如说怎么样以十陆进制方式展示二个三10人数(呈现地址的时候)以及哪些体现1个6个人数(显示读进去多少的编码,因为是3个字节二个字节读进去的,存放的时候也是1个字节2个字节存放在Content对象中),如下图便是二个来得3十四个人数的流程图。

澳门威尼斯人网址 34

就是源程序能够由此多重凡是转为汇编语言,而机器语言也可通过多重方式转为源程序

A途胜M反汇编软件的现实性实现

  A宝马7系M反汇编软件主要有八个大模块组成,贰进制可实施代码读取模块、指令和数据分离模块、指令反汇编模块、输出模块。本章节将整合程序中的源代码首要介绍APAJEROM反汇编软件各模块具体完成。由于时日等要素影响,本软件设计只思量到了A纳瓦拉M指令,THUMB指令不在思虑范围,可是事实上都以1样道理的业务,A驭胜M指令能够达成的话,THUMB指令添加进去只是岁月的难点。

1、数据协会格局

读进去的剧情的团队如下所示:

class Content
{
public:
        unsigned int            addr;                //地址
        bool                isInstruction;        //指令标记
        bool                isVisited;            //访问标记    
        bool                isHasLable;            //是否有标签标记
        unsigned int         firstB;                //第1个字节
        unsigned int         secondB;
        unsigned int         thirdB;
        unsigned int             fourthB;
};

在此类中,addr代表该内容的地址,是逻辑字节地址;isInstruction判断该内容是还是不是是指令代码;isVisited判断是还是不是被访问过;isHasLable,判断该指令前边要不要加贰个标签,firstB表示内容从左到右表示的率先个字节,secondB、thirdB、fourthB以此类推。

读源文件类

class MyRead
{
public:
           vector <Content>  contentVector;        //内容存储容器
        void readSourceFile(char * addr);        //读取源文件函数
};

剧情容器contentVector,用于存款和储蓄从源文件读进去的始末,几个字节为二个因素;readSourceFile方法,读取源文件2进制代码,并按个字节2个储存在容器里。

命令编码内容的集体

一声令下编码的团体其实依然很要紧的,好的团体章程得以大大节约后续工作的时间,后续开发照旧保卫安全都会变得更简便。由于篇幅关系,那里将介绍部分相比较常用到的授命内容的团伙。那里介绍的吩咐内容的公司都将选取结构体的花样,其实也能够用类来落到实处。

typedef unsigned  int QByte;                    //32位无符号数

(1)SWI指令

typedef struct swi                                
{
        QByte comment : 24;
        QByte mustbe1111 : 4;
        QByte condition : 4;
} SWI;

SWI指令的编码格式:

澳门威尼斯人网址 35

由指令的编码格式我们能够看看,comment的剧情表示immed_二肆,正好2二人;mustbe111壹是固定的,全体SWI指令的[27:24]都是1111,condition表示条件域,总共有1陆种景况,用几人表示即可。

(二) 分支指令

typedef struct branch {        
        QByte offset : 23;
        QByte sign : 1;
        QByte L : 1;
        QByte mustbe101 : 3;
        QByte condition : 4;
} Branch;

分层指令的编码格式:

澳门威尼斯人网址 36

从指令的编码格式中,我们发现,Offset其实是规定了转账地址的相对值;sign评释正负数;L用于分别是还是不是要把再次来到地址写入大切诺基第114中学;mustbe拾一评释那是一条分支指令,固定的,cond是条件域。

(三)加载/存款和储蓄指令

typedef struct singledatatrans {    
        QByte offset : 12;
        QByte Rd : 4;
        QByte Rn : 4;
        QByte L : 1;
        QByte W : 1;
        QByte B : 1;
        QByte U : 1;
        QByte P : 1;
        QByte I : 1;
        QByte mustbe01 : 2;
        QByte condition : 4;
} SingleDataTrans;

加载/存款和储蓄指令编码格式:

澳门威尼斯人网址 37

里头offset, I, P, U, W, 卡宴n共同决定总括出内部存款和储蓄器中的地址,Tiguand是目标寄存器,

L位用于区分是LDHighlander还是ST兰德普拉多指令;B位用于区分unsigned byte (B==一) 和 a word
(B==0)。

(4)数据处理指令

typedef struct dataproc {
        QByte operand2 : 12;
        QByte Rd : 4;
        QByte Rn : 4;
        QByte S : 1;
        QByte opcode : 4;
        QByte I : 1;
        QByte mustbe00 : 2;
        QByte condition : 4;
} DataProc;

相应的编码格式如下:

澳门威尼斯人网址 38

里面operand2是第三操作数,其计算方法也有四种格局,可参看AXC60M手册上的“Addressing
Mode 壹 – Data-processing operands on page
A伍-2”;奥迪Q伍d为指标寄存;奇骏n为率先操作数;S位用于区分是不是影响CPS大切诺基;opcode用于鲜明是那种数据操作,如MOV,ADD等;I用于分别第三操作数是寄存器情势照旧立刻数方式;mustbe00是一向的;Cond为条件域。

段表、展现表、重临表的组织

为不难起见,本程序中那些表统统用容器Vector来落到实处

typedef struct Elem{
         int re[16];
          unsigned int addr;
}Elem;
static vector <unsigned int>     segmentTable;        //段表
static vector < unsigned int >             returnAddrTable;        //返回表
static vector <Elem>         showAddrTable;        //显示表

如上所述,个中Elem结构体用于存款和储蓄展现表里面的要素。segmentTable为段表,returnAddrTable为回到表,showAddrTable为展现表。

怀有的填表操作都是用push_back
函数来贯彻的,还有正是操作显示表和再次回到表时要铭记重临表是后进先出的。

指令共用体

澳门威尼斯人网址 39澳门威尼斯人网址 40

typedef union access32 {
        QByte qbyte;
        SWI swi;                            //SWI instruction
        CPRegTrans cpregtrans;             // Coprocessor registesr transfers
        CPDataOp cpdataop;                    // Coprocessor data processing
// Coprocessor load/store and double register transfers[6]
        CPDataTrans cpdatatrans;  
//Branch and branch with link and change to Thumb
        Branch branch;                        
        Undefined4  undefined4;                //Undefined Ins[4]
        LoadStoreMultiple loadstoremultiple;    //load/store multiple
        Undefined47 undefined47;            //Undefined instruction [4,7]
        Undefined   undefined;                //Undefined instruction
//Load,store immediate offset,Load,store register offset
        SingleDataTrans singledatatrans;
        MSRImeToSReg  msrimetosreg;        //Move immediate to status register
        Undefined3    undefined3;                //Undefined instruction [3]
        DataProc dataproc;
        DataProcImmediate dataprocimme;
        MultiplyExtraLoadStore  multiextraloadstore;    //Multiplies, extra load/stores: 
        MiscellanesInstructOne    miscelinstrone;        //Miscellaneous instructions
        DataProcRegShift        dataprocregshift;
        MiscellanesInstructTwo    miscelinstrtwo;        //Miscellaneous instructions:            DataProcImmeShift     dataprocimmeshit;
} Access32;

View Code

其一命令共用体的设置相应算得13分优秀纷呈的,涵盖了富有项指标通令。在反汇编进度中,首先是从目的二进制代码中读取1个三10个人数到内存,然后将以此三二十人数从内部存款和储蓄器拷贝到共用体变量中,由于共用体的蕴藏空间是共享的,定义1个上边的共用体,其实也就只是陆个字节大小的长空,但是他得以代表任何一条指令,因而用那几个共用体变量来判断读进去的3二位数是这条指令分外便宜和直观,具体判断的将在接下去的吩咐反汇编模块介绍。

其余数据结构

协助处理理器寄存器:

static const char *cregister[16] = {    
        "cr0",  "cr1",  "cr2",  "cr3",
        "cr4",  "cr5",  "cr6",  "cr7",
        "cr8",  "cr9",  "cr10", "cr11",
        "cr12", "cr13", "cr14", "cr15"
};

寄存器:

static const char *registers[16] = {
        "R0", "R1", "R2", "R3",
        "R4", "R5", "R6", "R7",
        "R8", "R9", "R10","R11",
        "R12", "R13", "R14", "PC"
};

条件域:

static const char *condtext[16] = {
        "EQ",                    //"Equal (Z)" 
        "NE",                    //"Not equal (!Z)" 
        "CS",                    //"Unsigned higher or same (C)" },
        "CC",                    //"Unsigned lower (!C)" },
        "MI",                    //"Negative (N)" },
        "PL",                    //"Positive or zero (!N)" },
        "VS",                    //"Overflow (V)" },
        "VC",                    // "No overflow (!V)" },
        "HI",                    // "Unsigned higher (C&!Z)" },
        "LS",                    //"Unsigned lower or same (!C|Z)" },
        "GE",                    // "Greater or equal ((N&V)|(!N&!V))" },
        "LT",                    //"Less than ((N&!V)|(!N&V)" },
        "GT",                    //"Greater than(!Z&((N&V)|(!N&!V)))" },
        "LE",                    //"Less than or equal (Z|(N&!V)|(!N&V))" },
        "",                        //"Always" },         //AL,可以省略掉
        "NV"                   //, "Never - Use MOV R0,R0 for nop" }
};

数量处理指令的操作码编码,从0到一五,之所以弄成以下格局是为着扩大程序的可读性。

typedef enum operatecode
{
        AND,EOR ,SUB ,RSB                    //AND=0;    EOR=1.
           ,ADD,ADC ,SBC ,RSC
           ,TST, TEQ,CMP,CMN
           ,OPR ,MOV ,BIC,MVN
}OperCode;

数量处理指令字符:

static const char *opcodes[16] =
{
        "AND", "EOR", "SUB", "RSB",
        "ADD", "ADC", "SBC", "RSC",
        "TST", "TEQ", "CMP", "CMN",
        "ORR", "MOV", "BIC", "MVN"
};

专注里面包车型大巴逐条,要跟其编码规则对应。

贰、2进制可实施代码读取模块

2进制可进行代码的读取模块首要实现从外表文件中读取贰进制代码到内部存款和储蓄器中,并要合理协会数量。

读取函数如下所示:

澳门威尼斯人网址 41澳门威尼斯人网址 42

void MyRead::readSourceFile(char *addr)
{
        ifstream f1(addr,ios::binary);
        if(!f1)
        {
            cerr<<addr<<"不能打开"<<endl;
            return;
        }
        unsigned char x;    
        int k=0,i=0;
        while(f1.read(( char *)&x,1))
        {
            Content temp;                // 定义一个Content临时对象
            if(i==0)                
            {
                temp.fourthB=x;            //一个字里的第4个字节
            }
            else if(i==1)
            {
                temp.thirdB=x;         //一个字里的第3个字节

        }
        else if(i==2)
        {
            temp.secondB=x;    //一个字里的第2个字节
        }
        else if(i==3)                
        {
            temp.firstB=x;        //一个字里的第1个字节
        }
        i++;
        if(i==4)                
        {
            i=0;
            temp.addr=4*k;         //给地址赋值
            temp.isVisited = false;
            temp.isHasLable = false;
            k++;
            this->contentVector.push_back(temp);        //将temp存放到容器里
            Content temp;
        }
    }
    f1.close();
}

View Code

读取模块首先要做的是开拓指标文件,然后三个字节一个字节的读取进来,那里所谓的首先个字节FirstB指的是二个三拾个人数从左往右数算起率先个的,总共五个字节。然后要设置贰个Content
类型的temp中间值,将读进去的字节依次往temp赋值,赋完七个字节后,把地址,是不是访问标志等等也都早先化一下;最终将那个temp中间值压入contentVector容器中,这一个容器里面存放的正是指标代码读进去的二进制代码,多个字节为一个要素存放。

叁、指令和数据分离并标识模块

前边早已讲了指令和数据分离的驰念,重假使跟踪程序的控制流,这里讲结合程序的兑现持续证美赞臣(Meadjohnson)下。首先看一下指令和数据分离的函数。

澳门威尼斯人网址 43澳门威尼斯人网址 44

void MyDisassemble::separateI_D(MyRead &read)
{
        int k = 0;
        segmentTable.push_back(0);                        
        r[15] = 0;            //PC设为0
        disPart(read);
        while(true)
        {
            if(k == showAddrTable.size()) break;        //显示表都访问结束
            for(int i = 0;i<16;i++) r[i] = showAddrTable[k].re[i];    //恢复现场
            if(read.contentVector[((showAddrTable[k].addr)/4)].isVisited == false) 
//是否访问 
disPart(read);    
                k++;
        }
}
void MyDisassemble::disPart(MyRead &read)
{
            for(int i =r[15]/4;;i = r[15]/4)
            {
                unsigned int foo=((read.contentVector[i].firstB)<<24)+
((read.contentVector[i].secondB)<<16)+
((read.contentVector[i].thirdB)<<8)+read.contentVector[i].fourthB;
                read.contentVector[i].isInstruction = true;    //设置是指令                            read.contentVector[i].isVisited = true;    //已访问过
                disArm(foo,read);        //反汇编指令
                if ((0x0F&read.contentVector[i].firstB)==0x0f) //程序结束
                {    
                    segmentTable.push_back(r[15]);                break;
                }
                r[15]=r[15]+4;                                                }
}

View Code

上述separateI_D函数的目标是为着跟踪程序的控制流,遍历每一条指令(有点类似有向图的遍历),从而标识出指令。首先是segmentTable.push_back(0),将起首地址填入段表;然后按时下地点逐条分析指令类型disPart(read);在disPart函数中,当访问这条指令时,首先要做的是把该指令的isInstruction和isVisited标志设置为true;然后disAXC60M,disAMuranoM是反汇编函数,这一个函数可以反汇编出该条指令是哪条指令,在底下的反汇编模块将会有愈来愈详细的表明,在那边只要领会他得以分辨出是哪条指令即可。

当反汇编出来的指令是无条件转移指令时,以B指令为例,要执行以下代码:

segmentTable.push_back(r[15]);            
    segmentTable.push_back(r[15] + addr);    
r[15]=(r[15]+addr-4);    
    read.contentVector[(r[15]/4)].isHasLable = true;

r[15]指pc,r[15] +
addr为突显地址。(1)首先将此命令所在地点填入段表,(2)然后突显地址填入段表,(三)再然后展现地址作为当下地点,由于已经安装PC自动加了,所以那里先减一下,(肆)同时转向地址处的一声令下前边是一个标签,把isHasLable设置为true;

       若为无条件转移指令子程序调用指令,以BL为例,要推行以下代码:

r[14] = r[15] + 4;                    
    segmentTable.push_back(r[15]);            
    returnAddrTable.push_back(r[14]);        
    segmentTable.push_back(r[15] + addr);    
    r[15]=(r[15]+addr-4);
    read.contentVector[((r[15]+4)/4)].isHasLable = true;

各队语句的意趣依次是

(一)保存再次来到地址到奥德赛1四  

(二)此命令所在地点填入段表

(三)重临地址填入再次来到地址表

(四)彰显地址填入段表

(伍)突显地址作为当下地点,由于已经安装PC自动加了,所以那边先减一下

(陆)该地址处指令前边有个标签。

若为无条件转移指令中的重回指令,以MOV PC,L卡宴为例,如下:

unsigned int raddr;
    if(returnAddrTable.size()>0) {
            raddr = returnAddrTable[returnAddrTable.size()-1];  
return AddrTable.pop_back();
                }    
segmentTable.push_back(r[15]);            
    segmentTable.push_back(raddr);        
    r[15] = raddr-4;
read.contentVector[(raddr/4)].isHasLable = true;

次第做了以下工作,

(一)重回地址表中按“后进先出”原则找到重返地址

(2)删除再次回到表最终一个因素

(叁)指令所在地点填段表

(四)重返地址填段表

(伍)设置当前的PC值

(陆)设置标签标明

若为二分段指令,以BNE为例,如下:

Elem temp;temp.addr = r[15] + addr; for(int ii=0;ii<16;ii++) temp.re[ii] = r[ii];
    showAddrTable.push_back(temp);    
    read.contentVector[(( r[15] + addr)/4)].isHasLable = true;

次第做了以下工作,

(1)保存“现场”

(二)显式地址填入显式表(包罗当时的寄存器值)

(三)设置标签标明。

      
若不是更换指令,则继续按PC值自增下去,直到终结语句,然后还要判断呈现表是不是空,那里用了个K变量来落到实处,实际上并未当真从容器中删去取出的体现表里的要素。if(k
== showAddrTable.size())
break;用来判定是不是出示表里的地点都访问过了。如果未有,则继续按那条指令的地址disPart下去。直到把呈现表里的地址都访问三次。

      
执行完以上的代码后,就兑现了按控制流遍历每条指令,是命令的大半也都做上了标识。

4、指令反汇编模块

命令反汇编模块在宏观上海重机厂大反映在disArm这几个函数上,代码如下:

澳门威尼斯人网址 45澳门威尼斯人网址 46

 char * MyDisassemble::disArm(unsigned int uint,MyRead &read,int type)
{
    Access32 instruction;
    memcpy(&instruction, &uint,sizeof(uint));                                                        //拷贝数据
    if (0xF == instruction.swi.mustbe1111)                                                            //SWI指令 
    {
        decode_swi (instruction.swi);
    } 

    else if ( 0xE == instruction.cpregtrans.mustbe1110 )                                    // Coprocessor registesr transfers或者Coprocessor data processing
    {
        if (0x1 == instruction.cpregtrans.mustbe1)                                                //coprocessor register transfers
        {                     
            /* Coprocessor Register Transfer */
             decode_cpregtrans (instruction.cpregtrans);
        } 
        else                                                                                                        //coprocessor data processing
        {      
            /* Coprocessor Data Operation */
             decode_cpdataop (instruction.cpdataop);                                
        }
    }
    else if ( 0x6 == instruction.cpdatatrans.mustbe110  )                                        // Coprocessor load/store and double register transfers[6]
    {
        /* Coprocessor Data Transfer */
         decode_cpdatatrans (instruction.cpdatatrans);
    }
    else if ( 0x5 == instruction.branch.mustbe101 )                                                 //Branch and branch with link and change to Thumb //Branch and branch with link
    {
         decode_branch (instruction.branch,read,type);
    }
    else if (  (0xF==instruction.undefined4.condition1111) &&  ( 0x4==instruction.undefined4.mustbe100)   )    //Undefined Ins[4]
    {
         decode_unknown (instruction);
    }
    else if (0x4==instruction.loadstoremultiple.mustbe100)                                    //load/store multiple
    {
        /* load/store mutiple */
         decode_loadstoremultiple (instruction.loadstoremultiple);
    }
    else if (  (0xF==instruction.undefined47.condition1111)&& (1==instruction.undefined47.mustbe1) ) //Undefined Instruction[4,7]
    {
         decode_unknown (instruction);
    }
    else if ( (0x3==instruction.undefined.mustbe011)&& (1==instruction.undefined.mustbe1) ) //undefined Instruction
    {
        decode_unknown (instruction);
    }
    else if (0x1==instruction.singledatatrans.mustbe01)                                    //Load/Store register offset, Load /Store Immediate offset
    {
        /* Single Data  */
         decode_singledatatrans (instruction.singledatatrans,read, type);
    }
    else if ( ( 6==instruction.msrimetosreg.mustbe00110)&& (2==instruction.msrimetosreg.mustbe10)&& (0==instruction.msrimetosreg.SBO) )                            
    {                                                                                                                    //Move immediate to status register
         decode_msrimetoreg(instruction.msrimetosreg);
    }
    else if ( (0==instruction.undefined3.mustbe00)    && (1==instruction.undefined3.mustbe001)    && (2==instruction.undefined3.mustbe10) )                            
    {                                                                                                                        //undefined instruction[3]
         decode_unknown (instruction);

    }
    else if(1==instruction.dataprocimme.mustbe001)                                                //Data Processing immediate[2]
    {
         decode_dataproc (instruction.dataproc,read,type);

    }
    else if ( (0==instruction.multiextraloadstore.mustbe000)&& (1==instruction.multiextraloadstore.mustbeH1)&& (1==instruction.multiextraloadstore.mustbeL1) )                        
    {                                                                                                                    //Multipies ,extra load/stores 
        if ( 0 ==instruction.multiextraloadstore.dontcareB )
        {
            //Muptiply (accumulate
            //multiply long
            //Swap/swap byte
            //decode_multiply
            if ( 1==(instruction.multiextraloadstore.dontcareC & 0x10000))
            {
                SingleDataSwap *psingledataswap = (SingleDataSwap*)&instruction;
                if ( ( 0==psingledataswap->mustbe00)&&(9==psingledataswap->mustbe00001001) && (2==psingledataswap->mustbe00010) )
                {
                    decode_singledataswap ( *psingledataswap );
                }
            }
            else
            {
                //multiply
                Multiply*  pmultiply = (Multiply*)&instruction;
                if( (0==pmultiply->mustbe0000)&&(9==pmultiply->mustbe1001) )
                decode_multiply ( *pmultiply );
            }
        }
        else
        {//extra load store 
            decode_singledatatrans (instruction.singledatatrans, read,type);
        }
        /* Single Data Transfer */

    }
    else if ( ( 0== instruction.miscelinstrone.mustbe000)&&(0==instruction.miscelinstrone.mustbe0H)&&(0==instruction.miscelinstrone.mustbe0L)    &&(2==instruction.miscelinstrone.mustbe10)&&(1==instruction.miscelinstrone.mustbe1)     )                                
    {                                                                                                                            ///miscellaneous insturction
      decode_miscelinstrone( instruction.miscelinstrone );
    }
    else if ( (0==instruction.dataprocregshift.mustbe000)&& (0==instruction.dataprocregshift.mustbe0)     && (1==instruction.dataprocregshift.mustbe1) )                                                                                                                                                        
    {                                                                                                                    //data processing register shift[2]   
        decode_dataproc (instruction.dataproc,read,type);
    }
    else if( (0==instruction.miscelinstrtwo.mustbe000)&& (2==instruction.miscelinstrtwo.mustbe10)&&(0==instruction.miscelinstrtwo.mustbe0H)&& (0==instruction.miscelinstrtwo.mustbe0L) )                                        
    {                                                                                                                    //miscellaneous instructions;
        decode_miscelinstrone( instruction.miscelinstrone );
    }
    else if  ( (0==instruction.dataprocimmeshit.mustbe000)                                        //data processing immediate shift
        && (0==instruction.dataprocimmeshit.mustbe0 ) )
    {
         decode_dataproc (instruction.dataproc,read,type);
    }
    return (disasmstr);
}

View Code

在方今,大家已经介绍了ACR-VM指令的编码规则,从图二.第22中学,大家得以见见图中每1行都是一种指令的集和,也许说都以壹样档次的。当得到二个三十人数时,如何举办反汇编获得其汇编情势的汇编指令呢?

(一)首先将以此3一人数从内部存款和储蓄器中拷贝到instruction指令共用体变量中

memcpy(&instruction,
&uint,sizeof(uint));之所以拷贝到那一个共用体里面是因为它早已定义了独具品种的一声令下,那样相比较直观清晰。

(贰)判断该指令是哪个种类指令,那步是有肯定规则的,要从下往上那几个判断,具体可看附录里的代码,指标是为了记挂到拥有的命令。区分是哪条指令的依据是图二.第22中学的那个固定位,只要读进去的那三12人数中的某三位跟表中的那二人符合,就足以鲜明该指令属于哪壹类。比如说MOV 
r0, #0,该指令编码为0xe3a00000,由于[27:25]==001,所以为Data
processing immediate [2]那种类型,之所以不是Undefined instruction
[3](它的[27:25]==00壹),是因为在认清是还是不是Undefined instruction
[3]日前早已看清过不是了,在(一)里早就说过要从下往上判断,便是其一原因。

(叁)知道哪一类类型的下令后,要持续区分是那类别型指令里的哪条指令,然后再区分条件域,是或不是影响CP帕杰罗S\[13\],操作数等等。以(贰)里的MOV 
r0,
#0为例,由于其[24:21]==1拾1,所以可以断定其为MOV指令,条件域[31:28]==11十,表示总是执行,不需添加条件。二十个人S为0,表示不影响CPRubiconS,[15:12]==0000,表示指标寄存器为哈弗0,第三操作数也可计算得出为0.最后反汇编的结果为MOV 
r0, #0。

下边将结合程序代码重点研商一下多少处理指令中MOV指令的反汇编,因为那种指令是最普遍的,掌握了那种指令的反汇编,同她下令也可同理得出。

      
上述已经讲过,经过附录里disArm函数的论断之后,就能够精晓是哪一类指令,所在知道了是多少处理指令后,要做以下工作。

第二判断是否MOV指令,if (dataproc.opcode == MOV)
即可完毕判断,在规定是MOV指令后,还要判断第三操作数的样式,是即时数方式依旧寄存器格局,那间接影响到背后的反汇编。if
(dataproc.I)即可形成上述判断,真的话表达是立刻数,假的话,表明是寄存器方式。

比方是当时数情势,执行以下代码:

sprintf(disasmstr, " %s%s%s %s, %s",opcodes[dataproc.opcode],
condtext[dataproc.condition],(sFlag[dataproc.S]),registers[dataproc.Rd], 
dataoperandIm(dataproc) );
updateReg(dataproc,-1,read);

里头disasmstr
保存的是反汇编后的字符,opcodes[dataproc.opcode]是操作符,condtext[dataproc.condition],是执行规范,(sFlag[dataproc.S])是S标志位,
registers[dataproc.Rd]为指标寄存器,dataoperandIm(dataproc)那些函数执行后将回到第一操作数的值。函数源代码如下,其指标很简短,正是讲贰个6位数扩充成3十二位,再循环右移偶数位,获得1个311人数。updateReg(dataproc,-1,read);是立异各寄存器的值,跟踪程控流的时候要求。

static char *dataoperandIm (DataProc dataproc)                
{
        QByte data, rotate;
            rotate = (dataproc.operand2 >> 8) * 2;
            data = dataproc.operand2 & 0xFF;
            sprintf(workstr, " 0x%lX",
                (data >> rotate)|(data<<(32-rotate)));
        return (workstr);
}

壹经是寄存器情势,将会相比复杂,因为第二操作数会有三种情况,移位啊什么的,反汇编进程如下。

       假诺指标寄存器大于一5,表示无效的一声令下。

if (dataproc.Rd > 15 )            
  sprintf(disasmstr, "Invalid opcode");

(一)寄存器的值就是操作数

        if ( 0==(dataproc.operand2&0xFF0) ) 
        {
            updateReg(dataproc,r[dataproc.operand2&0x0F],read);
            sprintf(disasmstr, " %s%s%s %s, %s",
                        opcodes[dataproc.opcode],
                        condtext[dataproc.condition],
                        (sFlag[dataproc.S]),
                        registers[dataproc.Rd],
                        registers[dataproc.operand2&0x0F]);
        }

(二)寄存器循环右移

    else if ( 0x70==(dataproc.operand2 &0x0F0) )  
            {
                    sprintf(disasmstr, " %s%s%s %s, %s, ror %s",
                        opcodes[dataproc.opcode],
                        condtext[dataproc.condition],
                        (sFlag[dataproc.S]),
                        registers[dataproc.Rd],
                        registers[dataproc.operand2&0x0F],
                        registers[(dataproc.operand2&0xF00)>>8]
                    );
                }

而外,还有以下景况,由于处理情势类似,这里就不壹1列出代码了。

(3)<Rm>, LSL #<shift_imm>   霎时数逻辑左移

(四)<大切诺基m>, LSL <牧马人s>                寄存器逻辑左移

(5)<Rm>, LSR #<shift_imm>   登时数逻辑右移

(陆)<Odysseym>, LS奥迪Q5 <悍马H②s>               寄存器逻辑右移

(7) <Rm>, ASR #<shift_imm> 立时数算数右移

(8) <牧马人m>, ASCR-V <PRADOs>              寄存器算数右移

(9)<Rm>, ROR #<shift_imm>   马上数循环右移

经过上述处理后,基本上把MOV指令的装有情状都思量进去了,MOV指令的反汇编工作也基本做到,其余类别型的指令基本上也是这样三个流程。

实际上,二进制机器代码与汇编指令都以绝无仅有对应的,指令的反汇编最关键的正是要找到那种对应关系,知道每一人所代表的趣味,唯1明确出操作符,操作数等。

5、输出突显模块

      
本软件的输出显示模块是用MFC实现的,在vs2008条件下新建五个MFC工程,选取对话框框,然后添加菜单,编辑框,还有新闻处理函数。首要处理多个音信,点击Read
File菜单项、Sequence
Disassembling菜单项、ControlFlowDisassembling菜单项,分别用八个函数完毕,OnFileSelectfile(),OnOperateSequence(),OnOperateControlflowdisassembling()。

各类反汇编策略的界面如下图,当中左边第二列是命令或数额的地点,从0开端;第三列是命令的2进制编码,是存放在二进制可执行BIN文件里的直白内容,第贰列是反汇编后的汇编指令。由图可知,选用顺序扫描策略反汇编后的结果尚未区分出指令和数据,把恒河沙数多少也反汇编成指令,可读性相比较差,全部相比较散乱。

澳门威尼斯人网址 47

基于控制流的反汇编界面如下图,其中从左边早先率先列是命令或数额的地点(有个别地点有标签),第三列固然是命令的话展现指令的二进制编码,固然是数量的话平昔展现数据的值,第二列显示的是命令的汇编情势,数据不显示。从图中大家能够窥见,基于控制流的反汇编技术相比较好的兑现了指令和数据的分离,全部感到绝对清楚,可读性较好。

澳门威尼斯人网址 48

  至此,本软件的输出模块就归西了,其实,关于输出模块的安顿性还有许多可以立异的地点。比如能够兑现当点击有个别菜单项时,反汇编出一条指令,同时在左边的Other呈现界面展现出个中间各类寄存器的值,即单步反汇编,类似调节和测试进度;同时也得以一步到底反汇编。由于岁月关系,本软件在设计时,寄存器值的革新并未涉及全部的吩咐,只有当执行壹些重中之重或简捷指令时才履新寄存器的值,所以右侧的界面也就从未达成了。

A锐界M反汇编软件的现实贯彻

  A大切诺基M反汇编软件首要有多个大模块组合,2进制可实施代码读取模块、指令和数据分离模块、指令反汇编模块、输出模块。本章节将结合程序中的源代码首要介绍A中华VM反汇编软件各模块具体完成。由于时日等要素影响,本软件设计只思虑到了ALacrosseM指令,THUMB指令不在考虑范围,不超过实际在都是相同道理的业务,ATucsonM指令能够落到实处的话,THUMB指令添加进去只是时间的难题。

壹、数据组织情势

读进去的剧情的集体如下所示:

class Content
{
public:
        unsigned int            addr;                //地址
        bool                isInstruction;        //指令标记
        bool                isVisited;            //访问标记    
        bool                isHasLable;            //是否有标签标记
        unsigned int         firstB;                //第1个字节
        unsigned int         secondB;
        unsigned int         thirdB;
        unsigned int             fourthB;
};

在此类中,addr表示该内容的地方,是逻辑字节地址;isInstruction判断该内容是不是是指令代码;isVisited判断是还是不是被访问过;isHasLable,判断该指令前面要不要加1个标签,firstB表示内容从左到右表示的率先个字节,secondB、thirdB、fourthB以此类推。

读源文件类

class MyRead
{
public:
           vector <Content>  contentVector;        //内容存储容器
        void readSourceFile(char * addr);        //读取源文件函数
};

内容容器contentVector,用于存款和储蓄从源文件读进去的始末,多个字节为2个因素;readSourceFile方法,读取源文件二进制代码,并按个字节一个囤积在容器里。

命令编码内容的集体

一声令下编码的团组织其实依旧很要紧的,好的团体措施能够大大节省后续工作的小运,后续开发依旧保卫安全都会变得更不难。由于篇幅关系,那里将介绍部分相比常用到的授命内容的团伙。那里介绍的吩咐内容的公司都将动用结构体的花样,其实也能够用类来贯彻。

typedef unsigned  int QByte;                    //32位无符号数

(1)SWI指令

typedef struct swi                                
{
        QByte comment : 24;
        QByte mustbe1111 : 4;
        QByte condition : 4;
} SWI;

SWI指令的编码格式:

澳门威尼斯人网址 49

由指令的编码格式大家得以看看,comment的内容表示immed_二四,正好二十四位;mustbe111一是一向的,全数SWI指令的[27:24]都是111一,condition表示条件域,总共有16种情状,用四位表示即可。

(二) 分支指令

typedef struct branch {        
        QByte offset : 23;
        QByte sign : 1;
        QByte L : 1;
        QByte mustbe101 : 3;
        QByte condition : 4;
} Branch;

分层指令的编码格式:

澳门威尼斯人网址 50

从指令的编码格式中,大家发现,Offset其实是鲜明了转载地址的相对值;sign申明正负数;L用于分别是不是要把重临地址写入哈弗第11四中学;mustbe十一声明这是一条分支指令,固定的,cond是条件域。

(三)加载/存款和储蓄指令

typedef struct singledatatrans {    
        QByte offset : 12;
        QByte Rd : 4;
        QByte Rn : 4;
        QByte L : 1;
        QByte W : 1;
        QByte B : 1;
        QByte U : 1;
        QByte P : 1;
        QByte I : 1;
        QByte mustbe01 : 2;
        QByte condition : 4;
} SingleDataTrans;

加载/存款和储蓄指令编码格式:

澳门威尼斯人网址 51

里头offset, I, P, U, W, 劲客n共同决定总计出内部存款和储蓄器中的地点,RAV4d是目标寄存器,

L位用于区分是LD瑞虎依旧ST路虎极光指令;B位用于区分unsigned byte (B==一) 和 a word
(B==0)。

(4)数据处理指令

typedef struct dataproc {
        QByte operand2 : 12;
        QByte Rd : 4;
        QByte Rn : 4;
        QByte S : 1;
        QByte opcode : 4;
        QByte I : 1;
        QByte mustbe00 : 2;
        QByte condition : 4;
} DataProc;

对应的编码格式如下:

澳门威尼斯人网址 52

里头operand二是第一操作数,其计算情势也有多样情势,可参看A揽胜M手册上的“Addressing
Mode 一 – Data-processing operands on page
A5-2”;大切诺基d为指标寄存;奥德赛n为率先操作数;S位用于区分是还是不是影响CPS奥迪Q3;opcode用于明确是这种数据操作,如MOV,ADD等;I用于分别第2操作数是寄存器情势依旧当时数方式;mustbe00是固定的;Cond为条件域。

段表、彰显表、再次回到表的团体

为简便起见,本程序中那么些表统统用容器Vector来贯彻

typedef struct Elem{
         int re[16];
          unsigned int addr;
}Elem;
static vector <unsigned int>     segmentTable;        //段表
static vector < unsigned int >             returnAddrTable;        //返回表
static vector <Elem>         showAddrTable;        //显示表

看来,在那之中Elem结构体用于存款和储蓄呈现表里面包车型地铁因素。segmentTable为段表,returnAddrTable为回去表,showAddrTable为突显表。

不无的填表操作都以用push_back
函数来兑现的,还有正是操作呈现表和再次回到表时要牢记重回表是后进先出的。

命令共用体

澳门威尼斯人网址 53澳门威尼斯人网址 54

typedef union access32 {
        QByte qbyte;
        SWI swi;                            //SWI instruction
        CPRegTrans cpregtrans;             // Coprocessor registesr transfers
        CPDataOp cpdataop;                    // Coprocessor data processing
// Coprocessor load/store and double register transfers[6]
        CPDataTrans cpdatatrans;  
//Branch and branch with link and change to Thumb
        Branch branch;                        
        Undefined4  undefined4;                //Undefined Ins[4]
        LoadStoreMultiple loadstoremultiple;    //load/store multiple
        Undefined47 undefined47;            //Undefined instruction [4,7]
        Undefined   undefined;                //Undefined instruction
//Load,store immediate offset,Load,store register offset
        SingleDataTrans singledatatrans;
        MSRImeToSReg  msrimetosreg;        //Move immediate to status register
        Undefined3    undefined3;                //Undefined instruction [3]
        DataProc dataproc;
        DataProcImmediate dataprocimme;
        MultiplyExtraLoadStore  multiextraloadstore;    //Multiplies, extra load/stores: 
        MiscellanesInstructOne    miscelinstrone;        //Miscellaneous instructions
        DataProcRegShift        dataprocregshift;
        MiscellanesInstructTwo    miscelinstrtwo;        //Miscellaneous instructions:            DataProcImmeShift     dataprocimmeshit;
} Access32;

View Code

其一命令共用体的安装相应说是十一分巧妙的,涵盖了独具类型的指令。在反汇编进度中,首先是从目的二进制代码中读取四个三十个人数到内部存款和储蓄器,然后将以此三十二位数从内部存款和储蓄器拷贝到共用体变量中,由于共用体的存款和储蓄空间是共享的,定义1个方面包车型大巴共用体,其实也就只是两个字节大小的上空,然而她能够代表任何一条指令,因而用这么些共用体变量来判断读进去的33位数是那条指令格外方便和直观,具体判定的将在接下去的授命反汇编模块介绍。

别的数据结构

协助处理理器寄存器:

static const char *cregister[16] = {    
        "cr0",  "cr1",  "cr2",  "cr3",
        "cr4",  "cr5",  "cr6",  "cr7",
        "cr8",  "cr9",  "cr10", "cr11",
        "cr12", "cr13", "cr14", "cr15"
};

寄存器:

static const char *registers[16] = {
        "R0", "R1", "R2", "R3",
        "R4", "R5", "R6", "R7",
        "R8", "R9", "R10","R11",
        "R12", "R13", "R14", "PC"
};

条件域:

static const char *condtext[16] = {
        "EQ",                    //"Equal (Z)" 
        "NE",                    //"Not equal (!Z)" 
        "CS",                    //"Unsigned higher or same (C)" },
        "CC",                    //"Unsigned lower (!C)" },
        "MI",                    //"Negative (N)" },
        "PL",                    //"Positive or zero (!N)" },
        "VS",                    //"Overflow (V)" },
        "VC",                    // "No overflow (!V)" },
        "HI",                    // "Unsigned higher (C&!Z)" },
        "LS",                    //"Unsigned lower or same (!C|Z)" },
        "GE",                    // "Greater or equal ((N&V)|(!N&!V))" },
        "LT",                    //"Less than ((N&!V)|(!N&V)" },
        "GT",                    //"Greater than(!Z&((N&V)|(!N&!V)))" },
        "LE",                    //"Less than or equal (Z|(N&!V)|(!N&V))" },
        "",                        //"Always" },         //AL,可以省略掉
        "NV"                   //, "Never - Use MOV R0,R0 for nop" }
};

数据处理指令的操作码编码,从0到一五,之所以弄成以下格局是为了充实程序的可读性。

typedef enum operatecode
{
        AND,EOR ,SUB ,RSB                    //AND=0;    EOR=1.
           ,ADD,ADC ,SBC ,RSC
           ,TST, TEQ,CMP,CMN
           ,OPR ,MOV ,BIC,MVN
}OperCode;

数据处理指令字符:

static const char *opcodes[16] =
{
        "AND", "EOR", "SUB", "RSB",
        "ADD", "ADC", "SBC", "RSC",
        "TST", "TEQ", "CMP", "CMN",
        "ORR", "MOV", "BIC", "MVN"
};

留意里面包车型客车次第,要跟其编码规则对应。

二、二进制可实行代码读取模块

2进制可实施代码的读取模块首要成就从表面文件中读取2进制代码到内部存款和储蓄器中,并要合理组织数据。

读取函数如下所示:

澳门威尼斯人网址 55澳门威尼斯人网址 56

void MyRead::readSourceFile(char *addr)
{
        ifstream f1(addr,ios::binary);
        if(!f1)
        {
            cerr<<addr<<"不能打开"<<endl;
            return;
        }
        unsigned char x;    
        int k=0,i=0;
        while(f1.read(( char *)&x,1))
        {
            Content temp;                // 定义一个Content临时对象
            if(i==0)                
            {
                temp.fourthB=x;            //一个字里的第4个字节
            }
            else if(i==1)
            {
                temp.thirdB=x;         //一个字里的第3个字节

        }
        else if(i==2)
        {
            temp.secondB=x;    //一个字里的第2个字节
        }
        else if(i==3)                
        {
            temp.firstB=x;        //一个字里的第1个字节
        }
        i++;
        if(i==4)                
        {
            i=0;
            temp.addr=4*k;         //给地址赋值
            temp.isVisited = false;
            temp.isHasLable = false;
            k++;
            this->contentVector.push_back(temp);        //将temp存放到容器里
            Content temp;
        }
    }
    f1.close();
}

View Code

读取模块首先要做的是打开指标文件,然后贰个字节三个字节的读取进来,那里所谓的首先个字节FirstB指的是三个三十三人数从左往右数算起率先个的,总共多个字节。然后要设置1个Content
类型的temp中间值,将读进去的字节依次往temp赋值,赋完八个字节后,把地址,是或不是访问标志等等也都起始化一下;最后将这几个temp中间值压入contentVector容器中,那些容器里面存放的正是指标代码读进去的2进制代码,多个字节为3个成分存放。

三、指令和数据分离并标识模块

方今已经讲了指令和数据分离的思维,重即便跟踪程序的控制流,那里讲结合程序的完毕一连证宾博下。首先看一下指令和数据分离的函数。

澳门威尼斯人网址 57澳门威尼斯人网址 58

void MyDisassemble::separateI_D(MyRead &read)
{
        int k = 0;
        segmentTable.push_back(0);                        
        r[15] = 0;            //PC设为0
        disPart(read);
        while(true)
        {
            if(k == showAddrTable.size()) break;        //显示表都访问结束
            for(int i = 0;i<16;i++) r[i] = showAddrTable[k].re[i];    //恢复现场
            if(read.contentVector[((showAddrTable[k].addr)/4)].isVisited == false) 
//是否访问 
disPart(read);    
                k++;
        }
}
void MyDisassemble::disPart(MyRead &read)
{
            for(int i =r[15]/4;;i = r[15]/4)
            {
                unsigned int foo=((read.contentVector[i].firstB)<<24)+
((read.contentVector[i].secondB)<<16)+
((read.contentVector[i].thirdB)<<8)+read.contentVector[i].fourthB;
                read.contentVector[i].isInstruction = true;    //设置是指令                            read.contentVector[i].isVisited = true;    //已访问过
                disArm(foo,read);        //反汇编指令
                if ((0x0F&read.contentVector[i].firstB)==0x0f) //程序结束
                {    
                    segmentTable.push_back(r[15]);                break;
                }
                r[15]=r[15]+4;                                                }
}

View Code

上述separateI_D函数的指标是为了跟踪程序的控制流,遍历每一条指令(有点类似有向图的遍历),从而标识出指令。首先是segmentTable.push_back(0),将胚胎地址填入段表;然后按时下地点逐条分析指令类型disPart(read);在disPart函数中,当访问这条指令时,首先要做的是把该指令的isInstruction和isVisited标志设置为true;然后disA福睿斯M,disASportageM是反汇编函数,这一个函数能够反汇编出该条指令是哪条指令,在上边包车型大巴反汇编模块将会有进一步详实的认证,在此间只要理解她能够辨别出是哪条指令即可。

当反汇编出来的一声令下是无条件转移指令时,以B指令为例,要执行以下代码:

segmentTable.push_back(r[15]);            
    segmentTable.push_back(r[15] + addr);    
r[15]=(r[15]+addr-4);    
    read.contentVector[(r[15]/4)].isHasLable = true;

r[15]指pc,r[15] +
addr为展现地址。(一)首先将此命令所在地点填入段表,(2)然后展现地址填入段表,(三)再然后展现地址作为当前地方,由于已经安装PC自动加了,所以那边先减一下,(四)同时转向地址处的授命前边是四个标签,把isHasLable设置为true;

       若为无条件转移指令子程序调用指令,以BL为例,要推行以下代码:

r[14] = r[15] + 4;                    
    segmentTable.push_back(r[15]);            
    returnAddrTable.push_back(r[14]);        
    segmentTable.push_back(r[15] + addr);    
    r[15]=(r[15]+addr-4);
    read.contentVector[((r[15]+4)/4)].isHasLable = true;

各队语句的意味依次是

(一)保存再次回到地址到Murano1四  

(二)此命令所在地点填入段表

(3)再次来到地址填入再次来到地址表

(肆)呈现地址填入段表

(5)展现地址作为当前地点,由于已经安装PC自动加了,所以这边先减一下

(6)该地方处指令前边有个标签。

若为无条件转移指令中的重临指令,以MOV PC,LLX570为例,如下:

unsigned int raddr;
    if(returnAddrTable.size()>0) {
            raddr = returnAddrTable[returnAddrTable.size()-1];  
return AddrTable.pop_back();
                }    
segmentTable.push_back(r[15]);            
    segmentTable.push_back(raddr);        
    r[15] = raddr-4;
read.contentVector[(raddr/4)].isHasLable = true;

次第做了以下工作,

(壹)重回地址表中按“后进先出”原则找到返回地址

(二)删除再次回到表最终二个要素

(叁)指令所在地方填段表

(四)再次回到地址填段表

(五)设置当前的PC值

(6)设置标签标明

若为二分支指令,以BNE为例,如下:

Elem temp;temp.addr = r[15] + addr; for(int ii=0;ii<16;ii++) temp.re[ii] = r[ii];
    showAddrTable.push_back(temp);    
    read.contentVector[(( r[15] + addr)/4)].isHasLable = true;

次第做了以下工作,

(1)保存“现场”

(二)显式地址填入显式表(包罗当时的寄存器值)

(叁)设置标签标明。

      
若不是更换指令,则继续按PC值自增下去,直到终结语句,然后还要判断展现表是或不是空,那里用了个K变量来达成,实际上并从未当真从容器中剔除取出的显得表里的因素。if(k
== showAddrTable.size())
break;用来判断是或不是出示表里的地方都访问过了。假若未有,则继续按这条指令的地方disPart下去。直到把展现表里的地址都访问3次。

      
执行完以上的代码后,就贯彻了按控制流遍历每条指令,是命令的大半也都做上了标识。

四、指令反汇编模块

命令反汇编模块在宏观上海重机厂点呈以后disArm那么些函数上,代码如下:

澳门威尼斯人网址 59澳门威尼斯人网址 60

 char * MyDisassemble::disArm(unsigned int uint,MyRead &read,int type)
{
    Access32 instruction;
    memcpy(&instruction, &uint,sizeof(uint));                                                        //拷贝数据
    if (0xF == instruction.swi.mustbe1111)                                                            //SWI指令 
    {
        decode_swi (instruction.swi);
    } 

    else if ( 0xE == instruction.cpregtrans.mustbe1110 )                                    // Coprocessor registesr transfers或者Coprocessor data processing
    {
        if (0x1 == instruction.cpregtrans.mustbe1)                                                //coprocessor register transfers
        {                     
            /* Coprocessor Register Transfer */
             decode_cpregtrans (instruction.cpregtrans);
        } 
        else                                                                                                        //coprocessor data processing
        {      
            /* Coprocessor Data Operation */
             decode_cpdataop (instruction.cpdataop);                                
        }
    }
    else if ( 0x6 == instruction.cpdatatrans.mustbe110  )                                        // Coprocessor load/store and double register transfers[6]
    {
        /* Coprocessor Data Transfer */
         decode_cpdatatrans (instruction.cpdatatrans);
    }
    else if ( 0x5 == instruction.branch.mustbe101 )                                                 //Branch and branch with link and change to Thumb //Branch and branch with link
    {
         decode_branch (instruction.branch,read,type);
    }
    else if (  (0xF==instruction.undefined4.condition1111) &&  ( 0x4==instruction.undefined4.mustbe100)   )    //Undefined Ins[4]
    {
         decode_unknown (instruction);
    }
    else if (0x4==instruction.loadstoremultiple.mustbe100)                                    //load/store multiple
    {
        /* load/store mutiple */
         decode_loadstoremultiple (instruction.loadstoremultiple);
    }
    else if (  (0xF==instruction.undefined47.condition1111)&& (1==instruction.undefined47.mustbe1) ) //Undefined Instruction[4,7]
    {
         decode_unknown (instruction);
    }
    else if ( (0x3==instruction.undefined.mustbe011)&& (1==instruction.undefined.mustbe1) ) //undefined Instruction
    {
        decode_unknown (instruction);
    }
    else if (0x1==instruction.singledatatrans.mustbe01)                                    //Load/Store register offset, Load /Store Immediate offset
    {
        /* Single Data  */
         decode_singledatatrans (instruction.singledatatrans,read, type);
    }
    else if ( ( 6==instruction.msrimetosreg.mustbe00110)&& (2==instruction.msrimetosreg.mustbe10)&& (0==instruction.msrimetosreg.SBO) )                            
    {                                                                                                                    //Move immediate to status register
         decode_msrimetoreg(instruction.msrimetosreg);
    }
    else if ( (0==instruction.undefined3.mustbe00)    && (1==instruction.undefined3.mustbe001)    && (2==instruction.undefined3.mustbe10) )                            
    {                                                                                                                        //undefined instruction[3]
         decode_unknown (instruction);

    }
    else if(1==instruction.dataprocimme.mustbe001)                                                //Data Processing immediate[2]
    {
         decode_dataproc (instruction.dataproc,read,type);

    }
    else if ( (0==instruction.multiextraloadstore.mustbe000)&& (1==instruction.multiextraloadstore.mustbeH1)&& (1==instruction.multiextraloadstore.mustbeL1) )                        
    {                                                                                                                    //Multipies ,extra load/stores 
        if ( 0 ==instruction.multiextraloadstore.dontcareB )
        {
            //Muptiply (accumulate
            //multiply long
            //Swap/swap byte
            //decode_multiply
            if ( 1==(instruction.multiextraloadstore.dontcareC & 0x10000))
            {
                SingleDataSwap *psingledataswap = (SingleDataSwap*)&instruction;
                if ( ( 0==psingledataswap->mustbe00)&&(9==psingledataswap->mustbe00001001) && (2==psingledataswap->mustbe00010) )
                {
                    decode_singledataswap ( *psingledataswap );
                }
            }
            else
            {
                //multiply
                Multiply*  pmultiply = (Multiply*)&instruction;
                if( (0==pmultiply->mustbe0000)&&(9==pmultiply->mustbe1001) )
                decode_multiply ( *pmultiply );
            }
        }
        else
        {//extra load store 
            decode_singledatatrans (instruction.singledatatrans, read,type);
        }
        /* Single Data Transfer */

    }
    else if ( ( 0== instruction.miscelinstrone.mustbe000)&&(0==instruction.miscelinstrone.mustbe0H)&&(0==instruction.miscelinstrone.mustbe0L)    &&(2==instruction.miscelinstrone.mustbe10)&&(1==instruction.miscelinstrone.mustbe1)     )                                
    {                                                                                                                            ///miscellaneous insturction
      decode_miscelinstrone( instruction.miscelinstrone );
    }
    else if ( (0==instruction.dataprocregshift.mustbe000)&& (0==instruction.dataprocregshift.mustbe0)     && (1==instruction.dataprocregshift.mustbe1) )                                                                                                                                                        
    {                                                                                                                    //data processing register shift[2]   
        decode_dataproc (instruction.dataproc,read,type);
    }
    else if( (0==instruction.miscelinstrtwo.mustbe000)&& (2==instruction.miscelinstrtwo.mustbe10)&&(0==instruction.miscelinstrtwo.mustbe0H)&& (0==instruction.miscelinstrtwo.mustbe0L) )                                        
    {                                                                                                                    //miscellaneous instructions;
        decode_miscelinstrone( instruction.miscelinstrone );
    }
    else if  ( (0==instruction.dataprocimmeshit.mustbe000)                                        //data processing immediate shift
        && (0==instruction.dataprocimmeshit.mustbe0 ) )
    {
         decode_dataproc (instruction.dataproc,read,type);
    }
    return (disasmstr);
}

View Code

在前面,大家早已介绍了A景逸SUVM指令的编码规则,从图2.第22中学,大家得以看到图中每1行都是1种指令的集和,可能说都以1模壹样连串的。当获得贰个30人数时,如何举行反汇编获得其汇编情势的汇编指令呢?

(一)首先将这几个三12个人数从内部存款和储蓄器中拷贝到instruction指令共用体变量中

memcpy(&instruction,
&uint,sizeof(uint));之所以拷贝到这一个共用体里面是因为它曾经定义了独具品类的指令,那样对比直观清晰。

(二)判断该指令是哪个种类指令,那步是有一定规则的,要从下往上那几个判断,具体可看附录里的代码,目标是为了思量到独具的吩咐。区分是哪条指令的依照是图二.2中的那几个固定位,只要读进去的那三十几个人数中的某3个人跟表中的那二位符合,就能够显著该指令属于哪一类。比如说MOV 
r0, #0,该指令编码为0xe3a00000,由于[27:25]==001,所以为Data
processing immediate [2]那种类型,之所以不是Undefined instruction
[3](它的[27:25]==00一),是因为在认清是否Undefined instruction
[3]前面早已看清过不是了,在(1)里曾经说过要从下往上判断,正是其一缘故。

(三)知道哪类别型的授命后,要一而再区分是那连串型指令里的哪条指令,然后再区分条件域,是不是影响CP中华VS\[13\],操作数等等。以(二)里的MOV 
r0,
#0为例,由于其[24:21]==1拾1,所以能够判明其为MOV指令,条件域[31:28]==1110,表示总是执行,不需添加条件。1拾一人S为0,表示不影响CP奥迪Q3S,[15:12]==0000,表示指标寄存器为安德拉0,第一操作数也可总结得出为0.谈起底反汇编的结果为MOV 
r0, #0。

上边将组成程序代码重点商讨一下数据处理指令中MOV指令的反汇编,因为那种指令是最广泛的,通晓了那种指令的反汇编,同他命令也可同理得出。

      
上述已经讲过,经过附录里disArm函数的判断之后,就能够清楚是哪个种类指令,所在知道了是数量处理指令后,要做以下工作。

率先判断是或不是MOV指令,if (dataproc.opcode == MOV)
即可实现判断,在规定是MOV指令后,还要判断第3操作数的款式,是立刻数情势依旧寄存器情势,这直接影响到末端的反汇编。if
(dataproc.I)即可成功上述判断,真的话表明是及时数,假的话,表达是寄存器格局。

假使是立刻数方式,执行以下代码:

sprintf(disasmstr, " %s%s%s %s, %s",opcodes[dataproc.opcode],
condtext[dataproc.condition],(sFlag[dataproc.S]),registers[dataproc.Rd], 
dataoperandIm(dataproc) );
updateReg(dataproc,-1,read);

中间disasmstr
保存的是反汇编后的字符,opcodes[dataproc.opcode]是操作符,condtext[dataproc.condition],是实施尺度,(sFlag[dataproc.S])是S标志位,
registers[dataproc.Rd]为指标寄存器,dataoperandIm(dataproc)这一个函数执行后将赶回第2操作数的值。函数源代码如下,其指标非常粗略,就是讲一个6个人数扩张成三玖人,再循环右移偶数位,获得二个3多少人数。updateReg(dataproc,-1,read);是革新各寄存器的值,跟踪程控流的时候必要。

static char *dataoperandIm (DataProc dataproc)                
{
        QByte data, rotate;
            rotate = (dataproc.operand2 >> 8) * 2;
            data = dataproc.operand2 & 0xFF;
            sprintf(workstr, " 0x%lX",
                (data >> rotate)|(data<<(32-rotate)));
        return (workstr);
}

若是是寄存器格局,将会相比复杂,因为第1操作数会有两种情况,移位啊什么的,反汇编进度如下。

       借使指标寄存器大于一伍,表示无效的通令。

if (dataproc.Rd > 15 )            
  sprintf(disasmstr, "Invalid opcode");

(1)寄存器的值正是操作数

        if ( 0==(dataproc.operand2&0xFF0) ) 
        {
            updateReg(dataproc,r[dataproc.operand2&0x0F],read);
            sprintf(disasmstr, " %s%s%s %s, %s",
                        opcodes[dataproc.opcode],
                        condtext[dataproc.condition],
                        (sFlag[dataproc.S]),
                        registers[dataproc.Rd],
                        registers[dataproc.operand2&0x0F]);
        }

(二)寄存器循环右移

    else if ( 0x70==(dataproc.operand2 &0x0F0) )  
            {
                    sprintf(disasmstr, " %s%s%s %s, %s, ror %s",
                        opcodes[dataproc.opcode],
                        condtext[dataproc.condition],
                        (sFlag[dataproc.S]),
                        registers[dataproc.Rd],
                        registers[dataproc.operand2&0x0F],
                        registers[(dataproc.operand2&0xF00)>>8]
                    );
                }

除开,还有以下意况,由于处理格局类似,那里就不1一列出代码了。

(3)<Rm>, LSL #<shift_imm>   霎时数逻辑左移

(四)<奥迪Q7m>, LSL <奥德赛s>                寄存器逻辑左移

(5)<Rm>, LSR #<shift_imm>   立即数逻辑右移

(6)<CRUISERm>, LS汉兰达 <HummerH二s>               寄存器逻辑右移

(7) <Rm>, ASR #<shift_imm> 立刻数算数右移

(八) <大切诺基m>, AS科雷傲 <景逸SUVs>              寄存器算数右移

(9)<Rm>, ROR #<shift_imm>   马上数循环右移

通过上述处理后,基本上把MOV指令的富有情形都记挂进去了,MOV指令的反汇编工作也基本形成,别的体系型的下令基本上也是那般多少个流程。

事实上,二进制机器代码与汇编指令都是唯一对应的,指令的反汇编最要紧的正是要找到那种对应关系,知道每一位所表示的意趣,唯一鲜明出操作符,操作数等。

伍、输出呈现模块

      
本软件的出口展现模块是用MFC完毕的,在vs2010环境下新建1个MFC工程,选取对话框框,然后添加菜单,编辑框,还有音讯处理函数。重要处理八个音讯,点击Read
File菜单项、Sequence
Disassembling菜单项、ControlFlowDisassembling菜单项,分别用多个函数实现,OnFileSelectfile(),OnOperateSequence(),OnOperateControlflowdisassembling()。

逐条反汇编策略的界面如下图,个中左边第三列是命令或数量的地方,从0初步;第一列是命令的2进制编码,是存放在在二进制可执行BIN文件里的第1手内容,第1列是反汇编后的汇编指令。由图可知,采纳顺序扫描策略反汇编后的结果未有不相同出指令和数据,把过多数据也反汇编成指令,可读性比较差,全体相比混乱。

澳门威尼斯人网址 61

依照控制流的反汇编界面如下图,个中从右侧开端率先列是命令或数额的地方(有个别地方有标签),第叁列若是是命令的话突显指令的二进制编码,假若是多少的话平昔显示数据的值,第二列彰显的是命令的汇编格局,数据不显得。从图中大家能够发现,基于控制流的反汇编技术比较好的兑现了指令和数据的分开,全部感到相对清楚,可读性较好。

澳门威尼斯人网址 62

  至此,本软件的输出模块就甘休了,其实,关于输出模块的宏图还有众多能够革新的地方。比如能够兑现当点击某些菜单项时,反汇编出一条指令,同时在左侧的Other彰显界面展现出其内部种种寄存器的值,即单步反汇编,类似调节和测试进程;同时也可以一步到底反汇编。由于时日关系,本软件在统一筹划时,寄存器值的立异并从未提到全数的授命,唯有当执行一些重大或简捷指令时才履新寄存器的值,所以右侧的界面也就从未有过落实了。

用尤其反编写翻译c代码的编写翻译器来反编译delphi生成的代码,恐怕会油可是生特别乖的语法。同样用对windows
api一窍不通的反编译器反编写翻译windows二进制,也会出现上述结果

不足

由于时日、水平和阅历有限,许多地点仍有不足之处,有创新的后路,比如

在跟踪程序的控制流的长河中,按理说当执行完每一条指令后,只要遭逢会改变寄存器值的吩咐,都应该更新寄存器的值,但鉴于时日等要素,只兑现了有的发令;

而且在依照控制流的反汇编策略时,总共扫描了五次指标代码,效用相比低,理想的办法是只扫描一次;

别的本软件未有落实对THUMB指令的支撑。

不足

鉴于岁月、水平和阅历有限,许多方面仍有不足之处,有改正的后路,比如

在跟踪程序的控制流的进程中,按理说当执行完每一条指令后,只要碰着会改变寄存器值的吩咐,都应该更新寄存器的值,但鉴于时日等要素,只兑现了壹些限令;

再者在依照控制流的反汇编策略时,总共扫描了五次指标代码,效用相比较低,理想的法子是只扫描2遍;

此外本软件未有兑现对THUMB指令的协理。

这是3个非常大的搦战,反汇编器在此外反编写翻译阶段都有望错误或遗漏壹些代码而影响反编写翻译结果

正文链接地址

http://www.cnblogs.com/chenpi/p/5199226.html

本文链接地址

http://www.cnblogs.com/chenpi/p/5199226.html

规定反汇编代码区域

不乏先例指令和数据是勾兑在壹起的,这怎么去分别呢。首先可执行文件肯定的依据一定的格式规则,如:windows的PE(portable
executable),Unix的ELF(executable and linking
format),而这个格式日常就会讲述怎么分明代码和数码的职务,以及怎么找到程序入口点(贰个发令地址,壹旦程序加载到内部存款和储蓄器,操作系统就将控制权交给当前义务的通令)

当读取到该岗位的下令后,实行1次查表操作,将2进制的与他的汇编助记符对应起来

稍稍指令还有十分大也许供给操作数和目标操作数,如:mov

当助记符和操作数都有之后能够说是那条指令就反编写翻译实现了,然后输出

巡回处理这几个文件直到文件末尾。又大度的算法能够形成上述操作

从文件的始发向来处理到文件末尾。难题是不太好处理分支或非线性结构的流程。

亮点:完全覆盖所以代码段

缺陷:有一点都不小希望代码中混有数据,但当指令处理了

gdb,windbag,objdump都以运用那1算法

它利用了和线性完全不一致的法门定位代码逻辑。递归强调的是控制流,依据指令是或不是跳转在决定是还是不是反编写翻译。因而他会基于程序不一样控制流来反编写翻译,那有怎么着控制流呢

参照列表:

[1] 殷文建.面向AMuranoM种类布局的代码逆向分析关键技术商讨[D].
哈利法克斯:中华夏族民共和国人民解放军音讯工程大学,20拾.

[2] 董仁飞 .反汇编技术在嵌入式软件安全性分析中的应用[J].
品质与保证   性,201一,0二:57-5玖.

[3] 方海义,陈利峰,涂时亮.
基于A卡宴M嵌入式处理器的反汇编方法[J].总结机工程,200三,2九(z一):15玖-1陆一.

[4]
张不相同,王虹,王开铸.反汇编制程序序设计原理与贯彻格局[J].孟菲斯药科高校学报,壹玖87,陆:二一-二伍.

[5] 李驹光.
ALANDM应用系统开发详解——基于S3C45十B的系统规划[M].南开大学出版社,2004:一-1八.

[6] ARM Limited. ARM Architecture Reference Manual [EB/OL].
http://infocenter.arm.com/,2005.

[7]
许敏,陈前斌.静态反汇编算法研究[J].总计机与数字工程,2007,35(5):1三-1陆.

[8] 吴金波, 蒋烈辉, 赵鹏.基于控制流的静态反汇编算法研讨 [J].
计算机工程与利用, 200伍, 肆1(30):8九-90.

[9] 吴金波,蒋烈辉.反静态反汇编技术研究 [J]. 总计机应用, 2007,
二五(三):6二三-62伍.

[10] 欧阳清华.反汇编原理及其达成技术[M].纽伦堡院出版社, 一九玖伍:一三-4八.

[11] 王长青.壹种微处理器汇编和反汇编系统规划与探究[D].
苏州:西北方农业余大学学,200一.

[12] B.Schwarz, S.Debray, G.Andrews. Disassembly of Executable Code
Revisited[C]. Proceedings of the Ninth Working Conference on Reverse
Engineering,2002:45-54.

[13] Andrew N.Sloss, Dominic Symes, Chris Wright. ARM System
Developer’s Guide Designing and Optimizing System Software [M]. Morgan
Kaufmann publications, 2004:47-53.

 

参考列表:

[1] 殷文建.面向A陆风X8M种类布局的代码逆向分析关键技术商量[D].
卑尔根:中中原人民共和国人民解放军新闻工程大学,20十.

[2] 董仁飞 .反汇编技术在嵌入式软件安全性分析中的应用[J].
质量与保障   性,201一,02:57-59.

[3] 方海义,陈利峰,涂时亮.
基于A帕杰罗M嵌入式处理器的反汇编方法[J].总括机工程,200三,2玖(z一):15玖-1陆1.

[4]
张差异,王虹,王开铸.反汇编制程序序设计原理与贯彻方式[J].乌鲁木齐矿业学院学报,1987,陆:21-2伍.

[5] 李驹光.
AXC60M应用系统开发详解——基于S3C45拾B的种类规划[M].北大高校出版社,200四:一-1八.

[6] ARM Limited. ARM Architecture Reference Manual [EB/OL].
http://infocenter.arm.com/,2005.

[7]
许敏,陈前斌.静态反汇编算法商讨[J].总计机与数字工程,200柒,3伍(五):一三-1陆.

[8] 吴金波, 蒋烈辉, 赵鹏.基于控制流的静态反汇编算法钻探 [J].
计算机工程与行使, 200伍, 四一(30):8玖-90.

[9] 吴金波,蒋烈辉.反静态反汇编技术切磋 [J]. 总括机应用, 二零零五,
2伍(三):62三-6贰伍.

[10] 欧阳北大.反汇编原理及其达成技能[M].斯特拉斯堡高校出版社, 一九九四:1三-4八.

[11] 王长青.一种微处理器汇编和反汇编系统规划与研讨[D].
塞内加尔达喀尔:西北方外贸大学,200壹.

[12] B.Schwarz, S.Debray, G.Andrews. Disassembly of Executable Code
Revisited[C]. Proceedings of the Ninth Working Conference on Reverse
Engineering,2002:45-54.

[13] Andrew N.Sloss, Dominic Symes, Chris Wright. ARM System
Developer’s Guide Designing and Optimizing System Software [M]. Morgan
Kaufmann publications, 2004:47-53.

 

顺序流

以此就很不难了,就是一条指令接一条,包蕴算术运营add,传值mov,堆栈push和pop等一声令下

跳转指令

分支jnz,他有两条路径真或假,递归反编写翻译会对两条路线都反编译

职务分支

与种种流大约,只是下一条指令不必然紧跟当前下令前边。如若跳转指令的目的地址是一个运维值,那么静态反汇编不可能鲜明该值,也就无奈反编写翻译了,如:jmp
eax

函数调用指令

她和无调整指令很相像,同样反编写翻译器也不可能分辨call
eax那样的授命。唯一差异的是函数执行到位后会再次回到调用指令后边的吩咐,不过在调用函数时出现错误,就有极大希望引致反汇编失利,如:在函数中修改了回来地址

回来指令

偶然,递归下落算法访问了有着路线,且函数重临指令未有提供将要执行的指令地址。借使此时程序正在周转则足以从栈顶获取2个地点,而从那么些地址起头上涨。但是静态反汇编并从未那些力量,那时递归降低反汇编器会一而再反汇编原来搁置的反汇编地址列表

优点:具有很强的代码和数目区分能力

缺陷:不能够处理直接代码路径,如:通过指令表来查找指标地址的跳转或调用。可是选取一种用于识别指向代码的指针的启发式(heuristics)方法,则可以反汇编全部代码

即使自个儿的文章对来推动的扶助可能有不知情的地点,可加QQ群:1299611九伍,大家壹道交流

相关文章