cu629944 发表于 2012-4-1 13:18

菜鸟学逆向——简单的反汇编阅读与逆向(1)

本帖最后由 cu629944 于 2012-4-1 13:20 编辑

【文章标题】: 菜鸟学逆向——简单的反汇编阅读与逆向(1)
【文章作者】: Silence(cu629944,等试用期通过,我会修改ID为Silecne)
【作者邮箱】: mohen_ng@sina.cn
【下载地址】: 自己搜索下载
【编写语言】: VC++6.0
【操作平台】: WIN 7
【软件介绍】: IDA VC++6.0
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
    我会写一个系列的文,希望大家能够支持,这是第一篇

    我们先启动VC++6.0,输入下面的程序

    程序很短,大家看我输入一次,留意成对编码原则,防止对低级的错误

    #include <stdio.h>
    void Silence(int a,int b)
    {
            int c =a + b;
    }
    void main()
    {
            Silence(1,2);
    }

    一个简单的有2个形参的Silence()函数,接着在main()主函数调用Silence()函数。

    编译成Debug模式,Realse版本会把调试信息等去掉。

    我们用VC6.0自带的调试器,复制一个反汇编代码出来(为什么不立即用IDA看呢?因为VC6.0会把源码和反汇编代码一一对应起来,方便我们在IDA对照查看)

    void main()
    9:    {
    00401060   push                ebp                        
    00401061   mov                ebp,esp
    00401063   sub               esp,40h
    00401066   push                ebx
    00401067   push                esi
    00401068   push                edi
    00401069   lea               edi,
    0040106C   mov               ecx,10h
    00401071   mov                eax,0CCCCCCCCh
    00401076   rep stos   dword ptr
    10:       Silence(1,2);
    00401078   push               2
    0040107A   push               1
    0040107C   call                @ILT+5(_Silence) (0040100a)
    00401081   add               esp,8
    11:   }
    00401084   pop         edi
    00401085   pop         esi
    00401086   pop         ebx
    00401087   add         esp,40h
    0040108A   cmp      ebp,esp
    0040108C   call       __chkesp (004010b0)
    00401091   mov      esp,ebp
    00401093   pop      ebp
    00401094   ret

    然后我们载入IDA里面。IDA非常智能,载入分析完成后,直接停到了我们的main()函数处。我们就离线分析下他的每句话的作用。

    ; Attributes: bp-based frame

    _main proc near

    var_40= byte ptr -40h

    push    ebp             ; 保存EBP
    mov   ebp, esp      ; 原EBP值已经被压栈(位于栈顶),而新的EBP又恰恰指向栈顶。
                            ; 此时EBP寄存器就已经处于一个非常重要的地位,该寄存器中存储着栈中的一个地址(原EBP入栈后的栈顶),
                            ; 从该地址为基准,向上(栈底方向)能获取返回地址、参数值,向下(栈顶方向)能获取函数局部变量值,
                            ; 而该地址处又存储着上一层函数调用时的EBP值!
    sub   esp, 40h      ; 为局部变量申请空间,大小为40h(注意40h是16进制数,用IDA看看转换成10进制为多少,为64)
    push    ebx
    push    esi
    push    edi
    lea   edi, ; Var_40是IDA自己分析出来的,表示为局部变量,就是SUB ESP,40h分配的40h个大小,目的是保存局部变量的区域
    mov   ecx, 10h
    mov   eax, 0CCCCCCCCh ; 从ebp-40h开始的区域初始化成全部0CCCCCCCCh,就是int3断点
    rep stosd               ; 拷贝字符串,初始化局部变量空间
                            ; 以上的语句就是在栈中开辟一块空间放局部变量
                            ; 然后把这块空间都初始化为0CCCCCCCCh,就是int3断点,一个中断指令。
                            ; 因为局部变量不可能被执行,执行了就会出错,这时候发生中断提示开发者。
    push    2               ;
                            ; 参数2入栈
                            ; 这里就是我们在test.c的源代码里面写的那个Silence(1,2);函数,这里有一个很重要的概念
                            ; 就是调用约定,在 c/c++ 中, 函数的默认调用约定为 cdecl, 它约定参数从右到左入栈,
                            ; 由调用者清理堆栈, 所谓清理, 即调整ESP的值, 使得原来的局部数据不再属于栈
                            ;
    push    1               ; 参数1入栈
                            ;
    call    Func__Silence   ; 调用我们定义的Silence函数
                            ; 其实call 指令调用一个过程, 但它有一个小动作
                            ; 在参数入栈以后, 被调用函数执行 之前, 它会将当前函数的下一条指令地址, 即EIP的值压入
                            ;
    add   esp, 8          ; 调用完函数后恢复/释放栈
    pop   edi             ; 以下三句都是恢复三个保存的寄存器
    pop   esi
    pop   ebx
    add   esp, 40h      ; 这句对应的是上面的SUB ESP,40h,恢复堆栈,
    cmp   ebp, esp      ; 检测ESP是否恢复正常,如果不正常将调用下面的Chkesp
    call    __chkesp      ; 处理可能出现的堆栈错误(如果出错,将陷入debug)。
    mov   esp, ebp      ; 还记得上面那句mov ebp,esp吗?EBP里面保存着我们初始状态的ESP值,这句是将栈顶指针放回esp
    pop   ebp             ; 恢复原来的ebp和esp,让上一个调用的函数正常使用
    retn                  ; 将返回地址存入EIP, 转移流程
    _main endp            ;
                            ; 以上那部分代码在VC的Debug调试版才会有,主要检查栈是否被破坏了。这样就能及时在你出错的地方停下了告诉你。
                            ; 发行版自动消除这些代码(调试产生的)。
                            ; 如果函数有返回值,返回值将放在eax返回(这就是很多软件给秒杀爆破的原因了,因为eax的返回值是可以改的)

    下面来看看Silence()函数

    ; Attributes: bp-based frame

    _Silence proc near

    var_44= byte ptr -44h
    var_4= dword ptr -4
    arg_0= dword ptr8
    arg_4= dword ptr0Ch

    push    ebp             ; 下面的这几句和上面我们分析的一样,所以我们对Silence函数只分析不同的地方
    mov   ebp, esp
    sub   esp, 44h      ; 这里将局部变量的大小分配为44h
    push    ebx
    push    esi
    push    edi
    lea   edi,
    mov   ecx, 11h
    mov   eax, 0CCCCCCCCh
    rep stosd
    mov   eax,     ; 取第一个参数放到EAX里面,即参数a
    add   eax, ; 与保存在EBP+0Ch里面的参数b相加
    mov   , eax    ; 返回值放到ebp - 4里面,即最终结果放到参数c里面
                            ;
                            ; 一般而言,ss:处为返回地址
                            ; ss:处为第一个参数值(这里是a),ss:处为第二个参数(这里是b,这里8+4=12=0Ch)
                            ; ss:处为第一个局部变量(这里是c),ss:处为上一层EBP值
                            ; ebp和函数返回值是32位,所以占4个字节
    pop   edi
    pop   esi
    pop   ebx
    mov   esp, ebp
    pop   ebp
    retn
    _Silence endp

    到此处,我们就将这些代码翻译完毕了。有很多收获。

    根据我们这些分析,我们就可以逆向出我们的源码了(只看IDA反汇编的部分哈!):


    我们可以在IDA里面看到main函数没有返回值,和Cdecl调用约定的规则,我们就可以恢复出来main函数的代码。

void main()
    {
      Silence(1,2);
    }

    我们分析Silecne函数的反汇编代码,可以看出在每个局部变量里面,都是用的, ,等,我们可以发现都是4的倍数,我们知道INT类型,占4个字节,且这个函数有三个参数,而且也没有返回值,下面我们就可以恢复Silence的函数部分的代码:

    voidSilence(int a,int b)
    {
          int c = a + b;
    }

    然后我们整理下,就可以得到完整的代码:

   void Silence(int a,int b)
    {
         int c = a +b;
    }

    void main()
    {
      Silence(1,2);
    }

--------------------------------------------------------------------------------
【经验总结】
    里面讲了比较重要的,调用约定,大家可以百度下看看什么叫做调用约定。还有局部变量等是怎么在汇编中存在的,已经返回值的保存地址,及如何对返回值修改达到对程序的爆破。这就是一个简单的反汇编阅读和逆向了。我们可以恢复出我们的代码。

--------------------------------------------------------------------------------
【版权声明】: 本文原创于吾爱破解技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                         2012年04月01日 11:38:05



wgz001 发表于 2012-4-1 13:25

期待后续{:1_921:}

又一菜鸟 发表于 2012-4-1 13:36

给你加分,楼主辛苦了

formore 发表于 2012-4-1 14:00

good, 继续加油

willJ 发表于 2012-4-1 15:05

LZ可以将几种调用约定都讲下就更好了,不错的文章

夏若 发表于 2012-4-1 17:50

膜拜,给我加分!{:301_1005:}

明次 发表于 2012-4-1 19:42

好,支持笨笨阿姨

12394613643 发表于 2012-4-1 20:08

实用的教程

0#1 发表于 2012-4-1 20:26

支持原创,期待后续

pking5465 发表于 2012-4-2 11:34

先压箱底,以后绝对能用上   感谢原创
页: [1] 2 3
查看完整版本: 菜鸟学逆向——简单的反汇编阅读与逆向(1)