说明:作为一位新人在看雪这个高手如云的地方本是不敢随便发帖奈何破解完之后心情激动 思来想去 还是决定发此一贴 就当是给自己的鼓励,也希望前辈们能多多指教.不足之处敬请斧正,下面正文,国际惯例:
标 题: 菜鸟也破解(听说标题要长才能吸引人,不知道这样算不算长!!!!)
作 者: 我
时 间: 2010-04-16,12:45:49
链 接: http://bbs.pediy.com/newthread.php?do=newthread&f=37
【文章标题】: 菜鸟也破解 (听说标题要长才能吸引人,不知道这样算不算长!!!!)
【文章作者】: 我
【软件名称】: CM.exe
【下载地址】:忘了
【加壳方式】: 无壳
【保护方式】: 注册名+序列号
【编写语言】: Microsoft Visual C++ 6.0
【使用工具】: od+peid
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【开始】
1:PEID查壳,Microsoft Visual C++ 6.0,无壳
2:运行程序,填写注册资料 出现错误对话框“注册失败”,一喜,赶紧字符串查找,遗憾,已加密
3:OD载入 咱这里用硬件断点+内存访问断点 Ctrl+F9后来到此处 下面开始具体分析
00401020 81EC 08020000 sub esp, 208
00401026 8D8424 040100>lea eax, dword ptr [esp+104]
0040102D 53 push ebx
0040102E 56 push esi
0040102F 8B35 B4504000 mov esi, dword ptr [<&USER32.GetDlgI>; USER32.GetDlgItemTextA
00401035 57 push edi
00401036 8BBC24 180200>mov edi, dword ptr [esp+218]
0040103D 68 04010000 push 104 ; /Count = 104 (260.)
00401042 50 push eax ; |Buffer
00401043 68 E8030000 push 3E8 ; |ControlID = 3E8 (1000.)
00401048 57 push edi ; |hWnd
00401049 FFD6 call esi ; \GetDlgItemTextA 获取用户名
0040104B 8D4C24 0C lea ecx, dword ptr [esp+C]
0040104F 68 04010000 push 104 ; /Count = 104 (260.)
00401054 51 push ecx ; |Buffer
00401055 68 E9030000 push 3E9 ; |ControlID = 3E9 (1001.)
0040105A 57 push edi ; |hWnd
0040105B FFD6 call esi ; GetDlgItemTextA 获取注册码
0040105D 8B35 08504000 mov esi, dword ptr [<&KERNEL32.LoadL>; kernel32.LoadLibraryA
00401063 68 7C604000 push 0040607C ; /messageboxa
00401068 68 70604000 push 00406070 ; |/user32.dll
0040106D FFD6 call esi ; |\LoadLibraryA
0040106F 8B1D 04504000 mov ebx, dword ptr [<&KERNEL32.GetPr>; |kernel32.GetProcAddress
00401075 50 push eax ; |hModule
00401076 FFD3 call ebx ; \GetProcAddress
00401078 8038 CC cmp byte ptr [eax], 0CC
0040107B 0F84 6B010000 je 004011EC ; 不跳
00401081 68 60604000 push 00406060 ; /getdlgitemtexta
00401086 68 70604000 push 00406070 ; |/user32.dll
0040108B FFD6 call esi ; |\LoadLibraryA
0040108D 50 push eax ; |hModule
0040108E FFD3 call ebx ; \GetProcAddress
00401090 8038 CC cmp byte ptr [eax], 0CC
00401093 0F84 53010000 je 004011EC ; 不跳
00401099 8B8424 1C0200>mov eax, dword ptr [esp+21C]
004010A0 83F8 10 cmp eax, 10
004010A3 0F84 34010000 je 004011DD ; 不跳
004010A9 3D 11010000 cmp eax, 111 ; 不知道什么意思
004010AE 0F85 38010000 jnz 004011EC ; 不跳
004010B4 81BC24 200200>cmp dword ptr [esp+220], 3EA ; 不知道什么意思
004010BF 0F85 27010000 jnz 004011EC ; 不跳
004010C5 8D5424 0C lea edx, dword ptr [esp+C]
004010C9 8D8424 100100>lea eax, dword ptr [esp+110]
004010D0 52 push edx
004010D1 50 push eax
004010D2 E8 29010000 call 00401200
{
00401200 56 push esi ; kernel32.LoadLibraryA
00401201 57 push edi
00401202 8B7C24 0C mov edi, dword ptr [esp+C]
00401206 83C9 FF or ecx, FFFFFFFF
00401209 33C0 xor eax, eax
0040120B F2:AE repne scas byte ptr es:[edi]
0040120D F7D1 not ecx
0040120F 49 dec ecx
00401210 74 42 je short 00401254
00401212 83F9 06 cmp ecx, 6 ; 检查用户名>5
00401215 7C 3D jl short 00401254 ; 小于则跳走
00401217 8B5424 10 mov edx, dword ptr [esp+10]
0040121B 83C9 FF or ecx, FFFFFFFF
0040121E 8BFA mov edi, edx
00401220 F2:AE repne scas byte ptr es:[edi]
00401222 F7D1 not ecx
00401224 49 dec ecx
00401225 75 28 jnz short 0040124F ; 再次检查注册码长
00401227 BF A4604000 mov edi, 004060A4 ; check the input!
0040122C 83C9 FF or ecx, FFFFFFFF
0040122F F2:AE repne scas byte ptr es:[edi]
00401231 F7D1 not ecx
00401233 2BF9 sub edi, ecx
00401235 8BC1 mov eax, ecx
00401237 8BF7 mov esi, edi
00401239 8BFA mov edi, edx
0040123B C1E9 02 shr ecx, 2
0040123E F3:A5 rep movs dword ptr es:[edi], dword p>
00401240 8BC8 mov ecx, eax
00401242 B8 01000000 mov eax, 1
00401247 83E1 03 and ecx, 3
0040124A F3:A4 rep movs byte ptr es:[edi], byte ptr>
0040124C 5F pop edi
0040124D 5E pop esi
0040124E C3 retn
0040124F 5F pop edi
00401250 33C0 xor eax, eax ; 清空EAX 后面有用
00401252 5E pop esi
00401253 C3 retn
}
004010D7 83C4 08 add esp, 8 ; 跳转到这
004010DA A3 80854000 mov dword ptr [408580], eax ; EAX已被清空 将【408580】赋0 后面有用
004010DF 85C0 test eax, eax ; eax 不为空则跳走
004010E1 0F85 D4000000 jnz 004011BB ; 不跳
004010E7 8D4C24 0C lea ecx, dword ptr [esp+C]
004010EB 8D9424 100100>lea edx, dword ptr [esp+110]
004010F2 51 push ecx
004010F3 52 push edx
004010F4 E8 87010000 call 00401280 关键call 关键
{
00401280 81EC 18010000 sub esp, 118 ; -- 开辟局部变量空间
00401286 A1 B8604000 mov eax, dword ptr [4060B8] ; --
0040128B 66:8B0D BC604>mov cx, word ptr [4060BC]
00401292 53 push ebx
00401293 55 push ebp
00401294 56 push esi
00401295 8BB424 280100>mov esi, dword ptr [esp+128]
0040129C 57 push edi
0040129D 33DB xor ebx, ebx
0040129F 894424 14 mov dword ptr [esp+14], eax
004012A3 66:894C24 18 mov word ptr [esp+18], cx
004012A8 8BFE mov edi, esi
004012AA 83C9 FF or ecx, FFFFFFFF
004012AD 33C0 xor eax, eax
004012AF 891D 84854000 mov dword ptr [408584], ebx
004012B5 F2:AE repne scas byte ptr es:[edi]
004012B7 8A15 BE604000 mov dl, byte ptr [4060BE]
004012BD 8BAC24 300100>mov ebp, dword ptr [esp+130]
004012C4 F7D1 not ecx
004012C6 49 dec ecx
004012C7 885424 1A mov byte ptr [esp+1A], dl
004012CB 8BD1 mov edx, ecx
004012CD 8BFD mov edi, ebp
004012CF 83C9 FF or ecx, FFFFFFFF
004012D2 895424 1C mov dword ptr [esp+1C], edx
004012D6 F2:AE repne scas byte ptr es:[edi]
004012D8 F7D1 not ecx
004012DA 49 dec ecx
004012DB 8BC1 mov eax, ecx
004012DD 8D4A 04 lea ecx, dword ptr [edx+4]
004012E0 3BC1 cmp eax, ecx
004012E2 894424 10 mov dword ptr [esp+10], eax ; 以上代码功能:检测password-username==4
004012E6 74 0D je short 004012F5 ; 跳
004012E8 5F pop edi
004012E9 5E pop esi
004012EA 5D pop ebp
004012EB 33C0 xor eax, eax
004012ED 5B pop ebx
004012EE 81C4 18010000 add esp, 118
004012F4 C3 retn
004012F5 85D2 test edx, edx ; 再次检查usermane长度
004012F7 0F8E B6000000 jle 004013B3
004012FD 8D5424 14 lea edx, dword ptr [esp+14]
00401301 8D7C28 FF lea edi, dword ptr [eax+ebp-1]
00401305 2BD6 sub edx, esi
00401307 8D6C24 24 lea ebp, dword ptr [esp+24]
0040130B 895424 20 mov dword ptr [esp+20], edx
0040130F 2BEE sub ebp, esi
00401311 8BC3 /mov eax, ebx ; 计算出password后几位 长度等于username
00401313 25 01000080 |and eax, 80000001
00401318 79 05 |jns short 0040131F
0040131A 48 |dec eax
0040131B 83C8 FE |or eax, FFFFFFFE
0040131E 40 |inc eax
0040131F 74 37 |je short 00401358 ; 奇数次跳 偶数次不跳
00401321 8A06 |mov al, byte ptr [esi]
00401323 8A0C32 |mov cl, byte ptr [edx+esi]
00401326 3AC1 |cmp al, cl
00401328 7D 13 |jge short 0040133D
0040132A 8ACB |mov cl, bl
0040132C D0E1 |shl cl, 1
0040132E 2AC1 |sub al, cl
00401330 8A0F |mov cl, byte ptr [edi]
00401332 FEC8 |dec al
00401334 3AC8 |cmp cl, al
00401336 88042E |mov byte ptr [esi+ebp], al
00401339 ^ 75 AD |jnz short 004012E8 ; 不跳
0040133B EB 5C |jmp short 00401399
0040133D 8BC3 |mov eax, ebx
0040133F B9 06000000 |mov ecx, 6
00401344 99 |cdq
00401345 F7F9 |idiv ecx
00401347 8A07 |mov al, byte ptr [edi]
00401349 8A5414 14 |mov dl, byte ptr [esp+edx+14]
0040134D 2AD3 |sub dl, bl
0040134F 3AC2 |cmp al, dl
00401351 88142E |mov byte ptr [esi+ebp], dl
00401354 ^ 75 92 |jnz short 004012E8 ; 不跳
00401356 EB 3D |jmp short 00401395
00401358 8A0E |mov cl, byte ptr [esi]
0040135A 8A0432 |mov al, byte ptr [edx+esi]
0040135D 3AC8 |cmp cl, al
0040135F 7D 17 |jge short 00401378
00401361 8AC3 |mov al, bl
00401363 D0E0 |shl al, 1
00401365 02C1 |add al, cl
00401367 8A0F |mov cl, byte ptr [edi]
00401369 FEC0 |inc al
0040136B 3AC8 |cmp cl, al
0040136D 88042E |mov byte ptr [esi+ebp], al
00401370 ^ 0F85 72FFFFFF |jnz 004012E8 ; 不跳
00401376 EB 21 |jmp short 00401399
00401378 8BC3 |mov eax, ebx
0040137A B9 06000000 |mov ecx, 6
0040137F 99 |cdq
00401380 F7F9 |idiv ecx
00401382 8A07 |mov al, byte ptr [edi]
00401384 8A5414 14 |mov dl, byte ptr [esp+edx+14]
00401388 02D3 |add dl, bl
0040138A 3AC2 |cmp al, dl
0040138C 88142E |mov byte ptr [esi+ebp], dl
0040138F ^ 0F85 53FFFFFF |jnz 004012E8 ; 不跳
00401395 8B5424 20 |mov edx, dword ptr [esp+20]
00401399 8B4424 1C |mov eax, dword ptr [esp+1C]
0040139D 43 |inc ebx
0040139E 46 |inc esi
0040139F 4F |dec edi
004013A0 3BD8 |cmp ebx, eax
004013A2 ^ 0F8C 69FFFFFF \jl 00401311
004013A8 8B4424 10 mov eax, dword ptr [esp+10] ; 下面是对password前四位的计算
004013AC 8BAC24 300100>mov ebp, dword ptr [esp+130]
004013B3 2BC3 sub eax, ebx
004013B5 33F6 xor esi, esi
004013B7 85C0 test eax, eax
004013B9 894424 1C mov dword ptr [esp+1C], eax
004013BD 7E 40 jle short 004013FF ; 不跳
004013BF BF 01000000 mov edi, 1
004013C4 8D5424 24 lea edx, dword ptr [esp+24]
004013C8 8BC5 mov eax, ebp
004013CA 8D4C24 24 lea ecx, dword ptr [esp+24]
004013CE 2BFA sub edi, edx
004013D0 2BC1 sub eax, ecx
004013D2 894424 10 mov dword ptr [esp+10], eax
004013D6 8D4C34 24 /lea ecx, dword ptr [esp+esi+24]
004013DA 8BC3 |mov eax, ebx
004013DC 99 |cdq
004013DD 8D2C0F |lea ebp, dword ptr [edi+ecx]
004013E0 F7FD |idiv ebp
004013E2 8B4424 10 |mov eax, dword ptr [esp+10]
004013E6 8A5414 14 |mov dl, byte ptr [esp+edx+14]
004013EA 381408 |cmp byte ptr [eax+ecx], dl
004013ED 8811 |mov byte ptr [ecx], dl
004013EF ^ 0F85 F3FEFFFF |jnz 004012E8 ; 不跳
004013F5 8B4424 1C |mov eax, dword ptr [esp+1C]
004013F9 46 |inc esi
004013FA 4B |dec ebx
004013FB 3BF0 |cmp esi, eax
004013FD ^ 7C D7 \jl short 004013D6
004013FF 5F pop edi
00401400 B8 01000000 mov eax, 1
00401405 5E pop esi
00401406 5D pop ebp
00401407 A3 84854000 mov dword ptr [408584], eax
0040140C 5B pop ebx
0040140D 81C4 18010000 add esp, 118
00401413 C3 retn
}
004010F9 8B0D 80854000 mov ecx, dword ptr [408580] ; 地址【408580】 已被赋0
004010FF 83C4 08 add esp, 8
00401102 85C9 test ecx, ecx ; ecx 不为空则跳走 完蛋
00401104 A3 84854000 mov dword ptr [408584], eax
00401109 75 0B jnz short 00401116 ; 不跳
0040110B 85C0 test eax, eax ; 再次检查EAX是否空
0040110D 74 07 je short 00401116
0040110F B8 01000000 mov eax, 1
00401114 EB 02 jmp short 00401118
00401116 33C0 xor eax, eax
00401118 A3 88854000 mov dword ptr [408588], eax
0040111D 50 push eax
0040111E 8D4424 10 lea eax, dword ptr [esp+10]
00401122 8D8C24 140100>lea ecx, dword ptr [esp+114]
00401129 50 push eax
0040112A 51 push ecx
0040112B E8 F0020000 call 00401420 对字符串解密 跳转太多不易跟进
5.总结
分析到此就能写注册机了 ,不过这里我还有2个地方不懂 请大虾们赐教下
004010A3 0F84 34010000 je 004011DD ; 不跳
004010A9 3D 11010000 cmp eax, 111 ; 不知道什么意思
004010AE 0F85 38010000 jnz 004011EC ; 不跳
004010B4 81BC24 200200>cmp dword ptr [esp+220], 3EA ; 不知道什么意思
算法总结下:
username>5,注册码-用户名=4,
下面是注册机源码VC++6.0编译通过,感觉写的很糟糕,不过能计算出注册码
#include<stdio.h>
#include<string.h>
void main()
{
char firstname[40],lastname[20],p[24],table[]={'w','j','h','5','2','0','0','0','oxc','0','0','0'};
int a,c,y,i,j=0;
printf("enter your username must>5\n");
scanf("%s",lastname);
y=strlen(lastname); //取用户名长度y
for(i=0;i<y;i++) //计算后y位注册码
{
a=(int)lastname[i],c=(int)table[i];
if(i%2==0)
{
if(a>=c)
{
p[y-i-1]=table[i%6]+i;
}
else
{
c=a+i*2;
p[y-i-1]=++c;
}
}
else
{
if(a>=c)
{
p[y-i-1]=table[i%6]-i;
}
else
{
a=a-i*2;
p[y-i-1]=--a;
}
}
}
for(i=y;i>y-4;i--,j++) // 计算前4位注册码
{
firstname[j]=(int)table[i%(j+1)];
}
firstname[4]='\0';
strcat(firstname,p);
firstname[4+y]='\0';
printf("%s ",firstname);
}
【结束】
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!