real金龟子 发表于 2013-4-9 17:22

一个简单的CrackMe,带注册机。。

这个CM还是比较简单的,但是为什么会想要用这个CM写注册机,是因为我还没有写过注册机。。。额,第一次写,大神勿喷!

首先我们先运行下程序,程序的样子是这样子的


然后我们点击下OK,这个程序会先观点主对话框,然后再弹一个消息框出来,提示你


好的,这个程序是无壳的,那么就可以先去OD了吧。
先进OD,看到的是这样的,这个就可以看到它的对话框的回调函数的地址了。就是00403184,那么我们就直接去了。


我要下断点的话,就直接在GetDlgItemText这里下了。

然后我们继续向下,其实分析到后面就会发现这个对用户名和输入的密码根本没有要求,而且其实可以不要用户名的。。。嘿嘿

我们继续向下单步咯。。。这个下面就是在获取注册表里面的信息了,这个要获取的键值是“HKEY_LOCAL_MACHIN\\SOFTWARE\\Misrosoft\\Windows\\CurrentVersion"下面的一个
”ProductId“这样一个键值。
那么我机器上的这个值是”76481—640—8834005—23291“然后再在前面加上"WS",就是、、”WS76481—640—8834005—23291“,我在这里将这个称为”注册表码1",哈哈。


继续往下面走,看到这个call,注意这个call,嘿嘿。


我们可以进去看看。其实这里面是在对一个代码段进行解密,我觉得是解密吧,因为这个地址是00403052,可以再反汇编窗口跟一下,这个其实是代码段的代码,而且在没解密之前,这段代码,额。。看不懂,然后就是对他进行解密了。


我们可以看看解密之后的代码。,下面就是主要的解密之后的代码,一看就是关键代码,关键算法。。嘿嘿嘿。
00403038|.33C0                   xor eax,eax
0040303A|.68 93334000            push aescul.00403393
0040303F|.64:FF30                push dword ptr fs:
00403042|.64:8920                mov dword ptr fs:,esp
00403045|.9C                     pushfd
00403046|.9C                     pushfd
00403047|.58                     pop eax                        ;kernel32.7C81776F
00403048|.0D 00010000            or eax,0x100
0040304D|.50                     push eax
0040304E|.9D                     popfd
0040304F|.90                     nop
00403050|.33F6                   xor esi,esi
00403052|.33FF                   xor edi,edi                      ;ntdll.7C930208
00403054|.33D2                   xor edx,edx                      ;ntdll.KiFastSystemCallRet
00403056|.8B2D 124B4000          mov ebp,dword ptr ds:
0040305C|.BF 02454000            mov edi,aescul.00404502
00403061|>55                     /push ebp
00403062|.57                     |push edi                        ;ntdll.7C930208
00403063|.56                     |push esi                        ;注意密钥的地址
00403064|.BD C0444000            |mov ebp,aescul.004044C0         ;ASCII "0I5LZ7G123RXCV9OPAS6TBN48YUHJKDF0QWEM"
00403069|.BB BA434000            |mov ebx,aescul.004043BA         ;ASCII "WS76481-640-8834005-23291"
0040306E|.8A0433               |mov al,byte ptr ds:    ;将注册码循环放入AL
00403071|.C1F8 04                |sar eax,0x4
00403074|.83E0 0F                |and eax,0xF                     ;对注册码的ASCII的高位进行处理
00403077|.E8 BF000000            |call aescul.0040313B            ;一样的对处理函数
0040307C|.8807                   |mov byte ptr ds:,al      ;放正确的密码
0040307E|.8A0C33               |mov cl,byte ptr ds:
00403081|.83E1 0F                |and ecx,0xF
00403084|.8BC1                   |mov eax,ecx
00403086|.E8 B0000000            |call aescul.0040313B            ;对低位进行一样的处理
0040308B|.8847 01                |mov byte ptr ds:,al
0040308E|.5E                     |pop esi                         ;kernel32.7C81776F
0040308F|.5F                     |pop edi                         ;kernel32.7C81776F
00403090|.5D                     |pop ebp                         ;kernel32.7C81776F
00403091|.46                     |inc esi
00403092|.83C7 02                |add edi,0x2
00403095|.3BEE                   |cmp ebp,esi
00403097|.^ 75 C8                  \jnz short aescul.00403061
00403099|.33F6                   xor esi,esi                      ;在00404501里面保存的是算好的
0040309B|.8B86 BA424000          mov eax,dword ptr ds:[esi+0x4042>;其实下面这就是在对我输入的密码和算出来的密码进行判断
004030A1|.8B9E 02454000          mov ebx,dword ptr ds:[esi+0x4045>;下面就说明密码的位数必须的0x10位
004030A7|.3BC3                   cmp eax,ebx
004030A9|.75 45                  jnz short aescul.004030F0
004030AB|.83C6 04                add esi,0x4
004030AE|.8B86 BA424000          mov eax,dword ptr ds:[esi+0x4042>;这里是我输入的注册码
004030B4|.8B9E 02454000          mov ebx,dword ptr ds:[esi+0x4045>
004030BA|.3BC3                   cmp eax,ebx
004030BC|.75 32                  jnz short aescul.004030F0
004030BE|.83C6 04                add esi,0x4
004030C1|.8B86 BA424000          mov eax,dword ptr ds:[esi+0x4042>
004030C7|.8B9E 02454000          mov ebx,dword ptr ds:[esi+0x4045>
004030CD|.3BC3                   cmp eax,ebx
004030CF|.75 1F                  jnz short aescul.004030F0
004030D1|.83C6 04                add esi,0x4
004030D4|.8B86 BA424000          mov eax,dword ptr ds:[esi+0x4042>
004030DA|.8B9E 02454000          mov ebx,dword ptr ds:[esi+0x4045>
004030E0|.3BC3                   cmp eax,ebx
004030E2|.75 0C                  jnz short aescul.004030F0
004030E4|.C705 F2444000 01000000 mov dword ptr ds:,0x1
004030EE|.EB 0A                  jmp short aescul.004030FA
004030F0|>C705 F2444000 00000000 mov dword ptr ds:,0x0
004030FA|>9D                     popfd
004030FB|.33C0                   xor eax,eax
004030FD|.64:8F00                pop dword ptr fs:         ;kernel32.7C81776F
00403100|.83C4 04                add esp,0x4
00403103|.833D F2444000 01       cmp dword ptr ds:,0x1
0040310A|.75 15                  jnz short aescul.00403121
0040310C|.6A 40                  push 0x40                        ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040310E|.68 3D404000            push aescul.0040403D             ; |Title = "Congratulations..."
00403113|.68 AB414000            push aescul.004041AB             ; |Text = "Registered to: "
00403118|.6A 00                  push 0x0                         ; |hOwner = NULL
0040311A|.E8 A8030000            call <jmp.&USER32.MessageBoxA>   ; \MessageBoxA
0040311F|.EB 13                  jmp short aescul.00403134
00403121|>6A 30                  push 0x30                        ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00403123|.68 50404000            push aescul.00404050             ; |Title = "Error"
00403128|.68 56404000            push aescul.00404056             ; |Text = "Wrong Serial Number!"
0040312D|.6A 00                  push 0x0                         ; |hOwner = NULL
0040312F|.E8 93030000            call <jmp.&USER32.MessageBoxA>   ; \MessageBoxA
00403134|>6A 00                  push 0x0                         ; /ExitCode = 0
00403136\.E8 C8030000            call <jmp.&KERNEL32.ExitProcess> ; \ExitProcess
0040313B/$8935 EE444000          mov dword ptr ds:,esi
00403141|.8B15 EA444000          mov edx,dword ptr ds:
00403147|.8B0D E6444000          mov ecx,dword ptr ds:;这个是密钥的位数
0040314D|.3BD1                   cmp edx,ecx                      ;判断有没有循环完毕,这个edx计数器是上次算完了之后的结果
0040314F|.72 02                  jb short aescul.00403153
00403151|.33D2                   xor edx,edx                      ;ntdll.KiFastSystemCallRet
00403153|>0FBE7415 00            /movsx esi,byte ptr ss: ;依次循环取出密钥中的字符
00403158|.81E6 0F000080          |and esi,0x8000000F            ;取低位
0040315E|.79 05                  |jns short aescul.00403165
00403160|.4E                     |dec esi
00403161|.83CE F0                |or esi,-0x10
00403164|.46                     |inc esi
00403165|>3BF0                   |cmp esi,eax                     ;直到与注册表字符的高位相等就停止
00403167|.74 09                  |je short aescul.00403172
00403169|.42                     |inc edx                         ;ntdll.KiFastSystemCallRet
0040316A|.3BD1                   |cmp edx,ecx
0040316C|.^ 7C E5                  |jl short aescul.00403153
0040316E|.33D2                   |xor edx,edx                     ;ntdll.KiFastSystemCallRet
00403170|.^ EB E1                  \jmp short aescul.00403153
00403172|>8915 EA444000          mov dword ptr ds:,edx;将密钥计数器放回
00403178|.8B35 EE444000          mov esi,dword ptr ds:
0040317E|.0FBE042A               movsx eax,byte ptr ds:;将密钥中对应的算出来的正确密码放回正确密码的字符创
00403182|.42                     inc edx                        ;ntdll.KiFastSystemCallRet



好的,那我们直接去到解密之后的关键代码处,下面这个循环就是关键,这段代码的主要含义,就是将刚刚的代号为”注册表码1“的每一位的SCAII取出来,然后高位做一个处理,低为做一个处理。


下面我们就来看看具体的处理代码,这个就是具体的。他的那个算法的思路,就是先存一个密钥,就是”0I5LZ7G123RXCV9OPAS6TBN48YUHJKDF0QWEM“,然后依次取出每一位密钥的低位,然后和我们”注册表码1“的高低位依次比较,如果相等,就可以讲这个密钥对应的那个字符选出来,作为真的注册码的一个字符、


最后算出来的那个真的注册码字符一共有0x30位,但是我们只需要前面0x10位。。。嘿嘿嘿。
所以这个我的机子的注册码就是
57U33W3VST3XCABM



下面是注册机的代码

#include <stdio.h>
#include <windows.h>
#include <tchar.h>

TCHAR cMiyao[] = "0I5LZ7G123RXCV9OPAS6TBN48YUHJKDF0QWEM";

void main()
{
        TCHAR cbuffer ;

        TCHAR cGuodu[] = "WS";
        TCHAR cPassword = {0};
        int reg = 0;
        int regD = 0;
        int regG = 0;
        int miyao = 0;
        int i;
        static int j = 0, k = 0;
       
        LONG ret;
        DWORD regSize = 25;
        HKEY hMainKey = HKEY_LOCAL_MACHINE;
        HKEY hSubKey;
       
        LONG ReturnValue = RegOpenKeyEx(hMainKey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0L, KEY_QUERY_VALUE, &hSubKey);
        if (ReturnValue == ERROR_SUCCESS)
        {
                ret = RegQueryValueEx(hSubKey, "ProductId", NULL, NULL, (unsigned char *)cbuffer, ®Size);
        }
       
        if (ret == ERROR_SUCCESS)
        {
                _tcscat(cGuodu, cbuffer);
                for ( i = 0; i < 18; i++)
                {
                        if (j >= 0x25)
                        {
                                j = 0;
                        }
                        //高位
                        reg = cGuodu;
                        regG = (reg&0xf0)/16;
                        for (j; j < 0x25; j++)
                        {

                                miyao = cMiyao;
                                miyao = miyao&0x0f;
                                if (miyao == regG)
                                {
                                        cPassword = cMiyao;
                                        k++;
                                        break;       
                                }
                                if (j >= 0x24)
                                {
                                        j = 0;
                                }
                        }
                        //低位
                        regD = reg&0x0f;
                        if (j >= 0x25)
                        {
                                j = 0;
                        }
                        for (j; j<0x25; j++)
                        {
                                miyao = cMiyao;
                                miyao = miyao&0x0f;
                                if (miyao == regD)
                                {
                                        cPassword = cMiyao;
                                        k++;
                                        break;
                                }
                                if (j >= 0x24)
                                {
                                        j = 0;
                                }       
                        }
                }
                for (int m = 0; m <16; m++)
                {
                        printf("%c", cPassword);
                }
                printf("\n");
        }
}





我这个注册机写的确实有点差。。而且我还不知道有没有bug,大神不要喷,小菜第一次亮相。。。多多指导














Kavia 发表于 2013-4-9 17:26

金龟子的第二个沙发。哈哈

real金龟子 发表于 2013-4-9 17:29

Kavia 发表于 2013-4-9 17:26 static/image/common/back.gif
金龟子的第二个沙发。哈哈

嘿嘿。大神勿喷。。

pojie668 发表于 2013-4-9 17:29

不错能搞出算法,向你学习了!

real金龟子 发表于 2013-4-9 22:14

pojie668 发表于 2013-4-9 17:29 static/image/common/back.gif
不错能搞出算法,向你学习了!

一起学习!加油!

airldwdl 发表于 2013-4-10 08:52

学习一下,呵呵

yy281566609 发表于 2013-4-10 09:40

金龟子!凶!

real金龟子 发表于 2013-4-10 13:36

yy281566609 发表于 2013-4-10 09:40 static/image/common/back.gif
金龟子!凶!

{:1_903:}膜拜大神!

ipj 发表于 2013-4-10 13:48

来围观学习一下,牛哄哄的
页: [1]
查看完整版本: 一个简单的CrackMe,带注册机。。