原著:raZZia
翻译:TAE![CCG]
呵呵,今日闲来无事,碰巧最近对写注册机感兴趣所以翻译了一篇写注册机的教
程,较简单,不知有没有大侠翻过。有疏漏错误的地方还请各位更正!
工具!
你需要一个像softice那样的Windows下的调试软件,和一个Dos库C编译器
内容!
在这篇教程中我将告诉你如何做一个注册机,软件用的保护方式是很众所周知的
输入姓名和注册码的方式,在选择注册后,一个窗口弹了出来,那就是你要输入
名字和注册码的地方,这儿的对策就是在内存中找出输入的数据,在你继续之前
你必须确定你已经根据PWD的教程一设置了softice.dat文件
软件 1: Scanline Swiftsearch 2.0!
Swiftsearch 是一个很有用的小工具,你可以用它来在网络中搜索,我将一步步
的告诉你如何破解它!
步骤 1: 运行程序 :)
步骤 2: 选择菜单重的“注册”,你将发现一个可以输入姓名和注册码的窗口。
步骤 3: 进入softice (ctrl-d)
步骤 4: 我现在将设置一个像GetWindowText(a)和GetDlgItemText(a)这样的断点
来找到内存中我们刚刚输入的数据。能够被用于这个程序的函数仅仅是GetDlgItemTexta
(对与错还是你自己试试吧 :)所以,在SoftIce中输入 BPX GetDlgItemTexta
然后用 g 命令退出SoftIce。
步骤 5: 现在输入名字和注册码(我使用的是 razzia 和 12345)并且按 OK,这将带
你回到SoftIce,现在你已经在GetDlgItemTexta函数中了,按 F11离开函数。你应
该看到下面的代码:
lea eax, [ebp-2C] ;<--- 我们在找这个位置(?不理解)
push eax
push 00000404
push [ebp+08]
call [USER32!GetDlgItemTextA]
mov edi, eax ;<---
eax 已经指向字符串长度了,并且一会儿
就会被存储到 edi 中了。
我们看见 EAX 读入了一个内存地址并且作为函数GetDlgItemTextA的一个参数被
压进了堆栈中,而后函数GetDlgItemTextA准备开始执行了,我们来查看 EBP-2c
(用 ED EDP-2c)并且可以看见那儿有我们输入的名字,现在我们知道我们的名字
被存放在内存中的什么地方了,通常应该把这个地址记下来,但我们即将看到,
那是不必的。
那么,下一步做什么? 现在我们必须跟着程序来读取我们输入的注册码。输入 g 我
们再次返回softice的时候按F11,你将看到下面的代码:
push 0000000B
lea ecx, [ebp-18] ;<--所以, ebp-18
是存放输入的注册码的地方
push ecx
push 0000042A
push [ebp+08]
call [USER32!GetDlgItemTextA]
mov ebx, eax ;<--将字符长度保存在
EBX 中
test edi, edi ;<--还记得
EDI 是放我们输入名字长度的地方吗?
jne 00402FBF
我们看见我们输入得注册码被存放在 EBP-18 中了 ,不相信得话可以用ED EBP-18
查看一下。 通常这个地址也应该记下来,并且我们看见它检查我们的名字长度是
否是0,如果不是的话,程序将继续。
步骤 6: 那好,现在我们知道我们输入的数据被存放在哪里了。那么,下一步呢?
现在我们已经知道怎样做了,通常我们应该在内存中设置断点以便于知道程序哪些
地方读取了这里。但在这个步软件里仅仅需要按住F10,直到呢看见了以下代码:
cmp ebx, 0000000A ;<--记得 EBX 是放输入注册码长度的地方吗?
je 00402FDE
这两行很重要!它们检查了输入注册码的长度是否等于10。如果不是,那么程序就
已经认为注册码是错误的了。修改 EBX 或者在寄存器数据窗口修改标志位寄存器(FLAG)
以便让程序跳转.继续按F10知道呢到达下面的代码处。
(记住,这可能和你的地址不一样!)
:00402FDE xor esi, esi ;<-- 清空 ESI
:00402FE0 xor eax, eax ;<-- 清空 EAX
:00402FE2 test edi, edi
:00402FE4 jle 00402FF2
:00402FE6 movsx byte ptr ecx, [ebp + eax - 2C] ;<-- ECX 载入我们输入名字的一个字母.
:00402FEB add esi, ecx ;<-- 将字母加到
ESI
:00402FED inc eax ;<--
EAX 加1以便得到下一个字母
:00402FEE cmp eax, edi ;<-- 取完了吗?
:00402FF0 jl 00402FE6 ;<-- 如果没有,就去取下一个字母。
好的,我们看见程序将我们输入名字的所有字母加起来,那么 ESI 就是总和了,让
我们继续并且找出程序用那个值做什么!
:00402FF2 push 0000000A
:00402FF4 lea eax, [ebp-18] ;<-- 将输入注册码的地址放入 EAX
:00402FF7 push 00000000
:00402FF9 push eax ;<--
压入 EAX (作为下面一个Call的参数)
:00402FFA call 00403870 ;<-- 好的,你认为这个Call是干什么的呢?:)
:00402FFF add esp, 0000000C
:00403002 cmp eax, esi ;<-- 嘿!
:00403004 je 00403020
我们进入CALL,它最终反回 ESI,并和 EAX 比较.嗯,让我们看看 EAX 是什么。‘? EAX’显示
00003039 0000012345 "09"
好极了!那是我们输入的注册码! 那么ESI呢?我们知道,ESI中是我们输入名字
的所有字母总和!!
步骤 7: 现在我们知道程序是如何计算注册码的了,我们可以做注册机了!
但别忘了程序检查了注册码是不是10位!
一个简单的C程序将计算出这个软件的注册码:
#include <stdio.h>
#include <string.h>
main() {
char Name[100];
int NameLength,Offset;
long int Reg = 0, Dummy2 = 10;
int Dummy = 0;
int LengtDummy = 1;
int Lengt , Teller;
printf("Scanline SwiftSearch 2.0 crack by raZZia.\n");
printf("Enter your name: ");
gets(Name);
NameLength=strlen(Name);
/* 计算输入的名字字符的总和*/
/* 并保存到Reg中 */
for (Offset=0;Offset<NameLength;Offset=Offset+1)
{
Reg=Reg+Name[Offset];
}
/* the while lus calculates the lenght of the figure in */
/* Reg and places it in Lengt
*/
while (Dummy != 1) {
if ( Reg < Dummy2 ) {
Lengt = LengtDummy ; Dummy
=1;
}
else {
LengtDummy=LengtDummy
+ 1; Dummy2=Dummy2*10;
}
};
printf("\nYour registration number is : " );
/* 收先打印(10-Lengt)次0 */
Lengt=10-Lengt;
for (Teller=1;Teller<=Lengt;Teller=Teller+1)
printf("0");
/* 打印注册码
*/
printf("%lu\n",Reg);
}
- 标 题:翻译一篇写注册机的教程!大侠就不要看了 (5千字)
- 作 者:TAE!
- 时 间:2001-7-18 22:01:09
- 链 接:http://bbs.pediy.com