• 标 题:VB控件21Hex DockIt注册算法分析
  • 作 者:temerata
  • 时 间:2003年11月20日 12:40
  • 链 接:http://bbs.pediy.com

软件简介:DockIt.ocx,一个比较老的控件了,我也不记得什么时候放在电脑里的,如果要下载,估计得好好找找。其功能是在VB中实现可拖放的工具窗口。
保护方式:不需要用户名,纯注册码保护。
跟踪过程:
PART 1:
* Reference To: USER32.GetDlgItemTextA, ORd:0104h
|
:1001349B FF15E0510110 CALL dword PTR [100151E0]
:100134A1 50 PUSH eax
:100134A2 8D45E0 LEA eaxdword PTR [ebp-20]
:100134A5 50 PUSH eax
:100134A6 E8C1EAFFFF CALL 10011F6C ======>关键Call
:100134AB 59 POP ecx
:100134AC 85C0 TEST eaxeax
:100134AE 59 POP ecx
:100134AF 741A JE 100134CB ======>关键跳转
:100134B1 8D45E0 LEA eaxdword PTR [ebp-20]
:100134B4 50 PUSH eax
:100134B5 E86EE9FFFF CALL 10011E28
:100134BA 0FB7450C MOVZX eaxwORd PTR [ebp+0C]
:100134BE 59 POP ecx
:100134BF 50 PUSH eax
:100134C0 FF7604 PUSH [esi+04]

* Reference To: USER32.Enddialog, ORd:00B9h
|
:100134C3 FF1560520110 CALL dword PTR [10015260]
:100134C9 EB35 JMP 10013500

* Referenced by a (U)nconditional OR (C)onditional Jump at Address:
|:100134AF(C)
|
:100134CB 6A10 PUSH 00000010

* Possible StringData Ref from Data Obj ->"21Hex DockIt Registration"
|
:100134CD 68A8890110 PUSH 100189A8

* Possible StringData Ref from Data Obj ->"Invalid Registration Code" ======>注册失败
|
:100134D2 68788B0110 PUSH 10018B78
:100134D7 FF7604 PUSH [esi+04]

=============================================================================================================================================
PART 2:
* Referenced by a CALL at Address:
|:100134A6 
|
:10011F6C 56 PUSH esi
:10011F6D 8B742408 MOV esidword PTR [esp+08] ======>取假码置入ESI
:10011F71 57 PUSH edi
:10011F72 33FF XOR ediedi ======>EDI清零
:10011F74 33C0 XOR eaxeax ======>EAX清零
:10011F76 33D2 XOR edxedx ======>EDX清零

* Referenced by a (U)nconditional OR (C)onditional Jump at Address:
|:10011F8F(C)
|
:10011F78 0FBE0C32 MOVSX ecxbyte PTR [edx+esi] ======>逐位取假码置入ECX
:10011F7C 83E930 SUB ecx, 00000030 ======>将ECX的值减去30
:10011F7F 7809 JS 10011F8A ======>如果ECX的值为负则跳10011F8A —
:10011F81 83F909 CMP ecx, 00000009                 |检查是否数字字符
:10011F84 7F04 JG 10011F8A ======>如果ECX的值大于9则跳10011F8A—
:10011F86 03C1 ADD eaxecx ======>ECX的值累加到EAX
:10011F88 EB01 JMP 10011F8B

* Referenced by a (U)nconditional OR (C)onditional Jump at Addresses:
|:10011F7F(C), :10011F84(C)
|
:10011F8A 47 INC edi ======>EDI+1,记录非数字字符的个数

* Referenced by a (U)nconditional OR (C)onditional Jump at Address:
|:10011F88(U)
|
:10011F8B 42 INC edx ======>EDX+1,记录假码的长度
:10011F8C 83FA0B CMP edx, 0000000B
:10011F8F 7CE7 JL 10011F78 ======>取位达到11位为止
:10011F91 85C0 TEST eaxeax
:10011F93 7439 JE 10011FCE ======>如果EAX的值为0则注册失败
:10011F95 83FF02 CMP edi, 00000002
:10011F98 7534 JNE 10011FCE ======>假码中非数字字符必须为2个,否则注册失败
:10011F9A 6A07 PUSH 00000007
:10011F9C 99 CDQ
:10011F9D 59 POP ecx ======>ECX=7
:10011F9E F7F9 IdiV ecx
:10011FA0 85D2 TEST edxedx
:10011FA2 752A JNE 10011FCE ======>EAX的值必须能被7整除,否则注册失败(注意,没有包括字母的ASC值)
:10011FA4 807E0933 CMP byte PTR [esi+09], 33
:10011FA8 7524 JNE 10011FCE ======>注册码的第10位必须为3,否则注册失败
:10011FAA 837C24100B CMP dword PTR [esp+10], 0000000B
:10011FAF 751D JNE 10011FCE
:10011FB1 803E31 CMP byte PTR [esi], 31
:10011FB4 751C JNE 10011FD2
:10011FB6 807E0132 CMP byte PTR [esi+01], 32
:10011FBA 7516 JNE 10011FD2
:10011FBC 807E0237 CMP byte PTR [esi+02], 37
:10011FC0 7510 JNE 10011FD2
:10011FC2 807E0331 CMP byte PTR [esi+03], 31
:10011FC6 750A JNE 10011FD2
:10011FC8 807E0433 CMP byte PTR [esi+04], 33
:10011FCC 7504 JNE 10011FD2

* Referenced by a (U)nconditional OR (C)onditional Jump at Addresses:
|:10011F93(C), :10011F98(C), :10011FA2(C), :10011FA8(C), :10011FAF(C)
|
:10011FCE 33C0 XOR eaxeax ======>EAX清零
:10011FD0 EB03 JMP 10011FD5

* Referenced by a (U)nconditional OR (C)onditional Jump at Addresses:
|:10011FB4(C), :10011FBA(C), :10011FC0(C), :10011FC6(C), :10011FCC(C)
|
:10011FD2 6A01 PUSH 00000001
:10011FD4 58 POP eax

* Referenced by a (U)nconditional OR (C)onditional Jump at Address:
|:10011FD0(U)
|
:10011FD5 5F POP edi ======>EDI清零
:10011FD6 5E POP esi ======>ESI清零
:10011FD7 C3 RET

算法总结:
  刚开始破这个东西时我偷懒,把文件备份后直接修改关键跳转便注册成功了,后来发现恢复原文件后也是注册成功的!检查注册表,发现HKEY_CURRENT_USERSoftware21HexDockIt下的RegId保存注册信息,但我把这个键删除后,控件还是注册状态。费了很多功夫才确定HKEY_CURRENT_USERSoftware21HexDockIt下的CtrlType控制注册状态。只要CtrlType的值为8344065(十进制),控件就注册成功了。我觉得很好笑,于是写了个“伪注册机”,直接修改这个键值。
  言归正传吧,我验证过,只要符合下面的条件的注册码,可以注册成功:
1、长度为11位。
2、注册码中非数字字符必须为2位,可以任取,放在第10位以外的任何位置。
3、各位数字的ASC值减去48后的和能被7整除(不能为0)。(即各数字相加的和能被7整除。)
4、注册码的第10位必须是数字3。
  这个控件的注册码算法我也只是随便跟了一下,也许有些东西我漏掉了,不过跟它麻烦,每3次输入错误的注册码后注册按键便禁用了,还得重来,而且老是一不小心便跳走到注册失败处。人菜,没办法……。
  Win2000下测试通过。

注册机源码(见笑):(Delphi)
function RegCode(): string; 
var
intSum,rdmASC,i,j:Integer;
strSerial:String;
begin
intSum:=0;
strSerial:='';
for i:=1 to 7 do
begin
rdmASC:=Random(10);
intSum:=intSum+rdmASC;
rdmASC:=rdmASC+48;
strSerial:=strSerial+Chr(rdmASC);
end;
j:=(intSum+3) Div 7;
j:=7*(j+1)-(intSum+3);
Insert(IntToStr(j),strSerial,Random(8 ));
for i:=1 to 2 do
begin
j:=Random(5);
if j=0 then Insert(Chr(Random(16)+32),strSerial,Random(10))
else Insert(Chr(Random(70)+58 ),strSerial,Random(10));
end;
Insert('3',strSerial,10);
Result:=strSerial; 
end;