AddRemove 4GOOD 2.0 完全破解 算法分析+注册机
最近一直在从古董光盘上找软件练习,这个软件至少也得有两三年的岁数了。以前一直在爆破,或者直接从内存中看出明码来,这次终于静下心来把算法仔细分析了一下,写出注册机来的感觉,爽!兴奋之余写下这篇文章,请各位大哥指正。
好,闲话少说,书归正题。运行软件,点击"Order Info",填入NAME: RoBa, CODE: 87654321
下bpx hmemcpy (我用的98),点Unlock,按22次F12到了AR4的领空,再按F10直到如下:
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:0040192E(C)
|
:00401949 E8D2FCFFFF call
00401620<-这个是关键的CALL
:0040194E 85C0
test eax, eax
:00401950 0F84A2000000 je 004019F8<-eax为0就完蛋了
:00401956 8D45E8 lea
eax, dword ptr [ebp-18]
:00401959 8D4DEC lea
ecx, dword ptr [ebp-14]
:0040195C C745E800000000 mov [ebp-18], 00000000
:00401963 C745EC00000000 mov [ebp-14], 00000000
:0040196A 50
push eax
:0040196B 51
push ecx
:0040196C 6A00
push 00000000
:0040196E 683F000F00 push
000F003F
:00401973 6A00
push 00000000
:00401975 6A00
push 00000000
:00401977 6A00
push 00000000
在401949处F8跟进CALL,直接就来到这里:
* Referenced by a CALL at Addresses:
|:00401611 , :00401949
|
:00401620 64A100000000 mov eax, dword
ptr fs:[00000000]
:00401626 55
push ebp
:00401627 8BEC
mov ebp, esp
:00401629 6AFF
push FFFFFFFF
* Possible StringData Ref from
Code Obj ->"竝n@"
|
:0040162B 68A5174000 push
004017A5
:00401630 B9FFFFFFFF mov ecx,
FFFFFFFF
:00401635 50
push eax
:00401636 64892500000000 mov dword ptr fs:[00000000],
esp
:0040163D 83EC0C sub
esp, 0000000C
:00401640 2BC0
sub eax, eax
:00401642 57
push edi
:00401643 BF60834000 mov edi,
00408360
:00401648 F2
repnz
:00401649 AE
scasb
:0040164A F7D1
not ecx
:0040164C 49
dec ecx<-ecx为注册名的长度(下面简称长度)
:0040164D 83F906 cmp
ecx, 00000006<-与6比较
:00401650 7311
jnb 00401663<-大于6就跳
<-所以我把RoBa改为RoBa1986
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0040177F(U), :00401790(U)
|
:00401652 33C0
xor eax, eax<-eax被干掉了
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:0040176E(U)
|
:00401654 8B4DF4 mov
ecx, dword ptr [ebp-0C]
:00401657 5F
pop edi
:00401658 64890D00000000 mov dword ptr fs:[00000000],
ecx
:0040165F 8BE5
mov esp, ebp
:00401661 5D
pop ebp
:00401662 C3
ret<-如果长度小于6直接返回去就死翘翘了
<-所以我把RoBa改为RoBa1986
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:00401650(C)
|
:00401663 BF60834000 mov edi,
00408360
:00401668 B9FFFFFFFF mov ecx,
FFFFFFFF
:0040166D 2BC0
sub eax, eax
:0040166F F2
repnz
:00401670 AE
scasb<-上面这几句会出现好几次,看不懂
:00401671 F7D1
not ecx<-总之得到ecx为长度+1
:00401673 2BD2
sub edx, edx
:00401675 8D41FF lea
eax, dword ptr [ecx-01]<-eax为长度
:00401678 B90C000000 mov ecx,
0000000C<-ecx为0000000C(即十进制12)
:0040167D F7F1
div ecx<-eax为长度除以ecx的整数部分
<-edx为长度除以ecx的余数
* Possible StringData Ref from
Data Obj ->"87ae2401my69"<-一个小密码表
|
:0040167F A15C834000 mov eax,
dword ptr [0040835C]<-eax为密码表第一个字符的地址
:00401684 8D4DF0 lea
ecx, dword ptr [ebp-10]<-[ebp-10]即为长度+1
:00401687 8A0410 mov
al, byte ptr [eax+edx]<-得到密码表中第(edx+1)个字符
:0040168A 50
push eax<-压入堆栈
* Possible StringData Ref from
Data Obj ->"6582-"
|
:0040168B 689C854000 push
0040859C<-把字串"6582-"压入
* Reference To: MFC40.Ordinal:01E3,
Ord:01E3h
|
:00401690 E8F13C0000 Call
00405386
:00401695 50
push eax
:00401696 8D4DEC lea
ecx, dword ptr [ebp-14]
:00401699 C745FC00000000 mov [ebp-04], 00000000
:004016A0 51
push ecx
* Reference To: MFC40.Ordinal:0332,
Ord:0332h
|
:004016A1 E8EC3C0000 Call
00405392
:004016A6 C645FC02 mov
[ebp-04], 02
:004016AA E8EE000000 call
0040179D
:004016AF BF60834000 mov edi,
00408360
:004016B4 B9FFFFFFFF mov ecx,
FFFFFFFF
:004016B9 C745F000000000 mov [ebp-10], 00000000
:004016C0 2BC0
sub eax, eax
:004016C2 F2
repnz
:004016C3 AE
scasb
:004016C4 F7D1
not ecx
:004016C6 49
dec ecx
:004016C7 7478
je 00401741
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:0040173F(C)
|
:004016C9 F645F001 test
[ebp-10], 01<-循环开始
:004016CD 7559
jne 00401728<-这里不知是怎么回事
<-如果[ebp-10]为偶数就跳过
<-也就是说只有奇数位参加计算
:004016CF 8B45F0 mov
eax, dword ptr [ebp-10]
:004016D2 8A8060834000 mov al, byte
ptr [eax+00408360]<-得到要计算的字符
:004016D8 3C7F
cmp al, 7F<-与7F比较
:004016DA 0F8F93000000 jg 00401773<-大于就跳
:004016E0 3C20
cmp al, 20<-与20比较
:004016E2 0F8C9C000000 jl 00401784<-小于就跳
<-键盘输入的字符都在这个范围吧?
:004016E8 6698
cbw
:004016EA B102
mov cl, 02<-cl=2
:004016EC F6F9
idiv cl<-al为al除以2的整数部分
:004016EE 0420
add al, 20<-al=al+20;
:004016F0 3C5A
cmp al, 5A<-与5A比较,ASC(5A)='Z'
:004016F2 7E06
jle 004016FA<-小于等于就跳
:004016F4 3C61
cmp al, 61<-与61比较,ASC(61)='a'
:004016F6 7D02
jge 004016FA<-大于等于就跳
:004016F8 0406
add al, 06<-如果al在5A与61之间则+6
* Referenced by a (U)nconditional
or (C)onditional Jump at Addresses:
|:004016F2(C), :004016F6(C)
|
:004016FA 3C39
cmp al, 39<-与39比较,ASC(39)='9'
:004016FC 7E06
jle 00401704<-小于等于就跳
:004016FE 3C41
cmp al, 41<-与41比较,ASC(41)='A'
:00401700 7D02
jge 00401704<-大于等于就跳
:00401702 0408
add al, 08<-如果al在39与41之间则+8
* Referenced by a (U)nconditional
or (C)onditional Jump at Addresses:
|:004016FC(C), :00401700(C)
|
:00401704 50
push eax<-把结果压入堆栈
:00401705 8D4DE8 lea
ecx, dword ptr [ebp-18]
:00401708 8D45EC lea
eax, dword ptr [ebp-14]
:0040170B 50
push eax
:0040170C 51
push ecx
* Reference To: MFC40.Ordinal:0332,
Ord:0332h
|
:0040170D E8803C0000 Call
00405392
:00401712 50
push eax
:00401713 8D4DEC lea
ecx, dword ptr [ebp-14]
:00401716 C645FC03 mov
[ebp-04], 03
* Reference To: MFC40.Ordinal:02F8,
Ord:02F8h
|
:0040171A E86D3C0000 Call
0040538C
:0040171F C645FC02 mov
[ebp-04], 02
:00401723 E86D000000 call
00401795
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:004016CD(C)
|
:00401728 BF60834000 mov edi,
00408360
:0040172D B9FFFFFFFF mov ecx,
FFFFFFFF
:00401732 FF45F0 inc
[ebp-10]<-[ebp-10]+1
:00401735 2BC0
sub eax, eax
:00401737 F2
repnz
:00401738 AE
scasb
:00401739 F7D1
not ecx
:0040173B 49
dec ecx<-得到注册名长度
:0040173C 3B4DF0 cmp
ecx, dword ptr [ebp-10]<-将长度与[ebp-10]比较
:0040173F 7788
ja 004016C9<-大于则跳回去算下一个数
<-可以看出[ebp-10]为循环变量
* Referenced by a (U)nconditional
or (C)onditional Jump at Address:
|:004016C7(C)
|
:00401741 6860844000 push
00408460<-d 408460可看到假码
:00401746 8B45EC mov
eax, dword ptr [ebp-14]
:00401749 50
push eax<-d eax即可看到正确的注册码
* Reference To: MSVCRT40._mbscmp,
Ord:02ECh
|
:0040174A FF1510A84000 Call dword
ptr [0040A810]
:00401750 83C408 add
esp, 00000008
:00401753 8B4DF0 mov
ecx, dword ptr [ebp-10]
:00401756 C745FCFFFFFFFF mov [ebp-04], FFFFFFFF
:0040175D 83F801 cmp
eax, 00000001
:00401760 194DF0 sbb
dword ptr [ebp-10], ecx
:00401763 F75DF0 neg
[ebp-10]
:00401766 E844000000 call
004017AF
:0040176B 8B45F0 mov
eax, dword ptr [ebp-10]
:0040176E E9E1FEFFFF jmp 00401654
...........
可以看到注册码由三部分组成: 固定字串"6582-"+在密码表中得到的一个字符+注册名经过运算得到的字符
一个简易的注册机: (Borland Pascal 7.0)(写得很烂,高手莫笑)
Program CrackADDREMOVE;
var name,code,st :string;
ch :char;
len,p :integer;
begin
st:='87ae2401my69';
repeat
write('Please input the name:');
readln(name);
len:=length(name);
until len>=6;
ch:=st[(len mod 12)+1];
code:='6582-'+ch;
for p:=1 to len do
if (p mod 2)=1 then
begin
ch:=name[p];
ch:=chr(ord(ch) div 2+32);
if (ch>'Z') and (ch<'a') then ch:=chr(ord(ch)+6);
if (ch>'9') and (ch<'A') then ch:=chr(ord(ch)+8);
code:=code+ch;
end;
writeln('Your Register Code is:',code);
writeln;
writeln('Crack by RoBa Thank you');
end.
我实在不明白代码中出现很多次的 repnz scasb 是什么意思,请大侠指教。