一次简单的反汇编

简介: 一次简单的反汇编代码

首先,为了方便我们后面的逆向,我们选择一个简单的编译开发环境。
这里,我选择TC2.0
TC2.0是一个集成的开发环境,它集成了以下文件:
TC.EXE 集成编译器
EMU.LIB 8087仿真库 ,作用:系统将同8087仿真器连接,得到exe文件,只能用于程序的编译。
CS.LIB 不同模式运行库 ,作用:对于windows下程序的运行模式有很多种,普通用户模式、管理员模式,不同的运行模式,可能决定用户获得的不同的信息,该库决定了程序在不同模式下的运行机制。
C0S.OBJ 不同模式的共同启动代码
MATHS.LIB MATH(C、H、L、M、S).lib是编译器的五种存储模式,该maths.lib规定了tc2.0编译器的存储模式,连接成.exe的前提条件之一。
GRAPHICS.LIB C语言图形编程 图形库文件:
因为在编写C的图形程序时,用到了字体,文字库等库文件,生成的exe文件必须与这些库文件放在一起,程序才能正确跑起来,为了方便,我将这些文件都连接到了GRAPHICS.LIB这个文件中,以后编译好自己的程序后,只需一个exe文件就可以运行了,不需要别的什么文件了。
a_1_1_
**OK,我们最简易的集成环境搭建完成,接下来,我们将在这里写出.c,编译链接成.exe文件
**
在我们程序运行之前,系统大多会为我们程序将要使用的内存资源进行分配,然后运行我们的程序工作,结束后程序在对分配给我们的资源进行释放。
资源分配程序->我们写的程序->资源释放程序
TC2.0开发环境下资源分配程序与资源释放程序都C0S.OBJ中。
C0S.OBJ中代码结构类似:

start;
运行资源分配程序
调用main函数
运行资源释放程序
end;

于是,我们重写了C0S.OBJ。
b_2_1_
红色部分是为我们.c程序申请栈空间与数据存储空间相当于资源分配程序
蓝色部分等价于main函数调用,调用的是s:这个地址后面储存的指令。相当于运行main函数
绿色部分为结束我们的程序进程,cpu的使用权交付给cpu,相当于资源释放程序

好,我们写一个c程序编译连接必要的库和启动代码。
c程序如下:
c_1_
这里面我们没用main函数,因为我们自己重写了启动代码,所以有没有main函数已经无所谓了,我们这个代码链接的时候会自动的插入启动代码的S:后面。被当做main函数调用。
ds:0X100默认保存为数组的内存空间(这里搞了好久才发现,具体原因未知,留个疑问,待以后解决吧)
0xb800:0000为显存的地址,把字符放到这里会自动显示到显示屏上,单位2Byte,结构为(字符,属性),即低位存字符,高位存属性,0x2是字符的属性,绿色。
一个简单的输出KISS程序就写好了。
我们运行试一试:
d_1_
看,程序的第一行显示了绿色的KISS,成功。

于是,重点来了:(这里才是重点!!!)我们用windows自带的debug反汇编一下,得到如下汇编指令
我把这些指令全部翻译了一遍。

0B57:0000 B84F0B        MOV     AX,0B4F
0B57:0003 8ED0          MOV     SS,AX
0B57:0005 BC8000        MOV     SP,0080     
0B57:0008 E80500        CALL    0010                            ;调用jazzi函数
0B57:000B B8004C        MOV     AX,4C00
0B57:000E CD21          INT     21                              ;资源分配资源销毁 的启动程序
 
0B57:0010 55             PUSH    BP
0B57:0011 8BEC          MOV     BP,SP                           ;保存进入函数前的栈顶地址
 
0B57:0013 83EC02        SUB     SP,+02                          ;进入函数后,int i=0中的i内存保存在以原栈顶为栈底的栈中
0B57:0016 56                PUSH    SI                          ;si在子函数中值可能改变,所以原si值入栈
0B57:0017 33F6              XOR     SI,SI                       ;si=0 
0B57:0019 C746FE0000    MOV     WORD PTR [BP-02],0000           ;给i=0
0B57:001E 33F6              XOR     SI,SI                       ;si=0 
0B57:0020 EB32              JMP     0054
0B57:0022 8BDE              MOV     BX,SI                       ;等价于temp=i
0B57:0024 81C30001          ADD     BX,0100                     ;等价于temp=0x100+i
0B57:0028 8A07              MOV     AL,[BX]                     ;把ds:[0x100+i]中的值赋给AL,即‘K’'I''S''S'ascll码的十
                                                                ;六进制
0B57:002A 50                PUSH    AX                          ;+++++++++++++保存AX的值,因为以下代码要改变AX
0B57:002B 8BC6              MOV     AX,SI                       ;ax=i
0B57:002D D1E0              SHL     AX,1                        ;ax=2*i
0B57:002F 99                CWD                                 ;将ax变为双字节,高16位都为0
0B57:0030 050000            ADD     AX,0000                     ;ax=i*2+0
0B57:0033 81D200B8          ADC     DX,B800                     ;显存的段地址
0B57:0037 8BD8              MOV     BX,AX                       ;把ax的低16位赋给bx,即bx存着显存的最初偏移地址0000
0B57:0039 8EC2              MOV     ES,DX                       ;把显存的段地址赋给ES
0B57:003B 58                POP     AX                          ;+++++++++++++恢复AX的值
0B57:003C 26                ES:                                 ;改变[]的段地址罢了
0B57:003D 8807              MOV     [BX],AL                     ;因为显存中低位装着字符,所以把字符赋给这个显存地址
0B57:003F 8BC6              MOV     AX,SI                       ;-----------------------------------
0B57:0041 D1E0              SHL     AX,1                        ;与上面套路相同
0B57:0043 99                CWD
0B57:0044 050100            ADD     AX,0001
0B57:0047 81D200B8          ADC     DX,B800                     ;ax=i*2+1
0B57:004B 8BD8              MOV     BX,AX               
0B57:004D 8EC2              MOV     ES,DX                       ;------------------------------------
0B57:004F 26                ES:
0B57:0050 C60702            MOV     BYTE PTR [BX],02            ;只不过这里是吧02这个值赋给显存地址的高位,02表示绿色
0B57:0053 46                INC     SI                          ;等价于i++
0B57:0054 83FE04            CMP     SI,+04                      ;比较si是否为4,如果是4则退出
0B57:0057 7CC9              JL      0022                        ;如果si小于4,转移到22处
 
0B57:0059 5E                POP     SI                          ;原si值出栈,si恢复刚开始的值
0B57:005A 8BE5              MOV     SP,BP                       ;将子函数的栈中元素全部出栈,栈顶恢复为原栈顶的位置
0B57:005C 5D                POP     BP                          ;栈底恢复为原栈底的位置
0B57:005D C3                RET                                 ;程序交付启动函数处理后续
目录
相关文章
|
11月前
|
存储 机器学习/深度学习 小程序
|
11月前
|
人工智能 编译器 数据处理
|
11月前
|
存储 安全 Unix
|
Java 编译器
javap(反汇编命令)详解【转】
转自:http://blog.csdn.net/hudashi/article/details/7062668 javap是JDK自带的反汇编器,可以查看java编译器为我们生成的字节码。通过它,我们可以对照源代码和字节码,从而了解很多编译器内部的工作。
1124 0
|
Android开发 Python
【Android 逆向】使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 反汇编二进制机器码 | 打印反汇编数据 )
【Android 逆向】使用 Python 解析 ELF 文件 ( Capstone 反汇编 ELF 文件中的机器码数据 | 反汇编二进制机器码 | 打印反汇编数据 )
183 0
|
编译器 C语言 C++
用汇编分析C++程序,x86汇编
  说到用汇编的眼光看C++语言,那么怎么阅读汇编代码就成了我们需要解决的一个问题。其实,实话说,汇编其实不难。只是我们需要明白这样几个问题:   (1)汇编是什么语言?   (2)汇编中的主要内容有哪些?   (3)汇编语言是怎么和实际C/C++语言代码一一对应的?
149 0
|
存储 数据采集 监控
初学汇编
初学汇编
176 0
初学汇编
反汇编与反编译
反汇编得到的是汇编代码 反编译的到的是语言的源代码
568 0
|
C语言 芯片
使用 gcc 命令把C语言程序反汇编
之前看过一点汇编,不过现在都忘记得差不多了。最近又很蛋疼地想起反汇编这个东西。这里使用 gcc 命令对 .c 文件进行反汇编,把 C语言 翻译成汇编语言 先准备一个简单的 C 程序 sum.c #include int add(int, int); int mode(int, i...
3761 0
|
C++
我为什么要学习C++反汇编
写在开始 从6月7日开始到今天已经有5天了,在这5天的业余时间(工作之余)里终于系统的完成了C++反汇编的大部分问题的学习,今天写篇总结,算是对这几天学习的总结。 首先我想说明的一个问题就是我为什么要花时间研究C++反汇编? 这事得从笔者遇到的一个问题开始说起,大约2周前我们项目做在开发过程中遇到了一个Crash的问题,由于只有客户提供的一个.
952 0