找回密码
 立即注册

QQ登录

只需一步,快速开始

1401软件论坛总版规【新人必看】如何正确发布收费帖子加入vip系统学习仅需498元免费获得1401软件安全论坛vip开通本站VIP会员请联系QQ 564853771
论坛纪念优盘Beyond EXE超强加密器V1.61401论坛破解工具包 2017-9-12[破解班vip]入门篇[破解班vip]基础篇
[破解班vip]脱壳篇[破解班vip]实战篇[破解班vip]网络验证篇[破解班vip]零基础HOOK教程[破解班vip]零基础易语言入门
[破解班vip]零基础c语言入门[破解班vip]零基础Delphi编程入门[破解班vip]寒假培训课程共7课[破解班vip]破解提高篇[破解班vip]易语言培训课程
[破解班vip]核心技术培训篇[破解班vip]pe格式与pe操作[破解班vip]2022全新封包-山寨-爆破全系列[原创课程]c++单文档框架课程[逆向班vip]汇编语句与反汇编基础
[逆向班vip]全自动扫雷辅助[逆向班vip]手机模拟按键[逆向班vip]植物大战僵尸辅助广告位招租...付费破解软件 +Q 564853771
查看: 4560|回复: 0

【转】《基于VC平台下C++反汇编与逆向分析研究——No.4》

[复制链接]
  • TA的每日心情
    郁闷
    2024-4-18 08:48
  • 签到天数: 2752 天

    [LV.Master]伴坛终老

    963

    主题

    3310

    回帖

    2万

    积分

    管理员

    UID
    1
    元宝
    63683
    威望
    4309
    贡献
    607
    信誉值
    0
    精华
    34
    在线时间
    3589 小时
    注册时间
    2014-1-5
    最后登录
    2024-4-18
    违规
    -2
    积分
    22613

    最佳新人活跃会员推广达人宣传达人灌水之王突出贡献吾爱富翁论坛元老在线王已有小成管理团队

    QQ
    发表于 2015-11-22 23:49:09 | 显示全部楼层 |阅读模式
    Ȧ
    ————————————————————————————————————————————————
    分析环境:WIN7sp1
    所用工具:VC++6.0/OllyDBG/IDA
    适用人群:有一定计算机基础,熟悉C/C++编程,熟悉X86系列汇编/了解OD/IDA等调试工具使用,对逆向安全有极大兴趣者!
    ————————————————————————————————————————————————
    开篇前言:
            数据类型和运算符是任何编程语言的基础,而对于逆向而言亦是,只有牢固的基础才能走得更远...



    ————————————————————————————————————————————————
    正文部分:
           本节主要从汇编层面来全面解析程序的基本流程控制语句:while,do-while,goto 如下:
    ___________________________________________________________________________________________________
    本帖隐藏的内容
    • #include < stdio.h >
    • int main()
    • {
    •     int x = 1,
    •     y = 0;
    •     while (x <= 100)
    •     {
    •         y = x + y;
    •         x++;
    •     }
    •     printf("%d", y);
    •     return 0;
    • }

    [color=rgb(81, 112, 58) !important]复制代码


    ___________________________________________________________________________________________________
    上面是一个使用while语句来计算1+2+3...+100的和的程序,使用了一个计数器!

    Debug版本:
    00401010 >|> \55            push ebp                                 ;  ebp入栈保存
    00401011  |.  8BEC          mov ebp,esp                              ;  esp保存到ebp
    00401013  |.  83EC 48       sub esp,0x48                             ;  开辟局部变量空间
    00401016  |.  53            push ebx                                 ;  ebx入栈保存
    00401017  |.  56            push esi                                 ;  esi入栈保存
    00401018  |.  57            push edi                                 ;  edi入栈保存
    00401019  |.  8D7D B8       lea edi,[local.18]                       ;  设置CC操作起始化地址
    0040101C  |.  B9 12000000   mov ecx,0x12                             ;  设置循环次数
    00401021  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC                       ;  赋值eax CC int 3
    00401026  |.  F3:AB         rep stos dword ptr es:[edi]              ;  循环复制cc
    00401028  |.  C745 FC 01000>mov [local.1],0x1                        ;  赋值局部变量x
    0040102F  |.  C745 F8 00000>mov [local.2],0x0                        ;  赋值局部变量y
    00401036  |>  837D FC 64    /cmp [local.1],0x64                      ;  测试x是否为100
    0040103A  |.  7F 14         |jg short Test3.00401050                 ;  如果为100就跳出while循环
    0040103C  |.  8B45 FC       |mov eax,[local.1]                       ;  变量x值放入eax
    0040103F  |.  0345 F8       |add eax,[local.2]                       ;  x+y的值放入eax
    00401042  |.  8945 F8       |mov [local.2],eax                       ;  eax的值放入变量y
    00401045  |.  8B4D FC       |mov ecx,[local.1]                       ;  变量x的值放入ecx
    00401048  |.  83C1 01       |add ecx,0x1                             ;  exc自加1
    0040104B  |.  894D FC       |mov [local.1],ecx                       ;  ecx赋值到变量x
    0040104E  |.^ EB E6         \jmp short Test3.00401036                ;  无条件跳转到while条件判断处
    00401050  |>  8B55 F8       mov edx,[local.2]                        ;  最终y的值放入edx
    00401053  |.  52            push edx                                 ; /<%d>
    00401054  |.  68 1C204200   push Test3.0042201C                      ; |format = "%d"
    00401059  |.  E8 32000000   call Test3.printf                        ; \printf
    0040105E  |.  83C4 08       add esp,0x8                              ;  恢复esp
    00401061  |.  33C0          xor eax,eax                              ;  eax清零
    00401063  |.  5F            pop edi                                  ;  恢复edi
    00401064  |.  5E            pop esi                                  ;  恢复esi
    00401065  |.  5B            pop ebx                                  ;  恢复ebx
    00401066  |.  83C4 48       add esp,0x48                             ;  恢复局部变量空间
    00401069  |.  3BEC          cmp ebp,esp                              ;  测试堆栈平衡
    0040106B  |.  E8 A0000000   call Test3._chkesp                       ;  调用调试信息
    00401070  |.  8BE5          mov esp,ebp                              ;  恢复esp
    00401072  |.  5D            pop ebp                                  ;  恢复ebp
    00401073  \.  C3            retn                                     ;  返回  ret   add esp,4


    while循环基本结构:

    cmp ;判断while条件是否满足  
    jg ;不满足就跳出while循环
    ... ;while执行体
    jmp ;无条件跳转到条件判断处

    Release版本:
    00401000  /$  B8 01000000   mov eax,1                                ;  eax赋值为1
    00401005  |.  33C9          xor ecx,ecx                              ;  清零ecx,计数之用
    00401007  |>  03C8          /add ecx,eax                             ;  eax加上ecx放入ecx
    00401009  |.  40            |inc eax                                 ;  eax自加1
    0040100A  |.  83F8 64       |cmp eax,64                              ;  和100做比较
    0040100D  |.^ 7E F8         \jle short Test3.00401007                ;  如果不满足条件就跳回add ecx,eax
    0040100F  |.  51            push ecx                                 ;  参数
    00401010  |.  68 30704000   push Test3.00407030                      ;  ASCII "%d"
    00401015  |.  E8 06000000   call Test3.00401020                      ;  printf函数
    0040101A  |.  83C4 08       add esp,8                                ;  恢复esp
    0040101D  |.  33C0          xor eax,eax                              ;  eax清零
    0040101F  \.  C3            retn                                     ;  返回  ret  add esp,4

    while循环基本结构:

    自动判断是否满足while条件,如果否就直接跳过while,这里满足
    ... ;while执行体
    cmp ;判断while条件是否满足  
    jle ;不满足就跳出while循环

    总结:根据反汇编两种不同的编译方式可以看出,编译器已经自动识别出原始条件是否满足首次while条件,如满足则直接执行while内容,不满足就直接跳过while。
    ___________________________________________________________________________________________________

    • #include < stdio.h >
    • int main()
    • {
    •     int x;
    •     do
    •     {
    •         printf("请输入一个数字");
    •         scanf("%d", &x);
    •         printf("你输入的数字是:%d\n", x);
    •     } while ( x != 0 );
    •     return 0;
    • }


    [color=rgb(81, 112, 58) !important]复制代码


    ___________________________________________________________________________________________________

    上面程序是判断用户的输入数值,不等于0就一直输入,直到等于0就跳出do-while循环

    Debug版本:
    00401010   |> \55             push ebp                         ;  ebp入栈保存
    00401011   |.  8BEC           mov ebp,esp                      ;  esp保存到ebp
    00401013   |.  83EC 44        sub esp,44                       ;  开辟局部变量空间
    00401016   |.  53             push ebx                         ;  ebx入栈保存
    00401017   |.  56             push esi                         ;  esi入栈保存
    00401018   |.  57             push edi                         ;  edi入栈保存
    00401019   |.  8D7D BC        lea edi,dword ptr ss:[ebp-44]    ;  设置CC操作起始地址
    0040101C   |.  B9 11000000    mov ecx,11                       ;  设置循环次数
    00401021   |.  B8 CCCCCCCC    mov eax,CCCCCCCC                 ;  赋值 eax CC  int 3
    00401026   |.  F3:AB          rep stos dword ptr es:[edi]      ;  循环复制 CC
    00401028   |>  68 B82F4200    /push Test3.00422FB8             ; /参数入栈
    0040102D   |.  E8 5E000000    |call Test3.00401090             ; \调用printf函数
    00401032   |.  83C4 04        |add esp,4                       ;  恢复esp
    00401035   |.  8D45 FC        |lea eax,dword ptr ss:[ebp-4]    ;  取变量x的地址到eax
    00401038   |.  50             |push eax                        ; /参数入栈
    00401039   |.  68 1C204200    |push Test3.0042201C             ; |Arg1 = 0042201C ASCII "%d"
    0040103E   |.  E8 BDE80000    |call Test3.0040F900             ; \调用scanf函数
    00401043   |.  83C4 08        |add esp,8                       ;  恢复esp
    00401046   |.  8B4D FC        |mov ecx,dword ptr ss:[ebp-4]    ;  变量x的值放入ecx
    00401049   |.  51             |push ecx                        ; /参数入栈
    0040104A   |.  68 A42F4200    |push Test3.00422FA4             ; |参数入栈
    0040104F   |.  E8 3C000000    |call Test3.00401090             ; \调用printf函数
    00401054   |.  83C4 08        |add esp,8                       ;  恢复esp
    00401057   |.  837D FC 00     |cmp dword ptr ss:[ebp-4],0      ;  判断x值是否为0
    0040105B   |.^ 75 CB          \jnz short Test3.00401028        ;  不为0即跳到到do循环出执行
    0040105D   |.  33C0           xor eax,eax                      ;  eax清零
    0040105F   |.  5F             pop edi                          ;  恢复edi
    00401060   |.  5E             pop esi                          ;  恢复esi
    00401061   |.  5B             pop ebx                          ;  恢复ebx
    00401062   |.  83C4 44        add esp,44                       ;  恢复局部变量空间
    00401065   |.  3BEC           cmp ebp,esp                      ;  测试堆栈平衡
    00401067   |.  E8 A4000000    call Test3.00401110              ;  调用调试信息
    0040106C   |.  8BE5           mov esp,ebp                      ;  恢复esp
    0040106E   |.  5D             pop ebp                          ;  恢复ebp
    0040106F   \.  C3             retn                             ;  返回  ret  add esp,4

    do-while基本结构:
    .... ;do循环执行体
    cmp ;条件判断
    jnz ;如果不满足条件就跳出循环

    Release版本:
    00401000  /$  51            push ecx                                 ;  ecx入栈保存
    00401001  |>  68 48804000   /push Test3.00408048                     ;  参数
    00401006  |.  E8 4C000000   |call Test3.00401057                     ;  printf函数
    0040100B  |.  8D4424 04     |lea eax,dword ptr ss:[esp+4]            ;  取变量x地址到eax
    0040100F  |.  50            |push eax                                ;  参数入栈
    00401010  |.  68 44804000   |push Test3.00408044                     ;  ASCII "%d"
    00401015  |.  E8 26000000   |call Test3.00401040                     ;  scanf函数
    0040101A  |.  8B4C24 0C     |mov ecx,dword ptr ss:[esp+C]            ;  变量值赋值到ecx
    0040101E  |.  51            |push ecx                                ;  参数
    0040101F  |.  68 30804000   |push Test3.00408030                     ;  参数
    00401024  |.  E8 2E000000   |call Test3.00401057                     ;  printf函数
    00401029  |.  8B4424 14     |mov eax,dword ptr ss:[esp+14]           ;  变量值赋值到eax中
    0040102D  |.  83C4 14       |add esp,14                              ;  恢复esp
    00401030  |.  85C0          |test eax,eax                            ;  判断eax是否为零
    00401032  |.^ 75 CD         \jnz short Test3.00401001                ;  如果不为零,就跳回执行
    00401034  |.  33C0          xor eax,eax                              ;  eax清零
    00401036  |.  59            pop ecx                                  ;  恢复ecx
    00401037  \.  C3            retn                                     ;  返回 ret  add esp,4

    do-while基本结构:
    .... ;do循环执行体
    test ;条件判断
    jnz ;如果不满足条件就跳出循环

    两种编译模式的汇编判断流程很相似,这也就是do-while和while的区别,不管是否满足条件,都会先执行一次再做判断!

      ___________________________________________________________________________________________________

    goto语句:

    • #include < stdio.h >
    • int main()
    • {
    •     int a;
    •     qq: printf("请输入一个数字:");
    •     scanf("%d", &a);
    •     if (a == 0)
    •         goto qq;
    •     return 0;
    • }

    [color=rgb(81, 112, 58) !important]复制代码


    ___________________________________________________________________________________________________
    上面程序是判断用户输入,如果值为0就跳回重新输入判断,这里使用了goto语句

    Debug版本:
    00401010 >|> \55            push ebp                                                  ;  保存ebp
    00401011  |.  8BEC          mov ebp,esp                                               ;  保存esp到ebp
    00401013  |.  83EC 44       sub esp,44                                                ;  开辟局部变量空间
    00401016  |.  53            push ebx                                                  ;  ebx入栈保存
    00401017  |.  56            push esi                                                  ;  esi入栈保存
    00401018  |.  57            push edi                                                  ;  edi入栈保存
    00401019  |.  8D7D BC       lea edi,[local.17]                                        ;  设置CC操作起始地址
    0040101C  |.  B9 11000000   mov ecx,11                                                ;  设置循环次数
    00401021  |.  B8 CCCCCCCC   mov eax,CCCCCCCC                                          ;  赋值 eax CC  int 3
    00401026  |.  F3:AB         rep stos dword ptr es:[edi]                               ;  循环复制 CC
    00401028  |>  68 20504200   /push offset Test3.??_C@_0BB@FLPH@?G?k?J?d?H?k?R?$LL?$LI?>;  参数
    0040102D  |.  E8 AE000000   |call Test3.printfgvdbgind_blockeressges                  ;  printf函数
    00401032  |.  83C4 04       |add esp,4                                                ;  恢复esp
    00401035  |.  8D45 FC       |lea eax,[local.1]                                        ;  取变量地址到eax
    00401038  |.  50            |push eax                                                 ;  参数
    00401039  |.  68 1C504200   |push offset Test3.??_C@_02MECO@?$CFd?$AA@4k?5at?50x?$CF0>;  ASCII "%d"
    0040103E  |.  E8 3D000000   |call Test3.scanfalloc_basee_block_pages                  ;  scanf函数
    00401043  |.  83C4 08       |add esp,8                                                ;  恢复esp
    00401046  |.  837D FC 00    |cmp [local.1],0                                          ;  比较是否为0
    0040104A  |.  75 02         |jnz short Test3.0040104E                                 ;  为0就执行if语句内容
    0040104C  |.^ EB DA         \jmp short Test3.00401028                                 ;  jmp无条件跳转
    0040104E  |>  33C0          xor eax,eax                                               ;  eax清零
    00401050  |.  5F            pop edi                                                   ;  恢复edi
    00401051  |.  5E            pop esi                                                   ;  恢复esi
    00401052  |.  5B            pop ebx                                                   ;  恢复ebx
    00401053  |.  83C4 44       add esp,44                                                ;  恢复局部变量空间
    00401056  |.  3BEC          cmp ebp,esp                                               ;  测试堆栈平衡
    00401058  |.  E8 03010000   call Test3.__chkespleBuffers@4ingsW@4location?5size?3?5?$>;  调用调试信息
    0040105D  |.  8BE5          mov esp,ebp                                               ;  恢复esp
    0040105F  |.  5D            pop ebp                                                   ;  恢复ebp
    00401060  \.  C3            retn                                                      ;  返回  ret  add esp,4

    Release版本:
    00401000  /$  51            push ecx                                                  ;  ecx入栈保存
    00401001  |.  68 34804000   push Test3.00408034                                       ;  参数
    00401006  |.  E8 5C000000   call Test3.00401067                                       ;  printf函数
    0040100B  |.  8D4424 04     lea eax,dword ptr ss:[esp+4]                              ;  取变量地址到eax
    0040100F  |.  50            push eax                                                  ;  参数
    00401010  |.  68 30804000   push Test3.00408030                                       ;  ASCII "%d"
    00401015  |.  E8 36000000   call Test3.00401050                                       ;  scanf函数
    0040101A  |.  8B4424 0C     mov eax,dword ptr ss:[esp+C]                              ;  变量值赋值到eax
    0040101E  |.  83C4 0C       add esp,0C                                                ;  恢复esp
    00401021  |.  85C0          test eax,eax                                              ;  测试eax是否为0
    00401023  |.  75 24         jnz short Test3.00401049                                  ;  不满足就跳出if语句
    00401025  |>  68 34804000   /push Test3.00408034                                      ;  参数
    0040102A  |.  E8 38000000   |call Test3.00401067                                      ;  printf函数
    0040102F  |.  8D4C24 04     |lea ecx,dword ptr ss:[esp+4]                             ;  取变量地址到ecx
    00401033  |.  51            |push ecx                                                 ;  参数
    00401034  |.  68 30804000   |push Test3.00408030                                      ;  ASCII "%d"
    00401039  |.  E8 12000000   |call Test3.00401050                                      ;  scanf函数
    0040103E  |.  8B4424 0C     |mov eax,dword ptr ss:[esp+C]                             ;  变量值赋值到eax
    00401042  |.  83C4 0C       |add esp,0C                                               ;  恢复esp
    00401045  |.  85C0          |test eax,eax                                             ;  测试eax是否为0
    00401047  |.^ 74 DC         \je short Test3.00401025                                  ;  满足就跳回执行if语句
    00401049  |>  33C0          xor eax,eax                                               ;  eax清零
    0040104B  |.  59            pop ecx                                                   ;  恢复ecx
    0040104C  \.  C3            retn                                                      ;  返回  ret  add esp,4

    goto语句框架:

    在debug版本中,goto语句等价鱼jmp指令,但在这个Release版本中却没有goto语句的影子,原因在于由于if语句的原因,这里直接忽略了goto语句,而是把goto语句对应的内容直接拷贝到了if语句下!换种情况,也是jmp指令!

    ___________________________________________________________________________________________________


    本节主要对程序的流程化控制逆向分析完毕,各位私下还需要多多逆向联系,对日后大有帮助!好了,基础篇到此为止,中级篇主要讲解数组,指针,函数,以及类和对象...


    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|1401软件安全 ( ICP备16034480号 )

    GMT+8, 2024-4-28 12:54 , Processed in 0.167504 second(s), 26 queries , Gzip On.

    Powered by Discuz! X3.5

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表