刚写的关于如何提高反汇编代码阅读能力的帖子,顺便把一些call啊,堆栈平衡啊,局部变量访问啊这些东西结合实例说了一下
把自己写好的“hello world”程序源码加载到VC中,给main函数下个断点(F9下断点)
然后按F5运行至断点,VC把程序断下来的时候在断点代码处 右键菜单go to   disassembly就可以看汇编代码了!
而且还是一行一行,源码对照反汇编解释给你看的。。 写一个小程序 #include <stdio.h> void main(int argc[],char
*argv[]) { int a,b; a=1; b=2; a=a+b; } 然后按照我刚才说的方法看汇编代码。。
用VC看汇编代码的好处就是能对照着看,坏处就是,如果你想看指定内存地址或者寄存器的数据的话,得自己在监视窗口中添加,很麻烦,调试程序时通常要眼观八方,注意数据寄存器,内存地址,和堆栈发生的变化,所以明显VC翻译汇编代码的功能着实有点好处,但比起OD来还是有点麻烦,那还是用回OD吧,程序载入时先执行的其实不是main函数,而是编译器生成的一些初始化代码,这些代码暂且不讨论吧,直接来到main函数吧,在OD中怎么到达main函数呢,在这里介绍一个技巧:
将程序改写成如下: #include <stdio.h> void main(int argc[],char *argv[]) { char
*a="1234567"; printf("%s",a);

然后将程序载入OD,右键-查看-所有参考文本串,在弹出的窗口中招字符串“12345”,然后双击这个字符串,OD就会把你带到main函数的附近了,到了main函数附近之后,就找push
ebp吧(程序的经典开头代码) 下面把完整代码贴一遍(注意蓝色为main函数中代码 红色部分为一个校验堆栈平衡的一个函数。) 00401010 >  55  
           push ebp                           ; 保存原来的ebp 00401011    8BEC      
     mov ebp,esp                        ; 使得ebp=esp 00401013    83EC 44        
sub esp,44                         ; 预留44h个字节的空间
上面一句的详细解释:上面预留的44h个字节空间即68个字节的空间,即预留17个变量的空间(每个变量4个字节),其中我们的程序定义了一个变量--即指向常量字符串的指针a
00401016    53              push ebx 00401017    56              push esi
00401018    57              push edi ;上面三句是因为后面要用到这三个寄存器 所以为了程序执行完后不改变寄存器值
而保存他们,程序执行完后恢复 00401019    8D7D BC         lea edi,dword ptr
ss:[ebp-44];将edi设置为栈中一块连续区域的首地址 0040101C    B9 11000000     mov ecx,11        
                ; 11h=17,为什么要给ecx赋予17呢,我们往下看 00401021    B8 CCCCCCCC     mov
eax,CCCCCCCC       ;为什么要给eax赋予8个c呢,我们往下看 00401026    F3:AB           rep stos
dword ptr es:[edi]
现在开始解释上面三句,我先讲第三句吧,第三句的功能就是:将eax寄存器的值复制给由es:[edi]指向的内存区域,复制多少次呢?
ecx次!就是17次,就是将17个eax放到以es:[edi]为首地址的内存区域中,这样做没别的意思,就是初始化变量而已。
00401028    C745 FC 1C00420>mov dword ptr ss:[ebp-4],CPPlearn.>;
把字符串常量的指针给ss:[ebp-4]也就是我们定义的指针变量a 0040102F    8B45 FC         mov eax,dword ptr
ss:[ebp-4]       ; 再将指a赋值给eax 00401032    50              push eax 00401033  
 68 B0074200     push CPPlearn.004207B0             ; ASCII "%s" 00401038    E8
53000000     call CPPlearn.printf 0040103D    83C4 08         add esp,8        
                 ; 压栈调用函数,然后由主程序恢复堆栈平衡 压栈调用函数,你懂的! 00401040    5F            
 pop edi 00401041    5E              pop esi 00401042    5B              pop
ebx                            ; 犯罪现场重现 00401043    83C4 44         add esp,44
                        ; 释放掉占44h字节大小的在main中的所有变量 00401046    3BEC          
 cmp ebp,esp,在这里如果因为一些意外而使得恢复之后的esp不等于原来的esp(原来的esp保存在ebp)的话,将会出现一些问题,继续往下看
00401048    E8 C3000000     call CPPlearn._chkesp { 00401110 > /75 01          
jnz short CPPlearn.00401113        ; 当ebp与esp相等时,属于正常情况,所以就不跳转了直接
返回主程序,其实我觉得这个判断应该由主程序来做,那就不用进call了,进call要浪费点时间。这里为了跟踪代码,我故意将Z标志位改成0(即比较结果不为0)
所以他的jnz就能实现跳转了。(跳到下面的401112去了) 00401112   |C3              retn 00401113   \55
             push ebp                           ; 又一个子程序,犯罪现场保存恢复这些垃圾话我就不说了
00401114    8BEC            mov ebp,esp 00401116    83EC 00         sub esp,0
00401119    50              push eax 0040111A    52              push edx
0040111B    53              push ebx 0040111C    56              push esi
0040111D    57              push edi 0040111E    68 54004200     push
CPPlearn.00420054             ; ASCII "The value of ESP was not properly saved
across a function call.  This is usually a result of calling a function
declared with one calling convention with a function pointer declared with a
different calling convention. " 00401123    68 50004200     push
CPPlearn.00420050 00401128    6A 2A           push 2A 0040112A    68 40004200  
  push CPPlearn.00420040             ; ASCII "i386\chkesp.c" 0040112F    6A 01
          push 1 00401131    E8 CA140000     call
CPPlearn._CrtDbgReport//在这里会弹出一个警告的对话框,里面有调试按钮,忽略按钮 等等 00401136    83C4 14    
    add esp,14 00401139    83F8 01         cmp eax,1                          ;
在这里我点击了ignore按钮,所以跳过了下面的int 3指令 0040113C    75 01           jnz short
CPPlearn.0040113F 0040113E    CC              int3 0040113F    5F            
 pop edi                            ; 然后一直走着走着就回去了~~ 00401140    5E            
 pop esi 00401141    5B              pop ebx 00401142    5A              pop edx
00401143    58              pop eax 00401144    8BE5            mov esp,ebp
00401146    5D              pop ebp 00401147    C3              retn } 0040104D
   8BE5            mov esp,ebp                        ; 程序执行完了,esp自然要恢复了
0040104F    5D              pop ebp                            ; 把原来的ebp要回来
00401050    C3              retn

技术
©2019-2020 Toolsou All rights reserved,
数字滚动抽奖小程序VaR - 风险价值 - 蒙特卡罗法 - Python百度网盘偷偷更新,终于实现免费不限速了! Chrome OS,对程序员和Windows意味着什么?,互联网营销华为Mate 40 Pro+ 5G曝光:徕卡电影镜头、陶瓷机身Qt学习2——.pro文件和.h文件介绍python:将一个文件转换为二进制文件(binary)第十一届蓝桥杯C/C++ 大学 B 组大赛软件类省赛网站手机号码抓取方式蚂蚁集团香港IPO获得中国证监会批准