【原创】bxm 之 CrackMe #7 的简单算法分析 + 穷举注册机的实现
老规矩,拖入OD中,字符串参考,得到与注册相关大框架如下:
。。。。。。
00401640 . 83EC 3C sub esp, 3C
00401643 . 53 push ebx
00401644 . 56 push esi
00401645 . 57 push edi
00401646 . 8BD9 mov ebx, ecx
00401648 . 6A 01 push 1
0040164A . E8 65030000 call <jmp.&MFC42.#6334_CWnd::UpdateData>
0040164F . 8B7B 64 mov edi, dword ptr [ebx+64] ; 注册码
00401652 . 8B47 F8 mov eax, dword ptr [edi-8] ; 长度
00401655 . 83F8 10 cmp eax, 10 ; 16位数
00401658 . 0F85 12010000 jnz CrackMe_.00401770 ; 必须等于
0040165E . 83C9 FF or ecx, FFFFFFFF
00401661 . 33C0 xor eax, eax
00401663 . F2:AE repne scas byte ptr es:[edi]
00401665 . F7D1 not ecx
00401667 . 2BF9 sub edi, ecx
00401669 . 8D5424 20 lea edx, dword ptr [esp+20]
0040166D . 8BC1 mov eax, ecx
0040166F . 8BF7 mov esi, edi
00401671 . 8BFA mov edi, edx
00401673 . 6A 10 push 10
00401675 . C1E9 02 shr ecx, 2
00401678 . F3:A5 rep movs dword ptr es:[edi], dword ptr [esi]
0040167A . 8BC8 mov ecx, eax
0040167C . 83E1 03 and ecx, 3
0040167F . F3:A4 rep movs byte ptr es:[edi], byte ptr [esi]
00401681 . 8D4C24 24 lea ecx, dword ptr [esp+24] ; 注册码
00401685 . 51 push ecx
00401686 . E8 45FFFFFF call CrackMe_.004015D0 ; 注册码只能包含有:
0040168B . 83C4 08 add esp, 8
0040168E . 85C0 test eax, eax
00401690 . 0F84 DA000000 je CrackMe_.00401770 ; 为:0~9,A~F 的格式
00401696 . 8B7B 60 mov edi, dword ptr [ebx+60] ; 注册名
00401699 . 83C9 FF or ecx, FFFFFFFF
0040169C . 33C0 xor eax, eax
0040169E . 8D5424 0C lea edx, dword ptr [esp+C]
004016A2 . F2:AE repne scas byte ptr es:[edi] ; 串扫描
004016A4 . F7D1 not ecx
004016A6 . 2BF9 sub edi, ecx
004016A8 . 68 83FC0000 push 0FC83
004016AD . 8BC1 mov eax, ecx
004016AF . 8BF7 mov esi, edi
004016B1 . 8BFA mov edi, edx
004016B3 . 6A 0B push 0B
004016B5 . C1E9 02 shr ecx, 2
004016B8 . F3:A5 rep movs dword ptr es:[edi], dword ptr [esi]
004016BA . 8BC8 mov ecx, eax
004016BC . 83E1 03 and ecx, 3
004016BF . F3:A4 rep movs byte ptr es:[edi], byte ptr [esi]
004016C1 . 8D4C24 28 lea ecx, dword ptr [esp+28]
004016C5 . 51 push ecx
004016C6 . E8 45FFFFFF call CrackMe_.00401610 ; 取注册码前4位
004016CB . 83C4 04 add esp, 4
004016CE . 50 push eax
004016CF . E8 ACFEFFFF call CrackMe_.00401580 ; 计算 F7 进
004016D4 . 0FBE5424 18 movsx edx, byte ptr [esp+18] ; 第1个注册名的字符
004016D9 . 83C4 0C add esp, 0C
004016DC . 3BC2 cmp eax, edx
004016DE 0F85 8C000000 jnz CrackMe_.00401770
004016E4 . 68 83FC0000 push 0FC83
004016E9 . 8D4424 28 lea eax, dword ptr [esp+28] ; 剩下的12位注册码
004016ED . 6A 0B push 0B ; 12
004016EF . 50 push eax
004016F0 . E8 1BFFFFFF call CrackMe_.00401610 ; 取注册码前4位
004016F5 . 83C4 04 add esp, 4
004016F8 . 50 push eax
004016F9 . E8 82FEFFFF call CrackMe_.00401580 ; 计算
004016FE . 0FBE4C24 19 movsx ecx, byte ptr [esp+19] ; 第2个注册名的字符
00401703 . 83C4 0C add esp, 0C
00401706 . 3BC1 cmp eax, ecx
00401708 75 66 jnz short CrackMe_.00401770
0040170A . 68 83FC0000 push 0FC83
0040170F . 8D5424 2C lea edx, dword ptr [esp+2C] ; 剩下的8位注册码
00401713 . 6A 0B push 0B
00401715 . 52 push edx
00401716 . E8 F5FEFFFF call CrackMe_.00401610 ; 取注册码前4位
0040171B . 83C4 04 add esp, 4
0040171E . 50 push eax
0040171F . E8 5CFEFFFF call CrackMe_.00401580 ; 计算
00401724 . 0FBE4C24 1A movsx ecx, byte ptr [esp+1A] ; 第3个注册名的字符
00401729 . 83C4 0C add esp, 0C
0040172C . 3BC1 cmp eax, ecx
0040172E 75 40 jnz short CrackMe_.00401770
00401730 . 68 83FC0000 push 0FC83
00401735 . 8D5424 30 lea edx, dword ptr [esp+30] ; 剩下的4位注册码
00401739 . 6A 0B push 0B
0040173B . 52 push edx
0040173C . E8 CFFEFFFF call CrackMe_.00401610 ; 取注册码最后4位
00401741 . 83C4 04 add esp, 4
00401744 . 50 push eax
00401745 . E8 36FEFFFF call CrackMe_.00401580 ; 计算
0040174A . 0FBE4C24 1B movsx ecx, byte ptr [esp+1B] ; 第4个注册名的字符
0040174F . 83C4 0C add esp, 0C
00401752 . 3BC1 cmp eax, ecx
00401754 75 1A jnz short CrackMe_.00401770
00401756 . 6A 00 push 0
00401758 . 68 38304000 push CrackMe_.00403038 ; 恭喜你
0040175D . 68 2C304000 push CrackMe_.0040302C ; 验证成功!
00401762 . 8BCB mov ecx, ebx
00401764 . E8 45020000 call <jmp.&MFC42.#4224_CWnd::MessageBoxA>
00401769 . 5F pop edi
0040176A . 5E pop esi
0040176B . 5B pop ebx
0040176C . 83C4 3C add esp, 3C
0040176F . C3 retn
00401770 > 6A 00 push 0
00401772 . 6A 00 push 0
00401774 . 68 20304000 push CrackMe_.00403020 ; 验证失败!
00401779 . 8BCB mov ecx, ebx
0040177B . E8 2E020000 call <jmp.&MFC42.#4224_CWnd::MessageBoxA>
00401780 . 5F pop edi
00401781 . 5E pop esi
00401782 . 5B pop ebx
00401783 . 83C4 3C add esp, 3C
00401786 . C3 retn
。。。。。。 通过上面的分析,我们知道了CrackMe_.00401580这个子程序就是算法运算的地方,F7进入后,开始分析:
。。。。。。
00401580 /$ 8B4C24 08 mov ecx, dword ptr [esp+8] ; 剩下的位数
00401584 |. 56 push esi
00401585 |. 8B7424 08 mov esi, dword ptr [esp+8] ; 当前4位字符串 -》 esi
00401589 |. 57 push edi
0040158A |. 85C9 test ecx, ecx
0040158C |. BF 01000000 mov edi, 1 ; 1->edi
00401591 |. 74 2F je short CrackMe_.004015C2
00401593 |. 53 push ebx
00401594 |. 8B5C24 18 mov ebx, dword ptr [esp+18] ; $FC83 -> ebx
00401598 |> F6C1 01 /test cl, 1 ; and 1
0040159B |. 75 0F |jnz short CrackMe_.004015AC
0040159D |. 8BC6 |mov eax, esi ; 结果->eax
0040159F |. 33D2 |xor edx, edx ; edx 清零
004015A1 |. 0FAFC6 |imul eax, esi ; eax = eax x esi
004015A4 |. D1E9 |shr ecx, 1 ; ecx 右移1位数
004015A6 |. F7F3 |div ebx ; EAX/EBX 商EAX,余数EDX
004015A8 |. 8BF2 |mov esi, edx
004015AA |. EB 0C |jmp short CrackMe_.004015B8
004015AC |> 8BC7 |mov eax, edi ; 1/结果->eax
004015AE |. 33D2 |xor edx, edx ; edx 清零
004015B0 |. 0FAFC6 |imul eax, esi ; eax = eax x esi
004015B3 |. 49 |dec ecx ; ecx-1
004015B4 |. F7F3 |div ebx ; EAX/EBX 商EAX,余数EDX
004015B6 |. 8BFA |mov edi, edx ; 余数-》edi
004015B8 |> 85C9 |test ecx, ecx ; =0?
004015BA |.^ 75 DC \jnz short CrackMe_.00401598
004015BC |. 8BC7 mov eax, edi
004015BE |. 5B pop ebx
004015BF |. 5F pop edi
004015C0 |. 5E pop esi
004015C1 |. C3 retn
004015C2 |> 8BC7 mov eax, edi
004015C4 |. 5F pop edi
004015C5 |. 5E pop esi
004015C6 \. C3 retn
。。。。。。
通过上面的分析,我们知道了,是分两个小部分来运算的,而具体用哪部分,则是由 ecx and 1 的结果来决定的,并且由 ecx and ecx 的结果是否为
0 来决定是否退出该循环运算,其算法如下:
《《《《《《
Tecx := $B;
Tesi := RegCode;
Tedi := $1;
Tebx := $FC83;
repeat
if (Tecx and 1) = 0
then begin
Teax := Tesi;
Teax := Teax * Tesi;
Tecx := Tecx shr 1;
Tedx := Teax mod Tebx;
Tesi := Tedx;
end
else begin
Teax := Tedi;
Teax := Teax * Tesi;
Tecx := Tecx-1;
Tedx := Teax mod Tebx;
Tedi := Tedx;
end;
until (Tecx and Tecx) = 0;
《《《《《《
知道了算法,自然要编写一个注册机了,不过偶懒人,自然是希望机器自动帮我算了,那么我就写个穷举的注册机了,呵呵。
原理很简单,将$0000 到 $FFFF的数字依次带入上面的算法中,得到结果后,与注册名的1、2、3、4位依次比较,如若相等,那么带入的数字必然是正
确的了,也就是正确的注册码了!呵呵,注册机完整代码如下:
{ KOL MCK } // Do not remove this line!
{$DEFINE KOL_MCK}
unit MainPYG;
interface
{$IFDEF KOL_MCK}
uses Windows, Messages, KOL {$IFNDEF KOL_MCK},
StdCtrls, mirror, mckCtrls, Classes, Controls {$ENDIF (place your units here->)};
{$ELSE}
{$I uses.inc}
Windows;
{$ENDIF}
type
{$IFDEF KOL_MCK}
{$I MCKfakeClasses.inc}
{$IFDEF KOLCLASSES} TForm1 = class; PForm1 = TForm1; {$ELSE OBJECTS} PForm1 = ^TForm1; {$ENDIF CLASSES/OBJECTS}
{$IFDEF KOLCLASSES}{$I TForm1.inc}{$ELSE} TForm1 = object(TObj) {$ENDIF}
Form: PControl;
{$ELSE not_KOL_MCK}
TForm1 = class(TForm)
{$ENDIF KOL_MCK}
KOLProject1: TKOLProject;
KOLForm1: TKOLForm;
PanelBack: TKOLPanel;
GroupBox: TKOLGroupBox;
BitBtnReg: TKOLBitBtn;
BitBtnExit: TKOLBitBtn;
EditName: TKOLEditBox;
EditCode: TKOLEditBox;
Label1: TKOLLabel;
Label2: TKOLLabel;
ProgressBar: TKOLProgressBar;
procedure BitBtnRegClick(Sender: PObj);
procedure BitBtnExitClick(Sender: PObj);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1 {$IFDEF KOL_MCK} : PForm1 {$ELSE} : TForm1 {$ENDIF} ;
{$IFDEF KOL_MCK}
procedure NewForm1( var Result: PForm1; AParent: PControl );
{$ENDIF}
implementation
{$IFNDEF KOL_MCK} {$R *.DFM} {$ENDIF}
{$IFDEF KOL_MCK}
{$I main_1.inc}
{$ENDIF}
var
RegName : string;
RegCode : integer;
function SN(RegName: String): integer; //定义函数
var
Tesi, Teax, Tebx, Tecx, Tedx, Tedi : cardinal;
begin
Tecx := $B;
Tesi := RegCode;
Tedi := $1;
Tebx := $0000FC83;
repeat
if (Tecx and 1) = 0
then begin
Teax := Tesi;
Teax := Teax * Tesi;
Tecx := Tecx shr 1;
Tedx := Teax mod Tebx;
Tesi := Tedx;
//showmessage(int2hex(Tesi,8) + ' 2');
end
else begin
Teax := Tedi;
Teax := Teax * Tesi;
Tecx := Tecx-1;
Tedx := Teax mod Tebx;
Tedi := Tedx;
//showmessage(int2hex(Tedi,8) + ' 1');
end;
until (Tecx and Tecx) = 0;
Result := Tedi;
end;
//注册算法
procedure TForm1.BitBtnRegClick(Sender: PObj);
var
i, pos : integer;
cz : string;
begin
RegName := editname.Text;
if length(RegName) < 4
then begin
showmessage('输入字符应大于3位数!');
exit;
end;
for pos := 1 to 4 do
begin
for i:=$0000 to $FFFF do
begin
RegCode := i;
if SN(RegName)=ord(RegName[pos])
then cz := cz + int2hex(RegCode,4)
else if ProgressBar.Progress>9
then ProgressBar.Progress:=0
else ProgressBar.Progress:=ProgressBar.Progress+1;
end;
end;
EditCode.Text := cz;
end;
procedure TForm1.BitBtnExitClick(Sender: PObj);
begin
Form.Close;
end;
end. 附上相关的注册机,如下->
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
上传的附件: