• 一条汇编指令引发的 蝴蝶效应 (后记)


    系统 : Windows xp

    程序 : crackme1

    程序下载地址 :http://pan.baidu.com/s/1gdY4wMJ

    要求 : 编写注册机

    使用工具 :OD

    可在“PEDIY CrackMe 2007”中查找关于此程序的讨论,标题为“muckis's crakcme #1破解(检测OD)”。

    前天分析了一个crackme,对其中的浮点汇编指令有点头疼,并没有写出注册机。

    这两天上网查找了一些关于浮点汇编指令集的资料,补充完基础知识,我们再来分析一下这个crackme。

    接着上次,我们来到计算余数的子程序处:

    004010E0  /> 55            push    ebp
    004010E1  |.  8BEC          mov     ebp, esp
    004010E3  |.  83EC 58       sub     esp, 58
    004010E6  |.  53            push    ebx
    004010E7  |.  56            push    esi
    004010E8  |.  57            push    edi
    004010E9  |.  8D7D A8       lea     edi, dword ptr [ebp-58]
    004010EC  |.  B9 16000000   mov     ecx, 16
    004010F1  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
    004010F6  |.  F3:AB         rep     stos dword ptr es:[edi]          ;  用CC填充一段内存
    004010F8  |.  C745 FC 00000>mov     dword ptr [ebp-4], 0
    004010FF  |.  C745 F8 01000>mov     dword ptr [ebp-8], 1
    00401106  |.  C745 F4 00000>mov     dword ptr [ebp-C], 0
    0040110D  |.  C745 FC 0A000>mov     dword ptr [ebp-4], 0A
    00401114  |.  EB 09         jmp     short 0040111F
    00401116  |>  8B45 FC       /mov     eax, dword ptr [ebp-4]
    00401119  |.  83E8 01       |sub     eax, 1                          ;  循环变量递减
    0040111C  |.  8945 FC       |mov     dword ptr [ebp-4], eax
    0040111F  |>  837D FC 00     cmp     dword ptr [ebp-4], 0            ;  小于0?
    00401123  |.  7C 4F         |jl      short 00401174                  ;  则退出循环
    00401125  |.  DB45 08       |fild    dword ptr [ebp+8]               ;  将传入的参数转化为浮点数,并压栈
    00401128  |.  DD5D E8       |fstp    qword ptr [ebp-18]              ;  注意!这里将累加结果转化为双精度浮点型
    0040112B  |.  DB45 FC       |fild    dword ptr [ebp-4]               ;  将循环变量转化为浮点数,并压栈
    0040112E  |.  83EC 08       |sub     esp, 8                          ;  开辟8个字节的内存空间
    00401131  |.  DD1C24        |fstp    qword ptr [esp]                 ;  保存转化成浮点数的循环变量
    00401134  |.  68 00002440   |push    40240000                        ;  40240000入栈
    00401139  |.  6A 00         |push    0
    0040113B  |.  E8 C91E0000   |call    00403009
    00401140  |.  83C4 10       |add     esp, 10
    00401143  |.  DC7D E8       |fdivr   qword ptr [ebp-18]              ;  浮点反除
    00401146  |.  E8 AD210000   |call    004032F8                        ;  将st的值转为整数存入eax
    0040114B  |.  8945 F0       |mov     dword ptr [ebp-10], eax
    0040114E  |.  837D F0 00    |cmp     dword ptr [ebp-10], 0           ;  商太小则直接进行累加
    00401152  |.  7E 0F         |jle     short 00401163
    00401154  |.  8B4D F8       |mov     ecx, dword ptr [ebp-8]
    00401157  |.  51            |push    ecx
    00401158  |.  E8 DAFEFFFF   |call    00401037                        ;  变换数据
    0040115D  |.  83C4 04       |add     esp, 4
    00401160  |.  8945 F8       |mov     dword ptr [ebp-8], eax
    00401163  |>  8B55 F0       |mov     edx, dword ptr [ebp-10]         ;  取商
    00401166  |.  0FAF55 F8     |imul    edx, dword ptr [ebp-8]          ;  乘以 变换数据
    0040116A  |.  8B45 F4       |mov     eax, dword ptr [ebp-C]          ;  取出累加的值
    0040116D  |.  03C2          |add     eax, edx                        ;  累加
    0040116F  |.  8945 F4       |mov     dword ptr [ebp-C], eax          ;  保存
    00401172  |.^ EB A2         jmp     short 00401116
    00401174  |>  8B45 F4       mov     eax, dword ptr [ebp-C]           ;  算出一个值
    00401177  |.  99            cdq                                      ;  把EDX的所有位都设成EAX最高位的值
    00401178  |.  B9 0A000000   mov     ecx, 0A
    0040117D  |.  F7F9          idiv    ecx                              ;  除以0A
    0040117F  |.  8BC2          mov     eax, edx                         ;  余数放入eax
    00401181  |.  5F            pop     edi
    00401182  |.  5E            pop     esi
    00401183  |.  5B            pop     ebx
    00401184  |.  83C4 58       add     esp, 58
    00401187  |.  3BEC          cmp     ebp, esp
    00401189  |.  E8 32210000   call    004032C0
    0040118E  |.  8BE5          mov     esp, ebp
    00401190  |.  5D            pop     ebp
    00401191  .  C3            retn

    跟入403009:

    00403009   $  8D5424 0C     lea     edx, dword ptr [esp+C]
    0040300D   .  E8 630B0000   call    00403B75
    00403012   $  8BC8          mov     ecx, eax
    00403014   .  50            push    eax
    00403015   .  9B            wait
    00403016   .  D93C24        fstcw   word ptr [esp]                   ;  保存控制字寄存器
    00403019   .  66:813C24 7F0>cmp     word ptr [esp], 27F
    0040301F   .  74 05         je      short 00403026
    00403021   .  E8 1F0B0000   call    00403B45
    00403026   >  81E1 0000F07F and     ecx, 7FF00000
    0040302C   .  8D5424 08     lea     edx, dword ptr [esp+8]           ;  取一段内存
    00403030   .  81F9 0000F07F cmp     ecx, 7FF00000                    ;  是7FF00000吗?
    00403036   .  0F84 9D000000 je      004030D9
    0040303C   .  E8 340B0000   call    00403B75
    00403041   .  0F84 8E000000 je      004030D5
    00403047   .  A9 0000F07F   test    eax, 7FF00000
    0040304C   .  0F84 F6000000 je      00403148
    00403052   >  8A4C24 0F     mov     cl, byte ptr [esp+F]
    00403056   .  80E1 80       and     cl, 80
    00403059   .  0F85 61010000 jnz     004031C0
    0040305F   >  D9F1          fyl2x
    00403061   .  E8 CA0A0000   call    00403B30                         ;  生成除数
    00403066   .  80F9 01       cmp     cl, 1
    00403069   .  75 02         jnz     short 0040306D
    0040306B   .  D9E0          fchs
    0040306D   >  833D B8DE4200>cmp     dword ptr [42DEB8], 0
    00403074   .  0F85 540B0000 jnz     00403BCE
    0040307A   .  8D0D B8CB4200 lea     ecx, dword ptr [42CBB8]
    00403080   .  BA 1D000000   mov     edx, 1D
    00403085   .  E9 8F0B0000   jmp     00403C19
    0040308A   >  833D B8DE4200>cmp     dword ptr [42DEB8], 0
    00403091   .  0F85 370B0000 jnz     00403BCE
    00403097   .  8D0D B8CB4200 lea     ecx, dword ptr [42CBB8]
    0040309D   .  BA 1D000000   mov     edx, 1D
    004030A2   .  E8 290A0000   call    00403AD0
    004030A7   .  5A            pop     edx
    004030A8   .  C3            retn

    跟入关键call:

    00403B30  /$  D9C0          fld     st
    00403B32  |.  D9FC          frndint                                  ;  对st取整
    00403B34  |.  DCE1          fsubr   st(1), st                        ;  st - st(1)
    00403B36  |.  D9C9          fxch    st(1)                            ;  互换st和st(1)
    00403B38  |.  D9E0          fchs                                     ;  取相反数
    00403B3A  |.  D9F0          f2xm1
    00403B3C  |.  D9E8          fld1                                     ;  将1.0压栈
    00403B3E  |.  DEC1          faddp   st(1), st                        ;  加法,结果存入st(1),弹出st
    00403B40  |.  D9FD          fscale                                   ;  这个指令是计算ST(0)*2的ST(1)次方之值,再把结果存入 ST(0) 里而 ST(1) 之值不变
    00403B42  |.  DDD9          fstp    st(1)                            ;  将协处理器堆栈栈顶的数据传送到目标操作数中,并弹栈
    00403B44  .  C3            retn

    那么403009子程序主要就是自动生出一个除数出来,第一次生成10^10,第二次生成10 ^ 9,以此类推。

    再来看看4032F8:

    004032F8  /$  55            push    ebp
    004032F9  |.  8BEC          mov     ebp, esp
    004032FB  |.  83C4 F4       add     esp, -0C
    004032FE  |.  9B            wait
    004032FF  |.  D97D FE       fstcw   word ptr [ebp-2]                 ;  取出FCW
    00403302  |.  9B            wait
    00403303  |.  66:8B45 FE    mov     ax, word ptr [ebp-2]             ;  存入ax
    00403307  |.  80CC 0C       or      ah, 0C                           ;  按位或
    0040330A  |.  66:8945 FC    mov     word ptr [ebp-4], ax
    0040330E  |.  D96D FC       fldcw   word ptr [ebp-4]                 ;  存回FCW
    00403311  |.  DF7D F4       fistp   qword ptr [ebp-C]                ;  st转化为整数存入ebp-c,st出栈
    00403314  |.  D96D FE       fldcw   word ptr [ebp-2]                 ;  将原本的FCW保存回去
    00403317  |.  8B45 F4       mov     eax, dword ptr [ebp-C]           ;  结果存入eax
    0040331A  |.  8B55 F8       mov     edx, dword ptr [ebp-8]
    0040331D  |.  C9            leave
    0040331E  .  C3            retn

    还有401037:

    00401037   $ /E9 44000000   jmp     00401080

    继续跟:

    00401080  /> 55            push    ebp
    00401081  |.  8BEC          mov     ebp, esp
    00401083  |.  83EC 44       sub     esp, 44                          ;  开辟内存空间
    00401086  |.  53            push    ebx
    00401087  |.  56            push    esi
    00401088  |.  57            push    edi
    00401089  |.  8D7D BC       lea     edi, dword ptr [ebp-44]          ;  取一段内存
    0040108C  |.  B9 11000000   mov     ecx, 11
    00401091  |.  B8 CCCCCCCC   mov     eax, CCCCCCCC
    00401096  |.  F3:AB         rep     stos dword ptr es:[edi]          ;  用CC填充内存
    00401098  |.  C745 FC 07000>mov     dword ptr [ebp-4], 7
    0040109F  |.  837D 08 07    cmp     dword ptr [ebp+8], 7             ;  入栈数据是否等于7?
    004010A3  |.  75 07         jnz     short 004010AC
    004010A5  |.  C745 FC 03000>mov     dword ptr [ebp-4], 3
    004010AC  |>  837D 08 03    cmp     dword ptr [ebp+8], 3             ;  入栈数据是否等于3?
    004010B0  |.  75 07         jnz     short 004010B9
    004010B2  |.  C745 FC 01000>mov     dword ptr [ebp-4], 1
    004010B9  |>  8B45 FC       mov     eax, dword ptr [ebp-4]           ;  变换数据之后存入eax
    004010BC  |.  5F            pop     edi
    004010BD  |.  5E            pop     esi
    004010BE  |.  5B            pop     ebx
    004010BF  |.  8BE5          mov     esp, ebp
    004010C1  |.  5D            pop     ebp
    004010C2  .  C3            retn

    这样,整个子程序分析完毕。它的功能就是根据入栈的累加结果生成一个数,取其与10的余数并返回。

    我们直接打开之前搭建的框架,并修改OnBtnDecrypt函数如下:

    void CKengen_TemplateDlg::OnBtnDecrypt() 
    {
        // TODO: Add your control notification handler code here
        CString str;
        GetDlgItemText( IDC_EDIT_NAME,str );                    //获取用户名字串基本信息。
        int len = str.GetLength();
    
        if ( !str.IsEmpty() ){                                    //格式控制。
            str.MakeUpper();
    
            unsigned int sum = 0;
            for ( int i = 0 ; i != len ; i++ ){
                if ( str[i] == 0x20 )                            //字符为空格则continue
                    continue;
                sum += ( str[i] * 0x157A - 1 );
            }
            sum *= 0xA;
    
            sum += GetRes( sum );
    
            CString PassWord;
            PassWord.Format( "%d",sum );
            SetDlgItemText( IDC_EDIT_PASSWORD,PassWord );
        }
        else
            MessageBox( "用户名格式错误!" );
    }

    并添加如下类成员函数:

    int CKengen_TemplateDlg::GetRes(unsigned int Var)
    {
        double FVar;                                            //这里一定要设置成为double,否则会损失精度
        int ChangeVar = 1;
        unsigned int sum = 0;
    
        for ( int i = 0 ; i != 10 ; i++ ){
            __asm{                                                //转换为浮点数
                fild Var
                fstp FVar
            }
    
            int temp = (int)( FVar / GetDR(i) );                //进行除法,保存商
            if ( temp > 0 )
                Change( ChangeVar );                            //变换数据
    
            sum += temp * ChangeVar;                            //累加
        }
        
        /*
        CString PS;
        PS.Format( "%x",sum );
        MessageBox( PS );
        */
    
        return sum % 10;
    }
    
    float CKengen_TemplateDlg::GetDR(int temp)
    {
        float res = 1;
        for ( int i = 0 ; i != 10 - temp ; i++ )
            res *= 10;
    
        return res;
    }
    
    void CKengen_TemplateDlg::Change(int &Var)
    {
        int temp;
    
        if ( Var == 1 )
            temp = 7;
        if ( Var == 7 )
            temp = 3;
        if ( Var == 3 )
            temp = 1;
    
        Var = temp;
    }

    再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("crackme1_Keygen"));

    运行效果:

    一处细微的差异,会引起一连串连锁反应,最终导致结果的巨大差异。程序中,一处细小的设计失误,可能引起整个系统的崩溃,体现了计算机系统的高精度和复杂性。这就要求操作这个复杂系统的程序员要对自己的技术精益求精,刻意养成良好的习惯,这样一直不断堆砌,才能成就日后的巨大成功。

  • 相关阅读:
    elasticsearch 启动
    经纬度解析API
    http://t.cn/xxxxx的短链接如何生成?
    IIS+PHP上传文件大小限制和上传时间限制,iis7和iis8上传文件大小限制和上传时间限制
    WIN2003+IIS6环境SSL证书的安装
    如何创建文件名前带点的文件夹,文件夹名字带点
    解决MYSQL的错误:Got a packet bigger than 'max_allowed_packet' bytes
    php 设置临时内存和超时设置脚本最大执行时间
    谷歌地图 API 开发之获取坐标以及街道详情
    隐藏 google 地图 Logo 隐藏 百度 地图 Logo
  • 原文地址:https://www.cnblogs.com/ZRBYYXDM/p/5216782.html
Copyright © 2020-2023  润新知