菜鸟 学注册机编写之 “查表”

发布者:我是小三
发布于:2014-11-17 20:30

测试环境

系统: xp sp3

调试器 :od 1.10

    高手不要见笑,仅供小菜玩乐,有不对或不足的地方还请多多指教,不胜感激!

1.首先运行程序随便输入用户与注册码如下图所示:

2.载入OD通过下MessageBoxA函数, F9运行程序, 随便输入用户名与注册码, 点ok后断下,如下图所示:

3.然后堆栈回溯,来到如下关键地方

00415BB0                    6A FF           push -0x1

00415BB2                    68 58514200     push ahead_dv.00425158

00415BB7                    64:A1 00000000  mov eax,dword ptr fs:[0]

00415BBD                    50              push eax

00415BBE                    64:8925 0000000>mov dword ptr fs:[0],esp

00415BC5                    83EC 08         sub esp,0x8

00415BC8                    56              push esi

00415BC9                    8BF1            mov esi,ecx

00415BCB                    8D4C24 04       lea ecx,dword ptr ss:[esp+0x4]

00415BCF                    E8 74C90000     call <jmp.&MFC42.#??0CString@@QAE@XZ_540>

00415BD4                    6A 01           push 0x1

00415BD6                    8BCE            mov ecx,esi

00415BD8                    C74424 18 00000>mov dword ptr ss:[esp+0x18],0x0

00415BE0                    E8 7BC90000     call <jmp.&MFC42.#?UpdateData@CWnd@@QAEHH@Z_6334>        ; ----获得注册码

00415BE5                    E8 8EC90000     call <jmp.&MFC42.#?AfxGetModuleState@@YGPAVAFX_MODULE_ST>

00415BEA                    8B48 04         mov ecx,dword ptr ds:[eax+0x4]

00415BED                    E8 44CF0000     call <jmp.&MFC42.#?BeginWaitCursor@CCmdTarget@@QAEXXZ_16>

00415BF2                    8B46 64         mov eax,dword ptr ds:[esi+0x64]

00415BF5                    8B4E 60         mov ecx,dword ptr ds:[esi+0x60]

00415BF8                    50              push eax                                                 ; ----注册码

00415BF9                    51              push ecx                                                 ; ----用户名

00415BFA                    C64424 1C 01    mov byte ptr ss:[esp+0x1C],0x1

00415BFF                    E8 CCFCFFFF     call ahead_dv.004158D0                                   ; 关键CALL 注册码相同则返回1

00415C04                    83C4 08         add esp,0x8

00415C07                    85C0            test eax,eax

00415C09                    75 18           jnz short ahead_dv.00415C23                              ; 关键跳

00415C0B                    6A 40           push 0x40

00415C0D                    68 6C294300     push ahead_dv.0043296C                                   ; ASCII "Sorry"

00415C12                    68 40294300     push ahead_dv.00432940                                   ; ASCII "Invalid username or

 

registration code      "

00415C17                    8BCE            mov ecx,esi

00415C19                    E8 82CB0000     call <jmp.&MFC42.#?MessageBoxA@CWnd@@QAEHPBD0I@Z_4224>   ; 提示无效注册码

00415C1E                    E9 BB000000     jmp ahead_dv.00415CDE

 

4.分析关键CALL 004158D0 ; 关键CALL 注册码相同则返回1

004158D0                53              push ebx

004158D1                55              push ebp

004158D2                8B6C24 0C       mov ebp,dword ptr ss:[esp+0xC]

004158D6                56              push esi

004158D7                57              push edi

004158D8                BE 60354300     mov esi,ahead_dv.00433560

004158DD                8BC5            mov eax,ebp

004158DF                8A10            mov dl,byte ptr ds:[eax]                                 ; ---取用户名1字节

004158E1                8A1E            mov bl,byte ptr ds:[esi]

004158E3                8ACA            mov cl,dl                                                ; ---用户名第1字节

004158E5                3AD3            cmp dl,bl                                                ; ---判断是否为0

004158E7                75 1E           jnz short ahead_dv.00415907

004158E9                84C9            test cl,cl

004158EB                74 16           je short ahead_dv.00415903

004158ED                8A50 01         mov dl,byte ptr ds:[eax+0x1]

004158F0                8A5E 01         mov bl,byte ptr ds:[esi+0x1]

004158F3                8ACA            mov cl,dl

004158F5                3AD3            cmp dl,bl

004158F7                75 0E           jnz short ahead_dv.00415907

004158F9                83C0 02         add eax,0x2

004158FC                83C6 02         add esi,0x2

004158FF                84C9            test cl,cl

00415901              ^ 75 DC           jnz short ahead_dv.004158DF

00415903                33C0            xor eax,eax

00415905                EB 05           jmp short ahead_dv.0041590C

00415907                1BC0            sbb eax,eax

00415909                83D8 FF         sbb eax,-0x1

0041590C                85C0            test eax,eax

0041590E                74 51           je short ahead_dv.00415961

00415910                8B7C24 18       mov edi,dword ptr ss:[esp+0x18]                          ; --注册码

00415914                BE 60354300     mov esi,ahead_dv.00433560

00415919                8BC7            mov eax,edi

0041591B                8A10            mov dl,byte ptr ds:[eax]                                 ; ---取注册码1字节

0041591D                8A1E            mov bl,byte ptr ds:[esi]

0041591F                8ACA            mov cl,dl                                                ; 注册码第1字节

00415921                3AD3            cmp dl,bl                                                ; ---判断是否为0

00415923                75 1E           jnz short ahead_dv.00415943

00415925                84C9            test cl,cl

00415927                74 16           je short ahead_dv.0041593F

00415929                8A50 01         mov dl,byte ptr ds:[eax+0x1]

0041592C                8A5E 01         mov bl,byte ptr ds:[esi+0x1]

0041592F                8ACA            mov cl,dl

00415931                3AD3            cmp dl,bl

00415933                75 0E           jnz short ahead_dv.00415943

00415935                83C0 02         add eax,0x2

00415938                83C6 02         add esi,0x2

0041593B                84C9            test cl,cl

0041593D              ^ 75 DC           jnz short ahead_dv.0041591B

0041593F                33C0            xor eax,eax

00415941                EB 05           jmp short ahead_dv.00415948

00415943                1BC0            sbb eax,eax

00415945                83D8 FF         sbb eax,-0x1

00415948                85C0            test eax,eax

0041594A                74 15           je short ahead_dv.00415961

0041594C                57              push edi                                                 ; 注册码

0041594D                55              push ebp                                                 ; 用户名

0041594E                E8 3DFDFFFF     call ahead_dv.00415690                                   ; 算法

5.算法分析

00415690                6A FF           push -0x1

00415692                68 C0504200     push ahead_dv.004250C0

00415697                64:A1 00000000  mov eax,dword ptr fs:[0]

0041569D                50              push eax

0041569E                64:8925 0000000>mov dword ptr fs:[0],esp

004156A5                83EC 14         sub esp,0x14

004156A8                8B4424 24       mov eax,dword ptr ss:[esp+0x24]                         ; 用户名

004156AC                53              push ebx

004156AD                55              push ebp

004156AE                56              push esi

004156AF                57              push edi

004156B0                50              push eax

004156B1                8D4C24 18       lea ecx,dword ptr ss:[esp+0x18]                         ; 用户名

004156B5                E8 50D00000     call <jmp.&MFC42.#??0CString@@QAE@PBD@Z_537>

004156BA                33F6            xor esi,esi

004156BC                8D4C24 14       lea ecx,dword ptr ss:[esp+0x14]

004156C0                897424 2C       mov dword ptr ss:[esp+0x2C],esi

004156C4                E8 67D40000     call <jmp.&MFC42.#?TrimLeft@CString@@QAEXXZ_6282>       ; CString::TrimLeft 删除用户名的空格、换行符等

004156C9                8D4C24 14       lea ecx,dword ptr ss:[esp+0x14]

004156CD                E8 58D40000     call <jmp.&MFC42.#?TrimRight@CString@@QAEXXZ_6283>

004156D2                6A 20           push 0x20

004156D4                8D4C24 18       lea ecx,dword ptr ss:[esp+0x18]

004156D8                E8 93D00000     call <jmp.&MFC42.#?GetBuffer@CString@@QAEPADH@Z_2915>   ; CString::GetBuffer 用户名

004156DD                8B4C24 38       mov ecx,dword ptr ss:[esp+0x38]

004156E1                8BD8            mov ebx,eax

004156E3                51              push ecx

004156E4                8D4C24 14       lea ecx,dword ptr ss:[esp+0x14]

004156E8                E8 1DD00000     call <jmp.&MFC42.#??0CString@@QAE@PBD@Z_537>

004156ED                8D4C24 10       lea ecx,dword ptr ss:[esp+0x10]

004156F1                C64424 2C 01    mov byte ptr ss:[esp+0x2C],0x1

004156F6                E8 35D40000     call <jmp.&MFC42.#?TrimLeft@CString@@QAEXXZ_6282>       ; CString::TrimLeft 删除注册码的空格、换行符等

004156FB                8D4C24 10       lea ecx,dword ptr ss:[esp+0x10]

004156FF                E8 26D40000     call <jmp.&MFC42.#?TrimRight@CString@@QAEXXZ_6283>

00415704                6A 20           push 0x20

00415706                8D4C24 14       lea ecx,dword ptr ss:[esp+0x14]

0041570A                E8 61D00000     call <jmp.&MFC42.#?GetBuffer@CString@@QAEPADH@Z_2915>   ; CString::GetBuffer 注册码

0041570F                8BD0            mov edx,eax

00415711                83C9 FF         or ecx,0xFFFFFFFF

00415714                8BFA            mov edi,edx

00415716                33C0            xor eax,eax

00415718                F2:AE           repne scas byte ptr es:[edi]

0041571A                F7D1            not ecx

0041571C                49              dec ecx                                                 ; ---注册码长度

0041571D                8BFB            mov edi,ebx

0041571F                8BE9            mov ebp,ecx

00415721                83C9 FF         or ecx,0xFFFFFFFF

00415724                F2:AE           repne scas byte ptr es:[edi]

00415726                F7D1            not ecx

00415728                49              dec ecx                                                 ; 用户名长度

00415729                895424 20       mov dword ptr ss:[esp+0x20],edx                         ; ---注册码地址

0041572D                3BCD            cmp ecx,ebp                                             ; --用户名长度与注册码长度比较

0041572F                0F87 64010000   ja ahead_dv.00415899

00415735                8BFB            mov edi,ebx

00415737                83C9 FF         or ecx,0xFFFFFFFF

0041573A                F2:AE           repne scas byte ptr es:[edi]

0041573C                F7D1            not ecx

0041573E                49              dec ecx                                                 ; 用户名长度

0041573F                0F84 54010000   je ahead_dv.00415899

00415745                8BFA            mov edi,edx

00415747                83C9 FF         or ecx,0xFFFFFFFF

0041574A                F2:AE           repne scas byte ptr es:[edi]

0041574C                F7D1            not ecx

0041574E                49              dec ecx                                                 ; 注册码长度

0041574F                0F84 44010000   je ahead_dv.00415899

00415755                897424 38       mov dword ptr ss:[esp+0x38],esi

00415759                8B5424 38       mov edx,dword ptr ss:[esp+0x38]

0041575D                8D4C24 34       lea ecx,dword ptr ss:[esp+0x34]                         ; 用户名地址

00415761                8A82 C0284300   mov al,byte ptr ds:[edx+0x4328C0]                       ; 字符sdR

00415767                884424 18       mov byte ptr ss:[esp+0x18],al

0041576B                E8 D8CD0000     call <jmp.&MFC42.#??0CString@@QAE@XZ_540>

00415770                8BFB            mov edi,ebx

00415772                83C9 FF         or ecx,0xFFFFFFFF

00415775                33C0            xor eax,eax

00415777                33ED            xor ebp,ebp

00415779                F2:AE           repne scas byte ptr es:[edi]

0041577B                F7D1            not ecx

0041577D                49              dec ecx                                                 ; 用户名长度

0041577E                C64424 2C 02    mov byte ptr ss:[esp+0x2C],0x2

00415783                74 50           je short ahead_dv.004157D5                              ; --查表开始

00415785                8A0C2B          mov cl,byte ptr ds:[ebx+ebp]                            ; ---取用户名1字节

00415788                33F6            xor esi,esi

0041578A                B8 58284300     mov eax,ahead_dv.00432858                               ; ASCII "aGbEcVdmelfSgmhkiEjckxlsmtnYobpkqDrtsatfuwvlwjxDyIzPAZBXCPDoEKFgGyHmItJaKrLqMNNQOUPuQGRJSLTnUbVCWFXH"

0041578F                3A08            cmp cl,byte ptr ds:[eax]                                ; --用户名1字节与表1字节相比较

00415791                74 0D           je short ahead_dv.004157A0                              ; --是否相等

00415793                83C0 02         add eax,0x2                                             ; ---表往后移2个元素

00415796                46              inc esi                                                 ; 计数加1

00415797                3D C0284300     cmp eax,ahead_dv.004328C0                               ; 判断表是否到了结尾 ("sdR")

0041579C              ^ 7C F1           jl short ahead_dv.0041578F

0041579E                EB 11           jmp short ahead_dv.004157B1

004157A0                8A0C75 59284300 mov cl,byte ptr ds:[esi*2+0x432859]                     ; ----取表中与用户名1字节相等的后一个元素

004157A7                51              push ecx

004157A8                8D4C24 38       lea ecx,dword ptr ss:[esp+0x38]

004157AC                E8 93D10000     call <jmp.&MFC42.#??YCString@@QAEABV0@D@Z_940>          ; ---存放查表后的结果

004157B1                83FE 34         cmp esi,0x34                                            ; ---判断计数是否为0x34

004157B4                75 0E           jnz short ahead_dv.004157C4

004157B6                8B5424 18       mov edx,dword ptr ss:[esp+0x18]                         ; ---在表中没查到情况

004157BA                8D4C24 34       lea ecx,dword ptr ss:[esp+0x34]

004157BE                52              push edx

004157BF                E8 80D10000     call <jmp.&MFC42.#??YCString@@QAEABV0@D@Z_940>          ; 存放数字

004157C4                8BFB            mov edi,ebx

004157C6                83C9 FF         or ecx,0xFFFFFFFF

004157C9                33C0            xor eax,eax

004157CB                45              inc ebp

004157CC                F2:AE           repne scas byte ptr es:[edi]

004157CE                F7D1            not ecx

004157D0                49              dec ecx                                                 ; 用户名长度

004157D1                3BE9            cmp ebp,ecx                                             ; ---判断是否查表完成

004157D3              ^ 72 B0           jb short ahead_dv.00415785

004157D5                8B4424 34       mov eax,dword ptr ss:[esp+0x34]                         ; ----根据用户名从表中查出的字符

004157D9                8B48 F8         mov ecx,dword ptr ds:[eax-0x8]                          ; ---长度

004157DC                83F9 10         cmp ecx,0x10                                            ; 判断是否大于等于0x10

004157DF                7D 3A           jge short ahead_dv.0041581B                             ; 当用户名查表完后注册码长度不大于等于0x10,就自动填充

004157E1                8BC1            mov eax,ecx

004157E3                B9 10000000     mov ecx,0x10

004157E8                2BC8            sub ecx,eax

004157EA                8D5424 1C       lea edx,dword ptr ss:[esp+0x1C]

004157EE                51              push ecx

004157EF                52              push edx

004157F0                B9 04374300     mov ecx,ahead_dv.00433704

004157F5                E8 88CF0000     call <jmp.&MFC42.#?Left@CString@@QBE?AV1@H@Z_4129>

004157FA                50              push eax                                                ; 自动填充的字符

004157FB                8D4C24 38       lea ecx,dword ptr ss:[esp+0x38]

004157FF                C64424 30 03    mov byte ptr ss:[esp+0x30],0x3

00415804                E8 69CD0000     call <jmp.&MFC42.#??YCString@@QAEABV0@ABV0@@Z_939>      ; 与查表后的字符连接

00415809                8D4C24 1C       lea ecx,dword ptr ss:[esp+0x1C]

0041580D                C64424 2C 02    mov byte ptr ss:[esp+0x2C],0x2

00415812                E8 1FCD0000     call <jmp.&MFC42.#??1CString@@QAE@XZ_800>

00415817                8B4424 34       mov eax,dword ptr ss:[esp+0x34]                         ; 连接后的注册码

0041581B                8B4C24 20       mov ecx,dword ptr ss:[esp+0x20]                         ; 输入的注册码

0041581F                51              push ecx

00415820                50              push eax

00415821                FF15 94784200   call dword ptr ds:[<&MSVCRT._mbscmp>]                   ; 比较注册码是否相同

00415827                83C4 08         add esp,0x8

0041582A                85C0            test eax,eax

0041582C                74 24           je short ahead_dv.00415852

 

6.分析总结

a)   判断输入的用户名与注册码第1字节是否为空

b)   取输入的用户名循环在表中查找是否有该元素,如果有,则取表中该元素后一个元素做为注册码。

c)   如果在表中没有查找到元素,则注册码给值为字符’s’,这里会出现万能注册码,只要输入的用户名为0-9的数字,注册码都为 “ssssssssssssssss”。

d)   如果根用户名查找获得的注册码长度小于0x10则用固定字符填充。

7. 算法分析明白,就开始写注册机

#include "stdafx.h"

#include <stdio.h>

#include <windows.h>

 

//-密码表

char *Table = "aGbEcVdmelfSgmhkiEjckxlsmtnYobpkqDrtsatfuwvlwjxDyIzPAZBXCPDoEKFgGyHmItJaKrLqMNNQOUPuQGRJSLTnUbVCWFXHYoZwsdR";

 

//表结束标志

char tag[4] = "sdR";

 

//当查表后注册码不足16位长度时会用下面数据填充

char *AtuoCode = "OgEScVdhYoalmbwp";

 

 

int main(int argc, char* argv[])

{

 

    char UserName[256] = {0};

    char License[256] = {0};

 

    printf("--------------Ahead DVD Copy 注册机------------------------\n\n");

 

    printf("请输入用户名: ");

    scanf("%s",UserName);

 

    if (0x10 < strlen(UserName)-1)

    {

        printf("用户名不能超过16位,请重新输入!\n");

        memset(UserName, 0, strlen(UserName));

        scanf("%s",UserName);

    }

 

    //-判断用户名是否为空

    if (0 == UserName[0])

    {

        printf("请输入用户名\n");

        return -1;

    }

 

    for (int i=0; i<strlen(UserName); i++)

    {

        int index = 0;

 

        //--开始找表

        for (int n=0; n<= strlen(Table); n +=2)

        {

            //--如果在表中查到用户名数字

            if (UserName[i] == Table[n])

            {

                ////-------取表下一位数字做注册码

                License[i] = Table[index*2+1];

                break;

            }

 

            //--判断表是否结束

            if (!strncmp(Table+n, tag, 3))

            {

                break;

            }

 

            index++;

        }

       

        //---判断表是否查找完

        if (0x34 == index)

        {

            License[i] = 's';

        }

 

    }

 

    //--------当用户名查表完后注册码长度不等于0x10,就用固定字符填充

 

    if (0x10 != strlen(License)-1)

    {

 

        //--填充注册码

        strncpy(License+i, AtuoCode, strlen(AtuoCode)-strlen(License));

 

    }

 

    printf("\n");

    printf("注册码:%s\n",License);

 

    system("pause");

 

    return 0;

}

 

8.    测试注册机

输入用户名test

如下图:

9.运行软件输入注册码测试,如下图

10.点确定后注册成功,如下图

完成。

样本及注册机源码下载

http://yunpan.cn/cAFXm3tRsHJRU (提取码:2cac)


声明:该文观点仅代表作者本人,转载请注明来自看雪