菜鸟水平有限,凑合着看吧。时间紧张,排版糟糕,莫怪。顺便说一句,我花了30个十分钟
。
W32Dasm反汇编,找到“程序解锁”字符串,双击来到004012C2,向上看到算法函数入口004011B0。
OD载入,设断点004011B0,运行。输入用户名:wuhui,注册码:1234567890123456789012345678。
代码如下:
004011B0 /$ 81EC 00060000 sub esp, 600
004011B6 |. 8D8424 000100>lea eax, dword ptr [esp+100]
004011BD |. 53 push ebx
004011BE |. 8B9C24 080600>mov ebx, dword ptr [esp+608]
004011C5 |. 55 push ebp
004011C6 |. 56 push esi
004011C7 |. 57 push edi
004011C8 |. 8B3D AC504000 mov edi, dword ptr [<&USER32.GetDlgI>; USER32.GetDlgItemTextA
004011CE |. 6A 10 push 10 ; /Count = 10 (16.)
004011D0 |. 50 push eax ; |Buffer
004011D1 |. 68 E8030000 push 3E8 ; |ControlID = 3E8 (1000.)
004011D6 |. 53 push ebx ; |hWnd
004011D7 |. FFD7 call edi ; \GetDlgItemTextA
004011D9 |. 8D8C24 100200>lea ecx, dword ptr [esp+210]
004011E0 |. 6A 40 push 40 ; /Count = 40 (64.)
004011E2 |. 51 push ecx ; |Buffer
004011E3 |. 68 E9030000 push 3E9 ; |ControlID = 3E9 (1001.)
004011E8 |. 53 push ebx ; |hWnd
004011E9 |. 8BF0 mov esi, eax ; |
004011EB |. FFD7 call edi ; \GetDlgItemTextA
004011ED |. 83FE 03 cmp esi, 3 //用户名大于3位
004011F0 |. 0F8C D9000000 jl 004012CF
004011F6 |. 83F8 1C cmp eax, 1C //注册码为28(4位一组,共七组)位
004011F9 |. 0F85 D0000000 jnz 004012CF
004011FF |. 33DB xor ebx, ebx
00401201 |. 33FF xor edi, edi
00401203 |> 0FBE943C 1002>/movsx edx, byte ptr [esp+edi+210]
0040120B |. 52 |push edx
0040120C |. E8 4F010000 |call 00401360
00401211 |. 83C4 04 |add esp, 4
00401214 |. 85C0 |test eax, eax
00401216 |. 0F84 85000000 |je 004012A1
0040121C |. 47 |inc edi
0040121D |. 83FF 1C |cmp edi, 1C
00401220 |.^ 7C E1 \jl short 00401203
00401222 |. E8 D9FDFFFF call 00401000
00401227 |. 33FF xor edi, edi
00401229 |. 33C0 xor eax, eax
0040122B |. 3BF3 cmp esi, ebx
0040122D |. 7E 1A jle short 00401249 下面是处理用户名
0040122F |> 0FBE8C04 1001>/movsx ecx, byte ptr [esp+eax+110]//取出用户名一个字符
00401237 |. 03CF |add ecx, edi //累加
00401239 |. C1E1 03 |shl ecx, 3 //累加结果乘8
0040123C |. 8BF9 |mov edi, ecx
0040123E |. 81F7 30C90A8A |xor edi, 8A0AC930 //再与8A0AC930异或
00401244 |. 40 |inc eax
00401245 |. 3BC6 |cmp eax, esi
00401247 |.^ 7C E6 \jl short 0040122F //最后结果在edi中
00401249 |> 33ED xor ebp, ebp
0040124B |. 8DB424 110200>lea esi, dword ptr [esp+211]
00401252 |> 8A06 /mov al, byte ptr [esi]
00401254 |. 8A56 FF |mov dl, byte ptr [esi-1]
00401257 |. 8A4E 01 |mov cl, byte ptr [esi+1]
0040125A |. 884424 11 |mov byte ptr [esp+11], al
0040125E |. 885424 10 |mov byte ptr [esp+10], dl
00401262 |. 8A56 02 |mov dl, byte ptr [esi+2]
00401265 |. 8D4424 10 |lea eax, dword ptr [esp+10]
00401269 |. 57 |push edi //传入用户名处理结果
0040126A |. 50 |push eax //传入一组注册码
0040126B |. 884C24 1A |mov byte ptr [esp+1A], cl
0040126F |. 885424 1B |mov byte ptr [esp+1B], dl
00401273 |. 885C24 1C |mov byte ptr [esp+1C], bl
00401277 |. E8 04FEFFFF |call 00401080 //调用处理函数,见下面分析。
0040127C |. 83C4 08 |add esp, 8
0040127F |. 83F8 01 |cmp eax, 1 //这里必须第七组注册码比较完成以后返回1才成功。
00401282 |. 74 2A |je short 004012AE
00401284 |. 3BC3 |cmp eax, ebx
00401286 |. 74 47 |je short 004012CF
00401288 |. 45 |inc ebp
00401289 |. 83C6 04 |add esi, 4
0040128C |. 83FD 07 |cmp ebp, 7
0040128F |.^ 7C C1 \jl short 00401252
00401291 |. 5F pop edi
00401292 |. 5E pop esi
00401293 |. 5D pop ebp
00401294 |. B8 01000000 mov eax, 1
00401299 |. 5B pop ebx
0040129A |. 81C4 00060000 add esp, 600
004012A0 |. C3 retn
下面是处理每一组的函数。
00401080 /$ 83EC 08 sub esp, 8
00401083 |. 53 push ebx
00401084 |. 56 push esi
00401085 |. 8B7424 14 mov esi, dword ptr [esp+14]
00401089 |. 33C0 xor eax, eax
0040108B |. 33C9 xor ecx, ecx
0040108D |. 57 push edi
0040108E |. 8A46 03 mov al, byte ptr [esi+3]
00401091 |. 8A4E 02 mov cl, byte ptr [esi+2]
00401094 |. 8B3D C0844000 mov edi, dword ptr [4084C0]
0040109A |. 8D0480 lea eax, dword ptr [eax+eax*4]
0040109D |. 8D0441 lea eax, dword ptr [ecx+eax*2]
004010A0 |. 8D1480 lea edx, dword ptr [eax+eax*4]
004010A3 |. 33C0 xor eax, eax
004010A5 |. 8A46 01 mov al, byte ptr [esi+1]
004010A8 |. 8D0450 lea eax, dword ptr [eax+edx*2]
004010AB |. 33D2 xor edx, edx
004010AD |. 8A16 mov dl, byte ptr [esi]
004010AF |. 8D0C80 lea ecx, dword ptr [eax+eax*4]
004010B2 |. 8D844A B02FFF>lea eax, dword ptr [edx+ecx*2+FFFF2F> ; 上面几句作用将传入的那组注册码由字符串转为一个十进制数
004010B9 |. 8B4C24 1C mov ecx, dword ptr [esp+1C] 取出用户名处理结果
004010BD |. 0FAFC0 imul eax, eax
004010C0 |. 03C1 add eax, ecx ; 将十进制数的平方与用户名处理结果相加
004010C2 |. 33D2 xor edx, edx
004010C4 |. F7F7 div edi ; 除以[4084c0]的值,这个值初始为5040,也就是4KB,正好是表的大小了,这里说的表下面会用到。表首地址是004080c8,也是按4个字节为一组划分的,初始值是01230124012501260……看下去就明白了。
004010C6 |. 33C9 xor ecx, ecx
004010C8 |. 8B0495 C88440>mov eax, dword ptr [edx*4+4084C8] ; 除法余数值为索引查表
004010CF |. B2 30 mov dl, 30
004010D1 |. 894424 18 mov dword ptr [esp+18], eax
004010D5 |. 8815 C4844000 mov byte ptr [4084C4], dl
004010DB |. 8815 C5844000 mov byte ptr [4084C5], dl
004010E1 |> 33C0 /xor eax, eax
004010E3 |> 8A1C31 |/mov bl, byte ptr [ecx+esi]
004010E6 |. 3A5C04 18 ||cmp bl, byte ptr [esp+eax+18] ; 传入的注册码每位与查表数据依次比较
004010EA |. 75 12 ||jnz short 004010FE
004010EC |. 3BC8 ||cmp ecx, eax
004010EE |. 75 08 ||jnz short 004010F8
004010F0 |. FE05 C4844000 ||inc byte ptr [4084C4] ; 如相等且对应字节位置也相同则[4084c4]加一
004010F6 |. EB 06 ||jmp short 004010FE
004010F8 |> FE05 C5844000 ||inc byte ptr [4084C5] ; 相等但对应字节位置不同则[4084c5]加一
004010FE |> 40 ||inc eax 这两个值后面会用来比较,请看00401154处
004010FF |. 83F8 04 ||cmp eax, 4
00401102 |.^ 72 DF |\jb short 004010E3
00401104 |. 41 |inc ecx
00401105 |. 83F9 04 |cmp ecx, 4
00401108 |.^ 72 D7 \jb short 004010E1
0040110A |. 33C0 xor eax, eax
0040110C |. 85FF test edi, edi
0040110E |. 894424 0C mov dword ptr [esp+C], eax
00401112 |. 0F86 86000000 jbe 0040119E
00401118 |. 55 push ebp
00401119 |. BD C8844000 mov ebp, 004084C8
0040111E |. 896C24 14 mov dword ptr [esp+14], ebp
00401122 |. EB 02 jmp short 00401126
00401124 |> B2 30 /mov dl, 30
00401126 |> 885424 1C mov byte ptr [esp+1C], dl
0040112A |. 885424 20 |mov byte ptr [esp+20], dl
0040112E |. 33D2 |xor edx, edx
00401130 |> 8A0432 |/mov al, byte ptr [edx+esi]
00401133 |. 33C9 ||xor ecx, ecx
00401135 |> 3A0429 ||/cmp al, byte ptr [ecx+ebp] ; 传入注册码每位与ebp指向的一组数据依次比较
00401138 |. 75 0E |||jnz short 00401148
0040113A |. 3BD1 |||cmp edx, ecx
0040113C |. 75 06 |||jnz short 00401144
0040113E |. FE4424 1C |||inc byte ptr [esp+1C] ; 如相等且对应字节位置也相同则[esp+1C]加一
00401142 |. EB 04 |||jmp short 00401148
00401144 |> FE4424 20 |||inc byte ptr [esp+20] ; 相等但对应字节位置不同则[esp+20]加一
00401148 |> 41 |||inc ecx 这两个值会和前面那两个比较
00401149 |. 83F9 04 |||cmp ecx, 4
0040114C |.^ 72 E7 ||\jb short 00401135
0040114E |. 42 ||inc edx
0040114F |. 83FA 04 ||cmp edx, 4
00401152 |.^ 72 DC |\jb short 00401130
00401154 |. 8A4C24 1C |mov cl, byte ptr [esp+1C]
00401158 |. A0 C4844000 |mov al, byte ptr [4084C4]
0040115D |. 3AC1 |cmp al, cl
0040115F |. 75 26 |jnz short 00401187
00401161 |. 8A5424 20 |mov dl, byte ptr [esp+20]
00401165 |. A0 C5844000 |mov al, byte ptr [4084C5]
0040116A |. 3AC2 |cmp al, dl ;
0040116C |. 75 19 |jnz short 00401187
0040116E |. 8B4424 14 |mov eax, dword ptr [esp+14] ; 当[esp+1C]==[4084C4]&&[esp+20]==[4084C5]时修改表格
00401172 |. 8B4D 00 |mov ecx, dword ptr [ebp] ;[esp+14]是表的地址,初始为表头地址
00401175 |. 8B5424 10 |mov edx, dword ptr [esp+10]
00401179 |. 8908 |mov dword ptr [eax], ecx 这里把当前ebp指向的那组数据复制到[esp+14]指向的表地址内
0040117B |. 42 |inc edx
0040117C |. 83C0 04 |add eax, 4 ; 复制一次后,[esp+14]指向新的地址
0040117F |. 895424 10 |mov dword ptr [esp+10], edx 每相等一次后[esp+10]的值累加1。
00401183 |. 894424 14 |mov dword ptr [esp+14], eax
00401187 |> 83C5 04 |add ebp, 4 指向表下一组数据
0040118A |. 4F |dec edi
0040118B |.^ 75 97 \jnz short 00401124
0040118D |. 8B4424 10 mov eax, dword ptr [esp+10] ; 返回值就是[esp+10],同时也是下一次运算的除数,看看上面004010C4地址处的代码明白了。
00401191 |. 5D pop ebp
00401192 |. 5F pop edi
00401193 |. 5E pop esi
00401194 |. A3 C0844000 mov dword ptr [4084C0], eax ;[4084C0]除数
00401199 |. 5B pop ebx
0040119A |. 83C4 08 add esp, 8
0040119D |. C3 retn
考试了,时间有限,写了个简易的注册机,只算第七步, 用户名是wuhui,
注册码为123456789012345678901234XXXX,其中XXXX就是下面算出的东西,记得倒着用,例如最后一组是9992,于是注册码为1234567890123456789012342999。有兴趣的朋友写个完整版的注册码出来吧。
#include "stdio.h"
main()
{
char tab[]="2693462046915140519353205391462946915103514051495193530153205329539159235941294829733108317031793198360136203629";
char tab2[]="26402693462046915140519353205391462946915103514051495193530153205329539159235941294829733108317031793198360136203629369139283971410841704179419846014620462946914928497151035140514951935301532053295391540154205429549159235941317";
char ch[4];
unsigned int i,j,k,n,m,t;
int tong,butong,tong2,butong2;
for(i=0;i<10000;i++)
{
t=0;
tong=30;
butong=30;
k=i;
for(j=0;j<4;j++)
{
ch[j]=k%10+0x30;
k=k/10;
}
j=(i*i+0xe1d06d38)%8;
k=j;
for(j=0;j<4;j++)
{
for(n=0;n<4;n++)
{
if(tab[k*4+j]==ch[n])
if(j==n)
tong++;
else
butong++;
}
}
for(m=0;m<8;m++)
{
butong2=30;
tong2=30;
for(j=0;j<4;j++)
{
for(n=0;n<4;n++)
{
if(tab2[m*4+j]==ch[n])
{
if(j==n)
tong2++;
else
butong2++;
}
}
}
if(tong==tong2&&butong==butong2)
t++;
}
if(t==1)
printf("d\n",i);
}
getchar();
}