【文章标题】: 初学Delphi编写(TraceMe、serial)注册机
【文章作者】: Andy
【软件名称】: TraceMe、serial
【操作平台】: Windows xp
【软件介绍】: OD
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
这两个小程序都是在:加密与解密III 的光盘里的,虽然加密与解密III都说明了算法及serial的注册机制作!
我是初学Delphi7的,所以想根据自己所学的方式来讲一下 (只适合初学者)
咱们这里照样贴着分析算法的一些关键代码吧!
看了qqiu的 (【原创】traceMe 注册机 DELPHI版)
链接地址:http://bbs.pediy.com/showthread.php?t=82672&viewgoodnees=1&prefixid=
他也是Delphi写的注册机 但我看了代码混乱 ,所以我在写一个TraceMe的注册机;
下面是 TraceMe的关键算法:
00401347 |. 8B7C24 18 mov edi,dword ptr ss:[esp+18] //取用户名的长度
0040134B |. B9 03000000 mov ecx,3 //作为计数器,也就是需要循环三次了
00401350 |. 33F6 xor esi,esi //清O,因为后面要用到
00401352 |. 33C0 xor eax,eax //同上
00401354 |. 3BF9 cmp edi,ecx // 长度与计算器进行比较,
00401356 |. 7E 21 jle short TraceMe.00401379 //小于或等于就跳
00401358 |. 53 push ebx //压入堆栈,相当于长度
00401359 |> 83F8 07 /cmp eax,7 //EAX也作为一个计算器
0040135C |. 7E 02 |jle short TraceMe.00401360 //小于或等于就跳
0040135E |. 33C0 |xor eax,eax //清0
00401360 |> 33D2 |xor edx,edx //清0
00401362 |. 33DB |xor ebx,ebx //清0
00401364 |. 8A1429 |mov dl,byte ptr ds:[ecx+ebp] //使用ECX是计算器 + 指针 获取用户名的第三位
00401367 |. 8A98 30504000 |mov bl,byte ptr ds:[eax+405030] //获取一张表 分别是(0C、0A、13、09、0C、0B、0A、08)
0040136D |. 0FAFD3 |imul edx,ebx // 然后进行相乘 结果存放到EDX
00401370 |. 03F2 |add esi,edx // 然后进行叠加
00401372 |. 41 |inc ecx //计算器+1
00401373 |. 40 |inc eax //EAX+1
00401374 |. 3BCF |cmp ecx,edi
00401376 |.^ 7C E1 \jl short TraceMe.00401359
算法分析:
1、首先把ECX赋值为3 循环3次
2、然后取用户名的每位ASCII值 与 定义的一张表 进行相乘;
3、最后累加 相加 !
用Delphi7编写的代码如下
const //定义常量
thmp:array [1..11] of byte=($00, $00, $00, $0C, $0A, $13, $09, $0C, $0B, $0A, $08); //数组
var
i,sum,x:integer; 循环次数和注册码为 ‘整型’
begin
if length(edit1.text)<5 then //用户名的长度必须小于5五位
MessageBox(0, '用户名不能为空或少于五位!', '提示', MB_OK + MB_ICONWARNING); //提示
sum:=0; //初始化
for i:= 4 to length(edit1.text) do //从用户名第4开始循环
begin
sum:=sum + ord(edit1.text[i]) * thmp[i]; //用户名的每位ASCII值与上面定义的‘数组’进行相乘和相加;
end;
edit2.Text:=inttostr(sum); //最后转换类型输出
serial是一个 F1(用户名)=F2(序列号)的一个机制的。所有要想书本那样把F1求逆。因为你是靠‘用户名’来实现注册码的
所以必须把F1(用户名)求逆
下面是他的F1(用户名) 和 F2(序列号)的算法
F1(用户名)算法 关键代码如下
0040137E /$ 8B7424 04 mov esi,dword ptr ss:[esp+4] ; 用户名放到ESI作为指针
00401382 |. 56 push esi ; 压入堆栈
00401383 |> 8A06 /mov al,byte ptr ds:[esi] ; 取ESI的第一个字符
00401385 |. 84C0 |test al,al ; 测试是否还有其他字符
00401387 |. 74 13 |je short serial.0040139C
00401389 |. 3C 41 |cmp al,41 ; 是否大于41 小于就跳转
0040138B |. 72 1F |jb short serial.004013AC
0040138D |. 3C 5A |cmp al,5A ; 是否大于5A 大于则跳
0040138F |. 73 03 |jnb short serial.00401394 ; 如果小于ESI指针指向下一位
00401391 |. 46 |inc esi
00401392 |.^ EB EF |jmp short serial.00401383
00401394 |> E8 39000000 |call serial.004013D2
00401399 |. 46 |inc esi ; 指向下一位
0040139A |.^ EB E7 \jmp short serial.00401383
0040139C |> 5E pop esi ; 弹出ESI
0040139D |. E8 20000000 call serial.004013C2 //累加(也就是用户名的每一位相加)
004013A2 81F7 78560000 xor edi,5678 ; 叠加的结果与5678 异或
004013A8 |. 8BC7 mov eax,edi
F2(序列号)的关键算法代码如下
004013D8 /$ 33C0 xor eax,eax ; 清0
004013DA |. 33FF xor edi,edi
004013DC |. 33DB xor ebx,ebx
004013DE |. 8B7424 04 mov esi,dword ptr ss:[esp+4] ; 假吗存放到ESI指针去
004013E2 |> B0 0A /mov al,0A ; 0A放入AL
004013E4 |. 8A1E |mov bl,byte ptr ds:[esi] ; 取1放到BL
004013E6 |. 84DB |test bl,bl ; 测试是否为空
004013E8 |. 74 0B |je short serial.004013F5
004013EA |. 80EB 30 |sub bl,30 ; BI-30
004013ED |. 0FAFF8 |imul edi,eax ; EDI与0A相乘
004013F0 |. 03FB |add edi,ebx ; 叠加后存放到EDI
004013F2 |. 46 |inc esi
004013F3 |.^ EB ED \jmp short serial.004013E2
004013F5 |> 81F7 34120000 xor edi,1234 ; 在与1234 异或
到了 xor edi,1234 大家可以注意一下、EDI的值 也同样是你的假码
此时的关键就在与 XOR 1234 上面了 要让F1(用户名)和F2(序列号)相加
把用户名的结果十六进制(也像书本所说‘幸好是十六进制’) 所有把 F1(用户名)所计算的结果与 1234 XOR 看下(你会惊喜)!
Delphi注册机的代码如下
var
i,sun:integer; //定义为整型
sn:string; //作为转换大小写的,(因为初学所有不懂写一些判断大小写的代码)
begin
if length(edit1.text)<=11 then //根据上面的注册机了解
MessageBox(Handle, '用户名不能为空,或数字,或大于11位', '提示', MB_ICONHAND);
sun:=0;
sn:=UPPERCASE(edit1.text); //小写转换大写
for i:= 1 to length(sn) do 从1循环到输入用户名的次数
begin
sun:= sun + ord(sn[i]) ASCII叠加
end;
sun:= sun xor 22136 ; //与22136(因为Delphi7所编写的代码都是十进制的,OD里看的是十六进制的)所以必须转换,或者加上符号转换也行!
sun:= sun xor 4660 ; //同上
edit2.Text:=inttostr(sun) //输出
最后注明一下 本文只适合‘初学者’也是我从初学者的一个角度来写的!如果哪里不对,或者可以更简便的代码的可以指正我 谢谢!
--------------------------------------------------------------------------------
2010年02月07日 21:49:36
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
上传的附件: