逆向破解的基础

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 逆向破解的基础

1. 中断点:所谓中断点就是程式被中断的地方,这个词对于解密者来说是再熟悉不过了。那麽什麽又是中断呢?中断就是由于有特殊事件(中断事件)发生,电脑暂停当前的任务(即程式),转而去执行另外的任务(中断服务程式),然后再返回原先的任务继续执行。打个比方:你正在上班,突然有同学打电话告诉你他从外地坐火车过来,要你去火车站接他。然后你就向老板临时请假,赶往火车站去接同学,接著将他安顿好,随后你又返回公司继续上班,这就是一个中断过程。我们解密的过程就是等到程式去获取我们输入的注册码并准备和正确的注册码相比较的时候将它中断下来,然后我们通过分析程式,找到正确的注册码。所以我们需要为被解密的程式设置中断点,在适当的时候切入程式内部,追踪到程式的注册码,从而达到crack的目的。


2. 领空:这是个非常重要的概念,但是也初学者是常常不明白的地方。我们在各种各样的破解文章裡都能看到领空这个词,如果你搞不清楚到底程式的领空在哪裡,那麽你就不可能进入破解的大门。或许你也曾破解过某些软件,但那只是瞎猫碰到死老鼠而已(以前我就是这样的^_^,现在说起来都不好意思喔!)。所谓程式的领空,说白了就是程式自己的地方,也就是我们要破解的程式自己程式码所处的位置。也许你马上会问:我是在程式运行的时候设置的中断点,为什麽中断后不是在程式自己的空间呢?因为每个程式的编写都没有固定的模式,所以我们要在想要切入程式的时候中断程式,就必须不依赖具体的程式设置中断点,也就是我们设置的中断点应该是每个程式都会用到的东西。在DOS时代,基本上所有的程式都是工作在中断程式之上的,即几乎所有的DOS程式都会去调用各种中断来完成任务。但是到了WINDOWS时代,程式没有权力直接调用中断,WINDOWS系统提供了一个系统功能调用平台(API),就向DOS程式以中断程式为基础一样,WINDOWS程式以API为基础来实现和系统打交道,从而各种功能,所以WINDWOS下的软件破解其中断点设置是以API函数为基础的,即当程式调用某个API函数时中断其正常运行,然后进行解密。例如在SOFTICE中设置下麵的中断点:bpx GetDlgItemText(获取对话方块文本),当我们要破解的程式要读取输入的资料而调用GetDlgItemText时,立即被SOFTICE拦截到,从而被破解的程式停留在GetDlgItemText的程式区,而GetDlgItemText是处于WINDWOS自己管理的系统区域,如果我们擅自改掉这部分的程式码,那就大祸临头了^_^!所以我们要从系统区域返回到被破解程式自己的地方(即程式的领空),才能对程式进行破解,至于怎样看程式的领空请看前面的SOFTICE图解。试想一下:对于每个程式都会调用的程式段,我们可能从那裡找到什麽有用的东西吗?(怎麽样去加密是程式自己决定的,而不是调用系统功能实现的!)


3. API:即Application Programming Inte**ce的简写,中文叫应用程式设计发展介面,是一个系统定义函数的大集合,它提供了访问作业系统特徵的方法。 API包含了几百个应用程式调用的函数,这些函数执行所有必须的与作业系统相关的操作,如记忆体分配、向萤幕输出和创建视窗等,使用者的程式通过调用API介面同WINDOWS打交道,无论什麽样的应用程式,其底层最终都是通过调用各种API函数来实现各种功能的。通常API有两中基本形式:Win16和Win32。 Win16是原来的、API的16位版本,用于Windows 3.1;Win32是现在的、API的32位版本,用于Windows 95/98/NT/ME/2000。Win32包括了Win16,是Win16的超集合,大多数函数的名字、用法都是相同的。16位元的API函数和32位元的API函数的区别在于最后的一个字母,例如我们设置这样的中断点:bpx GetDlgItemText、bpx GetDlgItemTextA和bpx GetDlgItemTextW,其中 GetDlgItemText是16位元API函数,GetDlgItemTextA和GetDlgItemTextW是32位元API函数,而GetDlgItemTextA表示函数使用单字节,GetDlgItemTextW表示函数使用双位元组。现在我们破解中常用到的是Win32单字节API函数,就是和GetDlgItemTextA类似的函数,其它的两种(Win16 API和Win32双位元组API函数)则比较少见。 Win32 API函数包含在动态连结程式库(Dynamic Link Libraries,简称DLLs)中,即包含在kernel32.dll、user32.dll、gdi32.dll和comctl32.dll中,这就是为什麽我们要在softice中用exp=C:\windows\system\kernel32.dll等命令列将这些动态连结程式库导入softice中的原因。因为不这样做的话,我们就无法拦截到系统Win32 API函式呼叫了。


4. 关于程式中注册码的存在方式:破解过程中我们都会去找程式中将输入的注册码和正确的注册码相比较的地方,然后通过对程式的跟踪、分析找到正确的注册码。但是正确的注册码通常在程式中以两种形态存在:显式的和隐式的,对于显式存在的注册码,我们可以直接在程式所处的记忆体中看到它,例如你可以直接在SOFTICE的资料视窗中看到类似"297500523"这样存在的注册码(这裡是随意写的),对于注册码显式存在的软件破解起来比较容易;但是有些软件的程式中并不会直接将我们输入的注册码和正确的注册码进行比较,比如有可能将注册码换算成整数、或是将注册码拆开,然后将每一位注册码分开在不同的地方逐一进行比较,或者是将我们输入的注册码进行某种变换,再用某个特殊的程式进行验证等等。总之,应用程式会採取各种不同的複杂运算方式来回避直接的注册码比较,对于这类程式,我们通常要下功夫去仔细跟踪、分析每个程式功能,找到加密演算法,然后才能破解它,当然这需要一定的8086彙编程式设计功底和很大的耐心与精力。


5. 关于软件的破解方式:本人将破解方式分为两大类,即完全破解和暴力破解。所谓完全破解主要是针对那些需要输入注册码或密码等软件来说的,如果我们能通过对程式的跟踪找到正确的注册码,通过软件本身的注册功能正常注册了软件,这样的破解称之为完全破解;但如果有些软件本身没有提供注册功能,只是提供试用(DEMO),或是注册不能通过软件本身进行(例如需要获取另外一个专用的注册程式,通过INTERNET的注册等等),或者是软件本身的加密技术比较複杂,软件破解者的能力、精力、时间有限,不能直接得到正确的注册码,此时我们需要去修改软件本身的程式码,即人为改


6. 关于破解教程中程式码地址问题:破解教程中都会放上一部分程式码以说明讲解程式的分析方法,例如下面的一段程式码:


...... 
0167:00408033 PUSH 00 
0167:00408035 PUSH EBX 
0167:00408036 CALL [USER32!EndDialog] 
0167:0040803C JMP 0040812C 
......


在这裡程式中的代码位址如0167:00408033,其程式码片段的值(即0167)有可能根据不同的电脑会有区别,不一定一模一样,但偏移值应该是固定的(即00408033不变),所以如果看到破解文章裡的程式码的地址值和自己的电脑裡不一样,不要以为搞错地方了,只要你的程式码正确就不会有问题。


7. 关于如何设置中断点的问题:正确恰当的设置好中断点对于快速有效的解密非常重要,好的中断点设置可以使我们迅速找到关键的程式段,而不恰当的中断点则会对解密造成不必要的精力消耗,甚至根本就不能拦截到程式的运行。但是具体什麽时候用什麽中断点比较合适很难说,这需要自己用经验去累积,总的说来bpx hmemcpy这个万能中断点对大多数注册码方式的软件都有用,初学者不妨多试试这个中断点(通常我也是用这个中断点设置,懒嘛^_^,哈哈。。。)。对于那些需要暴力破解的非注册码方式的软件,通常我们应该拦截对话方块(如bpx DialogBox)和讯息方块(如bpx MessageBox(A))等。不论对于哪一类软件,当我们设置的中断点均没有效果时,可是试一下bpx lockmytask,这个中断点的作用是拦截任何一个按键的动作,具体常用的一些中断点设置请参考"破解常用中断点设置"一文。另外,在注册码的破解中通常需要输入用户名和注册码,一般说来用户名和密码都可以随意输入,但是根据我自己的经验,很多软件对于注册码都会逐位元的进行处理,假如输入"78787878"这串数位,那麽在跟踪程式的时候我们就无法知道我们当时所看到的"78"倒底是哪一个"78",所以我比较喜欢用"12345678"这样的注册码输入方式,这样的话就就能知道程式是在对注册码的哪一位进行运算,同样的对于那些需要输入较长序号的软件,输入类似"12345-67890-ABCDEF"这样的序号较好。 不过有一点大家需要特别的注意:上面讲的注册码输入方式"12345678"是针对拦截WIN32 API函数来说的,假如有些时候直接拦截WIN32 API函数难以找到程式的突破口,而要借助于"S"指令在记忆体中寻找我们输入的用户名或注册码时,就最好不要採用"12345678"作为注册码,因为记忆体中很可能有许多的"12345678"字串,这样我们没有办法知道倒底我们要破解的程式使用的是哪一个"12345678",所以我们应该选择一个不易和记忆体资料相同的注册码,比如:74747474(本人喜欢用,意思嘛:去死去死。。。哈哈哈^_^),对应的搜索指令为: S 30:0 L FFFFFFFF '74747474' 。当然,以上只是我个人的习惯而已,具体用什麽样的输入形式可以根据本人的爱好、习惯来定,不必拘泥于某一固定的模式。


8. 关于如何跟踪程式的问题:初学者在开始学习解密的时候往往不知道怎麽样去跟踪程式,怎麽样找到注册码比较的地方,当面对长长的一堆程式码时显得不知所措。通常软件的程式内部都会利用一个子程式(即 CALL ********)去验证我们输入的注册码正确与否,对于注册码显式存在的程式,一般都会将所输入的注册码和正确的注册码放进寄存器,然后调用验证副程式进行判断,将结果返回,应用程式根据副程式返回的结果决定是否注册成功,这样的程式经常具有如下的形式:

****:******** MOV EAX,[********]  (或 PUSH EAX等形式) 
****:******** MOV EDX,[********]  (或 PUSH EDX等形式) 
****:******** CALL ******** 
****:******** TEST EAX,EAX     (或 TEST AL,AL,或是没有这一句等形式) 
****:******** JNZ ********     (或 JZ ********等形式)

其中EAX和EDX指向的记忆体区域就是我们输入的注册码和正确的注册码,这裡的寄存器EAX和EDX是随意写的,也可以是ECX,EBX,EDI,ESI等等。对于注册码隐式存在的程式,虽然不能直接看到正确的注册码,但是通常也是先将所输入的注册码位址放进某个寄存器,然后调用副程式去验证,破解时就需要进入副程式去分析注册演算法。总之,看到副程式(call ********)后面跟著跳转指令(JNZ ********或JZ ********)的地方我们就应该提高警惕,多用 D EAX(或EBX、ECX、EDX、EDI、ESI...等)去看看寄存器指向的记忆体区域藏著什麽东西。有一点大家要提醒大家:看见程式中使用下面这个函数是要注意,即GetDlgItenInt,这个API函数的作用是将输入的文本转化为整数,所以这类程式中是不会有显示存在的注册码的,因为注册码被转换为整数了,程式通常会用CMP ECX,EDX 这种类型的指令去验证注册码的正确性,这裡ECX和EDX中存的就是所输入注册码和正确注册码的整数形式,此时可以用 ? edx 和 ? ecx 看到其十进位形式,即我们输入的形式。


9. 关于软件的反安装问题:经常我们使用某些软件时都会遇到一个问题,就是共用软件过期之后即使删掉原程式重新安装,程式依然不能用,还是一样提醒你试用期已过请注册;或者是你已经破解了某个软件,但是还想继续研究它,但是因为软件已经注册好,没有了注册选项,这时你即使彻底删掉程式再重新安装软件,结果程式运行后还是注册过的。遇到这样的情况,其实原因很简单,因为程式将注册或过期资讯存在了系统登录裡,所以简单的重新安装软件是无济于事的。解决的办法就是自己删掉注册表中有关的资讯,但是因为注册表是WINDOWS系统工作的基础,如果不小心就很可能会损坏它而引起系统异常,所以如果你对注册表不是很熟的话,应该在修改之前备份一下注册表。不论是修改还是备份注册表都可以使用WINDOWS下的注册表管理工具"REGEDIT"来进行,一种办法是在"开始->运行"下输入"regedit"启动它,也可以直接点击"C:\WINDOWS\regedit.EⅩE"来运行。大部分的应用软件都会将自己的资讯存在如下的路径中:HKEY_LOCAL_MACHINE\Software、HKEY_LOCAL_MACHINE\Software\Microsoft、HKEY_CURRENT_USER\Software、HKEY_CURRENT_USER\Software\Microsoft 或 HKEY_USERS\.DEFAULT\Software下,具体是哪个地方依据不同的程式而有所不同,只要按上面的顺序肯定能找到有关应用程式的键,然后将和用户名及注册码有关的键值删掉就搞定了。


10. 关于破解练习的问题:学习破解需要大量的练习,对于破解目标的选择,初学者不宜以大型的、著名的软件为目标,因为这些软件通常加密较为複杂,破解不易,应该选择一些比较不出名的、小型的和早些时候的共用软件来练习,因为加密相对简单的软件有利于初学者快速掌握破解思想和技能。至于习题的来源则很广泛,可以从网上下载,也可以去市面上购买一些共用软件光碟。

目录
相关文章
|
7月前
|
传感器 编解码 C++
C++视频基础
C++视频基础
|
IDE C# 开发工具
C#基础总结(1)
C#基础总结(1)
83 0
|
数据安全/隐私保护
基础练习-6
基础练习-6
79 0
|
JavaScript 前端开发 API
Typesctipt基础(二)
Typesctipt基础(二)
139 0
|
存储 C#
C#基础03
C#基础03
136 0
C#基础03
|
开发框架 安全 .NET
C#基础04
C#基础04
129 0
C#基础04
|
存储 Java 编译器
C/C++ - 基础篇(下)
C/C++ - 基础篇(下)
242 0
C/C++ - 基础篇(下)
|
图形学 Windows
GDI+基础
GDI+的核心是 Graphics 对象,Graphics 类定义了绘制和填充图形对象的方法和属性。Graphics 类的属性(字段)很多,具体可参见 MSDN。Graphics 类的方法分为三类:绘制、填充及其他。
749 0
GDI+基础
|
缓存 网络协议 Python
python网络编程基础
目录 1、udp 2、tcp 3、socket函数 4、粘包问题 标签(空格分隔): 网络编程 目录 tcp和udp 1、udp tcp、udp是第四层传输层拥有的协议,用于在完成寻址功能后的数据传输。