【文章标题】: 用php来编写注册机————第二节
【文章作者】: dahaij
【作者主页】: http://dahaij.spaces.live.com/
【作者QQ号】: 暂时不想说
【软件名称】: 加密与破解2光盘习题
【使用工具】: OD
【软件介绍】: 一个作业,大家一起分析。
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教! 更希望有共同兴趣者一起来讨论讨论。
--------------------------------------------------------------------------------
【详细过程】
昨天发的一贴,只是一个引子,今天我们要开始来实现我们第一个php语言注册机了,其实很多方法可以用在其它语言。
希望大家一通百通。
今天我拿出来的是加密与破解2光盘的第二题,书上是给出的爆破的办法,由于在调式的时候会生成完整的注册码,所以它也可以写出内存注册机。
这里我就不讲内存注册机了,因为大家都会。用keymake写算法注册机,我不会,请高人路过时能指点点我。
下面是我的分析过程。
具体调试过程,我用视频教程给出,这里我只谈关健的算法分析部分。
调试时我输入的是我的用户名
进入关键函数后,我们将看到。
004416F8 53 push ebx
004416F9 56 push esi
004416FA 57 push edi
004416FB 83C4 DC add esp,-24
004416FE 891424 mov dword ptr ss:[esp],edx 将前面取得用户名数输入堆,这里是6
00441701 8BF8 mov edi,eax 将dahaij输入给edi
00441703 BB 05033949 mov ebx,49390305 将常数49390305输入给ebx
00441708 BE 20126348 mov esi,48631220 将常数48631220输入给esi
0044170D 8BC7 mov eax,edi
0044170F E8 2023FCFF call echap303.00403A34 判断是否输入了用户名
00441714 85C0 test eax,eax
00441716 7E 2E jle short echap303.00441746
00441718 BA 01000000 mov edx,1 给edx 为1 ------------------------------------------------(1)
0044171D 33C9 xor ecx,ecx
0044171F 8A4C17 FF mov cl,byte ptr ds:[edi+edx-1] 取出d给cl
00441723 33D9 xor ebx,ecx d xor 49390305=49390361
00441725 33F3 xor esi,ebx 49390361 xor 48631220=015A1141
00441727 F6C3 01 test bl,1 判断最后一个位是否为1
0044172A 74 0F je short echap303.0044173B 是则跳,不是就继续
0044172C D1FB sar ebx,1 49390361算术右移为249C81B0
0044172E 79 03 jns short echap303.00441733 判断符号位是否为0
00441730 83D3 00 adc ebx,0 不为0就清0 (php中这项如何搞定,我不知道,请高人指点,我没有写段,不过不影响,因为产生这个的字付太少了。我只发出了一个“|”这个,我想用不上。
00441733 81F3 11032001 xor ebx,1200311 249C81B0 xor 1200311=25BC82A1
00441739 EB 07 jmp short echap303.00441742
0044173B D1FB sar ebx,1
0044173D 79 03 jns short echap303.00441742
0044173F 83D3 00 adc ebx,0
00441742 42 inc edx 给edx加1 目的是取一下字母 (2)
00441743 48 dec eax 给eax减1 实现 (3)
00441744 ^ 75 D7 jnz short echap303.0044171D
00441746 8B0424 mov eax,dword ptr ss:[esp]
00441749 50 push eax
0044174A 8BC3 mov eax,ebx
0044174C 25 FFFF0000 and eax,0FFFF
00441751 894424 08 mov dword ptr ss:[esp+8],eax
00441755 C64424 0C 00 mov byte ptr ss:[esp+C],0
0044175A C1EB 10 shr ebx,10
0044175D 895C24 10 mov dword ptr ss:[esp+10],ebx
00441761 C64424 14 00 mov byte ptr ss:[esp+14],0
00441766 8BC6 mov eax,esi
00441768 25 FFFF0000 and eax,0FFFF
0044176D 894424 18 mov dword ptr ss:[esp+18],eax
00441771 C64424 1C 00 mov byte ptr ss:[esp+1C],0
00441776 C1EE 10 shr esi,10
00441779 897424 20 mov dword ptr ss:[esp+20],esi
0044177D C64424 24 00 mov byte ptr ss:[esp+24],0
00441782 8D5424 08 lea edx,dword ptr ss:[esp+8]
00441786 B9 03000000 mov ecx,3
0044178B B8 A4174400 mov eax,echap303.004417A4 ; %.4x-%.4x-%.4x-%.4x
00441790 E8 6F68FCFF call echap303.00408004
00441795 83C4 24 add esp,24
00441798 5F pop edi
00441799 5E pop esi
0044179A 5B pop ebx
0044179B C3 retn
(1)(2)(3)共同构成一个循环结构。
根据上面的分析,我就可以分析出如下算法。
$x是输入的字符串
for ($i = 0; $i <strlen($x); $i++) {
取出的字符与ebx中49390305异或,生成的数存在ebx中
将生成的数与esi中48631220异或,生成的数存在esi中
判断ebx中数最后一位是否为0,为0则右移一位,并将生成的数与1200311异或,否则只右移一位。
}
下面我们来写php的代码。
function Button1Click($sender, $params)-------------------------------按钮事件
{
$ebx=hexdec(49390305); php中的运算都是在10进制下进行的。所以先来个转换。变量$ebx这样写是为了方便在分析算法的同时写出代码
$esi=hexdec(48631220); 转换esi中的值
$a=hexdec(1200311); 转换常数1200311
$x=$this->Edit1->Text; 取字符串
for ($i = 0; $i <strlen($x); $i++) { 写出循环
$ebx= ord(substr($x,$i,1)) ^ $ebx ; 将字符转成10进制后进行运算
// echo dechex($ebx).","; 此步是我为了测试生成的数与我调试过程的生成数是否一样。所以被注释了。
$esi=$esi^$ebx;
// echo dechex($esi).",";
if($ebx & 1) 判断最后一位是否为0就是让它与1并就行了。
{$ebx=$ebx >> 1; 移位
$ebx=$ebx^$a; 异或
// echo dechex($ebx).",";
}
else{
$ebx=$ebx >> 1;
// echo dechex($ebx).",";
}
}
$key =substr(dechex($ebx),-4)."-".str_pad(substr(dechex($ebx),0,strlen(dechex($ebx))-4), 4, "0", STR_PAD_LEFT)."-".substr(dechex($esi),-4)."-".str_pad(substr(dechex($esi),0,strlen(dechex($esi))-4), 4, "0", STR_PAD_LEFT) ;
$this->Edit2->Text=strtoupper ($key) ; 输出
}
大家看算法不复杂,下面把几个函数提出来讲一下。
php的位运算
$a & $b And(按位与) 将把 $a 和 $b 中都为 1 的位设为 1。
$a | $b Or(按位或) 将把 $a 或者 $b 中为 1 的位设为 1。
$a ^ $b Xor(按位异或) 将把 $a 和 $b 中不同的位设为 1。
~ $a Not(按位非) 将 $a 中为 0 的位设为 1,反之亦然。
$a << $b Shift left(左移) 将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
$a >> $b Shift right(右移) 将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。
警告
在 32 位系统上不要右移超过 32 位。不要在结果可能超过 32 位的情况下左移。 很庆幸我这里没有超过这个数,所以php的大数操作是个学问,我是新手,请高人指点。
与字符有关的函数
hexdec () 将16进制数转换成10进制数
dechex () 将10进制数转换成16进制数
strlen() 取字符串长度
substr(字符,a,b) 取字符串中从a位开始的b个数,如果a为负数则表示从后向前数第a个,b也一样。
ord() 返回字符串的ascii码(10进制)
str_pad() str_pad 函数用于进行字符串的填补,第一个参数是处理的字符串对象,第二参数是总长度,第三个参数是指长度不够总长以什么符号来填补,第四个参数为填补左边还是右边(默认不写为填补右边)。
算法不复杂,写出来也不复杂。希望对大家有用。如果大家对有些php的处理不太明白,可以去翻php手册。
今天就讲到这里,希望对大家有用。下面我原代码,crackme,实现视频都上传给大家,。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于dahaij, 转载请注明作者并保持文章的完整, 谢谢!
2009年01月07日 13:43:56