破解

      关于创作者 2004-12-11 19:23
二节 SoftICE与TRW2000操作入门

  由于TRW2000命令和操作完全兼容SoftICE,因此如不特殊说明,在本文对SoftICE的叙说都适合TRW2000。
  SoftICE的所有操作都发生在一个可以随时可激活的调试窗口中,在这个窗口中可以监视Windows应用程序和系统的运行。
一、 调试窗口简介
  我们假设你的SoftICE己经正常运行,此时在Windows里按"Ctrl+D"键就可以呼出SoftICE的调试窗口,当需要返回到Windows系统时,再按"Ctrl+D"键,也可使用X命令或按F5键。激活的调试窗口如图2.14所示,分为寄存器窗口、数据窗口、代码窗口、浮点窗口和命令窗口等部分。
如是在TRW2000环境下,激活是按"CTRL+N",和SoftICE不同的是TRW2000中没有浮点窗口,不过有一个堆栈窗口。



(图一)SoftICE或TRW2000调试截图

1、寄存器窗口
  在这里可以观察到各种寄存器的当前值,如数据寄存器EAX、EBX、ECX、EDX和控制寄存器(EIP和PSW)等,有一点要注意了,由于我们是在Windows平台下,所以看到的都是80386寄存器集,其与16位寄存器差别在前多了一字符"E",意为16位寄存器扩展。
2、数据窗口
  在数据窗口显示指定内存处中的数据,以十六进制和ASCII同时显示,这可以说是我们的眼睛,因此有必要了解一下各部分的含义。



(图二)

①号位置的0030:这是段选择器。
  在Windows的保护模式下CS、DS、ES、SS、FS和GS不叫段寄存器,叫段选择器。在保护模式中,内存分为了好多的段,在TRW200下用GDT就可以看到段的编号、类型、开始物理地址、大小、属性。让我们看看编号0030是什么东西:



(图三)

  这个段是32位数据类型,长度为4G ,我们还可以看到很多的段,它们有可能会指向同一个物理地址,但它们的类型,属性可能不同。如一些段指向的地址是不可读写的,但另外一个段指向的同一物理地址是可读写的!如果我们通过不可写的那段的编号放到段选择器,然后进行读写操作,肯定死掉了。 但换了另外一个段对同一个地方读写那就没问题!保护模式的内存管理挺有趣的,感兴趣的不妨看看这方面的书,当然作为初学者只需稍微了解就可。
②号位置00000000:此处表示内存的虚拟地址。
③号位置的值是当前内存的数据,以十六进制表示。
④号位置的值是"③"处值的另一种表示方法:ASCII码。
3、代码窗口
  此处显示的是当前程序的代码,因为不管是什么程序,最终在CPU执行时都是以机器语言方式,而汇编语言和机器语言是一一对应的,因此SoftICE为了方便我们理解,把所监视的代码以汇编代码形式显示在我们面前。例如:



(图四)


①段选择器;
②虚拟地址;
③机器码:这就是CPU执行的机器代码,此处是以十六进制表示。你可用Code on/off打开或关闭这项的显示。
④汇编指令:和机器码对应的程序代码。
4、堆栈窗口
  这个是TRW2000特有的,通过它很方便监视堆栈的状况。
5、命令窗口
  这是各种命令执行的地方,在屏幕底部的动作状态行显示执行命令的各种提示,以及可提供指令语法帮助。
6、程序领空
  所谓领空,实际上是指:在某一时刻,CPU 的 CS:IP(EIP) 所指向的某一段代码的所有者所在的区域。此例中SoftICE所停下来时光标所指的那一句代码是属于KERNEL32.DLL的,因此就叫KERNEL32.DLL领空,在图2.14中,可看到的领空名是KERNEL32!.text,那我怎么知道它就是KERNEL32.DLL文件呢?这个主要是经验,KERNEL32.DLL是Windows系统文件,在SoftICE里显示领空名时不显示扩展名,只是显示前一部份。

二、SoftICE常用命令简介

由于SoftICE命令操作较多,在此就把几个常用的命令介绍一下,其它详细说明请参考附录的"SoftICE手册"。
1、 G命令
语法:G [=start-address] [break-address]
作用:执行程序,后面如果加地址,则执行到该地址为止。
注意: TRW2000 中G命令与SoftICE稍有不同,SoftICE中G命令必须是在当前段中,这时IP(EIP)为指定值才中断;而TRW2000则不管段址如何,只要IP(EIP)是指定的值便停下,TRW2000这个特性大大方便我们的操作。
2、P命令
语法: P [ret]
作用:单步执行程序。
只执行P时,相当于按下F10键。在汇编模式中,当遇到 CALL、INT、LOOP、REP指令时,P将不跟踪进去,直到这些指令执行完毕,控制才返回SoftICE,换句话说,P命令是"跨"过这些指令的。
P RET 命令相当于快捷键 F12。SoftICE将一直单步执行直到它找到一条返回语句(RET、RETF),也就是说让SoftICE一直执行代码,直到出现 RET (XXXX) 命令,再跳出来拦截,这时,当前 IP(EIP) 会是停在 RET (XXXX) 后的某一条语句上,通常是在某一个CALL XXXXXXXX 后面。由于我们通常用SoftICE在某些底层的Windows函数上设置断点,所以 F12 是很管用的。因为程序的作者用的是高级语言,Windows又是提倡"透明",不希望程序员知道底层的操作,而只提供给他们高层的接口,而相当多的高级函数调用某个一定的底层函数,所以当你在底层函数上下断点,再用F12,就可以知道他用的是什么函数了。
3、T命令
语法:T [=start-address] [count]
start-address:执行起始地址;
count:指定SoftICE将单步跟踪多少次才停止。
作用:单步跟踪。
T命令相当于功能键F8,如没指定起始地址,将从CS:IP(EIP)指向的指令开始执行,此时当遇到 CALL、LOOP等指令时,T将跟踪进去。
注意: F8和F10功能键的主要差别就在这,遇到 CALL、LOOP等指令时,F10是路过,而F8是跟进去。
4、BPX命令
语法:BPX [address] [IF expression] [DO "command1;command2;..."]
address :断点所在的线性地址;
IF expression:条件表达式,只有条件为"真"时,SoftICE才在断点处弹出;
Do command:当SoftICE弹出时,自动执行的一些命令。
作用:在可执行语句上设置(或清除)断点。
BPX 用来在指令处下断点,程序一旦执行到此,SoftICE就会弹出。当光标在代码窗口中时,直接打入BPX就会在光标所在语句处设断点,再打BPX 就取消。BPX的快捷键是 F9,当光标在代码窗口中时,按F9就是设定(取消)。
BPX 也可用函数名来作地址参数:格式为"BPX 函数名"。
这个函数名可以是任意一个API函数、虚拟机指令、DLL文件的引出函数等等,功能强劲。例:
:bpx messageboxa(不用区分大小写)//只要程序调用了此函数,SoftICE将中断;
:bpx GetWindowTexta if EAX==8 // 当调用GetWindowTexta函数时EAX=8,SoftICE将中断;
:BPX GetWindowTexta do "d EAX"// 当 GetWindowTexta被中断,自动显示EAX的值。
注意: TRW2000与SoftICE条件格式有点不同,如在SoftICE下的是:bpx loadlibrarya do "dd esp->4",而相同的用法在TRW2000中是:bpx loadlibrarya do "dd *(esp+4)" 。另外SoftICE中用鼠标双击指令行可设断,而TRW2000中不行,只能按F9.
5、BPM命令
语法:BPM[size] address [条件表达式] DO[执行的命令]
size:内存单元大小,B为字节(默认);W 为字;D 为双字;
verb:所进行的操作,R为读;W为写;RW为读写(默认);X 为执行。
作用:设置内存访问断点。
注意: BPM用了DR3-DR0寄存器,所以最多只能设四个断点。
6、BMSG命令
语法:BMSG window-handle [条件表达式] DO[执行的命令]
window-handle:消息发向的窗口句柄,即消息名
作用:在Windows的消息上下断点。
Windows本身是由消息驱动的, 所以跟踪一个消息会得到相当底层的答案。如:
我们执行记事本程序(Notepad),然后Ctrl+D激活SoftICE输入:
   :bmsg wm_char
   :g
然后回到Notepad中,随便按一个键,SoftICE就激活了;原因在于我们在按键消息上设置了断点(退出SoftICE别忘下命令"BC *"清除刚才下的断点)。
7、BL命令
语法:BL
作用:显示当前所设的断点
注意: SoftICE会把所有断点按从0开始的编号列出,而TRW2000是从1开始编号列出。
8、BC命令
语法:BC list | *
list:可以清除指定编号的断点,多个时中间用空格或逗号隔开。
* :清除所有的断点。
作用:清除一个或多个断点
9、BD命令
语法: BD list | *
list:可以是单个,也可以是一系列断点,中间用空格或逗号隔开。
* :禁止所有的断点
作用:使一个或多个断点失效。
10、BE命令
语法:BE list | *
作用:使一个或多个断点恢复有效。
用来恢复前次用 BD 命令使之失效的断点。 (每当新定义断点或编辑断点时,系统自动将其置为有效)
11、BPE命令
语法:BPE index_number(断点索引号)
作用:编辑一个已存在的断点。
12、R命令
语法:R 寄存器名
作用:显示或更改寄存器的内容。
其可更改所有的寄存器的值。此命令较常用的一个功能是更改状态寄存器(PSW )的值,格式:R FL 标志位。比如当前 Z标志位(零位)为置位状态,执行"r fl z"之后会被清除;如果C标志位为清除状态,那么"r fl c"将使之置位。
注意: 利用此命令很方便在一些跳转指令上改变方向。
13、A命令
语法:A [地址]
作用:进入小汇编状态,可直接写入汇编代码。
如不加地址值,直接在当前CS:IP(EIP)处汇编。用SoftICE内置的汇编器在内存中写入汇编代码。汇编器支持标准的80x86指令集,包括386、486、Pentium、Pentium-Pro、MMX协处理器,新版的SoftICE还支持AMD的3D Now!、PII、PIII的特有指令集。
14、D命令
语法:D[size] [address [l length]]
size:B 字节;W 字;D 双字; S 短实型;L 长实型;T 10b长实型
作用:显示某内存区域的内容。
15、S命令
语法:S [-cu][address L length data-list]
address:搜索的起始地址
length :搜索的长度(字节长)
data-lis:可以是一系列字节,也可以是字符串,字符串可以用单引号,也
可以用双引号括住.
-c :使查找区分大小写
-u :查找Unicode 编码的字符串.
作用:在内存中搜寻特定数据,如果找到数据,那将在数据窗口中显示出来,如果在找到后,你还要继续查找,使用不带参数的S命令。由于S命令忽略不在内存中的页面,因此你可以使用32位平面地址数据段描述符30h在整个4GB(0~FFFFFFFFh )空间查找。如:
s 30:0 l FFFFFFFF "78787878" //在此令在内存中查找字串"78787878"位置。
注意: TRW2000中S命令的字串应是单引号(而SoftICE皆可)。如:s 30:0 l FFFFFFFF '78787878'.
16、E命令
语法:E[size] [address [data-list]]
作用: 修改内存单元
17、U命令
语法:U [address [l length]] | [symbol-name]
address :段:偏移量或选择符:偏移量
symbol-name:将从指定的函数开始反汇编
length :反汇编的长度(字节)
作用: 反汇编指令
你可以利用此命令抓取汇编代码,运行LOADER32后,将历史缓冲区(history buffer)调大些(默认为256,不能放足够多的缓冲数据)。然后切换到SoftICE调试画面下,来到你要抓取的地方,反汇编这些代码,如:U CS:EIP L 1000 ,立即按Ctrl+D返回到Windows环境,再次来到symbol loader程序,选择"File/Save SoftICE History As…"。
注意: 在TRW2000下可以直接反汇编代码输出到一个文件:
u 401000,402000 >路径/myfile。
18、FAULTS命令
语法:FAULTS [on | off]
作用:打开或关闭错误跟踪功能
由于SoftICE做为一个DEBUGGER,FAULTS 默认为ON,所以一旦CPU有非法指令,SoftICE就会不停地弹出。
19、?命令
语法:? 表达式
作用:计算一个表达式的值
一个非常高级的计算器,另外由于可以显示ASCII,所以可以很方便地在各种数制之间察看。
20、.命令
语法: .
作用:在代码窗口中定位当前指令
当你在代码窗口中上下浏览时,有可能走得很远,那么这时一个"."命令会让你在下一瞬间回到SoftICE当前所在的CS:EIP处。
21、EXP命令
语法: EXP [函数名]
作用: 显示DLL中的出口函数
函数名可以指定出其前几个字符, 可以用?来做替代不定字符,这样你就可查找相关函数及其是哪个DLL文件了。这对于你在Win2K系统上非常实用,Win2K系统的KERNEL32.DLL中许多函数形式和Windows 9x可能不同,用此命令你就可找到正确的函数名了。
22、PMODULE命令(TRW2000特有命令)
作用:'pret'(相当于按<F12>) 直至CS:EIP位于模块中,但比F12更实用,其可以快速回到你的当前程序领空,不用按多次F12了
23、SUSPEND命令(TRW2000特有命令)
作用: 暂停当前的线程,并退出 TRW2000,按热键返回,此命令相当方便。
24、ver blue命令(TRW2000特有命令)
如你的TRW2000背景颜色很暗,可通过此命令来调整背景。



第三节 常用Win32 API函数简介


  现在很多讲Windows程序设计的书都是讲基于MFC库和OWL库的Windows设计,对Windows实现的细节都鲜有讨论,而调试程序都是和系统底层打交道,所以有必要掌握一些Win32 API函数的知识,这样我们可快捷地找出程序调用错在哪?是哪个参数出了问题。
  Windows程序模块包括KERNEL、USER和GDI,其中KERNEL完成内存管理、程序的装人与执行和任务调度等功能,它需要调用原MS―DOS中的文件管理、磁盘输入输出和程序执行等功能;USER是一个程序库,它用来对声音、时钟、鼠标器及键盘输入等操作进行管理;GDI是一功能十分丰富的子程序库,它提供了图形与文字输出、图象操作和窗口管理等各种与显示和打印有关的功能。上述KERNEL、USER和GDI模块中的库函数可被应用程序调用,也可被其他程序模块调用。把包含库函数的模块称为输出者(export)。你应明白为什么跟踪软件时经常在KERNEL32!.text和USER32.text等系统领空转的问题吧。
  这里列出几个经常碰到的Win 32 API函数,它们都是存在Windows系统核心文件KERNEL32.DLL中和视窗管理文件USER32.DLL中。
Windows函数是区分字符集的:A表示ANSI,W表示Wide,即Unicode (Wide character-set),前者就是通常使用的单字节方式,但这种方式处理象中文这样的双字节字符不方便,容易出现半个汉字的情况。而后者是双字节方式,方便处理双字节字符。Windows的所有与字符有关的函数都提供两种方式的版本。尽管你编程时使用GetWindowText,但实际上编译程序会根据设置自动调用GetWindowTextA或GetWindowTextW。函数的最后一个字母告诉我们函数是使用单字节还是双字节字符串。
1、 Hmemcpy函数
void hmemcpy(hpvDest, hpvSource, cbCopy)
void _huge* hpvDest; // 目的数据地址
const void _huge* hpvSource; // 源数据地址
long cbCopy; // 数据大小 (Bytes)
这个函数在KERNEL32.DLL中,它很常用,俗称万能断点,但一般的编程书籍上很少提到,原因它是底层的东西,没有特殊需要,一般不直接调用。但的确它是很有用的!有意思的是它执行的操作很简单,只是将内存中的一块数据拷贝到另一个地方。
注意:此函数只在Windows 9x系统上有效,在Win NT/2K系统上相关的函数是memcpy,但在Win NT/2K上不同于Windows 9x上,很少再调用memcpy来处理数据了,用此函数设断基本上什么也拦不住。
2、 GetWindowText函数
此函数在USER32.DLL用户模块中,它的作用是复制指定窗口中的字符到缓冲区。函数原型:
int GetWindowText(
HWND hWnd//欲获取文字的那个窗口的句柄
LPTSTR lpString //预定义的一个缓冲区,至少有cch+1个字符大小;随同窗口文字载入
int nMaxCount//lpString缓冲区的长度
);
16位:GetWindowText
32位:GetWindowTextA,GetWindowTextW
3、 GetDlgItemText
此函数在USER32.DLL用户模块中,它的作用是返回对话框中某一个窗口的标题或文字。函数原型:
UINT GetDlgItemText(
HWND hDlg, // 对话框句柄
int nIDDlgItem, //控制标识符
LPTSTR lpString, / 预定义的一个字符缓冲区
int nMaxCount// 字符缓冲区的长度
);
16位:GetDlgItemText
32位:GetDlgItemTextA,GetDlgItemTextW
4、 MessageBox函数
此函数是在USER32.DLL用户模块中,它的作用创建、显示和操作信息框。函数原型:
int MessageBox(
HWND hWnd, //窗口句柄
LPCTSTR lpText, // 信息框中文字的地址
LPCTSTR lpCaption, // 信息框标题地址
UINT uType // 信息框类型
);
16位:MessageBox
32位:MessageBoxA,MessageBoxW

第四节 拆解教程

========================================================================
ED!SON's Windows 95 拆解教程 V1.00 (中文翻译: JIM TYAN)
========================================================================
附:ED!SON教程的示范程序下载
目录
========
1. Windows 拆解简介
2. SoftICE for windows 2.00 快速入门
3. 如何找注册码
3.1 Task Lock 3.00 - 一个简单的、仅有注册号保护的拆解例子
3.2 Command Line 95 - 容易的“用户名/注册号"注册方式的拆解
4. 为Command Line 95制作注册器
5. 当程序调用一个函数时,PUSH和CALL这些指令是如何工作的
6. 关于VB程序
附录
========
A. 如何让SOFTICE载入符号
B. 函数的语法
C. 到哪里获取软件
D. 如何与我联系
1. WINDOWS拆解简介
===================================
拆解一个WINDOWS程序要比拆解一个在DOS下运行的程序要容易得多。因为在WINDOWS
中,只要WINDOWS的函数被使用了,想对任何真正要寻找蛛丝马迹的人隐藏什么东西
是比较困难的。
你需要的第一个(常常也是唯一的一个)工具就是SoftICE/Win 2.oo, 它是NuMega
出品的一个非常强大的调试工具。有些人发现它很难用,但我会教你如何使用它进行
有效的调试,也希望你们能够明白我将要告诉你们的:-)。 你应该看看在附录A 中有
关SoftICE/Win 2.oo的一些资料。我在安装SoftICE中从来没有碰到任何问题, 如果
你碰到了,我只好让你查它的参考手册了。
你所需要的所有软件的URL列在附录C中
- ED!SON, edison@ccnux.utm.my

2. SOFTICE/WIN 2.OO 快速入门
=========================================
首先你应该对SOFTICE的屏幕有个大概的了解

|--------------------|
| 寄存器窗 | 用 'R' 编辑
|--------------------|
| 数据窗 | 用 'D' 列出某个地址的数据, 用 'E' 编辑
|--------------------|
| 代码窗 | 用 'U' 反汇编, 'A' 加入汇编代码
|--------------------|
| 命令窗 | 在这里输入命令和读出结果
|--------------------|
其它重要的功能键(在缺省的键定义下)
'H'/F1 - 在线帮助
F5/Ctr+D - 运行
F8 - 单步执行,切入子程序和中断
F10 - 单步执行,跳过子程序和中断
F11 - 跳出子程序,回到CALL的下一条指令
3. 如何寻找注册码
=============================
最容易的练习莫过于找个共享软件来试试把它注册。
3.1 Task Lock 3.00 - 一个简单的、仅有注册号保护的拆解例子
=================================================================
这是一个简单的保护,只有一个而且不会变化的注册码。
3.1.1 检查程序
===========================
它是16 bit程序,还是32 bit的? 在哪里输入注册信息? 在它的帮助里有没有
发现关于注册的一些线索?在你继续往下读之前,去把它们找一找!
....你现在应该在找吧!.....你是在找吗?.....你找到了吗?.......
好,你现在知道了,它是一个32位的WINDOWS 95应用程序,你可以在一个选择了
“Register|Register..."菜单就会弹出来的对话框中,输入一个注册码来注册
程序。通过阅读它的帮助,你也知道可以有两种注册方式:Individual和Site
License。所以这里对合法的注册码就可能有两次核对。
3.1.2 捕捉注册代码
===========================
注册码通常在普通的WINDOWS文字框中输入。为了检查输入的注册码, 程序必须
采用下面这些函数中的一个来把文字框中的内容读出来。
16-bit 32-bit
------ ------
GetWindowText GetWindowTextA, GetWindowTextW
GetDlgItemText GetDlgItemTextA, GetDlgItemTextW
32-BIT函数的最后一个字母告诉我们函数是使用单字节还是双字节字符串。双字
节的注册码是很少见的。
也许你已经体会到我的意思了...“如果我能在GetWindowText时中断...", 你
的确能这样做!但是你首先必须确认这些符号已经由SOFTICE载入了(详见附录A)
在SoftICE中设定一个“陷阱"(实际上我们叫断点),你得先按Ctrl+D进入调
试状态,然后用命令BPX,后面跟著是函数的名字或者内存地址。因为Task Lock
是32位程序,所以我们在GetWindowTextA处设一个断点。 如果这个不行, 我们
可以再试其它的。
象这样在SoftICE中输入:
:bpx getwindowtexta
如果你得到“No LDT"这样的错误信息,就要注意不要运行其它程序。我已经注
意到Norton Commander/Dos 会干扰这个功能。 你可以列出所有断点来检查一下
是否设好断点:
:bl
你会看到这样的信息:
00) BPX USER32!GetWindowTextA C=01
你可以再按一次Ctrl+D,从SoftICE中退出,。
好了,不管怎么样,你已经设定好了断点以捕捉任何对GetWinowTextA的调用。
现在我们来在该输入注册码的地方输入一些数字,然后按下OK....你只得到了
一个信息框告诉你输入的注册码是无效的。看来不是GetWindowTextA....我们
来试试GetDlgItemTextA。首先删除旧的断点:
:bc 0
(0 表示在断点列表中的第0个断点)
然后设定新的断点:
:bpx getdlgitemtexta
再来试一次.....

3.1.3 在调试器中
=====================
哇!行了!你已经在SoftICE中了,就在函数GetDlgItemTextA开始的地方。按
F11键,回到调用函数的地方。现在你到了SGLSET.EXE的内部,如果你还没把握
的话,看看代码窗和数据窗中间的一行,你应该看到这样的东西:
----------SGLSET!.text+1B13----------
你可以这样禁止一个断点:
:bd 0
以后想再开启它的话,可以这样:
:be 0
代码窗的第一行是:
CALL [USER32!GetDlgItemTextA]
按几次Ctrl+Up 直到你看到下面这几行。如果对汇编一点也不懂的话,看我加的 注解吧:
RET ; 函数结束
PUSH EBP ; 函数开始
MOV EBP, ESP
SUB ESP, 0000009C
PUSH ESI
> LEA EAX, [EBP-34] ; EAX = EBP-34
PUSH EDI
MOVE ESI, ECX
PUSH 32 ; 输入字符串的最大长度
> PUSH EAX ; 输入字符串的缓冲地址
PUSH 000003F4 ; 控制标识
PUSH DWORD PTR [ESI+1C] ; 对话框的句柄
CALL [USER32!GetDlgItemTextA] ; 取得输入
PUSH指令保存那些数值以供后面使用。我已经在重要的地方加上了一个 '>'字符
作上记号. 看这几行我们就知道字符缓冲区的地址保存在EAX中,而EAX等于 EBP-34。
所以我们来看看EBP-34那里有什么:
:d ebp-3
你应该能在数据窗中看到你输入的东西。下面我们得来找开始核对输入注册码的
地方。按F10一步一步地单步运行直到你发现与EBP-34有点关系的地方.... 你不
用单步运行多久,就会看到这些代码:
> LEA EAX, [EBP+FFFFFF64] ; EAX = EBP-9C
LEA ECX, [EBP-34] ; ECX = EBP-34
PUSH EAX ; 保存 EAX
PUSH ECX ; 保存 ECX
> CALL 00403DD0 ; Call 一子程序
ADD ESP, 08 ; 删除保存的信息
TEST EAX, EAX ; 检查返回值
JNZ 00402BC0 ; 如果不是零的话跳转
对我来说,马上就可以看出这象是一个字符比较程序。它们工作起来就是这样:
* 输入两个字符串
如果相同就返回零
否则返回非零
那为什么程序要用一个字符串来和你输入的相比较呢?看它是不是合法的!(可
能你已经想到了)。那么是什么东西躲在 [EBP+FFFFFF64] ? SoftICE处理负数
还不是很好,所以得算算:
100000000 - FFFFFF64 = 9C
在 SoftICE 用这样的命令:
:? 0-FFFFFF64
100000000 对SoftICE来说太大了,但它还是给出了相同的结果。
现在是...来看看什么东西躲在EBP-9C那里的时候了...这样输入命令:
:d ebp-9c
数据窗口会显示出一大排数字 ─ 注册码!但是记住我前面说过的...两种注册
方式对应两个注册码....所以你把这些注册码抄下来以后,继续用F10单步运行
....我们会遇到这些代码:
> 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 ; 如果非零跳转
你在EBP-68处找到了什么?不错吧...另一个注册码。
:d ebp-68
我们的练习结束了,希望一切顺利。

3.2 Command Line 95 -容易的用户名/注册码方式的注册、注册器
=================================================================
这是一个非常好的例子,注册码的计算也很简单。

3.1.1 检查程序
===========================
检查程序以后你知道它是32位的应用程序,要求输入名字和注册码。 让我们开始!
3.1.2 捕捉代码
===========================
我们象拆解TaskLock那样 ─ 设置断点。我们可以在两个可能性最大的两个函数
都设上断点:GetWindowTextA 和 GetDlgItemTextA. 按下Ctrl+D 进入SoftICE, 然后:
:bpx getwindowtexta
:bpx getdlgitemtexta
接下来进入注册对话框,输入一个名字和一些数字(多数情况下是一个整数),
我是这么写的,然后按OK....
Name: ED!SON '96
Code: 12345
程序在 GetDlgItemTextA 处停住了,就象TaskLock一样。我们按F11回到调用它
的地方。用 Ctrl+Up卷动窗口直到看到这些:
MOV ESI, [ESP+0C]
PUSH 1E ; 最大长度
PUSH 0040A680 ; 缓冲地址
PUSH 000003ED ; 控制柄
PUSH ESI ; 对话柄
CALL [User32!GetDlgItemTextA]
数字40A680引起了我们的注意,看看那里有什么:
:d 40a680
如果没有我们输入的名字,数据窗口里有些什么呢?好了,我们来研究下面的一 段代码:
PUSH 00
PUSH 00
PUSH 000003F6 ; 控制柄
MOV EDI, 0040A680 ; 保存缓冲区地址
PUSH ESI ; 对话柄
CALL [User32!GetDlgItemInt]
GetDlgItemInt 和 GetDlgItemText差不多,但它从文字框中返回一个整数。
它出在EAX中返回来的,所以单步运行通过这些代码,再来看看寄存器窗....
对我而言是:
EAX=00003039
十六进制数3039是多少? 输入:
:? 3039
我们得到:
00003039 0000012345 "09"
^ 16进制 ^ 十进制 ^ ASCII
正如你看到(和已经猜到)的那样,它是你输入的注册码。OK,下面怎么办?让
我们来看下面的代码:
MOV [0040A548], EAX ; 返回注册码
MOV EDX, EAX ; 同时保存在DX中

3.1.3 计算注册码
==========================
这样注册码就算出来了
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
验证合法性....
CMP ECX, EDX ; 比较
JZ 00402DA6 ; 如果相同就....
当你运行到比较这一步时,就可以得到你真正的注册码:
:? ecx
对我而言它是:
000DC0CC 0000901324
也就是说我的正确的注册码是901324.
按F5或者Ctrl+D让它运行,然后用正确的注册码(十进制)再来一次。这一次 成功了!


4. 为COMMAND LINE 95制作注册器
=========================================
我们把上面计算注册码的代码翻译成C语言程序。 最明了的计算公式就是:
code=((uppercase_first_char * length_of_string) << 0x0A) + 0x2f8cc;
注(1): 别忘了一件事 就是把所有字符转成大写
(2): "<< 0x0A" 实际上就是 "乘以 2^10"
完整的程序就是:
#include <string.h>
#include <stdio.h>
int main()
{
unsigned long code;
unsigned char buffer[0x1e];
printf("CommandLine95 Keymaker by ED!SON '96\n");
printf("Enter name: ");
gets(buffer);
strupr(buffer);
code = ( ((unsigned long)buffer[0] *
(unsigned long)strlen(buffer))
<< 0x0A) + 0x2f8cc;
printf("Your code is: %lu", code);
return 0;
}
爽吧?

4. 当程序调用一个函数时,PUSH和CALL这些指令是如何工作的
============================================================================
我们重新来看看TaskLock中的这段代码:
PUSH 32 ; 字符串最大长度
PUSH EAX ; 字符缓冲区地址
PUSH 000003F4 ; 控制标识
PUSH DWORD PTR [ESI+1C] ; 对话框柄
CALL [USER32!GetDlgItemTextA] ; 获得字符串
如果认为是C语言编译出来的话,这个CALL应该是这样:
GetDlgItemTextA(hwndDlg, 0x3F4, buffer, 0x32);
^ [ESI+1C] ^ EAX
PUSH把数据保存在叫做堆栈的地方。每个PUSH把新的数据放在堆栈的顶部,被调
用的子程序就挨个地检查躺在堆栈中的数据,按照定义来使用它们。
附录
A. 让SoftICE载入符号
==============================
你可以用exp getwindowtext命令来检查SoftICE是否已经为GetWindowText装入
了符号,象这样:
:exp getwindowtext
如果你没有得到所有GetWindowText函数的列表,你就得编辑\SIW95\WINICE.DAT,
在"Examples of export symbols that can be included for chicago"这段文字
以后的那些 'exp='的行首去掉';',为了节省内存,选择最重要的几个就可以了:
kernel32.dll
user32.dll
gdi32.dll
编辑完后,重新起动计算机使其生效。

B. 函数语法
============================
如果你看看下面的函数声明,对我们上面讲到的函数调用就容易明白了:
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);
这些函数的详细描述,可参考Windows/Win32编程手册

C. 如何与我联系
================
On IRC (EFNet): In #Ucf96, #Cracking
By e-mail: edison@ccnux.utm.my OR an461165@anon.penet.fi On my
homepage: www.geocities.com/SoHo/2680/cracking.html
======================================================================
译后记:
花了一个下午的时间(上班时间啊!),译完这篇拆解教程。不知大家看不看
得懂?ED!SON的文章是很浅显易懂的,我担心会让我毛手毛脚地闹出歧义来,
如果真有什么错误的话,帐应该算在我头上(请大家来信指出)。ED!SON的这
篇文章对初学者来说非常值得一读,我就是看完这篇文章以后,马上连续CRACK
了几个程序(就这么快、这么简单!)下次我就把CRACK WINZIP6.2的过程讲讲
吧(WINZIP6.2的注册器已经泛滥成灾了,就当练习练习吧)。欢迎来信交流,
你CRACK了什么程序,别忘了告诉我你用的方法;如果觉得我翻译得还算看得下
去话,就给些鼓励吧。
CFIDO ID : Jim Tyan
EMAIL : jimtyan@tasteful.com
田学军 8878888 CALL 29549 jimtyan@tasteful.co
第一节 基础知识

一、虚拟地址和偏移量转换

  由于Windows程序是运行在386保护模式下,在保护模式下,程序访问存储器所使用的逻辑地址称为虚拟地址(Virual Address,VA)。与实地址模式下的分段地址类似,虚拟地址也可写成"段:偏移量"的形式,这里的段是指段选择器。

  文件执行时将被映像到指定内存地址中,这个初始内存地址称为基址(ImageBase)。在Windows NT中,缺省的值是10000h;对于DLLs,缺省值为400000h。在Windows 9x中,10000h不能用来装入32位的执行文件,因为该地址处于所有进程共享的线性地址区域,因此Microsoft将Win32可执行文件的缺省基地址改变为400000h。

  相对虚拟地址(Relative Virual Address,RVA)表示此段代码在内存中相对于基地址的偏移。即:相对虚拟地址(RVA)=虚拟地址(VA)-基址(ImageBase)。

  文件中的地址与内存中表示不同,它是用偏移量(File offset)来表示的。

  在SoftICE和W32Dasm下显示的地址值是内存地址(memory offset),或称之为虚拟地址(Virual Address,VA)。而十六进制工具里,如:Hiew、Hex Workshop等显示的地址就是文件地址,称之为偏移量(File offset) 或物理地址(RAW offset)。

  在实际操作时,使用 RVA-Offset之类的转换器很容易查出字串RVA和偏移量的值。
以Pc_offset(光盘\tools\offset)此工具为例说说如何将SoftICE下看到的虚拟地址(Virual Address,VA)转换成十六进制工具里的偏移量(File offset),运行该软件打开记事本程序,在Memory Address(内存地址)输入虚拟地址(Virual Address,VA)的值:40117D,点击"Do it"按钮将显示己转换成文件偏移量(File offset),如图一所示。




(图一)内存虚拟地址转换成文件偏移量

二、文件类型分析

  文件分析是静态分析程序的第一步,通过相关工具显示欲调试文件的信息,如它是用什么语言写的,是否加壳等。常用的文件分析工具有TYP、Gtw或FileInfo。其中FileInfo(光盘\tools\file\File analysers)由于识别文件类型较多,使用方便,在这一节简单地讲讲它的用法。
FileInfo运行时是DOS界面,支持Windows长文件名,能识别DOS、NE、PE等各种文件类型和壳。
  语法:fi <drive:\path\><*.*> </r> </f> </d-> </l+> </p+>
     "fi /r"or "/s" 列出当前目录和子目录所有的文件信息;
     "fi /f" 仅列出能识别的文件
  由于每次要进入DOS窗口运行程序相当不便,在这可创建快捷方式,把要分析的文章复制到FileInfo目录下,用鼠标双击FileInfo主文件即可。FileInfo快捷方式如图二。在快捷方式中的命令行中可以键入相关参数,如:FI.EXE /l /p+,此后用鼠标双击FileInfo快捷方式,会自动分析出FileInfo当前目录内的所有文件,不包含子目录。



图二FileInfo快捷方式中命令参数配制

  双击此快捷方式就可执行带参数的FileInfo,显示结果如图三所示。



图三 FileInfo分析文件的报告

  在此例中,文件CHAP301.EXE被分析出是用VC6.0编译的, CHAP303.EXE文件类型是Win GUI,就是Windows图形用户界面程序(一般FileInfo分析不出类型就报此类型)。另外此工具也可分析出程序是被何种软件所加密的等。


第二节 W32Dasm简介

 W32Dasm是一个强大的反汇编工具,操作简单,使用方便。通常被程序员使用,当然也可被用来Crack软件了,很适合Cracker使用。我在这把与crack相关的功能简述如下:

1.0 开始
2.0 保存反汇编文本文件和创建方案文件
3.0 反汇编文本代码的基本操作
4.0 复制汇编代码文本
5.0 装载32位的汇编代码动态调试
6.0 运行,暂停或终止程序
7.0 单步跟踪程序
8.0 设置激活断点
9.0 偏移地址和虚拟地址转换

1.0 开始

1.1 运行W32Dasm,在这里以windows95自带的计算器为例:calc.exe。

1.2 从Disassembler(反汇编)菜单选择Disassembler Options(反汇编程序选项)选项将出现如下对话框:



1.3 在Disassembler(反汇编)菜单,选择Open File(打开文件)选项或按工具栏按钮

1.4 选择你要打开的文件就可。
注意:你反汇编文件后,如字符己超过屏幕外,这时你要选择合适的字体(在Font字体选项中Select Font选择字体) ,然后设为默认字体(Save Default Font)即可。 当然一般以默认值就可。

2.0 保存反汇编文本文件和创建方案文件(Save The Disassembly Text and Create A Project File )

略。

3.0 反汇编源代码的基本操作

3.1 转到代码开始(Goto Code Start)

在工具栏按或从菜单的转到(Goto)选项选择转到代码开始(Goto Code Start) 或按Ctrl S, 这样光标将来到代码的开始处,用户可通过双击鼠标或用shift+上下光标键改变光标的位置。

注:代码的开始处是反汇编代码列表清单汇编指令的开始,而不是代码运行的起点,程序运行的起点称为程序入口点(Program Entry Point)

3.2 转到程序入口点(Goto Program Entry Point)

在工具栏按或菜单的转到(Goto)选项选择 转到程序入口点(Goto Program Entry Point)或按F10,这样光标将来到程序入口点(Entry Point),这里就是程序执行的起始点,一般动态调试时LOAD时也就停在此处。

3.3 转到页(Goto Page)

在工具栏按或菜单的转到(Goto)选项选择转到页(Goto Page)或按F11,这时跳出一对话框,输入页数可跳转到相关页面去。



3.4 转到代码位置(Goto Code Location)

在工具栏按或菜单的转到(Goto)选项选择转到代码位置(Goto Code Location)或按F12,一个对话框将出现,充许用户输入代码偏移地址,以跳转到此位置上去。



3.5 执行文本跳转(Execute Text Jump)

这功能是在Execute Text(执行文本)菜单选项里的,执行跳跃(Execute Jump)功能激活条件是光标在代码的跳转指令这行上(这时光条是高亮度的绿颜色)。此时工具条Jump To按钮也激活。如图:



此时按或菜单选项Execute Jump(执行跳跃)或按右光标键,光条将来到跳转指令所指到的位置。在这例子里,将来到:004076CE xor eax,eax 这一行代码处:



如要返回到上一次跳跃,请参考3.6.

3.6 返回到上一次跳跃Return From Last Jump

这功能是在Execute Text(执行文本)菜单选项里的,此指令仅仅是在 执行文本跳转功能完成后才激活。当这条件成立时,按钮将激活。按或在菜单里选项返回到上一次跳跃(Return From Last Jump)或按左光标键,光条将返回到上一次跳跃位置处。

3.7 执行呼叫Execute Text Call


这功能是在Execute Text(执行文本)菜单选项里的,此功能激活的条件是光条在CALL指令一行。在这一行时光条将发绿,按钮将激活。执行时光条将会来到CALL所指的地址处。
如下图: 光条在0040751D call 004073D4 一行。



此时按或在菜单的执行呼叫(Execute Text Call)或按右光标键,光条将来到CALL所指的地址004073D4这一行。



如要返回到刚才起点的0040751D call 004073D4 一行,参考3.8的返回呼叫。

3.8 返回呼叫(Return From Last Call)

这功能是在Execute Text(执行文本)菜单选项里的,此指令仅仅是在执行呼叫Execute Text Call功能完成后才激活。当这条件成立时,按钮将激活。按或在菜单里选项返回呼叫(Return From Last Call)或按左光标键,光条将返回到上一次呼叫位置处。

3.9 导入功能(Imported)

在菜单功能选项里,其作用主要是查看import函数。按或在菜单功能选项里的导入(Imports)命令,执行后将列出当前文件的Import函数。



你可双击这些项目,光条将来到调用这些函数的代码处。
注意:如果代码多处引用了这些函数,你双击这个项目函数时,光条将在调用了其的几个位置代码处循环.
你也可用copy all或copy view复制import函数。

3.10 出口功能(Exported)

在菜单功能选项里,其作用主要是查看Export函数。按或在菜单功能选项里的出口(Exports)命令,执行后将列出当前文件的Exports函数。

注意:一般EXE文件没有exported,DLL文件有exported函数。

3.11 裁判(References)

在这个菜单选项里有菜单参考(MENU), 对话参考(DIALOG) or (串式数据参考STRING DATA),分别对应按钮:,或。

注意:其中(串式数据参考STRING DATA)功能破解时很常用。

4.0 复制汇编代码文本

W32dasm充许打印或复制指定行的汇编代码。首先你将鼠标移到W32DASM的最左边单击,将会出现一个小红点,再按住shift键,移到你需要的下一行,再单击鼠标一下,将选中一段,按CTRL+C复制或在菜单选项反汇编里的拷贝指定的行(Copy Lines of Text)功能或按,把数据复制到剪贴板里。如:



5.0 装载32位的汇编代码动态调试

5.1 反汇编windows自带的计算器程序 calc.exe.

5.2 选择菜单调试选项中的加载处理(Load Process),或按Ctrl+L.出现一个加载对话框,你可输入选项命令。现在你可按装载(load)按钮。

Calc.exe现在被W32DASM动态调试,将出现左右两个调试窗口(如下图),在初始化calc.exe程序后,指令将停留在入口点(Entry Point)处。

左边的调试窗口列出各种状态器如:CPU寄存器,CPU控制寄存器,断点,活动的DLL,段寄存器等等;

(左调试窗口)

(右调试窗口)

6.0 运行,暂停或终止程序

6.1 在右调试窗口,按运行(RUN)按钮或按F9,calc.exe将运行起来。

按暂停(PAUSE)按钮或空格键,程序将暂停,这在单步跟踪时经常用到。

按终止(TERMINAT)按钮,程序将停止,退出动态调试环境。

7.0单步跟踪程序

7.1 重新加载 calc.exe

7.2 在程序加载后,停留在入口点,你可按F7或F8单步调试程序,这两个键所不同的是F7是跟进CALL里,F8是路过。

7.3 进入自动调试按 (F5) 和结束自动调试按 (F6) 。

8.0设置激活断点

8.1 重新加载 calc.exe

8.2 在W32DASM的菜单转到选项转到代码处(goto code)功能,填上403198,按确定,你将在W32Dasm的主窗口(此时可能最小化了,把其还原即可)来到403198地址一行。光条在这一行显亮绿色,按F2或用鼠标左点击最左边(同时按住CTRL)设置断点。

这时如断点设置成功,光条最左边有一小段黄条,显示此行为断点。如下图:



如果断点不在这里,整行光条将是黄色的。

当断点设置好后,在左调试窗口中的断点小窗口显示断点情况(右边有一*):



此时按F2或(鼠标左键+CTRL),断点将取消。

8.3 此时按F9程序将运行到相关断点时停止。

9.0 偏移地址和虚拟地址转换

W32DASM、SOFTICE和Hiew(Decode模式)显示的地址都是虚拟地址,但是在Hiew(Decode模式)下,F5功能键查找的地址是偏移地址,因此必须将虚拟地址转换成偏移地址,才能找到正确的地址。常用的方法是在W32DASM下将绿色的光条移到某一行代码上 , 在窗口底部有一行字指示其偏移地址 , 如虚似地址:Code DaTa@0040534e而偏移地址为:@Offset 0000474Eh. 这就是偏移地址。



10.0 结束

(要了解更多的内容参考W32DASM的帮助文件)

三节 IDA Pro简介

程式猎人翻译
(译者注:欢迎访问程式猎人的主页:http://programhunter.126.com)
对象:IDA Pro反汇编软件
目标: N/A
URL: www.datarescue.com
作者: BlackB
日期: 2000-06-05
使用工具: Your brain
难度等级(级 1-5): 1

开始前

  IDA Pro Avanced是一个极好的反汇编工具,它大的胜过了w32dasm。近来它的盗版已经在网上传播开了,你可以很轻松得到它。对于这方面的观点有如下几种:一些人认为这是好的,是自由的;而另一些人认为是可耻的,那些认为是可耻的人通常是这个软件的老用户,事实上他们买了那个程序,如果你花了$500买了那个程序的话,你就可以理解他们的反应了。 对于读者来说,你们做什么不是我的问题及我所关心的。而我的观点是如果认为非法的winzip软件同IDA Pro 4.0x一样好或坏。如果你使用非法的winzip,你就不应当使用非法的IDA Pro。

I 介绍

  几天前我烈军属了一篇关于解密程序的教程,而这篇也是一个对于高效的,极好的IDA Pro 4.0x教程。通常菜鸟不喜欢,而高手又崇拜它。不喜欢的原因是因为IDA相对于w32dasm来说有更多的附加功能和作用,有更大的复杂性
在下面的教程中由于你过去可能喜欢使用w32dasm,我将尽力给出一个简单和清楚的解释来介绍如何使用IDA。也将试差回答"什么是最好的反汇编?"这里其实没有一个简单的回答。对于更多的高手来说可以读这个:向菜鸟100%解释IDA的使用过程。

II. IDA: 一个高效的反汇编工具

  当你运行IDA Pro时,你所最先注意到的是它的界面比w32dasm更加专业,这里比w32dasm有更多的选项或更先进的地方。它的优点是可以更好的反汇编和更有深层分析。而缺点是使用IDA更困难。
实际上IDA同w32dasm有很多相同的功能:可以快速到达指定的代码位置;可以看到跳到指定的位置的jmp的命令位置;可以看参考字符串;可以保存静态汇编等。
  现在让我们运行和反汇编一个小程序(我使用starclean.exe)一个窗口弹出来,那里有很多选项,不要动它,仅仅点击OK。让IDA来分析,当它结束后在name的选项中同w32dasm中参考字符串一样,查找"a"字符。在name窗口中搜索栏中按a,然后开始查找,一旦找到,按enter或双击它,它就将到达正确的位置。按ctrl+enter将到达下一个位置。参考字符串就在光标附近。IDA就可以到达相应的位置了。
另一个同w32dasm相同的:jmp和call参考在IDA也是有效的。在w32dasm反汇编的代码同IDA中相同的。

代码开始(w32dasm)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00403B50(C)
|
:00403B5F 81FAFC000000 cmp edx, 000000FC
:00403B65 0F8478010000 je 00403CE3
:00403B6B 8D8424B4000000 lea eax, dword ptr [esp+000000B4]
:00403B72 6804010000 push 00000104
:00403B77 50 push eax

* Reference To: KERNEL32.GetModuleFileNameA, Ord:00E9h
|
:00403B78 8B2D88924000 mov ebp, dword ptr [00409288]
:00403B7E 6A00 push 00000000
:00403B80 FFD5 call ebp
:00403B82 85C0 test eax, eax
:00403B84 7516 jne 00403B9C

* Possible StringData Ref from Data Obj ->""
|
:00403B86 BE206A4000 mov esi, 00406A20
:00403B8B 8DBC24B4000000 lea edi, dword ptr [esp+000000B4]
:00403B92 B905000000 mov ecx, 00000005
:00403B97 F3 repz
:00403B98 A5 movsd
:00403B99 66A5 movsw
:00403B9B A4 movsb结束结束

代码开始(IDA Pro 4.0x)

00403B5F loc_403B5F: ; CODE XREF: sub_403B00+50j
00403B5F cmp edx, 0FCh
00403B65 jz loc_403CE3
00403B6B lea eax, [esp+1B8h+var_104]
00403B72 push 104h
00403B77 push eax
00403B78 mov ebp, ds:GetModuleFileNameA
00403B7E push 0
00403B80 call ebp ; GetModuleFileNameA
00403B82 test eax, eax
00403B84 jnz short loc_403B9C
00403B86 mov esi, offset aProgramNameUnk ; ""
00403B8B lea edi, [esp+1B8h+var_104]
00403B92 mov ecx, 5
00403B97 repe movsd
00403B99 movsw
00403B9B movsb
代码结束

你在这里看到,IDA提供了更多的细节信息,它是更加清楚,用一个参考作为例子。
在w32dasm中如下:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00403B50(C)

在IDA Pro中如下:
CODE XREF: sub_403B00+50j

IDA provides 使用更短的行来提供更多的信息。
1. 用一个jump (j)
2. jump到代码的位置位于00403B50 (=403B00+50)
3. 函数/call本身在403B00(403B00+50)
4. jump在.code section

  如果参考的是一个call那么它将如下:
CODE XREF: sub_403B00+50p

  另一个大的优点是IDA可以转换变量。你可以双击变量以找到它们保存的地址处: lea edi, [esp+1B8h+var_104]。
功能中最有用的之一是使用近似查找。很容易解释:IDA尽力记住寄存器所关联的库函数。如下:

代码开始 (IDA Pro)


004012D2 loc_4012D2: ; CODE XREF: sub_401280+5Fj
004012D2 movsx ecx, byte ptr [eax]
004012D5 push eax
004012D6 lea ebp, [ebp+ecx*2+0]
004012DA call edi ; CharNextA ; Return a pointer to the next character in a ; string
004012DC cmp byte ptr [eax], 0
004012DF jnz short loc_4012D2
代码结束

代码开始 (w32dasm)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004012DF(C)
|
:004012D2 0FBE08 movsx ecx, byte ptr [eax]
:004012D5 50 push eax
:004012D6 8D6C4D00 lea ebp, dword ptr [ebp+2*ecx]
:004012DA FFD7 call edi
:004012DC 803800 cmp byte ptr [eax], 00
:004012DF 75F1 jne 004012D2代码结束

  你注意到它们的不同了吗?IDA将向解释每一件事情。
  在IDA中另一个同w32dasm近似的是十分简单的,如:"Goto code location" 等同于在IDA"Jump - Jump to adress" . 或者 "Goto entrypoint" 等同于在IDA"Jump - Jump to entry point" .

  那些就是在你了解IDA开始使用它前最为重要的东西。有时 ,IDA显示大量的"db",参考字符串,仅有代码。仅仅可以设好光标,按"c"键,IDA转换代码如下


开始 (在按'C'之前)

00401228 dd offset unk_406130
0040122C db 8Bh ; ?0040122D db 35h ; 5
0040122E dd offset RegSetvalueExA
00401232 db 6Ah ; j
00401233 db 1 ;
00401234 db 6Ah ; j
00401235 db 0 ;
00401236 db 68h ; h
00401237 dd offset aName ; "Name"
0040123B db 51h ; Q
0040123C db 0FFh ;
0040123D db 0D6h ; ?0040123E db 8Bh ; ?0040123F db 4Ch ; L
00401240 db 24h ; $
00401241 db 8 ;
00401242 db 68h ; h
代码结束

开始 (在按'C'之前)

0040122C mov esi, ds:RegSetvalueExA
00401232 ; ---------------------------------------------------------------------------
00401232 push 1
00401234 push 0
00401236 push offset aName ; "Name"
0040123B ; ---------------------------------------------------------------------------
0040123B push ecx
0040123C call esi ; RegSetvalueExA
0040123E mov ecx, [esp+8]
00401242 push 100h
00401247 push offset unk_406030
0040124C ; ---------------------------------------------------------------------------
0040124C push 1
0040124E push 0
00401250 push offset aCode ; "Code"
00401255 ; ---------------------------------------------------------------------------
00401255 push ecx
00401256 call esi ; RegSetvalueExA
00401258 mov eax, [esp+8]
0040125C push eax
0040125D call ds:RegCloseKey
代码结束

IDA另一个优点(快速相加):

1. 能够对w32dasm无法反汇编的最难的软件进行反汇编(如加壳程序)
2. 能够以.asm .sym 和甚至是 .exe及其它文件形式保存
3. 压缩的静态汇编,可以节省大量的磁盘空间。
4. 可以重命名函数
5. 能够分析巨大的程序
等等.... ;-)


III. w32dasm??


  你看完了后你现在可以自问"如果IDA这么好看,为什么我还要使用w32dasm?"下面就是对于这个的解释:
首先是速度,对于IDA来分析一个小程序是非常非常的快,但是如果分析一个大的exe它就要花费3个小时或更多的时间来全面分析exe。
其次,如果你对于一个指定的搜索,IDA将很慢的,而在w32dasm中在文本方面中搜索是很快的。
第三:当分析一个仅有简单的保护的程序时,w32dasm就为首选。因为你就不需要在IDA那些附加的功能了。
上面的三个因素可以说明一切了 :-) 如果你知道其它的使用w32dasm原因的话,请告诉我。


IV. 结束

  又一个教程结束了。享受IDA and w32dasm以及所有.....享受研究和保持学习和继续研究和破解吧。不是为了解密,仅是文章,写下你的文章,传播你的知识。对于解密这是重要的来说。不要用于解密吧。

感谢大家

The Blackbird

Endnote:
  The Blackbird 创作于1999-2000
此文章可以自由分发,出版,打印……等尽可能长的修饰。


标签集:TAGS:
回复Comments() 点击Count()

回复Comments

{commentauthor}
{commentauthor}
{commenttime}
{commentnum}
{commentcontent}
作者:
{commentrecontent}