【文章标题】: Password Tracker Deluxe 详细算法分析
【文章作者】: 海浪轻风
【作者邮箱】: futuring@126.com
【作者主页】: http://hi.baidu.com/beyond0769
【软件名称】: Password Tracker Deluxe (Version 3.63)
【下载地址】: http://www.clrpc.com/download.htm
【编写语言】: VC++
【软件介绍】: 常驻在工具条的密码保管员。当你开启需要密码的工具软件时,只需点选一下,它就会为你填入所 需的帐号与密码,也可以设定自动填入于跳出的对话框中,但是当然啦,它本身也是需要密码才能启用,以保护你众多的密码。
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
难度中等的加密算法。
一开始调试时感觉这个程序用了点花招。OD载入运行后在程序界面显示后,OD显示进程已经结束。然后在任务管理器里
发现有两个进程。把OD关掉,程序并没有退出。到底使用了什么技巧?懒得去理,因为这难不了OD,用OD的“附加”功能
把已经运行的程序附加,再重新加载就可以了。
输入假码马上有错误提示“invalid registration number.”
可以查ASCII也可以用bp MessagBoxA 下断,来到关键算法处:
00422370 . 6A FF PUSH -1 ; 注册按键事件 00422372 . 68 20914600 PUSH <PwTrkr.SEH_422370> ; SE 处理程序安装 00422377 . 64:A1 0000000>MOV EAX,DWORD PTR FS:[0] 0042237D . 50 PUSH EAX 0042237E . 64:8925 00000>MOV DWORD PTR FS:[0],ESP 00422385 . 83EC 08 SUB ESP,8 00422388 . A1 20A94800 MOV EAX,DWORD PTR DS:[48A920] 0042238D . 56 PUSH ESI 0042238E . 8BF1 MOV ESI,ECX 00422390 . 894424 08 MOV DWORD PTR SS:[ESP+8],EAX 00422394 . C74424 14 000>MOV DWORD PTR SS:[ESP+14],0 0042239C . 894424 04 MOV DWORD PTR SS:[ESP+4],EAX 004223A0 . 8D4424 08 LEA EAX,DWORD PTR SS:[ESP+8] 004223A4 . C64424 14 01 MOV BYTE PTR SS:[ESP+14],1 004223A9 . 50 PUSH EAX 004223AA . 68 E8030000 PUSH 3E8 004223AF . E8 CE560200 CALL PwTrkr.00447A82 004223B4 . 8BC8 MOV ECX,EAX 004223B6 . E8 2B2C0200 CALL <PwTrkr.?GetWindowTextA@CWnd@@QBEXA>; 读取用户名 004223BB . 8D4C24 04 LEA ECX,DWORD PTR SS:[ESP+4] 004223BF . 51 PUSH ECX ; (ASCII "4〩") 004223C0 . 68 0B040000 PUSH 40B 004223C5 . 8BCE MOV ECX,ESI 004223C7 . E8 B6560200 CALL PwTrkr.00447A82 004223CC . 8BC8 MOV ECX,EAX 004223CE . E8 132C0200 CALL <PwTrkr.?GetWindowTextA@CWnd@@QBEXA>; 读取假码 004223D3 . 8B5424 04 MOV EDX,DWORD PTR SS:[ESP+4] ; EDX返回假码 004223D7 . 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8] ; EDX返回用户名 004223DB . 52 PUSH EDX 004223DC . 50 PUSH EAX ; 分别入栈进行计算 004223DD . E8 DE050000 CALL PwTrkr.004229C0 ; 关键算法,F7进入 004223E2 . 83C4 08 ADD ESP,8 004223E5 . 3D 9D000000 CMP EAX,9D ; 函数返回值和 $9D 比较,相同则成功 004223EA . 75 09 JNZ SHORT PwTrkr.004223F5 004223EC . 8BCE MOV ECX,ESI 004223EE . E8 CD1B0200 CALL <PwTrkr.?OnOK@CDialog@@MAEXXZ> 004223F3 . EB 21 JMP SHORT PwTrkr.00422416 004223F5 > 6A 00 PUSH 0 ; /Arg3 = 00000000 004223F7 . 6A 30 PUSH 30 ; |Arg2 = 00000030 004223F9 . 68 849F4800 PUSH OFFSET <PwTrkr.aInvalidRegistr> ; |invalid registration number. 004223FE . E8 00DC0200 CALL PwTrkr.00450003 ; \PwTrkr.00450003 00422403 . 68 0B040000 PUSH 40B 00422408 . 8BCE MOV ECX,ESI 0042240A . E8 73560200 CALL PwTrkr.00447A82 0042240F . 8BC8 MOV ECX,EAX 00422411 . E8 F8590200 CALL PwTrkr.00447E0E 00422416 > 8D4C24 04 LEA ECX,DWORD PTR SS:[ESP+4] 0042241A . C64424 14 00 MOV BYTE PTR SS:[ESP+14],0 0042241F . E8 B75D0200 CALL PwTrkr.004481DB 00422424 . 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8] 00422428 . C74424 14 FFF>MOV DWORD PTR SS:[ESP+14],-1 00422430 . E8 A65D0200 CALL PwTrkr.004481DB 00422435 . 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C] 00422439 . 5E POP ESI 0042243A . 64:890D 00000>MOV DWORD PTR FS:[0],ECX 00422441 . 83C4 14 ADD ESP,14 00422444 . C3 RETN
主算法过程没有什么好说的,把用户名和假码入栈后准备处理,进入关键函数:
004223DD . E8 DE050000 CALL PwTrkr.004229C0 ; 关键算法,F7进入
004229C0 /$ 6A FF PUSH -1 ; 关键算法 004229C2 |. 68 F8914600 PUSH <PwTrkr.unknown_libname_65> ; SE 处理程序安装 004229C7 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0] 004229CD |. 50 PUSH EAX 004229CE |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP 004229D5 |. 83EC 14 SUB ESP,14 004229D8 |. 8B4424 24 MOV EAX,DWORD PTR SS:[ESP+24] ; 用户名 004229DC |. 56 PUSH ESI 004229DD |. 50 PUSH EAX 004229DE |. 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8] 004229E2 |. E8 B9FAFFFF CALL PwTrkr.004224A0 ; 用户名检测及计算过程 004229E7 |. 8B5424 2C MOV EDX,DWORD PTR SS:[ESP+2C] 004229EB |. 51 PUSH ECX 004229EC |. 8BCC MOV ECX,ESP 004229EE |. 896424 2C MOV DWORD PTR SS:[ESP+2C],ESP 004229F2 |. 52 PUSH EDX ; 假码入栈 004229F3 |. C74424 28 000>MOV DWORD PTR SS:[ESP+28],0 004229FB |. E8 49580200 CALL PwTrkr.00448249 00422A00 |. 8D4C24 08 LEA ECX,DWORD PTR SS:[ESP+8] 00422A04 |. E8 E7FBFFFF CALL PwTrkr.004225F0 ; 核心算法过程,F7步进 00422A09 |. 8D4C24 04 LEA ECX,DWORD PTR SS:[ESP+4] 00422A0D |. 8BF0 MOV ESI,EAX 00422A0F |. C74424 20 FFF>MOV DWORD PTR SS:[ESP+20],-1 00422A17 |. E8 84FBFFFF CALL PwTrkr.004225A0 00422A1C |. 8B4C24 18 MOV ECX,DWORD PTR SS:[ESP+18] 00422A20 |. 8BC6 MOV EAX,ESI 00422A22 |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX 00422A29 |. 5E POP ESI 00422A2A |. 83C4 20 ADD ESP,20 00422A2D \. C3 RETN
---------
这过程有两个重要CALL,
004229E2 |. E8 B9FAFFFF CALL PwTrkr.004224A0 ; 用户名检测及计算过程
00422A04 |. E8 E7FBFFFF CALL PwTrkr.004225F0 ; 核心算法过程,F7步进
先进入第一个看看。
004224A0 /$ 6A FF PUSH -1 ; 用户名检测及计算CALL 004224A2 |. 68 46914600 PUSH <PwTrkr.unknown_libname_60> ; SE 处理程序安装 004224A7 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0] 004224AD |. 50 PUSH EAX 004224AE |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP 004224B5 |. 51 PUSH ECX 004224B6 |. A1 20A94800 MOV EAX,DWORD PTR DS:[48A920] 004224BB |. 56 PUSH ESI 004224BC |. 8BF1 MOV ESI,ECX 004224BE |. 897424 04 MOV DWORD PTR SS:[ESP+4],ESI 004224C2 |. 8946 08 MOV DWORD PTR DS:[ESI+8],EAX 004224C5 |. 8B0D 20A94800 MOV ECX,DWORD PTR DS:[48A920] ; PwTrkr.0048A934 004224CB |. C74424 10 000>MOV DWORD PTR SS:[ESP+10],0 004224D3 |. 894E 0C MOV DWORD PTR DS:[ESI+C],ECX 004224D6 |. 8B5424 18 MOV EDX,DWORD PTR SS:[ESP+18] 004224DA |. 8BCE MOV ECX,ESI 004224DC |. 52 PUSH EDX 004224DD |. C64424 14 01 MOV BYTE PTR SS:[ESP+14],1 004224E2 |. E8 19000000 CALL PwTrkr.00422500 ; 关键算法,处理用户名,F7进入 004224E7 |. 8B4C24 08 MOV ECX,DWORD PTR SS:[ESP+8] 004224EB |. 8BC6 MOV EAX,ESI 004224ED |. 5E POP ESI 004224EE |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX 004224F5 |. 83C4 10 ADD ESP,10 004224F8 \. C2 0400 RETN 4
还没有看到什么有用东西,好东西在
004224E2 |. E8 19000000 CALL PwTrkr.00422500 ; 关键算法,处理用户名,F7进入
00422500 /$ 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4] ; 关键算法,处理用户名 00422504 |. 53 PUSH EBX 00422505 |. 8BD9 MOV EBX,ECX 00422507 |. 56 PUSH ESI 00422508 |. 57 PUSH EDI 00422509 |. 83CF FF OR EDI,FFFFFFFF 0042250C |. 8D73 08 LEA ESI,DWORD PTR DS:[EBX+8] 0042250F |. 50 PUSH EAX 00422510 |. 8BCE MOV ECX,ESI 00422512 |. 897B 10 MOV DWORD PTR DS:[EBX+10],EDI 00422515 |. E8 4A5E0200 CALL <PwTrkr.??4CString@@QAEABV0@PBD@Z> 0042251A |. 8BCE MOV ECX,ESI 0042251C |. E8 B1E70100 CALL PwTrkr.00440CD2 00422521 |. 8BCE MOV ECX,ESI 00422523 |. E8 F6E70100 CALL PwTrkr.00440D1E ; 返回用户名 00422528 |. 8B0E MOV ECX,DWORD PTR DS:[ESI] 0042252A |. 897B 04 MOV DWORD PTR DS:[EBX+4],EDI 0042252D |. 893B MOV DWORD PTR DS:[EBX],EDI 0042252F |. 8B41 F8 MOV EAX,DWORD PTR DS:[ECX-8] 00422532 |. 85C0 TEST EAX,EAX 00422534 |. 74 5C JE SHORT PwTrkr.00422592 00422536 |. BF A89F4800 MOV EDI,PwTrkr.00489FA8 0042253B |> 8B07 /MOV EAX,DWORD PTR DS:[EDI] ; EAX 指向内存中的黑名单 0042253D |. 8B0E |MOV ECX,DWORD PTR DS:[ESI] ; ECX指向 用户名 0042253F |. 50 |PUSH EAX ; /Arg2 00422540 |. 51 |PUSH ECX ; |Arg1 00422541 |. E8 D2E90000 |CALL <PwTrkr.__mbscmp> ; \将两者入栈比较 00422546 |. 83C4 08 |ADD ESP,8 00422549 |. 85C0 |TEST EAX,EAX 0042254B |. 74 45 |JE SHORT PwTrkr.00422592 ; 如果两者相等则OVER 0042254D |. 83C7 04 |ADD EDI,4 00422550 |. 81FF B49F4800 |CMP EDI,OFFSET <PwTrkr.aCoreJes> ; ASCII "CORE/JES" 00422556 |.^ 72 E3 \JB SHORT PwTrkr.0042253B 00422558 |. 8B36 MOV ESI,DWORD PTR DS:[ESI] 0042255A |. 33C0 XOR EAX,EAX 0042255C |. BF 0D000000 MOV EDI,0D ; 初始化EDI=$D 00422561 |. 8B56 F8 MOV EDX,DWORD PTR DS:[ESI-8] ; EDX=Length(用户名) 00422564 |. 85D2 TEST EDX,EDX 00422566 |. 7E 12 JLE SHORT PwTrkr.0042257A 00422568 |> 8D48 01 /LEA ECX,DWORD PTR DS:[EAX+1] ; 计数器i 0042256B |. 0FBE0406 |MOVSX EAX,BYTE PTR DS:[ESI+EAX] ; EAX=ord(用户名[ i ]) //请注意这里,如果要用中文注册,要考虑处理MOVSX指令。 0042256F |. 0FAFC1 |IMUL EAX,ECX ; EAX = EAX * i 00422572 |. 03F8 |ADD EDI,EAX ; EDI = EDI + EAX 00422574 |. 8BC1 |MOV EAX,ECX 00422576 |. 3BC2 |CMP EAX,EDX ; 到达最后一位了吗? 00422578 |.^ 7C EE \JL SHORT PwTrkr.00422568 ; 否则继续循环 0042257A |> 57 PUSH EDI ; 循环结果保存在EDI中,记为 N, 入栈 0042257B |. E8 8CEB0000 CALL <PwTrkr._srand> ; 随机数发生器的初始化函数 00422580 |. 83C4 04 ADD ESP,4 00422583 |. E8 91EB0000 CALL <PwTrkr._rand> ; 关键函数Func 00422588 |. 8903 MOV DWORD PTR DS:[EBX],EAX ; 返回结果记为 N1 0042258A |. E8 8AEB0000 CALL <PwTrkr._rand> ; 关键函数Func 0042258F |. 8943 04 MOV DWORD PTR DS:[EBX+4],EAX ; 返回结果记为 N2 00422592 |> 5F POP EDI 00422593 |. 5E POP ESI 00422594 |. 5B POP EBX 00422595 \. C2 0400 RETN 4
这个过程先利用一个循环对用户名进行检测,和内存中的黑名单进行比较,相等则注册失败。
把断点下在
0042253B |> 8B07 /MOV EAX,DWORD PTR DS:[EDI] ; EAX 指向内存中的黑名单
可以在内存中截取黑名单如下:
00489FB4 >43 4F 52 45 2F 4A 45 53 00 00 00 00 46 75 6C 6C CORE/JES....Full 00489FC4 79 20 4C 69 63 65 6E 73 65 64 20 55 73 65 72 00 y Licensed User. 00489FD4 >50 6C 75 73 68 6D 6D 20 50 43 27 39 37 00 00 00 Plushmm PC'97...
大概有三个:CORE/JES, Fully Licensed User和Plushmm PC'97。
然后再利用第二个循环对用户名进行简单计算:
用Delphi描述为:
function CalcName(Name:string):integer;
var
i,n:integer;
str:string;
begin
n:=$0D;
for i:=1 to Length(Name) do
begin
n:=n + ord(Name[i]) * i
{请注意上面这里,如果要支持中文注册,要考虑处理MOVSX指令。
end;
Result:= n;
end;
把计算结果记为 N ,下面有用。
接着调用关键函数Func对 N 进行计算。
00422583 |. E8 91EB0000 CALL <PwTrkr._rand> ; 关键函数Func
进行进一步计算
00431119 >/$ E8 25440000 CALL <PwTrkr.__getptd> ; 关键函数Func 0043111E |. 8B48 14 MOV ECX,DWORD PTR DS:[EAX+14] ; ECX = 读取[EAX+14]内存值(参数) 00431121 |. 69C9 FD430300 IMUL ECX,ECX,343FD ; ECX = ECX * $343FD 00431127 |. 81C1 C39E2600 ADD ECX,269EC3 ; ECX = ECX + $269EC3 0043112D |. 8948 14 MOV DWORD PTR DS:[EAX+14],ECX ; 先保存这个结果到[EAX+14],用于第二次调用函数时的参数 00431130 |. 8BC1 MOV EAX,ECX ; EAX = ECX 00431132 |. C1E8 10 SHR EAX,10 ; EAX = EAX shr $10 00431135 |. 25 FF7F0000 AND EAX,7FFF ; EAX = EAX and $7FFF 0043113A \. C3 RETN
这个过程用Delphi描述为
function Func(n:integer):integer;
begin
Result:= ( n * $343FD + $269EC3) shr $10 and $7FFF;
end;
调用 Func(N)返回结果记为 N1.
然后再次调用关键函数 Func (N1 * $343FD + $269EC3) 进行计算,结果记为 N2。
保存下来后面有用。
--------------------
接着跳出到 004229C0 /$ 6A FF PUSH -1 ; 关键算法 过程。来到
00422A04 |. E8 E7FBFFFF CALL PwTrkr.004225F0 ; 核心算法过程,F7步进
004225F0 /$ 6A FF PUSH -1 ; 核心算法过程 004225F2 |. 68 78914600 PUSH <PwTrkr.unknown_libname_62> ; SE 处理程序安装 004225F7 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0] 004225FD |. 50 PUSH EAX 004225FE |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP 00422605 |. 51 PUSH ECX 00422606 |. 55 PUSH EBP 00422607 |. 56 PUSH ESI 00422608 |. 57 PUSH EDI 00422609 |. 8BE9 MOV EBP,ECX 0042260B |. 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; 堆栈:[EBP]=$2DE1,即N1 0042260E |. 83CE FF OR ESI,FFFFFFFF 00422611 |. 3BC6 CMP EAX,ESI 00422613 |. C74424 18 000>MOV DWORD PTR SS:[ESP+18],0 ; 不为0吧 0042261B |. 75 05 JNZ SHORT PwTrkr.00422622 0042261D |. 3975 04 CMP DWORD PTR SS:[EBP+4],ESI 00422620 |. 74 50 JE SHORT PwTrkr.00422672 00422622 |> 8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20] 00422626 |. E8 F3E60100 CALL PwTrkr.00440D1E ; 假码 0042262B |. 8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20] 0042262F |. E8 9EE60100 CALL PwTrkr.00440CD2 00422634 |. 8B4424 20 MOV EAX,DWORD PTR SS:[ESP+20] ; EAX返回假码9-13位 00422638 |. 8378 F8 0D CMP DWORD PTR DS:[EAX-8],0D ; 假码的长度必须是13位 0042263C |. 75 34 JNZ SHORT PwTrkr.00422672 0042263E |. 53 PUSH EBX 0042263F |. 8D4C24 10 LEA ECX,DWORD PTR SS:[ESP+10] 00422643 |. 6A 02 PUSH 2 00422645 |. 51 PUSH ECX 00422646 |. 8D4C24 2C LEA ECX,DWORD PTR SS:[ESP+2C] 0042264A |. E8 50E20100 CALL PwTrkr.0044089F ; 返回假码前两位字符 0042264F |. 8B00 MOV EAX,DWORD PTR DS:[EAX] 00422651 |. 68 EC9F4800 PUSH OFFSET <PwTrkr.aPt_0> ; /pt 00422656 |. 50 PUSH EAX ; |Arg1 00422657 |. E8 BCE80000 CALL <PwTrkr.__mbscmp> ; \假码前两位和"PT"比较,如果不相等则注册失败 0042265C |. 83C4 08 ADD ESP,8 0042265F |. 8D4C24 10 LEA ECX,DWORD PTR SS:[ESP+10] 00422663 |. 85C0 TEST EAX,EAX 00422665 |. 0F95C3 SETNE BL 00422668 |. E8 6E5B0200 CALL PwTrkr.004481DB 0042266D |. 84DB TEST BL,BL 0042266F |. 5B POP EBX 00422670 |. 74 23 JE SHORT PwTrkr.00422695 ; 必须要跳,否则马上结束跳出函数至失败 00422672 |> 8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20] 00422676 |. 897424 18 MOV DWORD PTR SS:[ESP+18],ESI 0042267A |. E8 5C5B0200 CALL PwTrkr.004481DB 0042267F |. 8BC6 MOV EAX,ESI 00422681 |. 5F POP EDI 00422682 |. 5E POP ESI 00422683 |. 5D POP EBP 00422684 |. 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+4] 00422688 |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX 0042268F |. 83C4 10 ADD ESP,10 00422692 |. C2 0400 RETN 4 00422695 |> 6A 04 PUSH 4 00422697 |. 8D5424 10 LEA EDX,DWORD PTR SS:[ESP+10] 0042269B |. 6A 02 PUSH 2 0042269D |. 52 PUSH EDX 0042269E |. 8D4C24 2C LEA ECX,DWORD PTR SS:[ESP+2C] 004226A2 |. E8 E6E00100 CALL PwTrkr.0044078D ; 读取假码3-6位字符串 004226A7 |. 8B00 MOV EAX,DWORD PTR DS:[EAX] 004226A9 |. 50 PUSH EAX 004226AA |. E8 5EE80000 CALL <PwTrkr._atoi> ; C语言的_atoi相当于Delphi的strtoint函数,结果记为 T1 004226AF |. 83C4 04 ADD ESP,4 004226B2 |. 8D4C24 0C LEA ECX,DWORD PTR SS:[ESP+C] 004226B6 |. 8BF0 MOV ESI,EAX 004226B8 |. E8 1E5B0200 CALL PwTrkr.004481DB 004226BD |. 8D4424 0C LEA EAX,DWORD PTR SS:[ESP+C] 004226C1 |. 6A 06 PUSH 6 004226C3 |. 50 PUSH EAX 004226C4 |. 8D4C24 28 LEA ECX,DWORD PTR SS:[ESP+28] 004226C8 |. E8 9DE00100 CALL <PwTrkr.?Mid@CString@@QBE?AV1@H@Z> ; 读取假码7-13位 004226CD |. 8B00 MOV EAX,DWORD PTR DS:[EAX] 004226CF |. 50 PUSH EAX 004226D0 |. E8 38E80000 CALL <PwTrkr._atoi> ; StrtoInt(假码7-13位),结果记为 T2 004226D5 |. 83C4 04 ADD ESP,4 004226D8 |. 8D4C24 0C LEA ECX,DWORD PTR SS:[ESP+C] 004226DC |. 8BF8 MOV EDI,EAX 004226DE |. E8 F85A0200 CALL PwTrkr.004481DB 004226E3 |. 81FE B0FCFFFF CMP ESI,-350 ; T1 和 $-350 比较 004226E9 |. 75 08 JNZ SHORT PwTrkr.004226F3 ; 不相等跳走 004226EB |. 81FF 058BF9FF CMP EDI,FFF98B05 ; T2 和 $FFF98B05比较 004226F1 |. 74 77 JE SHORT PwTrkr.0042276A ; 相等则注册成功 004226F3 |> 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; EAX = N1 004226F6 |. B9 E8030000 MOV ECX,3E8 ; ECX = 1000 004226FB |. F7D8 NEG EAX ; EAX = -N1 004226FD |. 99 CDQ 004226FE |. F7F9 IDIV ECX ; EAX mod 1000 00422700 |. 3BF2 CMP ESI,EDX ; 结果和T1比较,如果不相等则注册失败 00422702 |. 74 28 JE SHORT PwTrkr.0042272C ; 必须要跳 00422704 |. 8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20] 00422708 |. C74424 18 FFF>MOV DWORD PTR SS:[ESP+18],-1 00422710 |. E8 C65A0200 CALL PwTrkr.004481DB 00422715 |. 5F POP EDI 00422716 |. 5E POP ESI 00422717 |. 83C8 FF OR EAX,FFFFFFFF 0042271A |. 5D POP EBP 0042271B |. 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+4] 0042271F |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX 00422726 |. 83C4 10 ADD ESP,10 00422729 |. C2 0400 RETN 4 0042272C |> 8B45 04 MOV EAX,DWORD PTR SS:[EBP+4] ; EAX = N2 0042272F |. 8D14C5 000000>LEA EDX,DWORD PTR DS:[EAX*8] ; EDX = N2 * 8 00422736 |. 2BD0 SUB EDX,EAX ; EDX = EDX - EAX 00422738 |. D1E2 SHL EDX,1 ; EDX = EDX shl 1 0042273A |. 2BD0 SUB EDX,EAX ; EDX = EDX - EAX 0042273C |. F7DA NEG EDX ; EDX = - EDX 0042273E |. 3BFA CMP EDI,EDX ; EDX 和 EDI 比较,相等则注册成功 00422740 |. 74 28 JE SHORT PwTrkr.0042276A ; 必须跳走 00422742 |. 8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20] 00422746 |. C74424 18 FFF>MOV DWORD PTR SS:[ESP+18],-1 0042274E |. E8 885A0200 CALL PwTrkr.004481DB 00422753 |. 5F POP EDI 00422754 |. 5E POP ESI 00422755 |. 83C8 FF OR EAX,FFFFFFFF 00422758 |. 5D POP EBP 00422759 |. 8B4C24 04 MOV ECX,DWORD PTR SS:[ESP+4] 0042275D |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX 00422764 |. 83C4 10 ADD ESP,10 00422767 |. C2 0400 RETN 4 0042276A |> 8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20] ; 跳到这里,通往成功 0042276E |. C74424 18 FFF>MOV DWORD PTR SS:[ESP+18],-1 00422776 |. E8 605A0200 CALL PwTrkr.004481DB 0042277B |. 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] 0042277F |. 5F POP EDI 00422780 |. 5E POP ESI 00422781 |. B8 9D000000 MOV EAX,9D ; EAX赋值 $9D 注册成功 00422786 |. 5D POP EBP 00422787 |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX 0042278E |. 83C4 10 ADD ESP,10 00422791 \. C2 0400 RETN 4
--------------------------------
核心算法过程总结如下:
1、检测注册码,必须是13位,否则失败
2、取注册码前2位,必须是"PT",否则失败
3、取注册码第3-6位,转换成数值,记为 T1;
取注册码第7-13位,转换成数值,记为 T2;
4、第一种注册成功的方法:如果T1= $-350 并且 T2 = $FFF98B05 则注册成功;
(因此可以反推算得一个通用注册码:PT-848-423163)
5、如果第4步没有通过,则 ( -N1 mod $3E8 )必须等于 T1,否则失败
6、0 - ( ( N2 * 8 - N2 ) shl 1 - N2 ) 的结果必须是T2,否则失败。
--------------------------------
至此为止,整个算法过程已经非常清晰了。用Delphi写个逆向算法注册机吧,个人感觉比较完美 ^_^ 。
function MOVSX(A: Byte): DWORD; //处理MOVSX指令,让注册机支持中文
begin
if A and $80 = 0 then Result := A
else Result := $FFFFFF00 or A;
end;
function CalcName(Name: string): integer;
var
i, n: integer;
str: string;
begin
n:= $0D;
for i:= 1 to Length(Name) do
begin
n:= n + MOVSX(ord(Name[i])) * i
end;
Result:= n;
end;
function Func(n: integer): integer;
begin
Result:= ((n * $343FD + $269EC3) shr $10) and $7FFF;
end;
function GetSn(UserName: string): string;
var
s: string;
iName: integer;
N1, N2: integer;
S1, S2: string;
begin
Result:= '';
//对用户名进行过滤
if (UserName = 'CORE/JES') or (UserName = 'Fully Licensed User') or
(UserName = 'Plushmm PC'' 97') then
begin
Result:= '该用户名已被列入黑名单';
Exit;
end;
iName:= CalcName(UserName); //对用户名进行计算处理。
N1:= Func(iName);
N2:= Func(iName * $343FD + $269EC3);
S1:= inttostr((-N1) mod $3E8);
S2:= inttostr(-((N2 * 7) shl 1 - N2));
//以下是为了使最终注册码长度为13的解决方法。
while (Length(S1 + S2) <> 11) do
begin
insert('0', S2, 2);
end;
Result:= 'PT' + S1 + S2;
end;
使用方法,直接调用 GetSn(用户名)即可返回真正注册码。
提供1组经上述代码计算出来的结果:
用户名:海浪轻风
注册码:PT-833-125892
注册成功后注册信息保存在注册表处:
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\CLR\Password Tracker\Install] "FirstRun"=dword:4a1deb26 "RegistrationNameDeluxe"="海浪轻风" "RegistrationNumberDeluxe"="PT-833-125892"
删除后可再调试。
--------------------------------------------------------------------------------
20090528 18:16:48
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课