【学习逆向工程,分析机器代码】(二)(C++篇)

【学习逆向工程,分析机器代码】(二)(C++篇)

by dreamerate


1、序


  大家好!再一次和大家见面了!我这次要告诉大家的是,一个C++程序产生的机器代码到底长什么样?通过这些代码及注释加以分析,您应该能了解C++程序的一些底层机制及CRT内幕!^_^

本篇算是根据ATField大侠的文章所衍生的续集!大家可访问ATField大侠的blog: http://blog.csdn.net/atfield/archive/2006/11/14/1382694.aspx,他可是一个很全面的高手哦!

  切入主题,由ATField大侠提供的简单C++小程序原代码,本人略作小许修改并重新进行了一次编译,然后再用OllyDbg进行了跟踪分析。发现在反汇编这些代码出入很大哦!终究其原因:编译器的差别(我用VC++6.0E,他用的是VC++8.0)。

例如像D8H的这个分配过程换来的而是8H,就两个MACHINE WORD(32位CPU的机器字。一个机器字占4个字节):

第一个是指向本对象地址,第二个搞不清楚是用来做什么用的(郁闷……),有谁知道吗?


2、一个具体而微的C++小程序


   包括内容:一个C++ entry point函数main及一个class。本文的中心思想是分析C++类机制。

------------------------------------------------------------------------

源程序如下:

#include <windows.h>
#include <stdio.h>

class my_class
{
public:
    my_class()
    {
        m_member = 1;
    }

    void method( int n )
    {
        m_member = n;
    }

    ~my_class()
    {
        m_member = 0;
    }
   
private:
    int m_member;
};


int main( int argc, char** argv )
{
    my_class a_class;
    printf( "I'm testor!" );
    a_class.method( 0x111 );
    return 0;
}

------------------------------------------------------------------------


3、编译


  在XP SP2环境下,开一个cmd.exe,键入VC6,进入我们的test.cpp目录,键入bcpp test,完成编译。
以下是vc6.bat及bcpp.bat的内容:

VC6.bat
-----------------------------------------------------------------------
@echo off
set VC6DIR=I:/Program Files/Microsoft Visual Studio/VC98
set include=I:/DXSDK/Include;%VC6DIR%/Include;%VC6DIR%/atl/include;%VC6DIR%/mfc/include
set lib=I:/DXSDK/Lib;%VC6DIR%/lib;%VC6DIR%/mfc/lib
set path=c:/;I:/Program Files/Microsoft Visual Studio/Common/MSDev98/Bin;%VC6DIR%/Bin
set %VC6DIR%=
echo on
-----------------------------------------------------------------------

bcpp.bat
-----------------------------------------------------------------------
@echo off
if exist %1.obj del %1.obj
if exist %1.exe del %1.exe
cl /c /Gz /GX %1.cpp
if not exist %1.obj goto EXITFLAG
link /machine:x86 /subsystem:console %1.obj user32.lib kernel32.lib gdi32.lib
if not exist %1.exe goto EXITFLAG
%1.exe
:EXITFLAG
-----------------------------------------------------------------------


4、逆向过程


   打开OllyDBG,加载test.exe,然后在00401000地址设置断点。按下F9后我们来到断点处,接着便是F8一路逐行分析代码:

-------- ---- ------------  -------------------------------------   ----------------------------------------------------
地址     流程 机器代码      汇编代码                                注释
-------- ---- ------------  -------------------------------------   ----------------------------------------------------

00401000  /$  55            push    ebp                             ;  保存旧的ebp
00401001  |.  8BEC          mov     ebp, esp                        ;  ebp保存当前栈的位置

00401003  |.  6A FF         push    -1                              ;  建立SEH链. ERR结构第三成员
00401005  |.  68 69684000   push    test.00406869                   ;  Structured Exception处理程序. ERR结构第二成员
0040100A  |.  64:A1 0000000>mov     eax, dword ptr fs:[0]           ;  fs:0指向当前线程的TEB
00401010  |.  50            push    eax                             ;  我们将它备份起来并且设为ERR结构第一成员
00401011  |.  64:8925 00000>mov     dword ptr fs:[0], esp           ;  建立当前的SEH的ERR结构(利用栈)

00401018  |.  83EC 08       sub     esp, 8                          ;  my_class a_class;
0040101B  |.  8D4D F0       lea     ecx, dword ptr ss:[ebp-10]      ;  a_class对象指针ECX
                                                                    ;  它指向值第一个private成员int m_member
0040101E  |.  E8 4D000000   call    test.00401070                   ;  呼叫构造函数

00401023  |.  C745 FC 00000>mov     dword ptr ss:[ebp-4], 0         ;  进入__try块,在Main中有一个隐式的__try/__except块

0040102A  |.  68 40804000   push    test.00408040                   ;  ASCII "I'm testor!"
0040102F  |.  E8 90000000   call    test.004010C4                   ;  printf
00401034  |.  83C4 04       add     esp, 4                          ;  释放前一个CALL的push

00401037  |.  68 11010000   push    111                             ; /Arg1 = 00000111
0040103C  |.  8D4D F0       lea     ecx, dword ptr ss:[ebp-10]      ; |                 <- a_class对象指针ECX
0040103F  |.  E8 4C000000   call    test.00401090                   ; /a_class.method

00401044  |.  C745 EC 00000>mov     dword ptr ss:[ebp-14], 0        ;  有谁知道这个DWORD是用来干什么的吗?

0040104B  |.  C745 FC FFFFF>mov     dword ptr ss:[ebp-4], -1        ;  标记TRY的正常结束

00401052  |.  8D4D F0       lea     ecx, dword ptr ss:[ebp-10]      ;  a_class对象指针ECX
00401055  |.  E8 56000000   call    test.004010B0                   ;  析构函数

0040105A  |.  8B45 EC       mov     eax, dword ptr ss:[ebp-14]      ;  ?奇怪哦!最接近ret的eax应该是本函数的返回值!
                                                                    ;  直接在最尾test eax, eax不就行了吗? 为什么要这样...
 
0040105D  |.  8B4D F4       mov     ecx, dword ptr ss:[ebp-C]       ;  恢复之前保存的TEB
00401060  |.  64:890D 00000>mov     dword ptr fs:[0], ecx

00401067  |.  8BE5          mov     esp, ebp                        ;  你知道...
00401069  |.  5D            pop     ebp

0040106A  /.  C3            retn                                    ;  恢复CALL影响的STACK及定位EIP

--------------------------------------------------------------------------------------------------

00401070  /$  55            push    ebp                             ;  my_class类构造函数
00401071  |.  8BEC          mov     ebp, esp
00401073  |.  51            push    ecx
00401074  |.  894D FC       mov     dword ptr ss:[ebp-4], ecx
00401077  |.  8B45 FC       mov     eax, dword ptr ss:[ebp-4]
0040107A  |.  C700 01000000 mov     dword ptr ds:[eax], 1
00401080  |.  8B45 FC       mov     eax, dword ptr ss:[ebp-4]
00401083  |.  8BE5          mov     esp, ebp
00401085  |.  5D            pop     ebp
00401086  /.  C3            retn

--------------------------------------------------------------------------------------------------

00401090  /$  55            push    ebp                             ;  void my_class::method(int n)
00401091  |.  8BEC          mov     ebp, esp
00401093  |.  51            push    ecx
00401094  |.  894D FC       mov     dword ptr ss:[ebp-4], ecx
00401097  |.  8B45 FC       mov     eax, dword ptr ss:[ebp-4]
0040109A  |.  8B4D 08       mov     ecx, dword ptr ss:[ebp+8]       ;  参数int n
0040109D  |.  8908          mov     dword ptr ds:[eax], ecx
0040109F  |.  8BE5          mov     esp, ebp
004010A1  |.  5D            pop     ebp
004010A2  /.  C2 0400       retn    4

--------------------------------------------------------------------------------------------------

004010B0  /$  55            push    ebp                             ;  my_class类析构函数
004010B1  |.  8BEC          mov     ebp, esp
004010B3  |.  51            push    ecx
004010B4  |.  894D FC       mov     dword ptr ss:[ebp-4], ecx
004010B7  |.  8B45 FC       mov     eax, dword ptr ss:[ebp-4]
004010BA  |.  C700 00000000 mov     dword ptr ds:[eax], 0
004010C0  |.  8BE5          mov     esp, ebp
004010C2  |.  5D            pop     ebp
004010C3  /.  C3            retn

--------------------------------------------------------------------------------------------------

004010C4  /$  53            push    ebx                             ;  CRT函数printf
004010C5  |.  56            push    esi
004010C6  |.  BE 90804000   mov     esi, test.00408090
004010CB  |.  57            push    edi
004010CC  |.  56            push    esi
004010CD  |.  E8 20050000   call    test.004015F2
004010D2  |.  8BF8          mov     edi, eax
004010D4  |.  8D4424 18     lea     eax, dword ptr ss:[esp+18]
004010D8  |.  50            push    eax
004010D9  |.  FF7424 18     push    dword ptr ss:[esp+18]
004010DD  |.  56            push    esi
004010DE  |.  E8 D9050000   call    test.004016BC
004010E3  |.  56            push    esi
004010E4  |.  57            push    edi
004010E5  |.  8BD8          mov     ebx, eax
004010E7  |.  E8 93050000   call    test.0040167F
004010EC  |.  83C4 18       add     esp, 18
004010EF  |.  8BC3          mov     eax, ebx
004010F1  |.  5F            pop     edi
004010F2  |.  5E            pop     esi
004010F3  |.  5B            pop     ebx
004010F4  /.  C3            retn
-------------------------------------------------------------------------------------------------------------------


5、总结


   懒得写了,哥们看注释吧!:)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值