一个简单的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 static/image/common/back.gif
金龟子的第二个沙发。哈哈
嘿嘿。大神勿喷。。
不错能搞出算法,向你学习了! pojie668 发表于 2013-4-9 17:29 static/image/common/back.gif
不错能搞出算法,向你学习了!
一起学习!加油!
学习一下,呵呵 金龟子!凶! yy281566609 发表于 2013-4-10 09:40 static/image/common/back.gif
金龟子!凶!
{:1_903:}膜拜大神!
来围观学习一下,牛哄哄的
页:
[1]