【软件名称】《加密与解密》随书光盘习题GC Crackme 9GC Crackme 9和GC Crackme 10
【应用平台】Win2000
【软件大小】86.0KB和130KB
【软件限制】Serial以及Name/Serial/Unlock Code
【破解声明】该文主要是讲解穷举法在写注册机中的具体应用,适合我这样的菜鸟
【破解工具】OD
【分析过程】
一《加密与解密》随书光盘习题GC Crackme 9GC Crackme 9破解及注册机的详细过程
1 用PEID查看,UPX 0.89.6 - 1.02 / 1.05 - 1.22 (Delphi) stub -> Markus & Lazlo发现加壳,手动脱壳后,发现程序是DELPHI的,本想用DEDE,结果Procedure中什么也看不到,很不爽了。
2 用OD加载脱壳后的程序,通过搜索字符串,发现下面的关键代码:
00427BB2 |. 68 EC7B4200 PUSH Crackme9.00427BEC ; |Title = "Success"
00427BB7 |. 68 F47B4200 PUSH Crackme9.00427BF4 ; |Text = "Serial Correct!"
00427BBC |. 6A 00 PUSH 0 ; |hOwner = NULL
00427BBE |. E8 45D9FDFF CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
向上查看程序,决定在42B748处下断点,点击“check”按钮,果然,中断在此,断点找到,大功告成1/3了。
00427B48 /. 55 PUSH EBP
00427B49 |. 8BEC MOV EBP,ESP
00427B4B |. 6A 00 PUSH 0
00427B4D |. 53 PUSH EBX
00427B4E |. 8BD8 MOV EBX,EAX
00427B50 |. 33C0 XOR EAX,EAX
00427B52 |. 55 PUSH EBP
00427B53 |. 68 E07B4200 PUSH Crackme9.00427BE0
00427B58 |. 64:FF30 PUSH DWORD PTR FS:[EAX]
00427B5B |. 64:8920 MOV DWORD PTR FS:[EAX],ESP
00427B5E |. 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
00427B61 |. 8B83 E0010000 MOV EAX,DWORD PTR DS:[EBX+1E0]
00427B67 |. E8 9CE2FEFF CALL Crackme9.00415E08
00427B6C |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; 取Serial
00427B6F |. E8 B0E8FDFF CALL Crackme9.00406424
00427B74 |. A3 60974200 MOV DWORD PTR DS:[429760],EAX ; 429760中存放Serial的Hex
00427B79 |. 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
00427B7C |. 8B83 E0010000 MOV EAX,DWORD PTR DS:[EBX+1E0]
00427B82 |. E8 81E2FEFF CALL Crackme9.00415E08
00427B87 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00427B8A |. E8 19BCFDFF CALL Crackme9.004037A8
00427B8F |. A2 64974200 MOV BYTE PTR DS:[429764],AL
00427B94 |. 803D 64974200>CMP BYTE PTR DS:[429764],5 ; Serial长度必须为5
00427B9B |. 75 2D JNZ SHORT Crackme9.00427BCA
00427B9D |. A1 60974200 MOV EAX,DWORD PTR DS:[429760] ; Serial的Hex
00427BA2 |. E8 11FFFFFF CALL Crackme9.00427AB8 ; 判断是否正确的注册码的函数
00427BA7 |. 803D 65974200>CMP BYTE PTR DS:[429765],0
00427BAE |. 75 1A JNZ SHORT Crackme9.00427BCA ; 关键跳转
00427BB0 |. 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
00427BB2 |. 68 EC7B4200 PUSH Crackme9.00427BEC ; |Title = "Success"
00427BB7 |. 68 F47B4200 PUSH Crackme9.00427BF4 ; |Text = "Serial Correct!"
00427BBC |. 6A 00 PUSH 0 ; |hOwner = NULL
00427BBE |. E8 45D9FDFF CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
00427BC3 |. C605 65974200>MOV BYTE PTR DS:[429765],1
00427BCA |> 33C0 XOR EAX,EAX
00427BCC |. 5A POP EDX
00427BCD |. 59 POP ECX
00427BCE |. 59 POP ECX
00427BCF |. 64:8910 MOV DWORD PTR FS:[EAX],EDX
00427BD2 |. 68 E77B4200 PUSH Crackme9.00427BE7
00427BD7 |> 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
00427BDA |. E8 4DB9FDFF CALL Crackme9.0040352C
00427BDF \. C3 RETN
其中CALL Crackme9.00427AB8 ; 判断是否正确的注册码的函数如下
00427AB8 /$ 53 PUSH EBX
00427AB9 |. 56 PUSH ESI
00427ABA |. 57 PUSH EDI
00427ABB |. 51 PUSH ECX
00427ABC |. 8BD8 MOV EBX,EAX
00427ABE |. BE 54974200 MOV ESI,Crackme9.00429754
00427AC3 |. E8 C0FFFFFF CALL Crackme9.00427A88 ; 设置比较对象的值
00427AC8 |. C605 65974200>MOV BYTE PTR DS:[429765],1
00427ACF |. C60424 01 MOV BYTE PTR SS:[ESP],1
00427AD3 |. 83FB 03 CMP EBX,3
00427AD6 |. 7C 2F JL SHORT Crackme9.00427B07
00427AD8 |> 8BC3 /MOV EAX,EBX
00427ADA |. BF 03000000 |MOV EDI,3
00427ADF |. 99 |CDQ
00427AE0 |. F7FF |IDIV EDI ; Serial/3
00427AE2 |. 33C9 |XOR ECX,ECX
00427AE4 |. 8A0C24 |MOV CL,BYTE PTR SS:[ESP]
00427AE7 |. 88540E FF |MOV BYTE PTR DS:[ESI+ECX-1],DL ; DL为余数,将其存放到429754单元中
00427AEB |. 8BC3 |MOV EAX,EBX
00427AED |. BB 03000000 |MOV EBX,3
00427AF2 |. 99 |CDQ
00427AF3 |. F7FB |IDIV EBX
00427AF5 |. 8BD8 |MOV EBX,EAX ; 商
00427AF7 |. 83FB 03 |CMP EBX,3
00427AFA |. 7D 03 |JGE SHORT Crackme9.00427AFF
00427AFC |. 881C0E |MOV BYTE PTR DS:[ESI+ECX],BL
00427AFF |> FE0424 |INC BYTE PTR SS:[ESP]
00427B02 |. 83FB 03 |CMP EBX,3
00427B05 |.^ 7D D1 \JGE SHORT Crackme9.00427AD8
00427B07 |> 8A0C24 MOV CL,BYTE PTR SS:[ESP]
00427B0A |. 80F9 01 CMP CL,1
00427B0D |. 72 31 JB SHORT Crackme9.00427B40
00427B0F |. 33C0 XOR EAX,EAX
00427B11 |. 8AC1 MOV AL,CL
00427B13 |. 8D4406 FF LEA EAX,DWORD PTR DS:[ESI+EAX-1]
00427B17 |. 33D2 XOR EDX,EDX
00427B19 |. 8AD1 MOV DL,CL
00427B1B |. 81C2 47974200 ADD EDX,Crackme9.00429747
00427B21 |> 8A1A /MOV BL,BYTE PTR DS:[EDX]
00427B23 |. 3A18 |CMP BL,BYTE PTR DS:[EAX]
00427B25 |. 75 09 |JNZ SHORT Crackme9.00427B30
00427B27 |. C605 65974200>|MOV BYTE PTR DS:[429765],0
00427B2E |. EB 09 |JMP SHORT Crackme9.00427B39
00427B30 |> C605 65974200>|MOV BYTE PTR DS:[429765],1 ; 429765为1就注册不正确
00427B37 |. EB 07 |JMP SHORT Crackme9.00427B40
00427B39 |> 49 |DEC ECX
00427B3A |. 4A |DEC EDX
00427B3B |. 48 |DEC EAX
00427B3C |. 84C9 |TEST CL,CL
00427B3E |.^ 75 E1 \JNZ SHORT Crackme9.00427B21
00427B40 |> 5A POP EDX
00427B41 |. 5F POP EDI
00427B42 |. 5E POP ESI
00427B43 |. 5B POP EBX
00427B44 \. C3 RETN
如果用手计算估计你和我一样都想爆破算了。如今电脑配置都这么好,不能浪费了,让它去算吧。穷举一下了。
根据上面的程序很容易得到C语言的注册机:
#include "stdio.h"
void main()
{
int a[10]={2,0,2,0,1,2,2,1,0,2};
int b[10];
int sn,sn1;
int length;
int i;
int flag=0;
for(sn=3;sn<99999;sn++)
{
sn1=sn;
i=0;
b[i++]=sn1%3;
sn1=sn1/3;
while(sn1>=3)
{
b[i++]=sn1%3;
sn1=sn1/3;
}
b[i]=sn1;
length=i+1;
flag=0;
for(i=0;i<length;i++)
{
if(a[i]==b[i])
flag=1;
else
{
flag=0;
break;
}
}
if(flag)
printf("The %.5d is the correct serial\n",sn);
}
}
二《加密与解密》随书光盘习题GC Crackme 9GC Crackme 10破解及注册机的详细过程
1 用PEID查看发现UPX 0.89.6 - 1.02 / 1.05 - 1.22 -> Markus & Lazlo加壳,用OD手动脱壳。
2 用OD搜索字符串并未发现什么有用的信息,但是用WinDasm搜索字符串发现下面重要信息,心里那个高兴啊!。。。。。。
:0042D630 C60511F7420000 mov byte ptr [0042F711], 00
:0042D637 C60512F7420000 mov byte ptr [0042F712], 00
:0042D63E E8ADFDFFFF call 0042D3F0
:0042D643 803D10F7420000 cmp byte ptr [0042F710], 00
:0042D64A 752F jne 0042D67B
:0042D64C E867FEFFFF call 0042D4B8
:0042D651 803D11F7420001 cmp byte ptr [0042F711], 01
:0042D658 7521 jne 0042D67B
:0042D65A E8F5FEFFFF call 0042D554
:0042D65F 803D12F7420001 cmp byte ptr [0042F712], 01
:0042D666 7513 jne 0042D67B
:0042D668 6A00 push 00000000
:0042D66A 687CD64200 push 0042D67C
* Possible StringData Ref from Data Obj ->"Good work cracker!"
|
:0042D66F 6888D64200 push 0042D688
:0042D674 6A00 push 00000000
* Reference To: USER32.MessageBoxA, Ord:01C4h
在0042D630下断点。
0042D630 C605 11F74200 0>MOV BYTE PTR DS:[42F711],0 ; 42F711标志置位0
0042D637 C605 12F74200 0>MOV BYTE PTR DS:[42F712],0 ; 42F712标志置位0
0042D63E E8 ADFDFFFF CALL GNCRK10_.0042D3F0 ; 检查输入是否合法
0042D643 803D 10F74200 0>CMP BYTE PTR DS:[42F710],0
0042D64A 75 2F JNZ SHORT GNCRK10_.0042D67B
0042D64C E8 67FEFFFF CALL GNCRK10_.0042D4B8 ; 检查Unlock Code是否正确
0042D651 803D 11F74200 0>CMP BYTE PTR DS:[42F711],1
0042D658 75 21 JNZ SHORT GNCRK10_.0042D67B
0042D65A E8 F5FEFFFF CALL GNCRK10_.0042D554 ; 检查Serial是否正确
0042D65F 803D 12F74200 0>CMP BYTE PTR DS:[42F712],1
0042D666 75 13 JNZ SHORT GNCRK10_.0042D67B
0042D668 6A 00 PUSH 0
0042D66A 68 7CD64200 PUSH GNCRK10_.0042D67C ; ASCII "Success!"
0042D66F 68 88D64200 PUSH GNCRK10_.0042D688 ; ASCII "Good work cracker!"
0042D674 6A 00 PUSH 0
0042D676 E8 817FFDFF CALL <JMP.&USER32.MessageBoxA>
0042D67B C3 RETN
其中CALL GNCRK10_.0042D3F0 ; 检查输入是否合法函数如下:
0042D3F0 55 PUSH EBP
0042D3F1 8BEC MOV EBP,ESP
0042D3F3 6A 00 PUSH 0
0042D3F5 6A 00 PUSH 0
0042D3F7 33C0 XOR EAX,EAX
0042D3F9 55 PUSH EBP
0042D3FA 68 ABD44200 PUSH GNCRK10_.0042D4AB
0042D3FF 64:FF30 PUSH DWORD PTR FS:[EAX]
0042D402 64:8920 MOV DWORD PTR FS:[EAX],ESP
0042D405 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
0042D408 A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D40D 8B80 E8010000 MOV EAX,DWORD PTR DS:[EAX+1E8]
0042D413 E8 64CAFEFF CALL GNCRK10_.00419E7C
0042D418 837D FC 00 CMP DWORD PTR SS:[EBP-4],0 ; 用户名不能为空
0042D41C 74 20 JE SHORT GNCRK10_.0042D43E
0042D41E 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8]
0042D421 A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D426 8B80 E8010000 MOV EAX,DWORD PTR DS:[EAX+1E8]
0042D42C E8 4BCAFEFF CALL GNCRK10_.00419E7C
0042D431 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
0042D434 E8 8763FDFF CALL GNCRK10_.004037C0
0042D439 83F8 05 CMP EAX,5 ; 取用户名长度,长度必须大于等于5
0042D43C 7D 09 JGE SHORT GNCRK10_.0042D447
0042D43E C605 10F74200 0>MOV BYTE PTR DS:[42F710],1 ; 42F710位用户名以及Unlock Code是否合法的标志位
0042D445 EB 07 JMP SHORT GNCRK10_.0042D44E
0042D447 C605 10F74200 0>MOV BYTE PTR DS:[42F710],0
0042D44E 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
0042D451 A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D456 8B80 EC010000 MOV EAX,DWORD PTR DS:[EAX+1EC]
0042D45C E8 1BCAFEFF CALL GNCRK10_.00419E7C
0042D461 837D FC 00 CMP DWORD PTR SS:[EBP-4],0 ; 0xCE967C取得Serial,不能为空
0042D465 74 19 JE SHORT GNCRK10_.0042D480
0042D467 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8]
0042D46A A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D46F 8B80 F0010000 MOV EAX,DWORD PTR DS:[EAX+1F0]
0042D475 E8 02CAFEFF CALL GNCRK10_.00419E7C
0042D47A 837D F8 00 CMP DWORD PTR SS:[EBP-8],0 ; 0xCE968C取得Unlock Code,不能为空
0042D47E 75 09 JNZ SHORT GNCRK10_.0042D489
0042D480 C605 10F74200 0>MOV BYTE PTR DS:[42F710],1
0042D487 EB 07 JMP SHORT GNCRK10_.0042D490
0042D489 C605 10F74200 0>MOV BYTE PTR DS:[42F710],0
0042D490 33C0 XOR EAX,EAX
0042D492 5A POP EDX
0042D493 59 POP ECX
0042D494 59 POP ECX
0042D495 64:8910 MOV DWORD PTR FS:[EAX],EDX
0042D498 68 B2D44200 PUSH GNCRK10_.0042D4B2
0042D49D 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
0042D4A0 BA 02000000 MOV EDX,2
0042D4A5 E8 BE60FDFF CALL GNCRK10_.00403568
0042D4AA C3 RETN
0042D4AB ^\E9 385BFDFF JMP GNCRK10_.00402FE8
0042D4B0 ^ EB EB JMP SHORT GNCRK10_.0042D49D
0042D4B2 59 POP ECX
0042D4B3 59 POP ECX
0042D4B4 5D POP EBP
0042D4B5 C3 RETN
其中CALL GNCRK10_.0042D4B8 ; 检查Unlock Code是否正确函数如下:
0042D4B8 55 PUSH EBP
0042D4B9 8BEC MOV EBP,ESP
0042D4BB 6A 00 PUSH 0
0042D4BD 53 PUSH EBX
0042D4BE 33C0 XOR EAX,EAX
0042D4C0 55 PUSH EBP
0042D4C1 68 46D54200 PUSH GNCRK10_.0042D546
0042D4C6 64:FF30 PUSH DWORD PTR FS:[EAX]
0042D4C9 64:8920 MOV DWORD PTR FS:[EAX],ESP
0042D4CC 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
0042D4CF A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D4D4 8B80 F0010000 MOV EAX,DWORD PTR DS:[EAX+1F0]
0042D4DA E8 9DC9FEFF CALL GNCRK10_.00419E7C
0042D4DF 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; 取得Unlock Code
0042D4E2 E8 5991FDFF CALL GNCRK10_.00406640 ; 计算Unlock Code的Hex
0042D4E7 8BD8 MOV EBX,EAX
0042D4E9 8D55 FC LEA EDX,DWORD PTR SS:[EBP-4]
0042D4EC A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D4F1 8B80 F0010000 MOV EAX,DWORD PTR DS:[EAX+1F0]
0042D4F7 E8 80C9FEFF CALL GNCRK10_.00419E7C
0042D4FC 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; 取得Unlock Code
0042D4FF E8 BC62FDFF CALL GNCRK10_.004037C0 ; 取Unlock Code的长度
0042D504 84C0 TEST AL,AL
0042D506 76 10 JBE SHORT GNCRK10_.0042D518
0042D508 81F3 865E0100 XOR EBX,15E86 ; Unlock Code的Hex异或0x15E86
0042D50E 81E3 F01E0100 AND EBX,11EF0 ; Unlock Code的Hex与0x11EF0
0042D514 FEC8 DEC AL
0042D516 ^ 75 F0 JNZ SHORT GNCRK10_.0042D508 ; Unlock Code的长度循环次数
0042D518 81FB E00A0100 CMP EBX,10AE0 ; 结果必须与0x10AE0相等,否则非法.
0042D51E 75 09 JNZ SHORT GNCRK10_.0042D529
0042D520 C605 11F74200 0>MOV BYTE PTR DS:[42F711],1 ; 置Unlock Code合法标志位
0042D527 EB 07 JMP SHORT GNCRK10_.0042D530
0042D529 C605 11F74200 0>MOV BYTE PTR DS:[42F711],0 ; 置Unlock Code不合法标志位
0042D530 33C0 XOR EAX,EAX
0042D532 5A POP EDX
0042D533 59 POP ECX
0042D534 59 POP ECX
0042D535 64:8910 MOV DWORD PTR FS:[EAX],EDX
0042D538 68 4DD54200 PUSH GNCRK10_.0042D54D
0042D53D 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
0042D540 E8 FF5FFDFF CALL GNCRK10_.00403544
0042D545 C3 RETN
0042D546 ^ E9 9D5AFDFF JMP GNCRK10_.00402FE8
0042D54B ^ EB F0 JMP SHORT GNCRK10_.0042D53D
0042D54D 5B POP EBX
0042D54E 59 POP ECX
0042D54F 5D POP EBP
0042D550 C3 RETN
计算正确Unlock Code的算法很简单,但要你一眼看出来估计也不是易事,我是菜鸟,差点就想爆破算了,但我还是忍了,决定一定要算出来了。参考了Cronos写的Tutorial,其中关于计算Unlock Code的说明如下:
“You can see the relevant parts of the above checking routine. This is all on the unlock code (string3 I called it at the time). It is obviously converted into a number and saved in ebx. We then get the length of it, loop around doing some maths and check it against an expected value before setting a flag.
There's actually an easy way to solve this problem and here is how. We loop based on the length of the number (call this unlock code X for now), and then check it against a 5 digit number, so let X have 5 digits, so we do 5 loops, ok. Now the problem is ((X xor 15e86) and 11ef0) etc etc = 10ae0. What do you notice about this ? Well for a start one digit in X has no effect on any others. Take the last digit of X. It is anded with 0 right ? On each iteration, so it will always be 0 at the end. So the last digit of X can be anything, we'll call it 0. You can actually solve the whole problem digit by digit. Or you could solve it bit by bit.....so this isnt so hard. The final code ? I used 1460h, or 5216 decimal. Ah but that has only 4 digits.......ok, input 05216......happy now ?
”
但这种办法需要你详细的用手计算了,如果你的数学功底不好的话,又不够细心,估计你看得都晕了。想如今电脑配置都这么好,不能浪费了,让它去算吧。穷举一下了。
根据上面算法,我们以5位数的Unlock Code计算为例说明,其求解正确的Unlock Code程序如下:
void computeUnlockCode()
{
int c[5];//说明c[5]代表穷举Unlock Code的Hex值的各位
int d[5];
int i,j;
long temp;
//c[0]代表Code的最高位,c[4]代表最低位。
//说明以5位Unlock Code为例说明,十进制的99999=0x1869F,所以我们只取c[0]=0,1,如果计算出来的
for(c[0]=0;c[0]<=0x1;c[0]++)
for(c[1]=0;c[1]<=0xF;c[1]++)
for(c[2]=0;c[2]<=0xF;c[2]++)
for(c[3]=0;c[3]<=0xF;c[3]++)
for(c[4]=0;c[4]<=0xF;c[4]++)
{
d[0]=c[0];
d[1]=c[1];
d[2]=c[2];
d[3]=c[3];
d[4]=c[4];
for(i=0;i<5;i++)
{
d[0]=d[0]^0x1;
d[0]=d[0]&0x1;
d[1]=d[1]^0x5;
d[1]=d[1]&0x1;
d[2]=d[2]^0xE;
d[2]=d[2]&0xE;
d[3]=d[3]^0x8;
d[3]=d[3]&0xF;
d[4]=d[4]^0x6;
d[4]=d[4]&0x0;
}
if(d[0]==0x1 && d[1]==0 && d[2]==0xA && d[3]==0xE && d[4]==0)
printf("The 0x%X%X%X%X%X is the correct unlock code\n",c[0],c[1],c[2],c[3],c[4]);
}
}
其中CALL GNCRK10_.0042D554 ; 检查Serial是否正确函数如下:
0042D554 55 PUSH EBP
0042D555 8BEC MOV EBP,ESP
0042D557 83C4 F8 ADD ESP,-8
0042D55A 53 PUSH EBX
0042D55B 56 PUSH ESI
0042D55C 57 PUSH EDI
0042D55D 33C0 XOR EAX,EAX
0042D55F 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
0042D562 33C0 XOR EAX,EAX
0042D564 55 PUSH EBP
0042D565 68 22D64200 PUSH GNCRK10_.0042D622
0042D56A 64:FF30 PUSH DWORD PTR FS:[EAX]
0042D56D 64:8920 MOV DWORD PTR FS:[EAX],ESP
0042D570 33DB XOR EBX,EBX
0042D572 BF 1B990800 MOV EDI,8991B ; 给EDI设置初值
0042D577 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8]
0042D57A A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D57F 8B80 E8010000 MOV EAX,DWORD PTR DS:[EAX+1E8]
0042D585 E8 F2C8FEFF CALL GNCRK10_.00419E7C
0042D58A 8B55 F8 MOV EDX,DWORD PTR SS:[EBP-8] ; 用户名
0042D58D A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D592 8B08 MOV ECX,DWORD PTR DS:[EAX]
0042D594 FF51 18 CALL DWORD PTR DS:[ECX+18]
0042D597 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8]
0042D59A A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D59F 8B80 EC010000 MOV EAX,DWORD PTR DS:[EAX+1EC]
0042D5A5 E8 D2C8FEFF CALL GNCRK10_.00419E7C
0042D5AA 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] ; 取Serial长度
0042D5AD E8 8E90FDFF CALL GNCRK10_.00406640
0042D5B2 8945 FC MOV DWORD PTR SS:[EBP-4],EAX ; 取Serial得Hex
0042D5B5 EB 20 JMP SHORT GNCRK10_.0042D5D7
0042D5B7 A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D5BC 8B40 08 MOV EAX,DWORD PTR DS:[EAX+8]
0042D5BF 0FB64430 FF MOVZX EAX,BYTE PTR DS:[EAX+ESI-1]
0042D5C4 B9 05000000 MOV ECX,5
0042D5C9 99 CDQ
0042D5CA F7F9 IDIV ECX
0042D5CC 69C2 5FFD0E00 IMUL EAX,EDX,0EFD5F ; 用户名字符除以5的余数
0042D5D2 33F8 XOR EDI,EAX
0042D5D4 80C3 02 ADD BL,2
0042D5D7 A1 0CF74200 MOV EAX,DWORD PTR DS:[42F70C]
0042D5DC 8B40 08 MOV EAX,DWORD PTR DS:[EAX+8]
0042D5DF E8 DC61FDFF CALL GNCRK10_.004037C0
0042D5E4 8BF3 MOV ESI,EBX
0042D5E6 81E6 FF000000 AND ESI,0FF
0042D5EC 3BC6 CMP EAX,ESI
0042D5EE ^ 7D C7 JGE SHORT GNCRK10_.0042D5B7 ; 用户名长度的循环
0042D5F0 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] ; Serial的Hex
0042D5F3 35 1B990800 XOR EAX,8991B ; Serial的Hex异或0x8991B
0042D5F8 3BF8 CMP EDI,EAX
0042D5FA 75 09 JNZ SHORT GNCRK10_.0042D605
0042D5FC C605 12F74200 0>MOV BYTE PTR DS:[42F712],1
0042D603 EB 07 JMP SHORT GNCRK10_.0042D60C
0042D605 C605 12F74200 0>MOV BYTE PTR DS:[42F712],0
0042D60C 33C0 XOR EAX,EAX
0042D60E 5A POP EDX
0042D60F 59 POP ECX
0042D610 59 POP ECX
0042D611 64:8910 MOV DWORD PTR FS:[EAX],EDX
0042D614 68 29D64200 PUSH GNCRK10_.0042D629
0042D619 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
0042D61C E8 235FFDFF CALL GNCRK10_.00403544
0042D621 C3 RETN
0042D622 ^ E9 C159FDFF JMP GNCRK10_.00402FE8
0042D627 ^ EB F0 JMP SHORT GNCRK10_.0042D619
0042D629 5F POP EDI
0042D62A 5E POP ESI
0042D62B 5B POP EBX
0042D62C 59 POP ECX
0042D62D 59 POP ECX
0042D62E 5D POP EBP
0042D62F C3 RETN
根据上面的程序很容易写出注册程序如下:
void main()
{
char name[20];
int length;
int temp;
int temp1;
int ediTemp=0x8991B;
int sn,i;
scanf("%s",name);
if((length=strlen(name))<5)
{
printf("The user name should at least 5 length\n");
return;
}
for(i=0;i<length;i++)
{
if(name[i]>=0x61 && name[i]<=0x7a)
name[i]-=0x20;
}
for(i=0;i<length/2;i++)
{
temp=name[2*i+1]%5;
temp1=temp*0xEFD5F;
ediTemp=temp1^ediTemp;
}
sn=ediTemp^0x8991B;
printf("The Serial is %d",sn);
computeUnlockCode();
}
【分析总结】要想得到所有正确的注册码,往往需要穷举了。为了给我这样的菜鸟一定的帮助,我拿《加密与解密》随书光盘习题GC Crackme 9GC Crackme 9和GC Crackme 10为例说明了。希望给菜鸟一定的帮助。
[培训]《安卓高级研修班(网课)》月薪三万计划,掌
握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法