找回密码
 立即注册

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
查看: 3627|回复: 0

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

[复制链接]
  • TA的每日心情

    前天 15:54
  • 签到天数: 2747 天

    [LV.Master]伴坛终老

    963

    主题

    3305

    回帖

    2万

    积分

    管理员

    UID
    1
    元宝
    63102
    威望
    4304
    贡献
    607
    信誉值
    0
    精华
    34
    在线时间
    3588 小时
    注册时间
    2014-1-5
    最后登录
    2024-3-27
    违规
    -2
    积分
    22489

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

    QQ
    发表于 2015-11-20 21:08:53 | 显示全部楼层 |阅读模式
    Ȧ
    《基于VC平台下C++反汇编与逆向分析研究——No.3》

    伤情最是晚凉天,憔悴斯人不堪怜。邀酒摧肠三杯醉,寻香惊梦五更寒。
    钗头凤斜卿有泪,荼蘼花了我无缘。小楼寂寞心宇月,也难如钩也难圆。

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


    本帖隐藏的内容————————————————————————————————————————————————
    正文部分:
           本节主要从汇编层面来全面解析程序的基本流程控制语句:if -else,switch,for 如下:
    ___________________________________________________________________________________________________

    源码:
    • #include<stdio.h>
    • int main()
    • {
    •         int x;
    •         printf("请输入密码");
    •         scanf("%d",&x);
    •         if(x==123456)
    •                 printf("成功");
    •         else
    •                 printf("失败");
    •         return 0;
    • }

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


    ___________________________________________________________________________________________________
    上面是一个模拟简单的程序注册流程,判断用户输入


    Debug版本:
    00401010 >|> \55            push ebp                                 ;  ebp入栈保存
    00401011  |.  8BEC          mov ebp,esp                              ;  esp保存到ebp中
    00401013  |.  83EC 44       sub esp,0x44                             ;  开辟局部变量空间
    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,0x11                             ;  设置循环次数
    00401021  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC                       ;  赋值eax CC,int 3
    00401026  |.  F3:AB         rep stos dword ptr es:[edi]              ;  循环赋值
    00401028  |.  68 10604200   push Test3.00426010                      ; /format = "请输入密码"
    0040102D  |.  E8 6E000000   call Test3.printf                        ; \printf
    00401032  |.  83C4 04       add esp,0x4                              ;  恢复esp
    00401035  |.  8D45 FC       lea eax,[local.1]                        ;  变量地址放入eax
    00401038  |.  50            push eax                                 ;  参数入栈
    00401039  |.  68 1C504200   push Test3.0042501C                      ; /format = "%d"
    0040103E  |.  E8 DD000000   call Test3.scanf                         ; \scanf
    00401043  |.  83C4 08       add esp,0x8                              ;  恢复esp
    00401046  |.  817D FC 40E20>cmp [local.1],0x1E240                    ;  判断是否为123456
    0040104D  |.  75 0F         jnz short Test3.0040105E                 ;  不等于就跳转
    0040104F  |.  68 20504200   push Test3.00425020                      ; /format = "成功"
    00401054  |.  E8 47000000   call Test3.printf                        ; \printf
    00401059  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040105C  |.  EB 0D         jmp short Test3.0040106B                 ;  跳出循环
    0040105E  |>  68 08604200   push Test3.00426008                      ; /format = "失败"
    00401063  |.  E8 38000000   call Test3.printf                        ; \printf
    00401068  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040106B  |>  33C0          xor eax,eax                              ;  eax清零
    0040106D  |.  5F            pop edi                                  ;  恢复edi
    0040106E  |.  5E            pop esi                                  ;  恢复esi
    0040106F  |.  5B            pop ebx                                  ;  恢复ebx
    00401070  |.  83C4 44       add esp,0x44                             ;  恢复局部变量空间
    00401073  |.  3BEC          cmp ebp,esp                              ;  判断堆栈平衡
    00401075  |.  E8 06010000   call Test3._chkesp                       ;  调用调试信息
    0040107A  |.  8BE5          mov esp,ebp                              ;  恢复esp
    0040107C  |.  5D            pop ebp                                  ;  恢复ebp
    0040107D  \.  C3            retn                                     ;  返回  ret  add esp,4

    if-else的基本框架:
    cmp xx1,xx2     ;测试比较指令,如test
    jnz  ;条件转移指令,如jle,jne等
    ........... ;if 语句内容
    jmp   ;跳出判断
    ........... ;else语句内容

    Release版本:
    00401000  /$  51            push ecx                                 ;  ecx入栈保存
    00401001  |.  68 44804000   push Test3.00408044                      ;  请输入密码
    00401006  |.  E8 5C000000   call Test3.00401067                      ;  printf函数
    0040100B  |.  8D4424 04     lea eax,dword ptr ss:[esp+4]             ;  获取变量指针到eax
    0040100F  |.  50            push eax                                 ;  参数
    00401010  |.  68 40804000   push Test3.00408040                      ;  %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  |.  3D 40E20100   cmp eax,1E240                            ;  比较是否相等
    00401026  |.  75 11         jnz short Test3.00401039                 ;  不相等就跳转
    00401028  |.  68 38804000   push Test3.00408038                      ;  成功
    0040102D  |.  E8 35000000   call Test3.00401067                      ;  printf函数
    00401032  |.  83C4 04       add esp,4                                ;  恢复esp
    00401035  |.  33C0          xor eax,eax                              ;  eax清零
    00401037  |.  59            pop ecx                                  ;  恢复ecx
    00401038  |.  C3            retn                                     ;  返回 ret  add esp,4
    00401039  |>  68 30804000   push Test3.00408030                      ;  失败
    0040103E  |.  E8 24000000   call Test3.00401067                      ;  printf函数
    00401043  |.  83C4 04       add esp,4                                ;  恢复esp
    00401046  |.  33C0          xor eax,eax                              ;  eax清零
    00401048  |.  59            pop ecx                                  ;  恢复ecx
    00401049  \.  C3            retn                                     ;  返回 ret  add esp,4

    if-else的基本框架:

    cmp xx1,xx2     ;测试比较指令,如test
    jnz  ;条件转移指令,如jle,jne等
    ........... ;if 语句内容
    retn
    ........... ;else语句内容
    retn
    ___________________________________________________________________________________________________

    • #include<stdio.h>
    • int main()
    • {
    •         int x;
    •         printf("请输入一个数字");
    •         scanf("%d",&x);
    •         switch(x)
    •         {
    •         case 0:
    •                  printf("你输入的数字是0");
    •                  break;
    •         case 1:
    •                  printf("你输入的数字是1");
    •                  break;
    •         case 2:
    •                  printf("你输入的数字是2");
    •                  break;
    •         default:
    •                  printf("你输入的数字大于2");
    •         }
    •         return 0;
    • }

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


    ___________________________________________________________________________________________________

    上面通过switch语句,来判断用户输入,有默认执行部分!

    Debug版本:
    0040F980 >/> \55            push ebp                                 ;  ebp入栈保存
    0040F981  |.  8BEC          mov ebp,esp                              ;  esp保存到ebp中
    0040F983  |.  83EC 48       sub esp,0x48                             ;  开辟局部变量空间
    0040F986  |.  53            push ebx                                 ;  ebx入栈保存
    0040F987  |.  56            push esi                                 ;  esi入栈保存
    0040F988  |.  57            push edi                                 ;  edi入栈保存
    0040F989  |.  8D7D B8       lea edi,[local.18]                       ;  设置CC初始化起始地址
    0040F98C  |.  B9 12000000   mov ecx,0x12                             ;  设置循环次数
    0040F991  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC                       ;  赋值eax CC,int 3
    0040F996  |.  F3:AB         rep stos dword ptr es:[edi]              ;  循环复制cc
    0040F998  |.  68 4C604200   push Test3.0042604C                      ; /format = "请输入一个数字"
    0040F99D  |.  E8 FE16FFFF   call Test3.printf                        ; \printf
    0040F9A2  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040F9A5  |.  8D45 FC       lea eax,[local.1]                        ;  取变量地址放入eax
    0040F9A8  |.  50            push eax                                 ;  参数入栈
    0040F9A9  |.  68 1C504200   push Test3.0042501C                      ; /format = "%d"
    0040F9AE  |.  E8 6D17FFFF   call Test3.scanf                         ; \scanf
    0040F9B3  |.  83C4 08       add esp,0x8                              ;  恢复esp
    0040F9B6  |.  8B4D FC       mov ecx,[local.1]                        ;  赋值变量值到ecx
    0040F9B9  |.  894D F8       mov [local.2],ecx                        ;  ecx放入局部变量中
    0040F9BC  |.  837D F8 00    cmp [local.2],0x0                        ;  判断是否为0
    0040F9C0  |.  74 0E         je short Test3.0040F9D0                  ;  等于0就跳转,执行相应内容
    0040F9C2  |.  837D F8 01    cmp [local.2],0x1                        ;  判断是否为1
    0040F9C6  |.  74 17         je short Test3.0040F9DF                  ;  等于1就跳转,执行相应内容
    0040F9C8  |.  837D F8 02    cmp [local.2],0x2                        ;  判断是否为2
    0040F9CC  |.  74 20         je short Test3.0040F9EE                  ;  等于2就跳转,执行相应内容
    0040F9CE  |.  EB 2D         jmp short Test3.0040F9FD                 ;  条件均不成立时,跳到默认执行处
    0040F9D0  |>  68 3C604200   push Test3.0042603C                      ; /format = "你输入的数字是0"
    0040F9D5  |.  E8 C616FFFF   call Test3.printf                        ; \printf
    0040F9DA  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040F9DD  |.  EB 2B         jmp short Test3.0040FA0A                 ;  跳出switch语句
    0040F9DF  |>  68 2C604200   push Test3.0042602C                      ; /format = "你输入的数字是1"
    0040F9E4  |.  E8 B716FFFF   call Test3.printf                        ; \printf
    0040F9E9  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040F9EC  |.  EB 1C         jmp short Test3.0040FA0A                 ;  跳出switch语句
    0040F9EE  |>  68 1C604200   push Test3.0042601C                      ; /format = "你输入的数字是2"
    0040F9F3  |.  E8 A816FFFF   call Test3.printf                        ; \printf
    0040F9F8  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040F9FB  |.  EB 0D         jmp short Test3.0040FA0A                 ;  跳出switch语句
    0040F9FD  |>  68 08604200   push Test3.00426008                      ; /format = "你输入的数字大于2"
    0040FA02  |.  E8 9916FFFF   call Test3.printf                        ; \printf
    0040FA07  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040FA0A  |>  33C0          xor eax,eax                              ;  eax清零
    0040FA0C  |.  5F            pop edi                                  ;  恢复edi
    0040FA0D  |.  5E            pop esi                                  ;  恢复esi
    0040FA0E  |.  5B            pop ebx                                  ;  恢复ebx
    0040FA0F  |.  83C4 48       add esp,0x48                             ;  恢复局部变量空间
    0040FA12  |.  3BEC          cmp ebp,esp                              ;  堆栈平衡判断
    0040FA14  |.  E8 6717FFFF   call Test3._chkesp                       ;  调用调试信息
    0040FA19  |.  8BE5          mov esp,ebp                              ;  恢复esp
    0040FA1B  |.  5D            pop ebp                                  ;  恢复ebp
    0040FA1C  \.  C3            retn                                     ;  返回 ret add esp,4


    switch语句基本框架:

    cmp xx0,xx1       ;可以是test等
    je  ;跳转执行体1  ;此处也可以是其他条件转移指令
    cmp xx0,xx2
    je ;跳转执行体2
    0,xx3
    je cmp xx;跳转执行体3
    jmp ;跳转默认执行体处
    ...... ;执行体1
    jmp
    ...... ;执行体2
    jmp
    ...... ;执行体3
    jmp
    ...... ;默认执行体

    Release版本:
    00401000  /$  51            push ecx                                 ;  ecx入栈
    00401001  |.  68 78804000   push Test3.00408078                      ;  请输入一个数字
    00401006  |.  E8 7C000000   call Test3.00401087                      ;  printf函数
    0040100B  |.  8D4424 04     lea eax,dword ptr ss:[esp+0x4]           ;  取变量指针到eax
    0040100F  |.  50            push eax                                 ;  参数
    00401010  |.  68 74804000   push Test3.00408074                      ;  %d
    00401015  |.  E8 56000000   call Test3.00401070                      ;  scanf函数
    0040101A  |.  8B4424 0C     mov eax,dword ptr ss:[esp+0xC]           ;  输入数值到eax
    0040101E  |.  83C4 0C       add esp,0xC                              ;  恢复esp
    00401021  |.  83E8 00       sub eax,0x0                              ;  判断; Switch (cases 0..2)
    00401024  |.  74 39         je short Test3.0040105F                  ;  如为0就跳转
    00401026  |.  48            dec eax                                  ;  判断
    00401027  |.  74 25         je short Test3.0040104E                  ;  如为1就跳转
    00401029  |.  48            dec eax                                  ;  判断
    0040102A  |.  74 11         je short Test3.0040103D                  ;  如为2就跳转
    0040102C  |.  68 60804000   push Test3.00408060                      ;  你输入的数字大于2; Default case of switch 00401021
    00401031  |.  E8 51000000   call Test3.00401087                      ;  printf函数
    00401036  |.  83C4 04       add esp,0x4                              ;  恢复esp
    00401039  |.  33C0          xor eax,eax                              ;  eax清零
    0040103B  |.  59            pop ecx                                  ;  恢复ecx
    0040103C  |.  C3            retn                                     ;  返回
    0040103D  |>  68 50804000   push Test3.00408050                      ;  你输入的数字是2; Case 2 of switch 00401021
    00401042  |.  E8 40000000   call Test3.00401087                      ;  printf函数
    00401047  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040104A  |.  33C0          xor eax,eax                              ;  eax清零
    0040104C  |.  59            pop ecx                                  ;  恢复ecx
    0040104D  |.  C3            retn                                     ;  返回
    0040104E  |>  68 40804000   push Test3.00408040                      ;  你输入的数字是1; Case 1 of switch 00401021
    00401053  |.  E8 2F000000   call Test3.00401087                      ;  printf函数
    00401058  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040105B  |.  33C0          xor eax,eax                              ;  eax清零
    0040105D  |.  59            pop ecx                                  ;  恢复ecx
    0040105E  |.  C3            retn                                     ;  返回
    0040105F  |>  68 30804000   push Test3.00408030                      ;  你输入的数字是0; Case 0 of switch 00401021
    00401064  |.  E8 1E000000   call Test3.00401087                      ;  printf函数
    00401069  |.  83C4 04       add esp,0x4                              ;  恢复esp
    0040106C  |.  33C0          xor eax,eax                              ;  eax清零
    0040106E  |.  59            pop ecx                                  ;  恢复ecx
    0040106F  \.  C3            retn                                     ;  返回


    switch语句基本框架:

    cmp xx0,xx1       ;可以是test等
    je  ;跳转执行体1  ;此处也可以是其他条件转移指令
    cmp xx0,xx2
    je ;跳转执行体2
    cmp xx0,xx3
    je ;跳转执行体3
    ...... ;默认执行体
    retn
    ...... ;执行体1
    retn
    ...... ;执行体2
    retn
    ...... ;执行体3
    retn
    ___________________________________________________________________________________________________

    • #include<stdio.h>
    • int main()
    • {
    •         int x,y=0;
    •         for(x=1;x<=100;x++)
    •         {
    •                 y=x+y;
    •         }
    •         printf("%d",y);
    •         return 0;
    • }


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


    __________________________________________________________________________________________________
    上述程序通过for循环来计算1+2+3...+100的值
    Debug版本:
    0040F980 >/> \55            push ebp                                 ;  ebp入栈保存
    0040F981  |.  8BEC          mov ebp,esp                              ;  保存esp到ebp
    0040F983  |.  83EC 48       sub esp,0x48                             ;  开辟局部变量空间
    0040F986  |.  53            push ebx                                 ;  ebx入栈保存
    0040F987  |.  56            push esi                                 ;  esi入栈保存
    0040F988  |.  57            push edi                                 ;  edi入栈保存
    0040F989  |.  8D7D B8       lea edi,[local.18]                       ;  设置CC操作起始地址
    0040F98C  |.  B9 12000000   mov ecx,0x12                             ;  设置循环地址
    0040F991  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC                       ;  赋值eax CC  int 3
    0040F996  |.  F3:AB         rep stos dword ptr es:[edi]              ;  循环复制CC
    0040F998  |.  C745 F8 00000>mov [local.2],0x0                        ;  赋值变量y
    0040F99F  |.  C745 FC 01000>mov [local.1],0x1                        ;  赋值变量x
    0040F9A6  |.  EB 09         jmp short Test3.0040F9B1                 ;  跳转到for循环判断
    0040F9A8  |>  8B45 FC       /mov eax,[local.1]                       ;  x的值放入eax
    0040F9AB  |.  83C0 01       |add eax,0x1                             ;  eax加1
    0040F9AE  |.  8945 FC       |mov [local.1],eax                       ;  自加1的值放入变量x
    0040F9B1  |>  837D FC 64     cmp [local.1],0x64                      ;  判断x值是否为100
    0040F9B5  |.  7F 0B         |jg short Test3.0040F9C2                 ;  相等就跳转
    0040F9B7  |.  8B4D FC       |mov ecx,[local.1]                       ;  变量x值放入ecx
    0040F9BA  |.  034D F8       |add ecx,[local.2]                       ;  x+y的值放入ecx
    0040F9BD  |.  894D F8       |mov [local.2],ecx                       ;  把ecx的值放入变量y
    0040F9C0  |.^ EB E6         \jmp short Test3.0040F9A8                ;  跳转到判断处
    0040F9C2  |>  8B55 F8       mov edx,[local.2]                        ;  最终变量y的值放入edx
    0040F9C5  |.  52            push edx                                 ; /<%d>
    0040F9C6  |.  68 08604200   push Test3.00426008                      ; |format = "%d"
    0040F9CB  |.  E8 D016FFFF   call Test3.printf                        ; \printf
    0040F9D0  |.  83C4 08       add esp,0x8                              ;  恢复esp
    0040F9D3  |.  33C0          xor eax,eax                              ;  eax清零
    0040F9D5  |.  5F            pop edi                                  ;  恢复edi
    0040F9D6  |.  5E            pop esi                                  ;  恢复esi
    0040F9D7  |.  5B            pop ebx                                  ;  恢复ebx
    0040F9D8  |.  83C4 48       add esp,0x48                             ;  恢复局部变量空间
    0040F9DB  |.  3BEC          cmp ebp,esp                              ;  测试堆栈平衡
    0040F9DD  |.  E8 9E17FFFF   call Test3._chkesp                       ;  调用调试信息
    0040F9E2  |.  8BE5          mov esp,ebp                              ;  恢复esp
    0040F9E4  |.  5D            pop ebp                                  ;  恢复ebp
    0040F9E5  \.  C3            retn                                     ;  返回  ret   add esp,4

    for基本循环框架:
    jmp  ;无条件跳转到条件判断语句
    .... ;for循环条件
    cmp  ;判断是否满足条件 ;可以是其他条件测试指令
    jg ;如果不满足就跳出for循环;可以是其他条件转移指令
    .... ;for循环执行体
    jmp ;无条件跳转到for循环条件

    Release版本:
    00401000  /$  33C9          xor ecx,ecx                              ;  ecx清零,作为计数器
    00401002  |.  B8 01000000   mov eax,0x1                              ;  eax初始化为为1
    00401007  |>  03C8          /add ecx,eax                             ;  eax加上ecx的值放入ecx中
    00401009  |.  40            |inc eax                                 ;  eax自加1
    0040100A  |.  83F8 64       |cmp eax,0x64                            ;  判断是否为100
    0040100D  |.^ 7E F8         \jle short Test3.00401007                ;  如不为100就跳转
    0040100F  |.  51            push ecx                                 ;  参数入栈
    00401010  |.  68 30704000   push Test3.00407030                      ;  ASCII "%d"
    00401015  |.  E8 06000000   call Test3.00401020                      ;  printf函数
    0040101A  |.  83C4 08       add esp,0x8                              ;  恢复esp
    0040101D  |.  33C0          xor eax,eax                              ;  eax清零
    0040101F  \.  C3            retn                                     ;  返回

    for基本循环框架:

    ......  ;初始化各个参数
    jle ;判断是否满足条件
    ......  ;跳出循环
    ___________________________________________________________________________________________________

    本节主要对程序的流程化控制做逆向分析,此节对以后无论是逆向还是病毒分析都极其重要,下半节更新,while,do-while,goto语句


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

    本版积分规则

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

    GMT+8, 2024-3-29 19:03 , Processed in 0.172608 second(s), 26 queries , Gzip On.

    Powered by Discuz! X3.5

    Copyright © 2001-2020, Tencent Cloud.

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