找回密码
 立即注册

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

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

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

    [LV.Master]伴坛终老

    963

    主题

    3310

    回帖

    2万

    积分

    管理员

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

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

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



    ————————————————————————————————————————————————
    正文部分:
           本节主要从汇编层面来全面解析基本的数据类型和运算符,如下:
    ___________________________________________________________________________________________________
    本帖隐藏的内容
    • #include<stdio.h>
    • int main()
    • {
    •         int a,b,c,s;
    •         scanf("%d%d%d",&a,&b,&c);
    •         s=a+b+c;
    •         printf("%d",s);
    •         return 0;
    • }


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


    _______________________________________________________________________________________________________
           上面的源码是一个简单的三角形求周边的程序,好了,直接复制到VC++6.0中选择Debug方式编译生成,直接载入OD,来到main函数:
    Debug版本:
    00401010 >|> \55            push ebp                                 ;  保存ebp
    00401011  |.  8BEC          mov ebp,esp                              ;  保存esp到ebp
    00401013  |.  83EC 50       sub esp,0x50                             ;  开辟局部变量空间
    00401016  |.  53            push ebx                                 ;  入栈ebx
    00401017  |.  56            push esi                                 ;  入栈esi
    00401018  |.  57            push edi                                 ;  入栈edi
    00401019  |.  8D7D B0       lea edi,[local.20]                       ;  设置初始化内存地址
    0040101C  |.  B9 14000000   mov ecx,0x14                             ;  设置循环次数
    00401021  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC                       ;  赋值eax int 3中断
    00401026  |.  F3:AB         rep stos dword ptr es:[edi]              ;  循环复制int 3
    00401028  |.  8D45 F4       lea eax,[local.3]                        ;  变量c的内存地址放到eax
    0040102B  |.  50            push eax                                 ;  入栈c的地址
    0040102C  |.  8D4D F8       lea ecx,[local.2]                        ;  变量b地址放到eax
    0040102F  |.  51            push ecx                                 ;  入栈b的地址
    00401030  |.  8D55 FC       lea edx,[local.1]                        ;  变量a地址放到eax
    00401033  |.  52            push edx                                 ;  入栈a的地址
    00401034  |.  68 20504200   push Test2.00425020                      ; /format = "%d%d%d"
    00401039  |.  E8 D2000000   call Test2.scanf                         ; \scanf
    0040103E  |.  83C4 10       add esp,0x10                             ;  恢复esp的值  4个push
    00401041  |.  8B45 FC       mov eax,[local.1]                        ;  变量a的值放入eax
    00401044  |.  0345 F8       add eax,[local.2]                        ;  变量b的值加上a的和放入eax中
    00401047  |.  0345 F4       add eax,[local.3]                        ;  变量c的值加上ab的和放入eax
    0040104A  |.  8945 F0       mov [local.4],eax                        ;  把abc的和放入变量s中
    0040104D  |.  8B4D F0       mov ecx,[local.4]                        ;  变量s的值放入ecx
    00401050  |.  51            push ecx                                    ; /<%d>
    00401051  |.  68 1C504200   push Test2.0042501C                      ; |format = "%d"
    00401056  |.  E8 35000000   call Test2.printf                        ; \printf
    0040105B  |.  83C4 08       add esp,0x8                              ;  恢复esp,2个push
    0040105E  |.  33C0          xor eax,eax                              ;  eax清零
    00401060  |.  5F            pop edi                                  ;  恢复寄存器edi
    00401061  |.  5E            pop esi                                  ;  恢复寄存器esi
    00401062  |.  5B            pop ebx                                  ;  恢复寄存器ebx
    00401063  |.  83C4 50       add esp,0x50                             ;  恢复局部变量空间
    00401066  |.  3BEC          cmp ebp,esp                              ;  测试esp值是否与之前一致
    00401068  |.  E8 03010000   call Test2._chkesp                       ;  如esp值不一致,调用调试信息
    0040106D  |.  8BE5          mov esp,ebp                              ;  恢复esp值
    0040106F  |.  5D            pop ebp                                  ;  恢复ebp
    00401070  \.  C3            retn                                     ;  返回 等于ret加上add esp,4

           和之前的Hello World大同小异,相信大家看起来都没问题,我希望大家能记熟这种框架模式,对以后逆向的深入有很大用处,我们再来看看 Release版本的:
    Release版本:
    00401000  /$  83EC 0C       sub esp,0xC                              ;  开辟局部变量空间
    00401003  |.  8D4424 08     lea eax,dword ptr ss:[esp+0x8]           ;  把变量c的地址放入eax
    00401007  |.  8D4C24 04     lea ecx,dword ptr ss:[esp+0x4]           ;  把变量b的地址放入ecx
    0040100B  |.  8D5424 00     lea edx,dword ptr ss:[esp]               ;  把变量a的地址放入edx
    0040100F  |.  50            push eax                                 ;  入栈c的地址
    00401010  |.  51            push ecx                                 ;  入栈b的地址
    00401011  |.  52            push edx                                 ;  入栈a的地址
    00401012  |.  68 34804000   push Test2.00408034                      ;  ASCII "%d%d%d"
    00401017  |.  E8 55000000   call Test2.00401071                      ;  调用scanf函数
    0040101C  |.  8B4424 10     mov eax,dword ptr ss:[esp+0x10]          ;  把a的值放入eax
    00401020  |.  8B4C24 14     mov ecx,dword ptr ss:[esp+0x14]          ;  把b的值放入ecx
    00401024  |.  03C1          add eax,ecx                              ;  a+b的和放入eax中
    00401026  |.  8B4C24 18     mov ecx,dword ptr ss:[esp+0x18]          ;  把c的值放入ecx
    0040102A  |.  03C1          add eax,ecx                              ;  c的值和ab的和放入eax中
    0040102C  |.  50            push eax                                 ;  入栈三数之和
    0040102D  |.  68 30804000   push Test2.00408030                      ;  ASCII "%d"
    00401032  |.  E8 09000000   call Test2.00401040                      ;  调用printf函数
    00401037  |.  33C0          xor eax,eax                              ;  eax清零
    00401039  |.  83C4 24       add esp,0x24                             ;  恢复esp   
    0040103C  \.  C3            retn                                     ;  返回  等于ret  add esp,4

                大家可能不理解的就是最后的add esp,0x24,OK,先看下入口处的sub esp,0xC,注意次数是十六进制,大家都知道一个push操作,eap就相当于sub esp,4 此处共6个push,所以这里的值等于6个push的值0x18加上sub esp,0xc 的0xC 正好是0x24,有疑问的大家可以试试在源码中多添加一个push操作来看看此处add esp的值!
    _______________________________________________________________________________________________________
    #include<stdio.h>
    int main()
    {
    short int a=1;
    int b=2;
    long int c=3;
    float d=1.222;
    double e=1.333;
    long double f=1.234;
    char g='a';
    char *h;
    h=&g;
    return 0;
    }
    _______________________________________________________________________________________________________

           上面这段简单的源码中,涉及了很多基本数据类型,如:int整型 ,float单精度浮点型,double双精度浮点型,char字符型,指针类型,本节重要点就是来分析这些基本数据类型在汇编中的表现形式,先看下Debug版本的:

    Debug版本:
    00401250 >/> \55            push ebp                                 ;  保存ebp
    00401251  |.  8BEC          mov ebp,esp                              ;  保存esp到ebp
    00401253  |.  83EC 68       sub esp,0x68                             ;  开辟局部变量空间
    00401256  |.  53            push ebx                                 ;  入栈ebx
    00401257  |.  56            push esi                                 ;  入栈esi
    00401258  |.  57            push edi                                 ;  入栈edi
    00401259  |.  8D7D 98       lea edi,[local.26]                       ;  设置初始化局部变量地址
    0040125C  |.  B9 1A000000   mov ecx,0x1A                             ;  设置循环次数
    00401261  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC                       ;  赋值eax int 3中断
    00401266  |.  F3:AB         rep stos dword ptr es:[edi]              ;  循环复制int3
    00401268  |.  66:C745 FC 01>mov word ptr ss:[ebp-0x4],0x1            ;  赋值1到局部变量short int类型a中,参数:word  16位
    0040126E  |.  C745 F8 02000>mov [local.2],0x2                        ;  赋值2到局部变量int类型b中,参数:dword  32位
    00401275  |.  C745 F4 03000>mov [local.3],0x3                        ;  赋值3到局部变量float类型c中,参数:dword  32位
    0040127C  |.  C745 F0 7F6A9>mov [local.4],0x3F9C6A7F                 ;  赋值0x3F9DF3B6到局部变量float类型d中,参数:dword  32位
    00401283  |.  C745 E8 8716D>mov [local.6],0xCED91687                 ;  存放低位
    0040128A  |.  C745 EC F753F>mov [local.5],0x3FF553F7                 ;  double类型e 存放高位  参数:qword 64位
    00401291  |.  C745 E0 5839B>mov [local.8],0xC8B43958                 ;  存放低位
    00401298  |.  C745 E4 76BEF>mov [local.7],0x3FF3BE76                 ;  long double类型f 存放高位  参数:qword 64位
    0040129F  |.  C645 DC 61    mov byte ptr ss:[ebp-0x24],0x61          ;  char类型g Ascll码的a对应0x61  参数:byte 8位
    004012A3  |.  8D45 DC       lea eax,[local.9]                        ;  获取字符变量地址到eax
    004012A6  |.  8945 D8       mov [local.10],eax                       ;  把eax放入指针中h中
    004012A9  |.  33C0          xor eax,eax                              ;  eax清零
    004012AB  |.  5F            pop edi                                  ;  出栈edi
    004012AC  |.  5E            pop esi                                  ;  出栈esi
    004012AD  |.  5B            pop ebx                                  ;  出栈ebx
    004012AE  |.  8BE5          mov esp,ebp                              ;  恢复esp
    004012B0 >|.  5D            pop ebp                                  ;  恢复ebp
    004012B1  \.  C3            retn                                     ;  返回 等于ret add esp,4

           分析前,我们先普及一下计算机微计量单位,位bit    即10101010   每个数为1位,字节byte 即大家看到的文件大小字节,一个字节等于8位,字word  1个字等于2个字节即16位  双字Dword  1个双字等于2个字,即32位  eax寄存器就是32位,4字qword  同理就是64位!当然还有更大的,我们这里不做描述!
            short int 类型为16位故:mov word ptr ss:[ebp-0x4],0x1    int类型为32位,故:mov [local.2],0x2    默认就是32位,double为64位,就会使用2个32位来存放,即一个存放高位,一个低位!例如这句:double e=1.333; 1.333在内存中是以IEEE编码来存储,1.333对应的IEEE是3FF553F7CED91687,故会出现这两句汇编指令:mov [local.6],0xCED91687    mov [local.5],0x3FF553F7,Ascll码的0x61对应的就是小写字母a,好了,看下Release版


    Release版本:
    00401000  /$  33C0          xor eax,eax         ;  eax清零
    00401002  \.  C3            retn         ;  返回  等于ret  add esp,4
    这些变量未参数实际使用,Release会自动优化掉!
    _______________________________________________________________________________________________________

    • #include < stdio.h >
    • int main()
    • {
    •     int a = 2,
    •     b = 4,
    •     c;
    •     c = a + b;
    •     c = a * b;
    •     c = a / b;
    •     c = a % b;
    •     c = a && b;
    •     c = a || b;
    •     c = !b;
    •     c++;
    •     c--;
    •     return 0;
    • }


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


    ______________________________________________________________________________________________________

    Debug版本:
    00410680 >/> \55            push ebp                                 ;  ebp入栈保存
    00410681  |.  8BEC          mov ebp,esp                              ;  保存esp
    00410683  |.  83EC 54       sub esp,0x54                             ;  开辟局部变量空间
    00410686  |.  53            push ebx                                 ;  入栈ebx
    00410687  |.  56            push esi                                 ;  入栈esi
    00410688  |.  57            push edi                                 ;  入栈edi
    00410689  |.  8D7D AC       lea edi,[local.21]                       ;  设置初始化局部变量地址
    0041068C  |.  B9 15000000   mov ecx,0x15                             ;  循环次数
    00410691  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC                       ;  赋值eax int 中断
    00410696  |.  F3:AB         rep stos dword ptr es:[edi]              ;  循环复制int 3 中断
    00410698  |.  C745 FC 05000>mov [local.1],0x5                        ;  赋值2到变量a
    0041069F  |.  C745 F8 02000>mov [local.2],0x2                        ;  赋值4到变量b
    004106A6  |.  8B45 FC       mov eax,[local.1]                        ;  赋值a的值到eax
    004106A9  |.  0345 F8       add eax,[local.2]                        ;  b的值与a的值相加放入eax
    004106AC  |.  8945 F4       mov [local.3],eax                        ;  ab的和放入变量c
    004106AF  |.  8B4D FC       mov ecx,[local.1]                        ;  赋值a的值到ecx
    004106B2  |.  0FAF4D F8     imul ecx,[local.2]                       ;  变量b与变量a的乘积放入ecx
    004106B6  |.  894D F4       mov [local.3],ecx                        ;  ab的积值放入变量c
    004106B9  |.  8B45 FC       mov eax,[local.1]                        ;  赋值a的值到eax
    004106BC  |.  99            cdq                                      ;  双字32位扩展到64位,eax的高位放入edx中
    004106BD  |.  F77D F8       idiv [local.2]                           ;  除法运算   idiv无符号除法
    004106C0  |.  8945 F4       mov [local.3],eax                        ;  ab的商放入变量c
    004106C3  |.  8B45 FC       mov eax,[local.1]                        ;  赋值a的值到eax
    004106C6  |.  99            cdq                                      ;  双字32位扩展到64位,eax的高位放入edx中
    004106C7  |.  F77D F8       idiv [local.2]                           ;  除法运算   idiv无符号除法
    004106CA  |.  8955 F4       mov [local.3],edx                        ;  ab的余数放入变量c
    004106CD  |.  837D FC 00    cmp [local.1],0x0                        ;  与运算,测试变量a是否为0,如为0就跳转
    004106D1  |.  74 0F         je short Test2.004106E2                  ;  a值不为0,未发生跳转
    004106D3  |.  837D F8 00    cmp [local.2],0x0                        ;  与运算,测试变量b是否为0,如为0就跳转
    004106D7  |.  74 09         je short Test2.004106E2                  ;  b值不为0,未发生跳转
    004106D9  |.  C745 F0 01000>mov [local.4],0x1                        ;  与运算为真
    004106E0  |.  EB 07         jmp short Test2.004106E9                 ;  无条件跳转
    004106E2  |>  C745 F0 00000>mov [local.4],0x0
    004106E9  |>  8B55 F0       mov edx,[local.4]                        ;  与运算值放入edx
    004106EC  |.  8955 F4       mov [local.3],edx                        ;  ab的与运算值放入变量c
    004106EF  |.  837D FC 00    cmp [local.1],0x0                        ;  或运算,测试变量a是否为0,如不等于0就跳转
    004106F3  |.  75 0F         jnz short Test2.00410704                 ;  a值不为0,发生跳转
    004106F5  |.  837D F8 00    cmp [local.2],0x0
    004106F9  |.  75 09         jnz short Test2.00410704
    004106FB  |.  C745 EC 00000>mov [local.5],0x0
    00410702  |.  EB 07         jmp short Test2.0041070B
    00410704  |>  C745 EC 01000>mov [local.5],0x1                  ;  ab或运算为真
    0041070B  |>  8B45 EC       mov eax,[local.5]                        ;  或运算值放入edx
    0041070E  |.  8945 F4       mov [local.3],eax                        ;  ab的或运算值放入变量c
    00410711  |.  33C9          xor ecx,ecx                              ;  ecx清零
    00410713  |.  837D F8 00    cmp [local.2],0x0                        ;  求反运算,测试变量b是否为0
    00410717  |.  0F94C1        sete cl                                  ;  依据zf标志位的值设置cl的值
    0041071A  |.  894D F4       mov [local.3],ecx                        ;  b逻辑取反的值放入变量c
    0041071D  |.  8B55 F4       mov edx,[local.3]                        ;  变量c的值放入edx
    00410720  |.  83C2 01       add edx,0x1                              ;  edx自加1
    00410723  |.  8955 F4       mov [local.3],edx                        ;  edx的值放入变量c
    00410726  |.  8B45 F4       mov eax,[local.3]                        ;  变量c的值放入eax
    00410729  |.  83E8 01       sub eax,0x1                              ;  eax自减1
    0041072C  |.  8945 F4       mov [local.3],eax                        ;  eax的值放入变量c
    0041072F  |.  33C0          xor eax,eax                              ;  eax清零
    00410731  |?  5F            pop edi         ;  恢复edi
    00410732  |.  5E            pop esi                                  ;  恢复esi
    00410733  |?  5B            pop ebx         ;  恢复ebx
    00410734  |?  8BE5          mov esp,ebp         ;  恢复esp的值
    00410736  |?  5D            pop ebp         ;  恢复ebp
    00410737  |?  C3            retn         ;  返回  等于ret add esp,4
           上述每条汇编指令的注释我写的都很详细,大家可以对照源码来看,注意cdq指令 ,重点看下理解乘除法运算,以及逻辑运算!Release版本同上。

    Release版本:
    00401000  /$  33C0          xor eax,eax
    00401002  \.  C3            retn

    这些变量未参数实际使用,Release会自动优化掉!
    _______________________________________________________________________________________________________

             本节中,肯定没有全面涉及数据类型和运算符,这里只做为一种分析的方法,各位私下多练习下这些基础,吃透吃熟,对以深入后尤关重要!至于逻辑判断,下节我会详细介绍。

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

    本版积分规则

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

    GMT+8, 2024-5-6 03:06 , Processed in 0.190289 second(s), 26 queries , Gzip On.

    Powered by Discuz! X3.5

    Copyright © 2001-2020, Tencent Cloud.

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