procedure TForm1.Button2Click(Sender: TObject); 这里是清空按钮的代码
begin
edit1.Text:='';
edit2.Text:='';
end;
procedure TForm1.FormCreate(Sender: TObject); 这个位置的作用后面再详细介绍
begin
var
isDebuggerPresent: function:Boolean;
DllModule: THandle;
begin
DllModule := LoadLibrary('kernel32.dll');
isDebuggerPresent := GetProcAddress(DllModule, 'IsDebuggerPresent');
if isDebuggerPresent then
asm
mov eax,eax
mov eax,eax
mov eax,eax
mov eax,eax
mov eax,eax
end;
end;
这个就是注册按钮功能的地方,也是最关键的地方
procedure TForm1.button1Click(Sender: TObject);
begin
var
i,j,n,b,m,a,c,d,k,o,rt,v,l,s,p,q,r,t,t1,t2,t3:integer;
name,sn,wr,at,at1,at2,at3,at4,at5,inp,su,ln,ps1,ps2:string;
tt:TMsgDlgType;
label
cz,cz0;
begin
name:=edit1.text;
inp:=edit2.Text;
at:='abcdefghijklmnopqrstuvwxyz ';
tt:=mtError;
n:=0;
m:=0;
o:=0;
if length(inp)<5 then exit;
if length(name)<6 then goto cz;
m:=m+1;
if length(name)>10 then goto cz;
b:=ord(name[4]) ;上面都是初始化
下面部分开始算主要注册码部分了
for i:=1 to length(name) do
begin
for j:=1 to length(name) do b:=b+ord(name[length(name)-i])*ord(name[j]) shr 6;
n:=n+b;
sn:=sn+inttostr(n);
end;下面就是用来判断的了,也是本次crackme重点关注的地方,引入了用除0异常来判断的编程思想
begin
q:=0;
p:=0;
for l:=1 to 3 do
begin
if l<2 then
begin
for s:=1 to 5 do
begin
p:=p+ord(sn[s]);
q:=q+ord(inp[s]);
end;
end
else
begin
if l=2 then
begin
for r:=6 to 12 do
begin
p:=p+ord(sn[r])+1;
q:=q+ord(inp[r]);
end;
q:=q+7;
end
else
begin
for t:=16 to length(sn) do
begin
p:=p+ord(sn[t]);
q:=q+ord(inp[t]);
end;
end;
end;
begin
try
o:=m div (p xor q);
o:=o+1;
except
on EDivByZero do
m:=m+1;
end;
end;
end;
end;
goto cz0;
asm
mov eax,eax
nop
end;
exit;
下面是字符串简单解码,是可以复杂的,但这毕竟是试验型crackme,点到为止
cz0:
begin
t1:=ord(inp[13])-31;
t2:=ord(inp[15])-36;
t3:=ord(inp[14])-49;
ps1:=at[t1]+at[5]+at[7]+at[9]+at[19]+at[t2];
ps2:=at[t3]+at[t1]+at[5]+at[m];
m:=m+7;
end;
cz:
begin
at1:=at[4]+at[5]+at[7]+at[8]+at[9];
at2:=at[15]+at[18]+at[19]+at[20]+at[14]+at[12];
at3:=at[19]+at[14]+' ';
at4:=at1[5]+at2[3]+' ';
at5:=at[23]+at[18]+at[15]+at[14]+at[7];
ln:=at2[6]+at2[1]+at2[5]+at1[3];最后的确认,是否输出正确结果
if m<1 then wr:=at2[3]+at1[4]+at2[1]+at2[2]+at[20] else
begin
if length(name)>10 then wr:=ln else
begin
if m>10 then
begin
wr:=ps1+ps2+at[27]+at[20]+at[15]+at[27]+name;
tt:=mtInformation;
end else
wr:=at5;
end;
end;
if o>20 then wr:=ps1+ps2;
messageDlg(at3+at4+wr,tt,[mbOK],0) ;
exit;
end;
end;
end.
q:=0;
p:=0;
for l:=1 to 3 do 设置循环3次,因为里面加入了三次的比较,公用一个异常比较
begin
if l<2 then 第一次比较
begin
for s:=1 to 5 do 长度为1-5
begin
p:=p+ord(sn[s]);
q:=q+ord(inp[s]);
end;
end
else
begin
if l=2 then 第二次比较部分,6-12
begin
for r:=6 to 12 do
begin
p:=p+ord(sn[r])+1;
q:=q+ord(inp[r]);
end;
q:=q+7;
end
else
begin
for t:=16 to length(sn) do 最后的比较部分,16-
begin
p:=p+ord(sn[t]);
q:=q+ord(inp[t]);
end;
end;
end;
begin
try 用到了try --except的除0异常来作判断,而本次中仅仅都是P=Q式,并且主体算法在外围,所以固此crackme强
度不大
o:=m div (p xor q);
o:=o+1; 这特殊计数器,用来记录特针,刚开始编程时也是为了测试try的执行情况
except
on EDivByZero do 指定0异常处理
m:=m+1; 参与解码,在本次crackme中意义不大,还是因为主体算法被放在外围
end;
end;
end;
end;
……
if o>20 then wr:=ps1+ps2; 为什么要用这段呢,我也不知道,反正除0的那段必须是后面要调用的,不然,他不产生
if m<1 then wr:=at2[3]+at1[4]+at2[1]+at2[2]+at[20] else M是个特征,在m小于1时,直接给出了错误的提示short
begin
if length(name)>10 then wr:=ln else 判断用户名长度
begin
if m>10 then
begin
wr:=ps1+ps2+at[27]+at[20]+at[15]+at[27]+name;
tt:=mtInformation; 这一段就是改变提示框的TMsgDlgType,
end else
wr:=at5;
end;
end;
if o>20 then wr:=ps1+ps2; 花指令,留给delphi的,此时是无意义的