穷举法破解 zebrone1.1

系统 : Windows xp

程序 : zebrone1.1

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

要求 : 编写注册机

使用工具 :OD

可在看雪论坛中查找关于此程序的讨论:传送门

用OD载入程序,查找字串发现成功提示“congratulations, you have cracked the zebra crackme ver 1.1”,双击定位该字串:

004012AA  |> 6A 0A         push    0A                               ; /Count = A (10.); Case 1 of switch 0040128D
004012AC  |.  8D45 EC       lea     eax, dword ptr [ebp-14]          ; |
004012AF  |.  50            push    eax                              ; |Buffer
004012B0  |.  6A 65         push    65                               ; |ControlID = 65 (101.)
004012B2  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
004012B5  |.  E8 F2010000   call    <jmp.&USER32.GetDlgItemTextA>    ; GetDlgItemTextA
004012BA  |.  6A 0A         push    0A                               ; /Count = A (10.)
004012BC  |.  8D45 F6       lea     eax, dword ptr [ebp-A]           ; |
004012BF  |.  50            push    eax                              ; |Buffer
004012C0  |.  6A 66         push    66                               ; |ControlID = 66 (102.)
004012C2  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
004012C5  |.  E8 E2010000   call    <jmp.&USER32.GetDlgItemTextA>    ; GetDlgItemTextA
004012CA  |.  8D45 F6       lea     eax, dword ptr [ebp-A]           ;  取序列号
004012CD  |.  50            push    eax                              ;  序列号入栈
004012CE  |.  8D45 EC       lea     eax, dword ptr [ebp-14]          ;  取用户名
004012D1  |.  50            push    eax                              ;  用户名入栈
004012D2  |.  E8 73000000   call    0040134A
004012D7  |.  83C4 08       add     esp, 8                           ;  平衡堆栈
004012DA  |.  09C0          or      eax, eax                         ;  eax 为 0?
004012DC  |.  74 16         je      short 004012F4                   ;  为0 则错误。
004012DE  |.  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
004012E0  |.  68 26324000   push    00403226                         ; |great !!!
004012E5  |.  68 30324000   push    00403230                         ; |congratulations, you have cracked the zebra crackme ver 1.1
004012EA  |.  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
004012ED  |.  E8 C6010000   call    <jmp.&USER32.MessageBoxA>        ; MessageBoxA
004012F2  |.  EB 14         jmp     short 00401308
004012F4  |>  6A 00         push    0                                ; /Style = MB_OK|MB_APPLMODAL
004012F6  |.  68 F8314000   push    004031F8                         ; |hmmmm :p
004012FB  |.  68 01324000   push    00403201                         ; |Text = "Sorry... The Serial isn't correct :?
00401300  |.  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
00401303  |.  E8 B0010000   call    <jmp.&USER32.MessageBoxA>        ; MessageBoxA

跟入关键call:

0040134A  /$  55            push    ebp
0040134B  |.  89E5          mov     ebp, esp
0040134D  |.  83EC 68       sub     esp, 68                          ;  ↓将用户名字串转化为浮点数
00401350  |.  FF75 08       push    dword ptr [ebp+8]                ; /s
00401353  |.  E8 78010000   call    <jmp.&CRTDLL.atof>               ; atof
00401358  |.  DD55 E8       fst     qword ptr [ebp-18]               ;  保存转化结果
0040135B  |.  83EC 08       sub     esp, 8                           ;  开辟内存
0040135E  |.  DD1C24        fstp    qword ptr [esp]                  ;  保存转化结果并弹栈
00401361  |.  E8 82010000   call    <jmp.&CRTDLL.floor>              ;  向下取整
00401366  |.  DD5D F8       fstp    qword ptr [ebp-8]                ;  ↓将序列号转化为浮点数
00401369  |.  FF75 0C       push    dword ptr [ebp+C]                ; /s
0040136C  |.  E8 5F010000   call    <jmp.&CRTDLL.atof>               ; atof
00401371  |.  DD55 D8       fst     qword ptr [ebp-28]               ;  保存转化后的序列号
00401374  |.  83EC 08       sub     esp, 8                           ;  平衡堆栈
00401377  |.  DD1C24        fstp    qword ptr [esp]                  ;  将结果入栈
0040137A  |.  E8 69010000   call    <jmp.&CRTDLL.floor>              ;  向下取整
0040137F  |.  83C4 18       add     esp, 18                          ;  平衡堆栈
00401382  |.  DD55 F0       fst     qword ptr [ebp-10]               ;  保存取整结果
00401385  |.  DC4D F8       fmul    qword ptr [ebp-8]                ;  乘以用户名
00401388  |.  D9EE          fldz                                     ;  载入0
0040138A  |.  DED9          fcompp                                   ;  比较st(0)st(1),并弹出寄存器堆栈
0040138C  |.  DFE0          fstsw   ax                               ;  把该状态寄存器的值传送给通用寄存器AX
0040138E  |.  9E            sahf                                     ;  标志传送指令
0040138F  |.  75 07         jnz     short 00401398                   ;  st0和st1相等?
00401391  |.  31C0          xor     eax, eax                         ;  清空eax
00401393  |.  E9 96000000   jmp     0040142E                         ;  函数结束
00401398  |>  DD45 F8       fld     qword ptr [ebp-8]                ;  用户名浮点数入栈
0040139B  |.  DC5D F0       fcomp   qword ptr [ebp-10]               ;  与序列号浮点数比较
0040139E  |.  DFE0          fstsw   ax
004013A0  |.  9E            sahf
004013A1  |.  75 07         jnz     short 004013AA                   ;  用户名浮点数与序列号浮点数相等则函数结束
004013A3  |.  31C0          xor     eax, eax                         ;  清空eax
004013A5  |.  E9 84000000   jmp     0040142E                         ;  函数结束
004013AA  |>  DD45 F8       fld     qword ptr [ebp-8]                ;  用户名浮点数入栈
004013AD  |.  DD5D C8       fstp    qword ptr [ebp-38]               ;  保存用户名浮点数
004013B0  |.  D9E8          fld1                                     ;  1入栈
004013B2  |.  DD55 C0       fst     qword ptr [ebp-40]               ;  保存1
004013B5  |.  DC5D C8       fcomp   qword ptr [ebp-38]               ;  1 > 用户名浮点数?
004013B8  |.  DFE0          fstsw   ax
004013BA  |.  9E            sahf
004013BB  |.  77 2D         ja      short 004013EA                   ;  是则错误
004013BD  |.  DF2D 38304000 fild    qword ptr [403038]               ;  载入10的10次方
004013C3  |.  DD55 B8       fst     qword ptr [ebp-48]               ;  保存
004013C6  |.  DC5D C8       fcomp   qword ptr [ebp-38]               ;  10的10次方 < 用户名浮点数?
004013C9  |.  DFE0          fstsw   ax
004013CB  |.  9E            sahf
004013CC  |.  72 1C         jb      short 004013EA                   ;  是则错误
004013CE  |.  DD45 F0       fld     qword ptr [ebp-10]               ;  序列号浮点数入栈
004013D1  |.  DD5D B0       fstp    qword ptr [ebp-50]               ;  保存
004013D4  |.  DD45 C0       fld     qword ptr [ebp-40]               ;  用户名浮点数入栈
004013D7  |.  DC5D B0       fcomp   qword ptr [ebp-50]               ;  用户名浮点数 > 序列号浮点数?
004013DA  |.  DFE0          fstsw   ax
004013DC  |.  9E            sahf
004013DD  |.  77 0B         ja      short 004013EA                   ;  是则错误
004013DF  |.  DD45 B8       fld     qword ptr [ebp-48]               ;  载入10的10次方
004013E2  |.  DC5D B0       fcomp   qword ptr [ebp-50]               ;  10的10次方 >= 序列号浮点数?
004013E5  |.  DFE0          fstsw   ax
004013E7  |.  9E            sahf
004013E8  |.  73 04         jnb     short 004013EE                   ;  是则继续流程
004013EA  |>  31C0          xor     eax, eax                         ;  清空eax
004013EC  |.  EB 40         jmp     short 0040142E                   ;  函数结束
004013EE  |>  DD45 F8       fld     qword ptr [ebp-8]                ;  用户名浮点数入栈
004013F1  |.  D9FE          fsin                                     ;  计算栈顶的正弦函数
004013F3  |.  DD5D A8       fstp    qword ptr [ebp-58]               ;  保存结果
004013F6  |.  DD45 F0       fld     qword ptr [ebp-10]               ;  序列号浮点数入栈
004013F9  |.  D9FE          fsin                                     ;  计算栈顶的正弦函数
004013FB  |.  DD5D A0       fstp    qword ptr [ebp-60]               ;  保存结果
004013FE  |.  DD45 A8       fld     qword ptr [ebp-58]               ;  用户名正弦值入栈
00401401  |.  DC4D A0       fmul    qword ptr [ebp-60]               ;  乘以 序列号正弦值
00401404  |.  DF2D 30304000 fild    qword ptr [403030]               ;  10的16次方入栈
0040140A  |.  DEC9          fmulp   st(1), st                        ;  再相乘
0040140C  |.  83EC 08       sub     esp, 8                           ;  开辟8个字节的空间
0040140F  |.  DD1C24        fstp    qword ptr [esp]                  ;  保存结果
00401412  |.  E8 D1000000   call    <jmp.&CRTDLL.floor>              ;  向下取整
00401417  |.  83C4 08       add     esp, 8
0040141A  |.  DD5D 98       fstp    qword ptr [ebp-68]               ;  保存
0040141D  |.  D9EE          fldz                                     ;  载入0
0040141F  |.  DC5D 98       fcomp   qword ptr [ebp-68]               ;  结果是否为0?
00401422  |.  DFE0          fstsw   ax
00401424  |.  9E            sahf                                     ;  (initial cpu selection)
00401425  |.  75 05         jnz     short 0040142C                   ;  不为0则失败
00401427  |.  31C0          xor     eax, eax
00401429  |.  40            inc     eax
0040142A  |.  EB 02         jmp     short 0040142E
0040142C  |>  31C0          xor     eax, eax
0040142E  |>  C9            leave
0040142F  .  C3            retn

这里的Sin指令是按弧度制算的,所以想用180的倍数充当乘数是不行的,我们只能遍历[1,10^10],找出其中正弦值为正数且正弦值小于10^-8的实数。这样的两个实数相乘再乘以10的16次方的乘积就满足了条件。{ x | 0 < x < 1 }

动手编写程序,验证我们的猜想:

=========================十年后============================》

好吧。。。肯定是哪儿出问题了,经过Debug之后源程序如下:

#include <iostream>
#include <math.h>
#include <iomanip>                                                // 精度控制头文件 

using namespace std;

inline double Sin( double Var )                                    //内联Sin指令
{
    __asm{
        fld Var
        fsin
        fstp Var
    }

    return Var;
}

int main( void )
{
    double i,j,res;
    const double min = 1e-8;

    cout << "Valid number:" << endl;

    for ( i = 1 ; i <= 1e+10 ; i++ ){
        res = Sin( i );                                                //接受正弦值。
        
        bool Flag = false;
        __asm{
                push eax

                fld res                                                //载入正弦值
                fldz                                                //载入0
                fcompp                                                 //0 < 正弦值?
                fstsw ax
                sahf
                jnb s                                                //不小于则跳转
                fld res                                                //载入正弦值
                fcomp min                                            //正弦值 < min?
                fstsw ax
                sahf
                jnb s                                                //不小于则跳转
                mov Flag,1

            s:    pop eax
        }

        if ( Flag )    
            cout << setprecision(10) << i <<endl;
    }
        

    cout << "Done." << endl;

    return 0;
}

运行效果:

但经过测试发现,算出的数中 大于 10的9次方的数的Sin值与zebrone1.1的Sin值有偏差,所以有效的数值有:

245850922
411557987
657408909
823115974

随便取出两个按照 升序填入:

就注册成功了:

原文地址:https://www.cnblogs.com/ZRBYYXDM/p/5222765.html