[PYG]2007年度认证CrackMe的算法分析(DELPHI版)
标 题: 【原创】2007年度认证CrackMe的算法分析(DELPHI版)作 者: acafeel
时 间: 2007-12-29,13:55
链 接: http://bbs.pediy.com/showthread.php?t=57301
【文章标题】: 2007年度认证CrackMe的算法分析(DELPHI版)
【文章作者】: aCaFeeL
【软件名称】: CrackMe2007.EXE
【软件大小】: 241 KB (247,021 字节)
【下载地址】: https://www.chinapyg.com/
【加壳方式】: NsPacK V3.7
【保护方式】: 压缩加壳
【编写语言】: delphi
【使用工具】: OllyDBG v1.10、C32Asm v0.412、DeDe v3.5、W32Dasm v8.93、ImportREC v1.6f、LordPE v1.4、PEid v0.94、Filemon v7.01
【操作平台】: Windows 98 second 或者 Windows XP sp2
【软件介绍】: 2007年度成员认证CrackMe程序
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
简单说下注册流程:
Form1.OnCreat事件: 检测文件自身的大小、名称,生成机器码,检测key文件,其格式成功、长度相等便成功读入,将读入的注册名运算
后与读入的注册码比较,如数据相等,则Button1按钮也就可用了;
Timer2.Timer 事件: 再次检测文件大小、检测key文件,成功才会启用Button1按钮,否则是Button1_a假注册按钮;
Button1.Click事件: 将Email的字符串运算之后,连接注册名,再次运算后,得到大数运算需要的KEY,大数运算后得到注册码的第一部份
数据,然后将机器码作浮点实数运算,结果转换为字符串后成为注册码的第二部分数据;
Edit4.Change 事件: 重复Button1.Click事件的前面,然后将MD5加密后的真、假注册码比较,相同,再比较尾部是否为字符串"PYG2007",
相等,便启动Timer1.Timer事件;
Timer1.Timer 事件: 将Email的字符串运算后连接注册名,再次运算后,得到大数运算需要的KEY。。。后面雷同,省略了。
具体分析过程,如下:
CrackMe用了NsPacK V3.7压缩,将其脱壳后,在窗口启动时下断点,得到与注册相关的信息如下:
》》》》》》
004747B9 .64:FF30 push dword ptr fs: ;窗口创建时:
004747BC .64:8920 mov dword ptr fs:, esp
004747BF .E8 3811FEFF call Cra.004558FC
004747C4 .8D45 F4 lea eax, dword ptr
004747C7 .BA E04C4700 mov edx, Cra.00474CE0 ;CrackMe2007.EXE
004747CC .E8 93FDF8FF call Cra.00404564
004747D1 .8D95 18FEFFFF lea edx, dword ptr
004747D7 .A1 0C934700 mov eax, dword ptr
004747DC .8B00 mov eax, dword ptr
004747DE .E8 E9FDFDFF call Cra.004545CC
004747E3 .8B85 18FEFFFF mov eax, dword ptr (TApplication):AnsiString
004747E9 .E8 360EFEFF call Cra.00455624
004747EE .8BD8 mov ebx, eax
004747F0 .E8 0711FEFF call Cra.004558FC
004747F5 .EB 01 jmp short Cra.004747F8
004747F7 0F db 0F
004747F8 >31F0 xor eax, esi
004747FA .EB 0C jmp short Cra.00474808
004747FC >33C8 xor ecx, eax
004747FE .EB 03 jmp short Cra.00474803
00474800 >EB 09 jmp short Cra.0047480B
00474802 0F db 0F
00474803 >59 pop ecx
00474804 .74 05 je short Cra.0047480B
00474806 .^ 75 F8 jnz short Cra.00474800
00474808 >51 push ecx
00474809 .^ EB F1 jmp short Cra.004747FC
0047480B >81FB C0450400 cmp ebx, 445C0 ;比较文件大小 与 280000
00474811 7F 39 jg short Cra.0047484C ;小于或等于,则不跳,表示没有被脱壳
00474813 .8D95 14FEFFFF lea edx, dword ptr
00474819 .A1 0C934700 mov eax, dword ptr
0047481E .8B00 mov eax, dword ptr
00474820 .E8 A7FDFDFF call Cra.004545CC ;得到程序名称
00474825 .8B85 14FEFFFF mov eax, dword ptr
0047482B .50 push eax
0047482C .8D95 10FEFFFF lea edx, dword ptr
00474832 .8B45 F4 mov eax, dword ptr
00474835 .E8 8228FEFF call Cra.004570BC ;Base64解密
0047483A .8B95 10FEFFFF mov edx, dword ptr ;界密结果: "CrackMe2007.EXE"
00474840 .58 pop eax
00474841 .E8 9200F9FF call Cra.004048D8 ;比较文件名称
00474846 0F84 CA000000 je Cra.00474916 ;相等,则跳!
0047484C >8B45 FC mov eax, dword ptr
0047484F .8B80 14030000 mov eax, dword ptr ;TButton1
00474855 .33D2 xor edx, edx
00474857 .E8 A0FBFBFF call Cra.004343FC ;Controls.TControl.SetVisible(TControl;Boolean)
0047485C .8B45 FC mov eax, dword ptr
0047485F .8B80 14030000 mov eax, dword ptr ;TButton1
00474865 .33D2 xor edx, edx
00474867 .8B08 mov ecx, dword ptr
00474869 .FF51 64 call dword ptr
0047486C .8B45 FC mov eax, dword ptr
0047486F .8B80 30030000 mov eax, dword ptr ;TButton1_a
00474875 .B2 01 mov dl, 1
00474877 .8B08 mov ecx, dword ptr
00474879 .FF51 64 call dword ptr
0047487C .8B45 FC mov eax, dword ptr
0047487F .8B80 30030000 mov eax, dword ptr ;TButton1_a
00474885 .B2 01 mov dl, 1
00474887 .E8 70FBFBFF call Cra.004343FC ;Controls.TControl.SetVisible(TControl;Boolean)
0047488C .8B45 FC mov eax, dword ptr
0047488F .8B80 00030000 mov eax, dword ptr ;TEdit2
00474895 .33D2 xor edx, edx
00474897 .E8 A48AFBFF call Cra.0042D340 ;StdCtrls.TCustomEdit.SetReadOnly
0047489C .E8 170FFEFF call Cra.004557B8 ;TApplication._PROC_004557B8()
004748A1 .33C0 xor eax, eax
004748A3 .55 push ebp
004748A4 .68 F4484700 push Cra.004748F4
004748A9 .64:FF30 push dword ptr fs: ;***** TRY
004748AC .64:8920 mov dword ptr fs:, esp
004748AF .B8 084D4700 mov eax, Cra.00474D08 ;c:\
004748B4 .E8 E30CFEFF call Cra.0045559C
004748B9 .69C0 39300000 imul eax, eax, 3039
004748BF .05 2770430B add eax, 0B437027
004748C4 .33D2 xor edx, edx
004748C6 .52 push edx ; /Arg2 => 00000000
004748C7 .50 push eax ; |Arg1
004748C8 .8D85 0CFEFFFF lea eax, dword ptr ; |
004748CE .E8 B93EF9FF call Cra.0040878C ; \Cra.0040878C
004748D3 .8B95 0CFEFFFF mov edx, dword ptr
004748D9 .8B45 FC mov eax, dword ptr
004748DC .8B80 FC020000 mov eax, dword ptr ;TEdit1
004748E2 .E8 25FCFBFF call Cra.0043450C ;Controls.TControl.SetText(TControl;TCaption)
004748E7 .33C0 xor eax, eax
004748E9 .5A pop edx
004748EA .59 pop ecx
004748EB .59 pop ecx
004748EC .64:8910 mov dword ptr fs:, edx
004748EF .E9 9E030000 jmp Cra.00474C92
004748F4 .^ E9 23F3F8FF jmp Cra.00403C1C
004748F9 .8B45 FC mov eax, dword ptr
004748FC .8B80 FC020000 mov eax, dword ptr ;TEdit1
00474902 .BA 144D4700 mov edx, Cra.00474D14 ;123456789
00474907 .E8 00FCFBFF call Cra.0043450C
0047490C .E8 73F6F8FF call Cra.00403F84
00474911 .E9 7C030000 jmp Cra.00474C92
00474916 >EB 01 jmp short Cra.00474919 ;检测正确,跳来了这里
00474918 0F db 0F
00474919 >31F0 xor eax, esi
0047491B .EB 0C jmp short Cra.00474929
0047491D >33C8 xor ecx, eax
0047491F .EB 03 jmp short Cra.00474924
00474921 >EB 09 jmp short Cra.0047492C
00474923 0F db 0F
00474924 >59 pop ecx
00474925 .74 05 je short Cra.0047492C
00474927 .^ 75 F8 jnz short Cra.00474921
00474929 >51 push ecx
0047492A .^ EB F1 jmp short Cra.0047491D
0047492C >E8 770FFEFF call Cra.004558A8 ;CreateFileA -> 打开Key文件
00474931 .E8 820EFEFF call Cra.004557B8 ;TApplication._PROC_004557B8()
00474936 .33C0 xor eax, eax
00474938 .55 push ebp
00474939 .68 86494700 push Cra.00474986
0047493E .64:FF30 push dword ptr fs: ;***** TRY
00474941 .64:8920 mov dword ptr fs:, esp
00474944 .B8 084D4700 mov eax, Cra.00474D08 ;c:\
00474949 .E8 4E0CFEFF call Cra.0045559C ;得到C:\下的卷标号
0047494E .69C0 39300000 imul eax, eax, 3039 ;卷标号与$3039 相乘 -> eax
00474954 .05 2770430B add eax, 0B437027 ;其结果 + $0B437027 -> eax
00474959 .33D2 xor edx, edx
0047495B .52 push edx ; /Arg2 => 00000000
0047495C .50 push eax ; |Arg1
0047495D .8D85 08FEFFFF lea eax, dword ptr ; |
00474963 .E8 243EF9FF call Cra.0040878C ; \[将上面的结果转换为无符号数字(即:机器码)
00474968 .8B95 08FEFFFF mov edx, dword ptr ;结果 -》 eax
0047496E .8B45 FC mov eax, dword ptr
00474971 .8B80 FC020000 mov eax, dword ptr ;TEdit1
00474977 .E8 90FBFBFF call Cra.0043450C ;Controls.TControl.SetText(TControl;TCaption)
0047497C .33C0 xor eax, eax
0047497E .5A pop edx
0047497F .59 pop ecx
00474980 .59 pop ecx
00474981 .64:8910 mov dword ptr fs:, edx
00474984 .EB 1D jmp short Cra.004749A3
00474986 .^ E9 91F2F8FF jmp Cra.00403C1C
0047498B .8B45 FC mov eax, dword ptr
0047498E .8B80 FC020000 mov eax, dword ptr
00474994 .BA 144D4700 mov edx, Cra.00474D14 ;123456789
00474999 .E8 6EFBFBFF call Cra.0043450C
0047499E .E8 E1F5F8FF call Cra.00403F84
004749A3 >E8 100EFEFF call Cra.004557B8
004749A8 .8D4D F8 lea ecx, dword ptr
004749AB .33D2 xor edx, edx
004749AD .B8 284D4700 mov eax, Cra.00474D28 ;tR^A+.-%=tpc*
004749B2 .E8 0D0DFEFF call Cra.004556C4 ;解密后:oJG_4207.dau=
004749B7 .E8 FC0DFEFF call Cra.004557B8
004749BC .8D4D F8 lea ecx, dword ptr
004749BF .33D2 xor edx, edx
004749C1 .B8 404D4700 mov eax, Cra.00474D40 ;thg^%#()_=3WD
004749C6 .E8 F90CFEFF call Cra.004556C4 ;解密后:op~@:?5;L-"AS
004749CB .E8 E80DFEFF call Cra.004557B8
004749D0 .8D4D F8 lea ecx, dword ptr
004749D3 .33D2 xor edx, edx
004749D5 .B8 584D4700 mov eax, Cra.00474D58 ;FDS_^&$#@@~~_
004749DA .E8 E50CFEFF call Cra.004556C4 ;解密后:]\JAA:91SPohH
004749DF .E8 D40DFEFF call Cra.004557B8
004749E4 .8D4D F8 lea ecx, dword ptr
004749E7 .33D2 xor edx, edx
004749E9 .B8 704D4700 mov eax, Cra.00474D70 ;TV%B^&()_+#$%
004749EE .E8 D10CFEFF call Cra.004556C4 ;解密后:ON<\A:5;L;222
004749F3 .E8 C00DFEFF call Cra.004557B8 ;(最初的 CPU 选择)
004749F8 .8D4D F8 lea ecx, dword ptr
004749FB .33D2 xor edx, edx
004749FD .B8 884D4700 mov eax, Cra.00474D88 ;2-atr^%hGIj-%
00474A02 .E8 BD0CFEFF call Cra.004556C4 ;解密后:)5xjmB8zTY{;2
00474A07 .E8 AC0DFEFF call Cra.004557B8
00474A0C .EB 01 jmp short Cra.00474A0F
00474A0E 0F db 0F
00474A0F >31F0 xor eax, esi
00474A11 .EB 0C jmp short Cra.00474A1F
00474A13 >33C8 xor ecx, eax
00474A15 .EB 03 jmp short Cra.00474A1A
00474A17 >EB 09 jmp short Cra.00474A22
00474A19 0F db 0F
00474A1A >59 pop ecx
00474A1B .74 05 je short Cra.00474A22
00474A1D .^ 75 F8 jnz short Cra.00474A17
00474A1F >51 push ecx
00474A20 .^ EB F1 jmp short Cra.00474A13
00474A22 >8D4D F8 lea ecx, dword ptr
00474A25 .BA 01000000 mov edx, 1
00474A2A .B8 A04D4700 mov eax, Cra.00474DA0 ;KA^A-,-%=tpb-
00474A2F .E8 900CFEFF call Cra.004556C4 ;解密后:PYG_2007.dat:
00474A34 .E8 7F0DFEFF call Cra.004557B8
00474A39 .8D95 00FEFFFF lea edx, dword ptr
00474A3F .33C0 xor eax, eax
00474A41 .E8 DEDFF8FF call Cra.00402A24
00474A46 .8B85 00FEFFFF mov eax, dword ptr
00474A4C .8D95 04FEFFFF lea edx, dword ptr
00474A52 .E8 9142F9FF call Cra.00408CE8
00474A57 .8D85 04FEFFFF lea eax, dword ptr
00474A5D .8B55 F8 mov edx, dword ptr ;KEy文件名称 -》 edx
00474A60 .E8 2FFDF8FF call Cra.00404794
00474A65 .8B85 04FEFFFF mov eax, dword ptr
00474A6B .E8 B40BFEFF call Cra.00455624
00474A70 .8BD8 mov ebx, eax
00474A72 .E8 410DFEFF call Cra.004557B8
00474A77 .83FB FF cmp ebx, -1
00474A7A .0F84 A2010000 je Cra.00474C22 ;如为空,则跳走
00474A80 .83FB 20 cmp ebx, 20 ;长度是否为: 32
00474A83 .0F85 99010000 jnz Cra.00474C22 ;不相等,也跳走
00474A89 .8D95 F8FDFFFF lea edx, dword ptr
00474A8F .33C0 xor eax, eax
00474A91 .E8 8EDFF8FF call Cra.00402A24
00474A96 .8B85 F8FDFFFF mov eax, dword ptr
00474A9C .8D95 FCFDFFFF lea edx, dword ptr
00474AA2 .E8 4142F9FF call Cra.00408CE8
00474AA7 .8D85 FCFDFFFF lea eax, dword ptr
00474AAD .8B55 F8 mov edx, dword ptr
00474AB0 .E8 DFFCF8FF call Cra.00404794
00474AB5 .8B95 FCFDFFFF mov edx, dword ptr
00474ABB .8D85 1CFEFFFF lea eax, dword ptr
00474AC1 .E8 DEE2F8FF call Cra.00402DA4
00474AC6 .8D85 1CFEFFFF lea eax, dword ptr
00474ACC .E8 6FE0F8FF call Cra.00402B40
00474AD1 .E8 8EDDF8FF call Cra.00402864
00474AD6 .8D55 F0 lea edx, dword ptr
00474AD9 .8D85 1CFEFFFF lea eax, dword ptr
00474ADF .E8 38E6F8FF call Cra.0040311C
00474AE4 .8D85 1CFEFFFF lea eax, dword ptr
00474AEA .E8 99E6F8FF call Cra.00403188
00474AEF .E8 70DDF8FF call Cra.00402864
00474AF4 .8D85 1CFEFFFF lea eax, dword ptr
00474AFA .E8 61E3F8FF call Cra.00402E60
00474AFF .E8 60DDF8FF call Cra.00402864
00474B04 .8D4D E8 lea ecx, dword ptr
00474B07 .BA 10000000 mov edx, 10
00474B0C .8B45 F0 mov eax, dword ptr
00474B0F .E8 3453FBFF call Cra.00429E48
00474B14 .33DB xor ebx, ebx
00474B16 .B8 01000000 mov eax, 1 ;循环初时计算KEY文件中的前16位
00474B1B >8B55 F0 mov edx, dword ptr
00474B1E .0FB65402 FF movzx edx, byte ptr
00474B23 .83EA 0F sub edx, 0F ;减去F
00474B26 .83F2 20 xor edx, 20 ;xor 20
00474B29 .03DA add ebx, edx ;ebx := ebx + edx;
00474B2B .40 inc eax
00474B2C .83F8 11 cmp eax, 11 ;十进制:17
00474B2F .^ 75 EA jnz short Cra.00474B1B ;小于17
00474B31 .66:9C pushfw
00474B33 .6A 0A push 0A
00474B35 >E8 02000000 call Cra.00474B3C
00474B3A .^ 73 F9 jnb short Cra.00474B35
00474B3C $83C4 04 add esp, 4
00474B3F .FF0C24 dec dword ptr
00474B42 .^ 79 F1 jns short Cra.00474B35
00474B44 .83C4 04 add esp, 4
00474B47 .66:9D popfw
00474B49 .69C3 697A0000 imul eax, ebx, 7A69 ;整数乘法 x $7A69
00474B4F .8BD8 mov ebx, eax
00474B51 .8D85 F4FDFFFF lea eax, dword ptr
00474B57 .50 push eax ; /Arg1
00474B58 .899D ECFDFFFF mov dword ptr , ebx ; |
00474B5E .C685 F0FDFFFF 00 mov byte ptr , 0 ; |
00474B65 .8D95 ECFDFFFF lea edx, dword ptr ; |
00474B6B .33C9 xor ecx, ecx ; |
00474B6D .B8 B84D4700 mov eax, Cra.00474DB8 ; |%0x
00474B72 .E8 B149F9FF call Cra.00409528 ; \[将上面的结果转换成字符串
00474B77 .8B85 F4FDFFFF mov eax, dword ptr ;字符串 -> eax 中
00474B7D .8D55 EC lea edx, dword ptr
00474B80 .E8 CB37F9FF call Cra.00408350
00474B85 .66:9C pushfw
00474B87 .6A 0A push 0A
00474B89 >E8 02000000 call Cra.00474B90
00474B8E .^ 73 F9 jnb short Cra.00474B89
00474B90 $83C4 04 add esp, 4
00474B93 .FF0C24 dec dword ptr
00474B96 .^ 79 F1 jns short Cra.00474B89
00474B98 .83C4 04 add esp, 4
00474B9B .66:9D popfw
00474B9D .8D95 E8FDFFFF lea edx, dword ptr
00474BA3 .8B45 E8 mov eax, dword ptr ;取后面的16个字符串
00474BA6 .E8 F539F9FF call Cra.004085A0 ;返回一个删除了空制字符和空格的结果字符串
00474BAB .8B85 E8FDFFFF mov eax, dword ptr ;-》 eax
00474BB1 .8B55 EC mov edx, dword ptr ;前16位数的运算结果
00474BB4 .E8 1FFDF8FF call Cra.004048D8 ;比较两字符串 是否 相等?
00474BB9 .0F85 D3000000 jnz Cra.00474C92 ;不相等,便跳走!
00474BBF .8B45 FC mov eax, dword ptr
》》》》》》
通过对上面的的分析,知道了机器码为:得到C:盘的卷标序列号,然后乘以12345,再加上188968999的结果的无符号数;
而KEY文件的名称为:PYG_2007.dat,其长度必须是32字节,前16位保存注册名,后16位保存注册码,其算法表述为:
var
pos, ebx, edx : integer;
ResultName : string;
handle : Thandle;
const
name : array of byte =
($00,$00,$00,$00,$00,$00,$00,$00,
$00,$00,$00,$00,$00,$00,$00,$00);
code : array of char = //默认为16个空格符号
(' ',' ',' ',' ',' ',' ',' ',' ',
' ',' ',' ',' ',' ',' ',' ',' ');
begin
for pos := 1 to length(Form1.EditName.Text) do
name := ord(Form1.EditName.Text);
EBX := 0;
for pos := 1 to length(name) do
begin
EDX := ord(name) - $0F;
EDX := EDX xor $20;
EBX := EBX + EDX;
end;
EBX := EBX * $7A69;
ResultName := int2hex(EBX,0);
for pos := 1 to length(ResultName) do
code := ResultName;
end;
然后,将name和code的缓冲区中的数据写入到PYG_2007.dat文件中,即可!
前面的条件符合之后,再看Timer2.Timer事件中的代码,如下:
》》》》》》
0047672E .64:FF30 push dword ptr fs: ;Timer2.Timer事件:
00476731 .64:8920 mov dword ptr fs:, esp
00476734 .E8 C3F1FDFF call Cra.004558FC
00476739 .8D95 1CFEFFFF lea edx, dword ptr
0047673F .A1 0C934700 mov eax, dword ptr
00476744 .8B00 mov eax, dword ptr
00476746 .E8 81DEFDFF call Cra.004545CC ;得到程序名称
0047674B .8B85 1CFEFFFF mov eax, dword ptr
00476751 .E8 CEEEFDFF call Cra.00455624
00476756 .3D C0450400 cmp eax, 445C0 ;十进制:280000
0047675B 0F8E CA000000 jle Cra.0047682B ;小于,便跳!(表示:加了壳)
00476761 .8B45 FC mov eax, dword ptr
(省略)
0047682B >E8 78F0FDFF call Cra.004558A8 ;CreateFileA
00476830 .E8 83EFFDFF call Cra.004557B8
00476835 .33C0 xor eax, eax
00476837 .55 push ebp
00476838 .68 85684700 push Cra.00476885
0047683D .64:FF30 push dword ptr fs: ;***** TRY
00476840 .64:8920 mov dword ptr fs:, esp
00476843 .B8 886B4700 mov eax, Cra.00476B88 ;c:\
00476848 .E8 4FEDFDFF call Cra.0045559C ;得到C:\的序列号
0047684D .69C0 39300000 imul eax, eax, 3039
00476853 .05 2770430B add eax, 0B437027 ;eax 的10进制结果为机器码
00476858 .33D2 xor edx, edx
0047685A .52 push edx ; /Arg2 => 00000000
0047685B .50 push eax ; |Arg1
0047685C .8D85 14FEFFFF lea eax, dword ptr ; |
00476862 .E8 251FF9FF call Cra.0040878C ; \Cra.0040878C
00476867 .8B95 14FEFFFF mov edx, dword ptr ;//机器码,上面结果的无符号数字
0047686D .8B45 FC mov eax, dword ptr
(省略)
0047694E .8B85 10FEFFFF mov eax, dword ptr
00476954 .E8 CBECFDFF call Cra.00455624
00476959 .8BD8 mov ebx, eax
0047695B .E8 58EEFDFF call Cra.004557B8
00476960 .83FB FF cmp ebx, -1 ;为空
00476963 .0F84 72010000 je Cra.00476ADB ;不能跳!
00476969 .83FB 20 cmp ebx, 20 ;十进制:32
0047696C .0F85 69010000 jnz Cra.00476ADB ;不能跳!
00476972 .8D95 04FEFFFF lea edx, dword ptr
(省略)
004769FD .33DB xor ebx, ebx
004769FF .B8 01000000 mov eax, 1
00476A04 >8B55 F4 mov edx, dword ptr ;取前16位数字
00476A07 .0FB65402 FF movzx edx, byte ptr
00476A0C .83EA 0F sub edx, 0F
00476A0F .83F2 20 xor edx, 20
00476A12 .03DA add ebx, edx
00476A14 .40 inc eax
00476A15 .83F8 11 cmp eax, 11 ;十进制:17
00476A18 .^ 75 EA jnz short Cra.00476A04 ;小于17
00476A1A .69C3 697A0000 imul eax, ebx, 7A69 ;整乘法
00476A20 .8BD8 mov ebx, eax
00476A22 .8D85 00FEFFFF lea eax, dword ptr
00476A28 .50 push eax ; /Arg1
00476A29 .899D F8FDFFFF mov dword ptr , ebx ; |
00476A2F .C685 FCFDFFFF 00 mov byte ptr , 0 ; |
00476A36 .8D95 F8FDFFFF lea edx, dword ptr ; |
00476A3C .33C9 xor ecx, ecx ; |
00476A3E .B8 386C4700 mov eax, Cra.00476C38 ; |%0x
00476A43 .E8 E02AF9FF call Cra.00409528 ; \Cra.00409528
00476A48 .8B85 00FEFFFF mov eax, dword ptr ;//结果
00476A4E .8D55 F0 lea edx, dword ptr
00476A51 .E8 FA18F9FF call Cra.00408350 ;SysUtils.UpperCase(AnsiString):AnsiString;
00476A56 .8D95 F4FDFFFF lea edx, dword ptr
00476A5C .8B45 EC mov eax, dword ptr ;取后16位数字
00476A5F .E8 3C1BF9FF call Cra.004085A0 ;SysUtils.Trim(AnsiString):AnsiString;overload;
00476A64 .8B85 F4FDFFFF mov eax, dword ptr
00476A6A .8B55 F0 mov edx, dword ptr
00476A6D .E8 66DEF8FF call Cra.004048D8 ;System.@LStrCmp;
00476A72 .0F85 C3000000 jnz Cra.00476B3B ;不能跳!要相等
00476A78 .8B45 FC mov eax, dword ptr
(省略)
》》》》》》
通过对上面的分析,发现其检测的代码和窗口创建时候的几乎雷同,故跳过,不用分析了;
但是必须注意:
要将 0047675B /0F8E CA000000 jle Cra.0047682B 这行改为jmp强制跳转哟!
不然到不了Button1按钮中的代码,呵呵;谁让我不是带壳调试呐 ;)
将上面修改之后,这时点击『注册』按钮,便来到了Button1按钮点击后的事件中(不是Button1_a按钮哟),其代码如下:
》》》》》》
00474263|.51 push ecx ;Button1 按钮中的代码:
00474264|.53 push ebx
00474265|.56 push esi
00474266|.8945 FC mov dword ptr , eax
00474269|.8D45 E8 lea eax, dword ptr
0047426C|.8B15 88594500 mov edx, dword ptr ;Cra.0045598C
00474272|.E8 0D0CF9FF call Cra.00404E84 ;System.@InitializeRecord
00474277|.8D45 E0 lea eax, dword ptr ;System.@AddRefRecord
0047427A|.8B15 88594500 mov edx, dword ptr ;Cra.0045598C
00474280|.E8 FF0BF9FF call Cra.00404E84 ;System.@InitializeRecord
00474285|.8D45 D8 lea eax, dword ptr ;System.@AddRefRecord
00474288|.8B15 88594500 mov edx, dword ptr ;Cra.0045598C
0047428E|.E8 F10BF9FF call Cra.00404E84 ;System.@InitializeRecord
00474293|.33C0 xor eax, eax
00474295|.55 push ebp
00474296|.68 15474700 push Cra.00474715
0047429B|.64:FF30 push dword ptr fs:
0047429E|.64:8920 mov dword ptr fs:, esp
004742A1|.E8 1215FEFF call Cra.004557B8
004742A6|.8D55 84 lea edx, dword ptr
004742A9|.8B45 FC mov eax, dword ptr
004742AC|.8B80 04030000 mov eax, dword ptr ;TEdit3
004742B2|.E8 2502FCFF call Cra.004344DC ;Controls.TControl.GetText(TControl):TCaption
004742B7|.8B45 84 mov eax, dword ptr
004742BA|.E8 1512FEFF call Cra.004554D4
004742BF|.84C0 test al, al ;是否输入了Email?
004742C1|.75 0F jnz short Cra.004742D2 ;有,则跳
004742C3|.8D45 F8 lea eax, dword ptr
004742C6|.BA 30474700 mov edx, Cra.00474730 ;[email protected]
004742CB|.E8 9402F9FF call Cra.00404564
004742D0|.EB 11 jmp short Cra.004742E3
004742D2|>8D55 F8 lea edx, dword ptr
004742D5|.8B45 FC mov eax, dword ptr
004742D8|.8B80 04030000 mov eax, dword ptr ;TEdit3
004742DE|.E8 F901FCFF call Cra.004344DC ;得到Email的长度 -> eax
004742E3|>33DB xor ebx, ebx
004742E5|.C745 98 596F7520 mov dword ptr , 20756F59 ;'You '
004742EC|.C745 9C 6C6F7665 mov dword ptr , 65766F6C ;'love'
004742F3|.C745 A0 20505947 mov dword ptr , 47595020 ;' PYG'
004742FA|.8B45 F8 mov eax, dword ptr ;Email -> eax
004742FD|.E8 8A04F9FF call Cra.0040478C ;得到Email的长度 -> eax
00474302|.8BC8 mov ecx, eax
00474304|.85C9 test ecx, ecx ;Emai长度是否为0?
00474306|.7E 19 jle short Cra.00474321
00474308|.BE 01000000 mov esi, 1
0047430D|>8B45 F8 /mov eax, dword ptr ;Email -> eax
00474310|.0FB64430 FF |movzx eax, byte ptr ;依次取Email的ASCII码
00474315|.83C0 0F |add eax, 0F ;加上 $F
00474318|.83F0 20 |xor eax, 20 ;异或 $20
0047431B|.03D8 |add ebx, eax ;ebx := ebx + eax;(结果)
0047431D|.46 |inc esi
0047431E|.49 |dec ecx ;减去1
0047431F|.^ 75 EC \jnz short Cra.0047430D ;不为0,则循环
00474321|>8BC3 mov eax, ebx ;-> eax
00474323|.33D2 xor edx, edx
00474325|.52 push edx ; /Arg2 => 00000000
00474326|.50 push eax ; |Arg1
00474327|.8D45 F4 lea eax, dword ptr ; |
0047432A|.E8 5D44F9FF call Cra.0040878C ; \[将上面的结果转换为10进制的字符串
0047432F|.8D55 80 lea edx, dword ptr
00474332|.8B45 FC mov eax, dword ptr
00474335|.8B80 00030000 mov eax, dword ptr ;TEdit2
0047433B|.E8 9C01FCFF call Cra.004344DC
00474340|.8B4D 80 mov ecx, dword ptr ;注册名 -> ecx
00474343|.8D45 F0 lea eax, dword ptr
00474346|.8B55 F4 mov edx, dword ptr ;前面计算结果的十进制数 字符串
00474349|.E8 8A04F9FF call Cra.004047D8 ;两字符串连接
0047434E|.8B45 F0 mov eax, dword ptr ;新结果 -> eax
00474351|.E8 3604F9FF call Cra.0040478C ;得到新字符串的长度 -> eax
00474356|.8BC8 mov ecx, eax ;ecx := eax;
00474358|.85C9 test ecx, ecx ;新字符串是否为空?
0047435A|.7E 22 jle short Cra.0047437E ;为空,则跳
0047435C|.BE 01000000 mov esi, 1
00474361|>8B45 F0 /mov eax, dword ptr ;新字符串 -> eax
00474364|.0FB64430 FF |movzx eax, byte ptr ;依次取该字符串的ASCII码 -> eax
00474369|.0345 98 |add eax, dword ptr ;初始值: $20756F59 加法
0047436C|.25 FF000000 |and eax, 0FF ;与 运输 $FF
00474371|.03C3 |add eax, ebx ;加上前面的结果
00474373|.99 |cdq
00474374|.33C2 |xor eax, edx
00474376|.2BC2 |sub eax, edx ;eax := eax - edx;
00474378|.8BD8 |mov ebx, eax ;-> ebx
0047437A|.46 |inc esi
0047437B|.49 |dec ecx ;减去1
0047437C|.^ 75 E3 \jnz short Cra.00474361 ;不为0,这循环运算
0047437E|>8BC3 mov eax, ebx
00474380|.C1E0 0A shl eax, 0A ;上面的结果 shl $0A
00474383|.0345 9C add eax, dword ptr ;再加上 $65766F6C
00474386|.99 cdq
00474387|.33C2 xor eax, edx
00474389|.2BC2 sub eax, edx
0047438B|.8BD8 mov ebx, eax
0047438D|.8BC3 mov eax, ebx
0047438F|.33D2 xor edx, edx
00474391|.52 push edx ; /Arg2 => 00000000
00474392|.50 push eax ; |Arg1
00474393|.8D85 7CFFFFFF lea eax, dword ptr ; |
00474399|.E8 EE43F9FF call Cra.0040878C ; \Cra.0040878C
0047439E|.8B85 7CFFFFFF mov eax, dword ptr ;上面运算结果的10进制字符串 ->eax
004743A4|.8D55 E8 lea edx, dword ptr
004743A7|.E8 B017FEFF call Cra.00455B5C ;字上面的符串转换为大数
004743AC|.8B45 A0 mov eax, dword ptr ;' PYG'的ascII码 -> eax
004743AF|.05 40E20100 add eax, 1E240 ;eax := $47595020 + $1E240
004743B4|.33D2 xor edx, edx
004743B6|.52 push edx ; /Arg2 => 00000000
004743B7|.50 push eax ; |$475B3260 <- eax
004743B8|.8D85 78FFFFFF lea eax, dword ptr ; |
004743BE|.E8 C943F9FF call Cra.0040878C ; \Cra.0040878C
004743C3|.8B85 78FFFFFF mov eax, dword ptr ;上面运算结果的10进制字符串(就是固定的)
004743C9|.8D55 E0 lea edx, dword ptr
004743CC|.E8 8B17FEFF call Cra.00455B5C ;字上面的符串转换为大数
004743D1|.8D4D D8 lea ecx, dword ptr
004743D4|.8D55 E0 lea edx, dword ptr
004743D7|.8D45 E8 lea eax, dword ptr
004743DA|.E8 891BFEFF call Cra.00455F68 ;//计算第一组数据 大数加法
004743DF|.8D55 D4 lea edx, dword ptr
004743E2|.8D45 D8 lea eax, dword ptr
004743E5|.E8 D219FEFF call Cra.00455DBC ;//将其转换为10进制的字符串(去掉前面的0)
004743EA|.8D4D D8 lea ecx, dword ptr
004743ED|.8D55 E0 lea edx, dword ptr
004743F0|.8D45 E8 lea eax, dword ptr
004743F3|.E8 041FFEFF call Cra.004562FC ;//计算第二组数据 大数乘法
004743F8|.8D55 D0 lea edx, dword ptr
004743FB|.8D45 D8 lea eax, dword ptr
004743FE|.E8 B919FEFF call Cra.00455DBC ;//将其转换为10进制的字符串(去掉前面的0)
00474403|.8D4D D8 lea ecx, dword ptr
00474406|.8D55 E0 lea edx, dword ptr
00474409|.8D45 E8 lea eax, dword ptr
0047440C|.E8 AB1DFEFF call Cra.004561BC ;//计算第三组数据 不是大数运算哟!
00474411|.8D45 D8 lea eax, dword ptr
00474414|.E8 A71EFEFF call Cra.004562C0
00474419|.8D55 CC lea edx, dword ptr
0047441C|.8D45 D8 lea eax, dword ptr
0047441F|.E8 9819FEFF call Cra.00455DBC ;//将其转换为10进制的字符串(去掉前面的0)
00474424|.FF75 D4 push dword ptr ;//(ASCII)1
00474427|.FF75 D0 push dword ptr ;//(ASCII)2
0047442A|.FF75 CC push dword ptr ;//(ASCII)3
0047442D|.8D45 C8 lea eax, dword ptr
00474430|.BA 03000000 mov edx, 3
00474435|.E8 1204F9FF call Cra.0040484C ;System.@LStrCatN
0047443A|.8D55 E8 lea edx, dword ptr
0047443D|.8B45 C8 mov eax, dword ptr ;//(ASCII)1+2+3 -> eax
00474440|.E8 1717FEFF call Cra.00455B5C ;字上面的符串转换为大数
00474445|.8D95 74FFFFFF lea edx, dword ptr
0047444B|.B8 00DE0000 mov eax, 0DE00 ;KEy: $DC00 -> eax
00474450|.E8 4B42F9FF call Cra.004086A0 ;转为字符串
00474455|.8B85 74FFFFFF mov eax, dword ptr ;即为(ASCII "56832") -> eax
0047445B|.8D55 E0 lea edx, dword ptr
0047445E|.E8 F916FEFF call Cra.00455B5C ;字上面的符串转换为大数
00474463|.8D4D D8 lea ecx, dword ptr
00474466|.8D55 E0 lea edx, dword ptr
00474469|.8D45 E8 lea eax, dword ptr
0047446C|.E8 8B1EFEFF call Cra.004562FC ;得到注册码的第一部份 大数乘法
00474471|.8D55 C4 lea edx, dword ptr
00474474|.8D45 D8 lea eax, dword ptr
00474477|.E8 4019FEFF call Cra.00455DBC ;//将其转换为10进制的字符串(去掉前面的0)
0047447C|.8D45 C4 lea eax, dword ptr
0047447F|.BA 20000000 mov edx, 20 ;取长度为:32
00474484|.E8 8F06F9FF call Cra.00404B18 ;从头开始截取32长度
00474489|.8D85 6CFFFFFF lea eax, dword ptr
0047448F|.50 push eax
00474490|.8D95 64FFFFFF lea edx, dword ptr
00474496|.8B45 FC mov eax, dword ptr
00474499|.8B80 FC020000 mov eax, dword ptr ;TEdit1
0047449F|.E8 3800FCFF call Cra.004344DC ;Controls.TControl.GetText(TControl):TCaption
004744A4|.8B85 64FFFFFF mov eax, dword ptr ;//机器码 -> eax
004744AA|.E8 0558F9FF call Cra.00409CB4 ;机器码转化为实数
004744AF|.D80D 44474700 fmul dword ptr ;* 3.000000
004744B5|.D805 48474700 fadd dword ptr ;+ 521725.0
004744BB|.83C4 F4 add esp, -0C
004744BE|.DB3C24 fstp tbyte ptr ; |出栈 -> ST7
004744C1|.9B wait ; |
004744C2|.8D85 68FFFFFF lea eax, dword ptr ; |
004744C8|.E8 8757F9FF call Cra.00409C54 ; \[转化为字符串
004744CD|.8B85 68FFFFFF mov eax, dword ptr ;//ST7 由机器码得来 -> eax
004744D3|.B9 08000000 mov ecx, 8 ;ecx := 8;
004744D8|.BA 01000000 mov edx, 1
004744DD|.E8 0A05F9FF call Cra.004049EC ;System.@LStrCopy
004744E2|.8B85 6CFFFFFF mov eax, dword ptr ;//上面结果的前8位字符 -> eax
004744E8|.E8 C757F9FF call Cra.00409CB4 ;再次转化为实数
004744ED|.D80D 4C474700 fmul dword ptr ;* 321.0000
004744F3|.DB2D 50474700 fld tbyte ptr ;9614516412.0000000000 -> ST0
004744F9|.DEC1 faddp st(1), st ;ST1 + ST0
004744FB|.DB2D 5C474700 fld tbyte ptr ;96145164.000000000000 -> ST0
00474501|.DEE9 fsubp st(1), st ;ST1 - ST0
00474503|.83C4 F4 add esp, -0C
00474506|.DB3C24 fstp tbyte ptr ; |出栈 -> ST7
00474509|.9B wait ; |
0047450A|.8D85 70FFFFFF lea eax, dword ptr ; |
00474510|.E8 3F57F9FF call Cra.00409C54 ; \Cra.00409C54
00474515|.8B95 70FFFFFF mov edx, dword ptr ;//ST7 注册码第2部分 -> edx
0047451B|.8D45 C4 lea eax, dword ptr
0047451E|.E8 7102F9FF call Cra.00404794 ;注册码第1/2部分连接
00474523|.8D55 88 lea edx, dword ptr
00474526|.8B45 C4 mov eax, dword ptr ;注册码1/2部分连接后 -> eax
00474529|.E8 9E29FEFF call Cra.00456ECC ;将上面的结果MD5加密
0047452E|.8D95 60FFFFFF lea edx, dword ptr
00474534|.8D45 88 lea eax, dword ptr
00474537|.E8 042AFEFF call Cra.00456F40
0047453C|.8B85 60FFFFFF mov eax, dword ptr ;MD5加密结果 -> eax
00474542|.8D55 C0 lea edx, dword ptr
00474545|.E8 063EF9FF call Cra.00408350 ;转为大写
0047454A|.8D45 BC lea eax, dword ptr
0047454D|.50 push eax
0047454E|.B9 08000000 mov ecx, 8
00474553|.BA 01000000 mov edx, 1
00474558|.8B45 C0 mov eax, dword ptr
0047455B|.E8 8C04F9FF call Cra.004049EC ;System.@LStrCopy
00474560|.8D45 B8 lea eax, dword ptr
00474563|.50 push eax
00474564|.B9 08000000 mov ecx, 8
00474569|.BA 09000000 mov edx, 9
0047456E|.8B45 C0 mov eax, dword ptr ;MD5加密结果 -> eax
00474571|.E8 7604F9FF call Cra.004049EC ;System.@LStrCopy
00474576|.8D4D B4 lea ecx, dword ptr
00474579|.BA 10000000 mov edx, 10
0047457E|.8B45 C0 mov eax, dword ptr
00474581|.E8 C258FBFF call Cra.00429E48 ;StrUtils.RightStr(AnsiString;Integer):AnsiString
00474586|.8D95 5CFFFFFF lea edx, dword ptr
0047458C|.8B45 FC mov eax, dword ptr
0047458F|.8B80 28030000 mov eax, dword ptr ;TEdit4
00474595|.E8 42FFFBFF call Cra.004344DC ;Controls.TControl.GetText(TControl):TCaption
0047459A|.8B85 5CFFFFFF mov eax, dword ptr ;获取输入的注册码 -> eax
004745A0|.8D55 88 lea edx, dword ptr
004745A3|.E8 2429FEFF call Cra.00456ECC ;将输入的注册码 MD5加密
004745A8|.8D95 58FFFFFF lea edx, dword ptr
004745AE|.8D45 88 lea eax, dword ptr
004745B1|.E8 8A29FEFF call Cra.00456F40 ;MD5加密
004745B6|.8B85 58FFFFFF mov eax, dword ptr ;加密结果 -> eax
004745BC|.8D55 B0 lea edx, dword ptr
004745BF|.E8 8C3DF9FF call Cra.00408350 ;转为大写
004745C4|.8D45 AC lea eax, dword ptr
004745C7|.50 push eax
004745C8|.B9 08000000 mov ecx, 8
004745CD|.BA 01000000 mov edx, 1
004745D2|.8B45 B0 mov eax, dword ptr
004745D5|.E8 1204F9FF call Cra.004049EC ;System.@LStrCopy
004745DA|.8D45 A8 lea eax, dword ptr
004745DD|.50 push eax
004745DE|.B9 08000000 mov ecx, 8
004745E3|.BA 09000000 mov edx, 9
004745E8|.8B45 B0 mov eax, dword ptr
004745EB|.E8 FC03F9FF call Cra.004049EC ;System.@LStrCopy
004745F0|.8D4D A4 lea ecx, dword ptr
004745F3|.BA 10000000 mov edx, 10
004745F8|.8B45 B0 mov eax, dword ptr
004745FB|.E8 4858FBFF call Cra.00429E48 ;StrUtils.RightStr(AnsiString;Integer):AnsiString
00474600|.8B45 BC mov eax, dword ptr ;//被MD5加密的真正的注册码 前8位
00474603|.8B55 AC mov edx, dword ptr ;//被MD5加密的输入的注册码 前8位
00474606|.E8 CD02F9FF call Cra.004048D8 ;比较,是否相同?
0047460B 75 7F jnz short Cra.0047468C ;不同,则跳出
0047460D|.8B45 B8 mov eax, dword ptr ;//被MD5加密的真正的注册码9~16位
00474610|.8B55 A8 mov edx, dword ptr ;//被MD5加密的输入的注册码9~16位
00474613|.E8 C002F9FF call Cra.004048D8 ;System.@LStrCmp
00474618|.75 72 jnz short Cra.0047468C ;不同,则跳出
0047461A|.8B45 B4 mov eax, dword ptr ;//被MD5加密的真正的注册码 其余剩下的
0047461D|.8B55 A4 mov edx, dword ptr ;//被MD5加密的输入的注册码 其余剩下的
00474620|.E8 B302F9FF call Cra.004048D8 ;System.@LStrCmp
00474625|.75 65 jnz short Cra.0047468C ;不同,则跳出
00474627|.B8 70474700 mov eax, Cra.00474770 ;注册假成功!
0047462C|.E8 6742FBFF call Cra.00428898 ;* Reference to: Dialogs.ShowMessage(AnsiString);
00474631|.8D95 54FFFFFF lea edx, dword ptr
00474637|.B8 84474700 mov eax, Cra.00474784 ;糟糕!中计了!
0047463C|.E8 7B2AFEFF call Cra.004570BC
00474641|.8B85 54FFFFFF mov eax, dword ptr
00474647|.E8 4C42FBFF call Cra.00428898 ;Dialogs.ShowMessage(AnsiString)
0047464C|.8B45 FC mov eax, dword ptr
》》》》》》
通过对上面的分析,知道了其算法为:
读取E-mail中的字符串,检查是否为空,不为空,则依次取其字符码,循环运算,得到一个数字,然后将该数字转换为10进制的字符串,
再和Key文件中读入的注册名相连接,然后再参与一个循环运算,得到的数字转换为10进制的字符串后,即为大数运算的一个变量,而另一
个大数变量则是固定的16进制数:475B3260,即为2进制的:1000111010110110011001001100000,将两者先做加法运算,得到第一个字符
串STR1;再做乘法运算,得到第二个字符串STR2;然后将Email和注册名连接运算后的结果再次加上16进制数$80000000,然后减去16进制数
$475B3260,再和16进制数$7FFFFFFF作与(and)运算,其结果转化为字符串后,即为第三个字符串STR3;将三个字符串连接起来后,再以
字符串'56832'作key,进行大数乘法运算,得到新的结果后,取该结果前面的32位字符,即成为最终注册码的第一部分;
接着,将机器码转化为实数,乘以 3.000000 后,加上 521725.0 后,取该结果的前8位字符,然后再次将该结果转化为实数,乘以321.00
00后,加上 9614516412.0000000000 后,再减去 96145164.000000000000 之后,转换为字符串便得到了最终注册码的第二部分;
将上面的一、二部分连接后,便得到了一个长字符串;将该字符串再次输入到CrackMe的注册码编辑框中,这是被断在了Edit4编辑框被改
变的事件处,通过对其分析,发现其前部分几乎和Button1按钮点击事件的代码雷同,而不同的仅是如下的代码:
》》》》》》
004754C3 . /74 05 je short Cra.004754CA
004754C5 .^|75 F8 jnz short Cra.004754BF
004754C7 > |51 push ecx
004754C8 .^|EB F1 jmp short Cra.004754BB
004754CA > \8B45 BC mov eax, dword ptr ;被MD5加密的真正的注册码 前8位
004754CD .8B55 AC mov edx, dword ptr ;被MD5加密的输入的注册码 前8位
004754D0 .E8 03F4F8FF call Cra.004048D8 ;比较
004754D5 75 7B jnz short Cra.00475552 ;相等,则不跳
004754D7 .8B45 B8 mov eax, dword ptr ;被MD5加密的真正的注册码9~16位
004754DA .8B55 A8 mov edx, dword ptr ;被MD5加密的输入的注册码9~16位
004754DD .E8 F6F3F8FF call Cra.004048D8 ;比较
004754E2 75 6E jnz short Cra.00475552 ;相等,则不跳
004754E4 .8B45 B4 mov eax, dword ptr ;被MD5加密的真正的注册码 其余剩下的
004754E7 .8B55 A4 mov edx, dword ptr ;被MD5加密的输入的注册码 其余剩下的
004754EA .E8 E9F3F8FF call Cra.004048D8 ;比较
004754EF 75 61 jnz short Cra.00475552 ;相等,则不跳
004754F1 .8B45 A0 mov eax, dword ptr
004754F4 .BA 44564700 mov edx, Cra.00475644 ;'PYG2007'
004754F9 .E8 DAF3F8FF call Cra.004048D8 ;比较
004754FE 75 12 jnz short Cra.00475512 ;相等,则不跳
00475500 .8B45 FC mov eax, dword ptr
00475503 .8B80 34030000 mov eax, dword ptr ;Timer1 : TTimer
00475509 .B2 01 mov dl, 1
0047550B .E8 B444FBFF call Cra.004299C4 ;ExtCtrls.TTimer.SetEnabled(TTimer;Boolean);
00475510 .EB 40 jmp short Cra.00475552 ;成功!! 跳向光明之颠!!
00475512 >8B45 FC mov eax, dword ptr
》》》》》》
发现上面的代码要检查注册码的最后是否有‘PYG2007’这个字符串,将其加上后,呵呵,注册成功了哟!飞向光明之颠!!
通过对上面的分析后,写出了该CrackMe的相关算法代码如下:(使用了kol&mck控件,已经写成为一个函数,方便你的调用,嘿嘿)
///////////////////// //PYG_CrackMe 2007 的注册算法// //////////////////////
function keygen_PYG2007(Email : string) : string; //返回结果为字符串类型函数
var
i, x, EmailKey1, EmailKey2 : integer;
tempStr, KeyStr1, KeyStr2, KeyStr3, KeyStrA, KeyStrB, KeyStr : string;
tempFG1, tempFG2, FGintKey : TFGInt;
tempMAC : real;
begin
if (Form1.EditName.Text = '') //是否输入了注册名
then begin
Result := '请输入你的大名,呵呵 ;)';
Exit;
end;
if length(Form1.EditName.Text) > 16 //注册名长度是否大于16位数
then begin
Result := '注册名长度不能超过16位字符 ;)';
Exit;
end;
if (Email = '') //是否输入了电子邮件
then begin
Result := '请输入你的电邮,呵呵 ;)';
Exit;
end;
if (pos('@', Email) = 0) or (pos('.', Email) = 0) //电子邮件格式是否正确
then begin
Result := '电邮中没有@符号或者.符号 ;)';
Exit;
end;
//算法开始
EmailKey1 := 0;//初始化
for x := 1 to length(Email) do
begin//取字符的ASCII码
i := ord(Email) + $0F;
i := i xor $20;
EmailKey1 := EmailKey1 + i;
end;
tempStr := int2str(EmailKey1) + Form1.EditName.Text; //结果连接上注册名的字符串
//第一次
//EmailKey2 := 0;//初始化
EmailKey2 := ord(tempStr) + $20756F59; //加法
EmailKey2 := EmailKey2 and $0FF;
EmailKey2 := EmailKey2 + EmailKey1; //加上Email运算结果的16进制数
//第二次开始循环
if length(tempStr) >1 then
begin
for x := 2 to length(tempStr) do
begin//取字符的ASCII码
i := ord(tempStr)+ $20756F59; //加法
i := i and $0FF;
EmailKey2 := EmailKey2 + i;
end;
end;
EmailKey2 := EmailKey2 shl $0A;
EmailKey2 := EmailKey2 + $65766F6C;
tempStr := int2str(EmailKey2);//转换为字符串,为下面的大数运算作准备
Base10StringToFGInt(tempStr, tempFG1);
Base2StringToFGInt('1000111010110110011001001100000',tempFG2); //二进制字符串即为十六进制的Key$475B3260
FGIntAdd(tempFG1, tempFG2, FGIntKey); //大数加法
FGIntToBase10String(FGIntKey,KeyStr1);//第一个字符串
FGIntMul(tempFG1, tempFG2, FGIntKey); //大数乘法
FGIntToBase10String(FGIntKey,KeyStr2);//第二个字符串
EmailKey2 := EmailKey2 + ($80000000 - $475B3260);
EmailKey2 := EmailKey2 and $7FFFFFFF;
KeyStr3 := int2str(EmailKey2); //第三个字符串
KeyStrA := KeyStr1 + KeyStr2 + KeyStr3; //将三个字符串连接起来
KeyStrB := '56832'; //默认的key字符串
Base10StringToFGInt(KeyStrA, tempFG1);
Base10StringToFGInt(KeyStrB, tempFG2);
FGIntMul(tempFG1, tempFG2, FGIntKey); //大数乘法
FGIntToBase10String(FGIntKey,KeyStr); //最终注册码的前部分
FGIntDestroy(tempFG1);//撤销大数变量
FGIntDestroy(tempFG1);//撤销大数变量
FGIntDestroy(FGIntKey); //撤销大数变量
KeyStr := copy(KeyStr, 1, 32);//取前面的32位字符,成为最终注册码的第一部分
tempMAC := Str2Double(Form1.EditID.Text); //将机器码转化为实数
tempMAC := tempMAC * 3.000000;
tempMAC := tempMAC + 521725.0;
tempStr := copy(Double2Str(tempMAC), 1, 8);//取结果的前8位字符
tempMAC := Str2Double(tempStr); //将该结果再次转化为实数
tempMAC := tempMAC * 321.0000;
tempMAC := tempMAC + 9614516412.0000000000;
tempMAC := tempMAC - 96145164.000000000000;
tempStr := Double2str(tempMAC); //最终注册码的第二部分
KeyStr := KeyStr + tempStr + 'PYG2007'; //连接一/二/三部分
Result :=KeyStr; //生成真正的注册码,返回结果
end;
最后,再在计算按钮中添加如下代码,即可:
procedure TForm1.ButtonCountClick(Sender: PObj);
begin
EditCode.Text := keygen_PYG2007(EditEMail.Text);
end;
好的,就到这里结束吧!在我的附件中放有:PYG官方的'CrackMe2007.EXE'原版CrackMe程序以及我写的注册机'注册机(delphi版)
.exe'供参考,分析难免有不当之处,还请给我指出来!
--------------------------------------------------------------------------------
【版权声明】: 本文由 aCaFeeL 原创, 转载请注明作者并保持文章的完整性, 谢谢! 再见!! 学习研究一下算法 向高手致敬!/:good 唉,看了一下,有点晕头转向啊!/:011 有点晕头转向
人太菜 好东西,就该多支持 好东西,是该认真学习下!!!!!!!!!!!! 学习了.谢谢分享精神 学习中,正在破这方面的软件。 分析很详细 看的很吃力啊
页:
[1]
2