【文章标题】: 动态生成代码CrackMe(De-KryptZo2)算法分析+批量注册码生成
【文章作者】: 壹只老虎
【作者邮箱】: tiger..tiger@163.com
【软件名称】: De-KryptZo2
【软件大小】: 6.00
【下载地址】: 自己搜索下载
【加壳方式】: 无
【保护方式】: 注册名+序列号+动态代码生成+程序崩溃
【编写语言】: 不知道
【使用工具】: od+peid
【操作平台】: windowsxp sp2
【软件介绍】: http://www.crackmes.de/下载的一个crackme
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
昨天刚分析了 De-KryptZo1 感觉比较有意思,今天找到了第二版来分析看看。
第2版当然比第一版有所加强了哦。不会那么简单了。
老规矩。
先贴一下作者关于本crackme的说明,对分析有些帮助。
===============================================================================
DeKryptZo - 2
Greetz PPL ...
Yea ... finally a part 2 ...
part was easy defeated with luck ...
but here i have decided to screw up ur luck .. he he he
Rules!
no patching ... unless ur totally clueless !
no bruteforcing
find valid serial
and tut plz . . .
Unless you Enter a Valid Serial ... the Decryption will be wrong and the
app will crash !
On entering a Correct Serial ... you will get a goodboy message !
Mail tut to me ...
starzboy / iCU
starzboy@gmail.com
===============================================================================
作者的意思好像是说:不要补丁,不要爆破。
当输入正确注册码时,你将得到一个"goodboy"消息框,
当输入错误时,本程序会错误,并且崩溃。
作者还说和运气有关系,看了我昨天写的De-KryptZo1文章之后,
很明显,运气的命中概率为1/128。应该是相当低了。嘿嘿。
作者还是,第一个太简单了。昨天搞得我还有点郁闷的。哎!
我们今天的目标当然不至于像昨天一样简单,
今天我们不但要找到注册码,还要写出注册机,呵呵,
我保证。
===============================================================================
运行一下,发现和昨天唯一不同的是多了一个key验证。估计要复杂些了。
随便输入了一个name和key,获取hash值,这里会发现,是一个8位的hash值。
哎!麻烦了,如果用昨天的方法,不死人才怪。有点心理恐惧了。看来的另外想办法。
解密,ok,很好,程序崩溃了。是作者故意这么写的。
peid和fi查都没有提示,不确定是否有壳。
od载入,没有加密提示,应该没有壳。
字符串参考,看一下,发现正确提示“Decryption Successfull ... Good Work !”,
一切都很顺利,双击过去,来到这里。
===============================================================================
00401396 /EB 14 jmp short De-Krypt.004013AC
00401398 |6A 00 push 0
0040139A |68 81304000 push De-Krypt.00403081 ; ASCII "[iCU]"
0040139F |68 5A304000 push De-Krypt.0040305A ; ASCII "Decryption Successfull ... Good Work !"
004013A4 |FF75 08 push dword ptr ss:[ebp+8]
004013A7 |E8 68000000 call <jmp.&user32.MessageBoxA>
004013AC \8D23 lea esp,dword ptr ds:[ebx]
004013AE 8BA453 63238B7D mov esp,dword ptr ds:[ebx+edx*2+7D8B2363>
004013B5 53 push ebx
004013B6 6323 arpl word ptr ds:[ebx],sp
004013B8 2298 2B0B8B23 and bl,byte ptr ds:[eax+238B0B2B]
004013BE 2323 and esp,dword ptr ds:[ebx]
===============================================================================
根据昨天的经验,发现下面这段代码是不可能执行到的。他的目的就是提示正确的代码
是怎么个样子的。我第一次也不知道的,昨天分析完了才明白的。如果有兴趣,可以看
一下我昨天的那篇文章。
===============================================================================
00401398 |6A 00 push 0
0040139A |68 81304000 push De-Krypt.00403081 ; ASCII "[iCU]"
0040139F |68 5A304000 push De-Krypt.0040305A ; ASCII "Decryption Successfull ... Good Work !"
004013A4 |FF75 08 push dword ptr ss:[ebp+8]
004013A7 |E8 68000000 call <jmp.&user32.MessageBoxA>
===============================================================================
和昨天不一样的是:
===============================================================================
004013AC \8D23 lea esp,dword ptr ds:[ebx]
004013AE 8BA453 63238B7D mov esp,dword ptr ds:[ebx+edx*2+7D8B2363>
004013B5 53 push ebx
004013B6 6323 arpl word ptr ds:[ebx],sp
004013B8 2298 2B0B8B23 and bl,byte ptr ds:[eax+238B0B2B]
004013BE 2323 and esp,dword ptr ds:[ebx]
===============================================================================
昨天的这段代码开始的时候全部是nop.这段代码开始的时候已经有数据了,估计后面会用到。
废话不说,按照昨天的思路,先把生成算法分析出来。如下,一共4段,一段是注册名计算。
一段是注册码计算,一段是注册码和注册名计算结果综合计算得到hash值,最后一段是生成
代码的算法。
===============================================================================
第一段:注册名计算算法。
===============================================================================
004010C6 E8 43030000 call <jmp.&user32.GetDlgItemTextA> ; 取注册名
004010CB C745 FC 00000000 mov dword ptr ss:[ebp-4],0
004010D2 8945 FC mov dword ptr ss:[ebp-4],eax
004010D5 83F8 03 cmp eax,3 ; 注册名长度是否>3
004010D8 77 17 ja short De-Krypt.004010F1 ; 必须大于3
004010DA 68 0D304000 push De-Krypt.0040300D ; ASCII "wtf . . .more than 4 chars plz . . ."
004010DF 68 ED030000 push 3ED
004010E4 FF75 08 push dword ptr ss:[ebp+8]
004010E7 E8 34030000 call <jmp.&user32.SetDlgItemTextA>
004010EC E9 CF020000 jmp De-Krypt.004013C0
004010F1 8D3D 8C304000 lea edi,dword ptr ds:[40308C] ; edi=注册名地址
004010F7 57 push edi ; 压栈
004010F8 E8 41030000 call <jmp.&kernel32.lstrlenA>
004010FD 33F6 xor esi,esi ; esi=0
004010FF 33DB xor ebx,ebx ; ebx=0
00401101 8BF0 mov esi,eax ; esi=注册名长度
00401103 33C9 xor ecx,ecx ; ecx=0
00401105 33C0 xor eax,eax ; eax=0
00401107 8BD7 mov edx,edi ; edx=注册名
00401109 81C1 65320000 add ecx,3265 ; ecx=3265H
0040110F 41 inc ecx ; ecx=3266H
00401110 43 inc ebx ; ebx=1
00401111 03D1 add edx,ecx ; edx=注册名地址+3266H
00401113 8D0C0A lea ecx,dword ptr ds:[edx+ecx] ; ecx=edx+3266H
00401116 0FBE5C07 01 movsx ebx,byte ptr ds:[edi+eax+1] ; ebx=从第2位开始取注册名
0040111B 03DA add ebx,edx ; ebx=ebx+edx
0040111D 03CB add ecx,ebx ; ecx=ecx+ebx
0040111F 03CB add ecx,ebx ; ecx=ecx+ebx
00401121 0FAFCB imul ecx,ebx ; ecx=ecx*ebx
00401124 03C8 add ecx,eax ; ecx= ecx+eax
00401126 0FAFC8 imul ecx,eax ; ecx=ecx*eax
00401129 43 inc ebx ; ebx=ebx+1
0040112A 81F3 56120400 xor ebx,41256 ; ebx=ebx xor 41256H
00401130 D1E1 shl ecx,1 ; ecx=ecx shl 1
00401132 81F1 6C050000 xor ecx,56C ; ecx=ecx xor 56CH
00401138 81E3 0F000008 and ebx,800000F ; ebx=ebx and 800000F
0040113E 03CB add ecx,ebx ; ecx=ecx+ebx
00401140 40 inc eax ; eax=eax+1
00401141 3BC6 cmp eax,esi
00401143 ^ 72 D1 jb short De-Krypt.00401116 ; eax小于注册名长度就返回
00401145 894D F0 mov dword ptr ss:[ebp-10],ecx
===============================================================================
上面这段代码把注册名计算的结果保存到[ebp-10],我们设为A.
对应的delphi代码为:
===============================================================================
/*****************************************************************************/
function funHashName(name:string):integer;
var
ecx,ebx,edx,eax:integer;
i:integer;
begin
eax:=0;
edx:=$40308C+$3266;
ecx:=edx+$3266;
for i:=2 to length(name)+1 do
begin
ebx:=ord(name[i])+edx;
ecx:=ecx+ebx+ebx;
ecx:=ecx*ebx+eax;
ecx:=ecx*eax;
ebx:=ebx+1;
ebx:=ebx xor $41256;
ecx:=ecx*2;
ecx:=ecx xor $56C;
ebx:=ebx and $800000F;
ecx:=ecx+ebx;
eax:=eax+1;
end;
result:=ecx;
end;
/*****************************************************************************/
===============================================================================
第二段:注册码生成算法。
===============================================================================
004011C4 33F6 xor esi,esi ; esi=0
004011C6 33DB xor ebx,ebx ; ebx=0
004011C8 8BF0 mov esi,eax ; esi=试验码长度
004011CA 33C9 xor ecx,ecx ; ecx=0
004011CC 33C0 xor eax,eax ; eax=0
004011CE 8BD7 mov edx,edi ; edx=[0040308C]试验码地址
004011D0 81C1 85FF0000 add ecx,0FF85 ; ecx=0FF85H
004011D6 41 inc ecx ; ecx=FF86H
004011D7 43 inc ebx ; ebx=1
004011D8 03D1 add edx,ecx ; edx=edx+FF86H
004011DA 8D0C0A lea ecx,dword ptr ds:[edx+ecx] ; ecx=edx+FF86H
004011DD 0FBE5C07 05 movsx ebx,byte ptr ds:[edi+eax+5] ; ebx=从第6位开始取key(多取一个结束符号)
004011E2 03DA add ebx,edx ; ebx=ebx+edx
004011E4 03CB add ecx,ebx ; 下面不写了,没意思.大家都懂
004011E6 03CB add ecx,ebx
004011E8 0FAFCB imul ecx,ebx
004011EB 2BC8 sub ecx,eax
004011ED 0FAFC8 imul ecx,eax
004011F0 43 inc ebx
004011F1 43 inc ebx
004011F2 81F3 56120400 xor ebx,41256
004011F8 D1E1 shl ecx,1
004011FA 81C9 6C050000 or ecx,56C
00401200 81E3 0F000008 and ebx,800000F
00401206 03CB add ecx,ebx
00401208 40 inc eax
00401209 3BC6 cmp eax,esi
0040120B ^ 72 D0 jb short De-Krypt.004011DD
0040120D 894D EC mov dword ptr ss:[ebp-14],ecx ; key运算结果保存在[ebp-14H]
===============================================================================
上面这段代码把注册名计算的结果保存到[ebp-14],我们设为B.
对应的delphi代码为:
===============================================================================
/*****************************************************************************/
function funHashKey(key:string):integer;
var
i,eax,edx,ebx,ecx:integer;
str:string;
begin
eax:=0;
edx:=$40308C+$FF86;
ecx:=$40308C+$FF86*2;
str:=key+'xxxxxxxx';
for i:=length(key)+1 to length(key)+5 do
str[i]:=#0;
for i:=6 to length(key)+5 do
begin
ebx:=ord(str[i])+edx;
ecx:=ecx+ebx+ebx;
ecx:=ecx*ebx;
ecx:=ecx-eax;
ecx:=ecx*eax;
ebx:=ebx+2;
ebx:=ebx xor $41256;
ecx:=ecx *2;
ecx:=ecx or $56C;
ebx:=ebx and $800000F;
ecx:=ecx+ebx;
inc(eax);
end;
result:=ecx ;
end;
/*****************************************************************************/
===============================================================================
第3段:注册码和注册名计算结果综合计算得到hash值
===============================================================================
0040120D 894D EC mov dword ptr ss:[ebp-14],ecx ; key运算结果保存在[ebp-14H]
00401210 8B55 F0 mov edx,dword ptr ss:[ebp-10] ; edx=注册名的运算结果
00401213 8B4D EC mov ecx,dword ptr ss:[ebp-14] ; ecx=key的运算结果
00401216 8955 E8 mov dword ptr ss:[ebp-18],edx
00401219 014D E8 add dword ptr ss:[ebp-18],ecx ; [ebp-18]=注册名和key运算结果相加
0040121C 0FAFCA imul ecx,edx ; ecx=注册名和key运算结果相乘
0040121F 81F2 655F0200 xor edx,25F65 ; edx=注册名运算结果 xor 25F65H
00401225 0155 E8 add dword ptr ss:[ebp-18],edx ; [ebp-18]=[ebp-18]+edx
00401228 014D E8 add dword ptr ss:[ebp-18],ecx ; [ebp-18]=[ebp-18]+ecx
0040122B FF75 E8 push dword ptr ss:[ebp-18] ; 结果压栈
0040122E 68 57304000 push De-Krypt.00403057 ; ASCII "%x"
00401233 68 8C344000 push De-Krypt.0040348C ; ASCII "7d119559"
00401238 E8 B3010000 call <jmp.&user32.wsprintfA> ; 格式化结果为16进制的字符串
0040123D 83C4 0C add esp,0C ; 保存在0040348C(结果就是HASH值)
00401240 68 8C344000 push De-Krypt.0040348C ; ASCII "7d119559"
00401245 68 ED030000 push 3ED
0040124A FF75 08 push dword ptr ss:[ebp+8]
0040124D E8 CE010000 call <jmp.&user32.SetDlgItemTextA> ; 设置第3个文本框数据为HASH值
===============================================================================
这一段代码就是HASH值得生成代码了,hash值生成后放在第3个文本框里面,
后面再从这个文本框里面取数据。
对应的delphi代码如下:
===============================================================================
/*****************************************************************************/
function funHash(hashname,hashkey:integer):string;
var
ecx,edx,temp,i:integer;
str:string;
p:Pchar;
begin
temp:=hashname+hashkey;
ecx:=hashname*hashkey;
edx:=hashname xor $25F65;
temp:=temp+ecx+edx;
str:=inttohex(temp,8);
p:=@str[1];
while p^='0'do
inc(p);
str:=string(p);
for i:=1 to length(str) do
if (ord(str[i])>64)and (ord(str[i])<91) then
str[i]:=chr(ord(str[i])+32);
result:=str;
end;
/*****************************************************************************/
===============================================================================
第4段分为两个部分,我们称之为A部分和B部分。
===============================================================================
A部分
===============================================================================
00401319 E8 F0000000 call <jmp.&user32.GetDlgItemTextA> ; 取得hash值
0040131E 8945 E4 mov dword ptr ss:[ebp-1C],eax ; 计数器=hash码长度
00401321 BE 8C324000 mov esi,De-Krypt.0040328C ; esi=[0040328C]=hash值地址
00401326 33DB xor ebx,ebx ; ebx=0
00401328 8BD8 mov ebx,eax ; ebx=eax=hash值长度
0040132A 8A06 mov al,byte ptr ds:[esi] ; al=按位取hash码
0040132C 04 32 add al,32 ; 下面不写了,很明白
0040132E FEC0 inc al
00401330 34 56 xor al,56
00401332 04 71 add al,71
00401334 2C 65 sub al,65
00401336 04 95 add al,95
00401338 04 9C add al,9C
0040133A C0E3 05 shl bl,5
0040133D 02C3 add al,bl
0040133F 0045 F7 add byte ptr ss:[ebp-9],al ; [ebp-9]=[ebp-9]+al([ebp-9]初始值为0)
00401342 8045 F7 91 add byte ptr ss:[ebp-9],91
00401346 46 inc esi
00401347 FF4D E4 dec dword ptr ss:[ebp-1C]
0040134A 837D E4 00 cmp dword ptr ss:[ebp-1C],0
0040134E ^ 77 DA ja short De-Krypt.0040132A ; 计数器>0就继续循环
===============================================================================
设[ebp-9]为X,A部分的作用就是根据hash码,生成一个byte类型的X,呵呵,是不是和第一个
差不多了,第一个的hash值就是一个byte大小的.从这点上看,的确是差不多了.
===============================================================================
B部分
===============================================================================
00401350 33F6 xor esi,esi ; 设上面这个循环后[ebp-9]=A
00401352 33FF xor edi,edi
00401354 BE AC134000 mov esi,De-Krypt.004013AC ; esi=004013AC
00401359 BF AC134000 mov edi,De-Krypt.004013AC ; edi=004013AC
0040135E 33C9 xor ecx,ecx ; ecx=0
00401360 33C0 xor eax,eax ; eax=0
00401362 8A06 mov al,byte ptr ds:[esi] ; al=按位取esi,esi是一个固定的表
;(也就是写入代码的那一段的初始数据)
00401364 8A4D F7 mov cl,byte ptr ss:[ebp-9] ; cl=A
00401367 2C 71 sub al,71
00401369 FEC0 inc al
0040136B 04 51 add al,51
0040136D 04 34 add al,34
0040136F 04 46 add al,46
00401371 02C1 add al,cl
00401373 0245 F7 add al,byte ptr ss:[ebp-9] ; al=al+A
00401376 04 09 add al,9
00401378 04 53 add al,53
0040137A 04 54 add al,54
0040137C 04 20 add al,20
0040137E 2C 97 sub al,97
00401380 2C 71 sub al,71
00401382 8807 mov byte ptr ds:[edi],al ; 关键(生成代码)
00401384 46 inc esi ; esi表偏移+1
00401385 47 inc edi ; 代码写入地址+1
00401386 FF4D FC dec dword ptr ss:[ebp-4]
00401389 837D FC 00 cmp dword ptr ss:[ebp-4],0
0040138D ^ 77 CF ja short De-Krypt.0040135E ; 循环20次
0040138F C605 BC134000 54 mov byte ptr ds:[4013BC],54
00401396 EB 14 jmp short De-Krypt.004013AC
===============================================================================
B部分的功能是根据A部分得到的X,来动态生成正确提示的代码.
这里我不得不讲一个小插曲.我开始的时候是用PYG-OD调试的,
后来到达这一句的时候发生了奇迹:
00401362 8A06 mov al,byte ptr ds:[esi]
什么奇迹呢, 过 00401362 之前,byte ptr ds:[esi]的数据为8D,
过 00401362 之后,al数据为CC,把我吓了一跳,郁闷了一段时间,
后来 在abest 兄弟的帮助下,我知道为什么了,原来是PYG-OD的BUG,
我马上换了OllyIce来调试,没有问题.就继续我们的分析.
第4部分对应的delphi代码如下:
===============================================================================
/*****************************************************************************/
function funCreateCode(hash:string):string;
const
table:array[1..20]of byte =($8D, $23, $8B, $A4, $53,
$63, $23, $8B, $7D, $53,
$63, $23, $22, $98, $2B,
$0B, $8B, $23, $23, $23);
{这段代码就被写入地址处的初始数据}
var
bkey,al,bl:byte;
i:integer;
str:string;
begin
bkey:=0;
bl:=length(hash);
for i:=1 to length(hash) do
begin
al:=ord(hash[i]);
al:=al+$33;
al:=al xor $56;
al:=al+$71-$65+$95+$9c;
bl:=bl*32;
al:=al+bl;
bkey:=bkey+al+$91;
end;
str:='xxxxxxxxxxxxxxxxxxxx';
for i:=1 to 20 do
begin
al:=table[i]-$70+$51+$34+$46+bkey+bkey+$9+$53+$54+$20-$97-$71;
str[i]:=chr(al);
end;
str[17]:=chr($54);
result:=str;
end;
/*****************************************************************************/
===============================================================================
上面分析完了,现在来总结一下.
1:从总体上看,关键决定生成代码的是根据hash生成的那个byte类型的数据,这里有256种可能,
2:根据昨天的crackme的经验,我们知道,我们需要生成的代码为,
===============================================================================
004013AC > \6A 00 push 0
004013AE . 68 81304000 push 00403081 ; ASCII "[iCU]"
004013B3 ? 68 5A304000 push 0040305A ; ASCII "Decryption Successfull ... Good Work !"
004013B8 . FF75 08 push dword ptr [ebp+8]
004013BB ? E8 54000000 call <jmp.&user32.MessageBoxA>
===============================================================================
3:由于利用注册名和注册码生成hash值,在根据hash值生成成功提示代码的过程类似于
有损压缩,是不可逆的.所以,我们这里只能采用一种办法来进行破解,那就是"暴力破解",
注意,这里的"暴力破解"不是说修改代码,而是用程序来实现枚举.
4:分析讨论一下,我们的"暴力破解"程序的效率怎么样,很好推理,由于成功提示代码的关键在于
哪一个byte类型的数据,只有256中可能,也就是说,碰撞率是相当高的,所以我们的暴力破解程序
的效率应该会很高的,如果说可能性为1000000000种,那么还是不要考虑暴力破解为妙,
那真的是很需要运气的了.
5:既然程序的暴力破解可行,那么我们就来设计一下这个程序吧,首先,为了方便,我们将
name和key都设置为整型,这样方便计算.是用双循环实现,每次name和key加1,用其计算
hash值,然后生成代码保存,我们把正确的代码与之比较,匹配的话,就保存这对数据.
下面是我在delphi7.0下设计的代码,写的很乱,见笑乐,速度还是很不错的,一会儿就几千个了,
毕竟碰撞率太高了.呵呵.
===============================================================================
/*****************************************************************************/
procedure TForm1.Button1Click(Sender: TObject);
const
bRealCode:array[1..20] of byte =($6A, $00, $68, $81, $30,
$40, $00, $68, $5A, $30,
$40, $00, $FF, $75, $08,
$E8, $68, $00, $00, $00);
var
code,hash,sRealCode:string;
i,j,hashkey,hashname,startname,endname,startkey,endkey,count,numkey:integer;
res:tstringlist;
begin
sRealCode:='xxxxxxx';
for i:=1 to 7 do
sRealCode[i]:=chr(bRealCode[i]);
label10.Caption:='已经找到了 0 组密码';
try
startname:=strtoint(edit5.Text);
endname:=strtoint(edit6.Text);
startkey:=strtoint(edit7.Text);
endkey:=strtoint(edit8.Text);
numkey:=strtoint(edit9.Text);
except
Application.MessageBox('非法输入','错误',MB_ICONINFORMATION+MB_OK);
exit;
end;
if (startname<1000)or (endname<1000)or (startkey<1000)or (endkey<1000) then
begin
Application.MessageBox('起始和结束值至少4位','错误',MB_ICONINFORMATION+MB_OK);
exit;
end;
if (endname-startname>1000000) or (endkey-startkey>1000000) then
begin
Application.MessageBox('这么多,你想累死我啊!','错误',MB_ICONINFORMATION+MB_OK);
exit;
end;
if (endname<=startname) or (endkey<=startkey) then
begin
Application.MessageBox('结束值必须大于开始值','错误',MB_ICONINFORMATION+MB_OK);
exit;
end;
if (numkey<1)then
begin
Application.MessageBox('你至少得找出一个密码吧','提示',MB_ICONINFORMATION+MB_OK);
exit;
end;
if (numkey>100000)then
begin
Application.MessageBox('密码太多太多了吧!','提示',MB_ICONINFORMATION+MB_OK);
exit;
end;
edit5.Enabled:=false;
edit6.Enabled:=false;
edit7.Enabled:=false;
edit8.Enabled:=false;
edit9.Enabled:=false;
res:=tstringlist.Create;
res.Add('Name Key');
count:=0;
i:=startname;
proexit:=0;
while i<=endname do
begin
j:=startkey;
while j<=endkey do
begin
hashname:=funHashName(inttostr(i));
hashkey:=funHashKey(inttostr(j));
hash:=funHash(hashname,hashkey);
code:=funCreateCode(hash);
if pos(sRealCode,code)<>0 then
begin
inc(count);
res.Add(inttostr(i)+' '+inttostr(j));
label10.Caption:='已经找到了 '+inttostr(count)+' 组密码';
application.ProcessMessages;
if proexit=1 then
begin
Application.MessageBox('是你叫我不干了的哈!','提示',MB_ICONINFORMATION+MB_OK);
proexit:=0;
edit5.Enabled:=true;
edit6.Enabled:=true;
edit7.Enabled:=true;
edit8.Enabled:=true;
edit9.Enabled:=true;
res.SaveToFile('破解结果.txt');
Application.MessageBox('结果已经保存到 破解结果.txt 中!','提示',MB_ICONINFORMATION+MB_OK);
exit;
end;
if count>=numkey then
begin
Application.MessageBox(pchar('完成了,找到 '+inttostr(count)+' 组密码'),'提示',MB_ICONINFORMATION+MB_OK);
edit5.Enabled:=true;
edit6.Enabled:=true;
edit7.Enabled:=true;
edit8.Enabled:=true;
edit9.Enabled:=true;
res.SaveToFile('破解结果.txt');
Application.MessageBox('结果已经保存到 破解结果.txt 中!','提示',MB_ICONINFORMATION+MB_OK);
exit;
end;
end;
inc(j);
end;
inc(i);
end;
edit5.Enabled:=true;
edit6.Enabled:=true;
edit7.Enabled:=true;
edit8.Enabled:=true;
edit9.Enabled:=true;
proexit:=0;
res.SaveToFile('破解结果.txt');
Application.MessageBox(pchar('哎!还没达标啊,只找到 '+inttostr(count)+' 组密码'),'提示',MB_ICONINFORMATION+MB_OK);
Application.MessageBox('结果已经保存到 破解结果.txt 中!','提示',MB_ICONINFORMATION+MB_OK);
end;
/*****************************************************************************/
===============================================================================
这是主要的处理事件,其中调用的函数前面已经写过.
好了,就到这里吧,搞了一天了.
===============================================================================
--------------------------------------------------------------------------------
【经验总结】
这是我第一次真正的全自动"暴力破解",留下一个纪念,增加一点经验.
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年04月13日 21:22:09
[注意]APP应用上架合规检测服务,协助应用顺利上架!
上传的附件: