标 题:AddRemove 4GOOD 注册算法+注册机
发信人:RoBa
时 间:2003/07/25 05:21pm
详细信息:
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 是什么意思,请大侠指教。