📄 lesson5032.htm
字号:
还不是很好,所以得算算:</span></pre>
<pre><span class="p9"> 100000000 - FFFFFF64 = 9C</span></pre>
<pre><span class="p9">在 SoftICE 用这样的命令:</span></pre>
<pre><span class="p9"> :? 0-FFFFFF64</span></pre>
<pre><span class="p9">100000000 对SoftICE来说太大了,但它还是给出了相同的结果。</span></pre>
<pre><span class="p9">现在是...来看看什么东西躲在EBP-9C那里的时候了...这样输入命令:</span></pre>
<pre><span class="p9"> :d ebp-9c</span></pre>
<pre><span class="p9">数据窗口会显示出一大排数字 ─ 注册码!但是记住我前面说过的...两种注册
方式对应两个注册码....所以你把这些注册码抄下来以后,继续用F10单步运行
....我们会遇到这些代码:</span></pre>
<pre> <span class="p9">> LEA EAX, [EBP-68] ; EAX = EBP-68
LEA ECX, [EBP-34] ; ECX = EBP-34
PUSH EAX ; 保存 EAX
PUSH ECX ; 保存 ECX
> CALL 00403DD0 ; 再次调用子程序
ADD ESP, 08 ; 删除保存的信息
TEST EAX, EAX ; 检查返回结果
JNZ 00402BFF ; 如果非零跳转</span></pre>
<pre><span class="p9">你在EBP-68处找到了什么?不错吧...另一个注册码。</span></pre>
<pre><span class="p9"> :d ebp-68</span></pre>
<pre><span class="p9">我们的练习结束了,希望一切顺利。
</span></pre>
<pre><span class="p9">3.2 Command Line 95 -容易的用户名/注册码方式的注册、注册器
=================================================================
这是一个非常好的例子,注册码的计算也很简单。
</span></pre>
<pre><span class="p9">3.1.1 检查程序
===========================
检查程序以后你知道它是32位的应用程序,要求输入名字和注册码。 让我们开始!</span></pre>
<pre><span class="p9">3.1.2 捕捉代码
===========================
我们象拆解TaskLock那样 ─ 设置断点。我们可以在两个可能性最大的两个函数
都设上断点:GetWindowTextA 和 GetDlgItemTextA. 按下Ctrl+D 进入SoftICE, 然后:</span></pre>
<pre><span class="p9"> :bpx getwindowtexta
:bpx getdlgitemtexta</span></pre>
<pre><span class="p9">接下来进入注册对话框,输入一个名字和一些数字(多数情况下是一个整数),
我是这么写的,然后按OK....</span></pre>
<pre><span class="p9"> Name: ED!SON '96
Code: 12345</span></pre>
<pre><span class="p9">程序在 GetDlgItemTextA 处停住了,就象TaskLock一样。我们按F11回到调用它
的地方。用 Ctrl+Up卷动窗口直到看到这些:</span></pre>
<pre><span class="p9"> MOV ESI, [ESP+0C]
PUSH 1E ; 最大长度
PUSH 0040A680 ; 缓冲地址
PUSH 000003ED ; 控制柄
PUSH ESI ; 对话柄
CALL [User32!GetDlgItemTextA]</span></pre>
<pre><span class="p9">数字40A680引起了我们的注意,看看那里有什么:
:d 40a680</span></pre>
<pre><span class="p9">如果没有我们输入的名字,数据窗口里有些什么呢?好了,我们来研究下面的一 段代码:</span></pre>
<pre><span class="p9"> PUSH 00
PUSH 00
PUSH 000003F6 ; 控制柄
MOV EDI, 0040A680 ; 保存缓冲区地址
PUSH ESI ; 对话柄
CALL [User32!GetDlgItemInt]</span></pre>
<pre><span class="p9">GetDlgItemInt 和 GetDlgItemText差不多,但它从文字框中返回一个整数。
它出在EAX中返回来的,所以单步运行通过这些代码,再来看看寄存器窗....
对我而言是:</span></pre>
<pre><span class="p9"> EAX=00003039</span></pre>
<pre><span class="p9">十六进制数3039是多少? 输入:
:? 3039</span></pre>
<pre><span class="p9">我们得到:</span></pre>
<pre><span class="p9"> 00003039 0000012345 "09"
^ 16进制 ^ 十进制 ^ ASCII</span></pre>
<pre><span class="p9">正如你看到(和已经猜到)的那样,它是你输入的注册码。OK,下面怎么办?让
我们来看下面的代码:</span></pre>
<pre><span class="p9"> MOV [0040A548], EAX ; 返回注册码
MOV EDX, EAX ; 同时保存在DX中
</span></pre>
<pre><span class="p9">3.1.3 计算注册码
==========================
这样注册码就算出来了</span></pre>
<pre><span class="p9"> MOV ECX, FFFFFFFF ; 这几行计算字符长度
SUB EAX, EAX ; .
REPNZ SCASB ; .
NOT ECX ; .
DEC ECX ; ECX <-- 长度
MOVSX EAX, BYTE PTR [0040A680] ; 读入40A680处的一字节
IMUL ECX, EAX ; ECX = ECX * EAX
SHL ECX, 0A ; 左移 0A 次
ADD ECX, 0002F8CC ; 结果加上2F8CC
MOV [0040A664], ECX</span></pre>
<pre><span class="p9">验证合法性....</span></pre>
<pre><span class="p9"> CMP ECX, EDX ; 比较
JZ 00402DA6 ; 如果相同就....</span></pre>
<pre><span class="p9">当你运行到比较这一步时,就可以得到你真正的注册码:</span></pre>
<pre><span class="p9"> :? ecx</span></pre>
<pre><span class="p9">对我而言它是:
000DC0CC 0000901324</span></pre>
<pre><span class="p9">也就是说我的正确的注册码是901324.</span></pre>
<pre><span class="p9">按F5或者Ctrl+D让它运行,然后用正确的注册码(十进制)再来一次。这一次 成功了!
</span></pre>
<pre><span class="p9">4. 为COMMAND LINE 95制作注册器
=========================================
我们把上面计算注册码的代码翻译成C语言程序。 最明了的计算公式就是:</span></pre>
<pre><span class="p9">code=((uppercase_first_char * length_of_string) << 0x0A) + 0x2f8cc;</span></pre>
<pre><span class="p9">注(1): 别忘了一件事 就是把所有字符转成大写
(2): "<< 0x0A" 实际上就是 "乘以 2^10"</span></pre>
<pre><span class="p9">完整的程序就是:</span></pre>
<pre><span class="p9"> #include <string.h>
#include <stdio.h></span></pre>
<pre><span class="p9"> int main()
{
unsigned long code;
unsigned char buffer[0x1e];</span></pre>
<pre><span class="p9"> printf("CommandLine95 Keymaker by ED!SON '96\n");
printf("Enter name: ");
gets(buffer);</span></pre>
<pre><span class="p9"> strupr(buffer);
code = ( ((unsigned long)buffer[0] *
(unsigned long)strlen(buffer))
<< 0x0A) + 0x2f8cc;</span></pre>
<pre><span class="p9"> printf("Your code is: %lu", code);</span></pre>
<pre><span class="p9"> return 0;
}</span></pre>
<pre><span class="p9">爽吧?
</span></pre>
<pre><span class="p9">4. 当程序调用一个函数时,PUSH和CALL这些指令是如何工作的
============================================================================
我们重新来看看TaskLock中的这段代码:</span></pre>
<pre><span class="p9"> PUSH 32 ; 字符串最大长度
PUSH EAX ; 字符缓冲区地址
PUSH 000003F4 ; 控制标识
PUSH DWORD PTR [ESI+1C] ; 对话框柄
CALL [USER32!GetDlgItemTextA] ; 获得字符串</span></pre>
<pre><span class="p9">如果认为是C语言编译出来的话,这个CALL应该是这样:</span></pre>
<pre><span class="p9"> GetDlgItemTextA(hwndDlg, 0x3F4, buffer, 0x32);
^ [ESI+1C] ^ EAX</span></pre>
<pre><span class="p9">PUSH把数据保存在叫做堆栈的地方。每个PUSH把新的数据放在堆栈的顶部,被调
用的子程序就挨个地检查躺在堆栈中的数据,按照定义来使用它们。</span></pre>
<pre><span class="p9">5. 关于VISUAL BASIC 程序
==============================
Visual Basic 的EXE文件并不是真正的编译可执行文件。它们只是包含调用
VBRUNxxx.DLL代码,它从EXE文件中读去数据然后运行程序。这就是为什么为什
么VB程序这么慢。因为这些EXE文件并不是真正的EXE文件,你没法反汇编它们,
你只能得到一些到DLL的调用和大量的垃圾。当你试图调试它们时,也只能在DLL
中打转。解决的办法就是用反编译器。有个叫DoDiD的人写过一个Visual Basic 2 &
3的反编译器,是个共享软件,在网上可以找到(见附录C)。对Windows 95 中的Visual
Basic version 4 32-bit 程序,具我所知现在还没有反编译器,虽然我很想有一个。</span></pre>
<pre><span class="p9">注:真正的(或者聪明的)程序员是不用VB编程的。</span></pre>
<pre><span class="p9">附录</span></pre>
<pre><span class="p9">A. 让SoftICE载入符号
==============================
你可以用exp getwindowtext命令来检查SoftICE是否已经为GetWindowText装入
了符号,象这样:
:exp getwindowtext</span></pre>
<pre><span class="p9">如果你没有得到所有GetWindowText函数的列表,你就得编辑\SIW95\WINICE.DAT,
在"Examples of export symbols that can be included for chicago"这段文字
以后的那些 'exp='的行首去掉';',为了节省内存,选择最重要的几个就可以了:</span></pre>
<pre><span class="p9"> kernel32.dll
user32.dll
gdi32.dll</span></pre>
<pre><span class="p9">编辑完后,重新起动计算机使其生效。
</span></pre>
<pre><span class="p9">B. 函数语法
============================
如果你看看下面的函数声明,对我们上面讲到的函数调用就容易明白了:</span></pre>
<pre><span class="p9">int GetWindowText(int windowhandle, char *buffer, int maxlen); int
GetDlgItemText(int dialoghandle, int controlid, char *buffer,
int maxlen);
int GetDlgItemInt(int dialoghandle, int controlid, int *flag, int type);</span></pre>
<pre><span class="p9">这些函数的详细描述,可参考Windows/Win32编程手册
</span></pre>
<pre><span class="p9">C. 如何获得软件
================================
CRACKING TOOLS
SoftICE/Win 2.oo: http://www.geocities.com/SoHo/2680/cracking.html
(译者注:目前最新版本3.01,详见NuMega主页 http://www.numega.com/ )</span></pre>
<pre><span class="p9"> VB Decompiler: ftp://ftp.sn.no/user/balchen/vb/decompiler/</span></pre>
<pre><span class="p9">SAMPLE PROGRAMS
TaskLock: http://users.aol.com/Sajernigan/sgllck30.zip
CommandLine 95: ftp://ftp.winsite.com/pub/pc/win95/miscutil/cline95.zip
</span></pre>
<pre><span class="p9">D. 如何与我联系
================
On IRC (EFNet): In #Ucf96, #Cracking
By e-mail: edison@ccnux.utm.my OR an461165@anon.penet.fi On my
homepage: http://www.geocities.com/SoHo/2680/cracking.html</span></pre>
<pre><span class="p9">======================================================================</span></pre>
<pre><span class="p9">译后记:
花了一个下午的时间(上班时间啊!),译完这篇拆解教程。不知大家看不看
得懂?ED!SON的文章是很浅显易懂的,我担心会让我毛手毛脚地闹出歧义来,
如果真有什么错误的话,帐应该算在我头上(请大家来信指出)。ED!SON的这
篇文章对初学者来说非常值得一读,我就是看完这篇文章以后,马上连续CRACK
了几个程序(就这么快、这么简单!)下次我就把CRACK WINZIP6.2的过程讲讲
吧(WINZIP6.2的注册器已经泛滥成灾了,就当练习练习吧)。欢迎来信交流,
你CRACK了什么程序,别忘了告诉我你用的方法;如果觉得我翻译得还算看得下
去话,就给些鼓励吧。</span></pre>
<pre><span class="p9">CFIDO ID : Jim Tyan
EMAIL : jimtyan@tasteful.com</span></pre>
<pre><span class="p9">我已将本文以及两个用来练习的程序TaskLock和Commandline 95打成一个包上
传至蓝天龙加密解密区,名字叫CRACKIT.RAR。
</span></pre>
<pre><span class="p9">田学军 8878888 CALL 29549 jimtyan@tasteful.com</span></pre>
<table width="80%" border="1" cellspacing="0" cellpadding="0" align="center" bgcolor="#99CCFF" bordercolorlight="#99CCFF" bordercolordark="#99CCFF">
<tr>
<td width="82%" class="p8" height="34">Copyright @看雪 2000 All rights reserved
<a href="mailto:toye@126.com">与我联系</a></td>
<td width="10%" class="p9" height="34"><a href="index.htm" tppabs="http://toye.dihou.org/index.htm">返回<br>
首页</a></td>
<td width="8%" class="p8" height="34"><a href="molu.htm" tppabs="http://toye.dihou.org/molu.htm" class="p9">返回<br>
目录</a></td>
</tr>
</table>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -