一. 测试的C语句及编译后的x86汇编代码

int a;
int b; int main(void) {
int c; if (c)
a = 4;
else
b = 5; return 0;
}
 1 .text:0000000000400457                 push    rbp
2 .text:0000000000400458 mov rbp, rsp
3 .text:000000000040045B sub rsp, 10h
4 .text:000000000040045F mov [rbp-10], rsp
5 .text:0000000000400463 lea rax, [rbp-4]
6 .text:0000000000400467 movsxd rax, dword ptr [rax]
7 .text:000000000040046A cmp eax, 0
8 .text:000000000040046D jz short loc_400483
9 .text:000000000040046F lea rax, a
10 .text:0000000000400476 push rax
11 .text:0000000000400477 mov rax, 4
12 .text:000000000040047E pop rdi
13 .text:000000000040047F mov [rdi], eax
14 .text:0000000000400481 jmp short loc_400495
15 .text:0000000000400483 ; ---------------------------------------------------------------
16 .text:0000000000400483
17 .text:0000000000400483 loc_400483: ; CODE XREF: main+16↑j
18 .text:0000000000400483 lea rax, b
19 .text:000000000040048A push rax
20 .text:000000000040048B mov rax, 5
21 .text:0000000000400492 pop rdi
22 .text:0000000000400493 mov [rdi], eax
23 .text:0000000000400495
24 .text:0000000000400495 loc_400495: ; CODE XREF: main+2A↑j
25 .text:0000000000400495 mov rax, 0
26 .text:000000000040049C jmp short loc_4004A5
27 .text:000000000040049E ; ---------------------------------------------------------------
28 .text:000000000040049E mov rax, 0
29 .text:00000000004004A5
30 .text:00000000004004A5 loc_4004A5: ; CODE XREF: main+45↑j
31 .text:00000000004004A5 mov rsp, rbp
32 .text:00000000004004A8 pop rbp
33 .text:00000000004004A9 retn

二. x86汇编到虚拟机汇编

  第4句"mov [rbp-10], rsp",内存地址 [rbp-10]在第2句"mov rbp, rsp"赋值,所以第4句转化为

"mov [rsp-10], rsp",再来判断rsp的值,rsp在第3句"sub rsp, 10h",所以第4句转化为"mov [rsp-10], rsp-10",

此时可以定义变量v1,v1地址为[rsp-10],生成虚拟机汇编语句v1 = &v1。

  第8句"jz short loc_400483"也是我们重点关注的语句,因为这是一条条件跳转,程序的执行流可能因为

这条语句不再是顺序执行。第8句的跳转判断cpu flag寄存器标志位z位是否为0,所以搜寻最近一条影响标志位

的语句,这条语句就是第7句"cmp eax, 0",向上搜寻修改eax的语句,第6句"movsxd  rax, dword ptr [rax]",

这是一条读内存操作,继续向上寻找谁修改了rax,找到第5句"lea rax, [rbp-4]",则生成变量v2,v2地址为

[rbp-4],并生成if语句,if语句条件判断为v2。

  继续向下分析汇编语句,接下来的汇编语句是if语句的then部分,遇到第13句"mov [rdi], eax",这是一条

写内存操作,分析内存地址和值。内存地址在rdi中,第12句"pop rdi",继续搜索最近的压栈操作,遇到第10句

"push rax",继续分析rax的值,第9句"lea rax, a",则rdi为a的地址。再来追寻eax,第11句"mov rax, 4",

则生成虚拟机汇编语句a = 4。第14句jmp生成一条goto标签,then部分直到汇编语言地址小于地址loc_400483

的最大值为止。

  再来分析第8句"jz short loc_400483",跳转到loc_400483,接下来的语句是if的else部分,分析看到第22

句"mov     [rdi], eax",这是一条写内存操作,分析内存地址和值。内存地址在rdi中,第21句"pop     rdi",

继续搜索最近的压栈操作,第19句"push rax",继续分析rax的值,第18句"lea rax, b",则rdi为b的地址。再来

追寻eax,第20句"mov rax, 5",则生成虚拟机汇编语句b = 5。此时判断汇编指令的地址是否大于第14句生成的

goto标签,如果大于或等于则结束else部分。

三. 虚拟机汇编到c语言

  1. 虚拟机汇编语言

  code段如下

                 |OP_GET_LOCAL|

                 |1|

                 |OP_JUMP_IF_FALSE|

                 |0xXX|

                 |0xXX|  

                 |OP_POP|

                 |OP_CONSTANT|

                 |0|

                 |OP_SET_GLOBAL|

                 |2|

                 |OP_JUMP|

                 |0xYY|

         |0xYY|

0xXXXX:|OP_POP|

         |OP_CONSTANT|

         |1|

         |OP_SET_GLOBAL|

      |3|

  0xYYYY:|其他指令|

  常量段为:

  |4|

  |5|

  |a|

  |b|

 Local段为:

  |v1|

  |v2|

  上面的语句执行过程为,OP_GET_LOCAL 1将变量v2 push到栈中,OP_JUMP_IF_FALSE判断栈顶v2

是否为真,如果为真则不跳转,执行then分支,反之跳转到0xXXXX处运行else分支。then分支中先将栈顶v2

弹出,然后将常量4压入栈,然后将4写入变量a。然后跳转到0xYYYY处运行后面的语句。else分支中先将

栈顶v2弹出,然后将常量5压入栈,然后将5写入变量b。

  2. 反编译为c语言

  遇到OP_JUMP_IF_FALSE,生成if语句,if的条件为栈顶元素,追踪操作栈顶的操作,为

OP_GET_LOCAL,则if语句的条件为v2。

  顺序分析到OP_SET_GLOBAL 2,此条语句写公共变量a,值为OP_CONSTANT 0压入的4,生成语句

a = 4。OP_JUMP 生成一条标签,if语句的then部分结束,因为此时汇编地址已经到达0xXXXX了。

  再来分析从0xXXXX开始处的指令,OP_SET_GLOBAL  3,此条语句写公共变量b,值为

OP_CONSTANT 1压入的5,生成语句b = 5。此时结束else分支,因为汇编地址已经到达OP_JUMP

生成的标签。

  

x86汇编反编译到c语言之——(2)if语句的更多相关文章

  1. x86汇编反编译到c语言之——(1)表达式求值及赋值语句

    一. 反编译一种可能的实现方式 我们的目的是将多种平台的汇编如x86,ARM,6502反编译为c语言,所以实现时先将多种汇编转化为 特定虚拟机汇编语言,然后只需要将虚拟机汇编语言反编译为c语言.其中多 ...

  2. apk反编译(2)smali语言及文件

    Smali语言是Davlik的虚拟机使用的一种语言,用toolapk反编译apk后,可以见到大量的.smali文件. 可以按照smali语法对其修改,然后重新生成一个未签名的apk. 下面是一个示例: ...

  3. 性能分析 函数粒度 函数里的一条语句 汇编 反编译 机器指令 %rbx,%rbp

    在Linux下做性能分析3:perf - 知乎 https://zhuanlan.zhihu.com/p/22194920 Linux Perf 性能分析工具及火焰图浅析 - 知乎 https://z ...

  4. .net反编译原理

    目录 目录 前言 ILdasm ILasm 结语 推荐文献 目录 NLog日志框架使用探究-1 NLog日志框架使用探究-2 科学使用Log4View2 前言 本来没有想写反编译相关的文章,但是写着写 ...

  5. 教你使用 Reflexil 反编译.NET 转

    转自:http://www.wxzzz.com/711.html http://sebastien.lebreton.free.fr/reflexil/ http://www.aneasystone. ...

  6. 【转载】教你使用 Reflexil 反编译.NET

    简介 反编译的方式有很多种,其实最靠谱的还是IL反编译. 如果不懂IL可以尝试我这边文章入门:http://www.wxzzz.com/278.html 不过我下面要说的不是IL这种底层的代码反编译, ...

  7. 教你使用 Reflexil 反编译.NET

    简介 反编译的方式有很多种,其实最靠谱的还是IL反编译. 如果不懂IL可以尝试我这边文章入门:http://www.wxzzz.com/278.html 不过我下面要说的不是IL这种底层的代码反编译, ...

  8. android之apk反编译

    今天就来详细的讲一讲apk的反编译过程,之前自己一直没彻底搞清楚. 一.准备工作 反编译首先要准备三个工具.这三个工具都是可以百度下载的.就是下图所示的三个工具. 这三个工具是有各自作用的: (1)a ...

  9. android 反编译和代码解读

    二 错误代码还原规则 if…else 语句: 反编译代码 if (paramBoolean) paramTextView.setTextColor(-16727809); while (true) { ...

随机推荐

  1. Go语言核心36讲(Go语言进阶技术一)--学习笔记

    07 | 数组和切片 我们这次主要讨论 Go 语言的数组(array)类型和切片(slice)类型. 它们的共同点是都属于集合类的类型,并且,它们的值也都可以用来存储某一种类型的值(或者说元素). 不 ...

  2. Java和jmeter环境变量的配置来这就对了!

    java环境变量设置 1.新建JAVA_HOME 变量 点击 新建按钮 变量名:JAVA_HOME 变量值:电脑上JDK安装的绝对路径 2.新建/修改 CLASSPATH 变量 如果存在 CLASSP ...

  3. 初学python-day11 函数3

    函数 1. global关键字 修改全局变量,声明函数内外使用同一个变量 示例: 1 name = 'xiaoming' 2 3 def test(): 4 global name 5 name = ...

  4. CentOS 文本编辑器

    目录 1.Nano 1.1.基础命令 1.2.快捷操作 1.3.配置文件 2.Vim 2.1.四大模式 2.2.基础命令 2.3.标准操作 2.4.高级操作 2.5.配置文件 Linux 终端的文本编 ...

  5. Unity——计时器功能实现

    Unity计时器 Demo展示 介绍 游戏中有非常多的计时功能,比如:各种cd,以及需要延时调用的方法: 一般实现有一下几种方式: 1.手动计时 float persistTime = 10f flo ...

  6. 为Kubernetes集群添加用户认证

    Kubernetes中的用户 K8S中有两种用户(User)--服务账号(ServiceAccount)和普通意义上的用户(User) ServiceAccount是由K8S管理的,而User通常是在 ...

  7. 高斯消元de小板几

    感觉就是模拟解方程,还比手动解方程笨一些.... 但是大数据的话,他毕竟比我解得快多了.... 1 inline int Gauss(int n){ 2 int cnt=1;//真实到达的行列式行数 ...

  8. camera HSYNC:VSYNC

    HSYNC:行锁存,换行信号VSYNC:祯锁存,换页信号 320×240的屏,每一行需要输入320个脉冲来依次移位.锁存进一行的数据,然后来个HSYNC 脉冲换一行:这样依次输入240行之后换行同时来 ...

  9. IM服务器:我的千万级在线聊天服务器集群

    一.服务器特点 01.傻瓜式部署,一键式启动: 02.单机支持10万以上在线用户聊天(8G内存,如果内存足够大,并发量可超过10万): 03.支持服务器集群,集群间高内聚.低耦合,可动态横向扩展IM服 ...

  10. 二进制插入 牛客网 程序员面试金典 C++ Python java

    二进制插入 牛客网 程序员面试金典 题目描述 有两个32位整数n和m,请编写算法将m的二进制数位插入到n的二进制的第j到第i位,其中二进制的位数从低位数到高位且以0开始. 给定两个数int n和int ...