【转】适合的新手破解教程+练手的各种基础软件(本教程的亮点是练手的软件实战破解)
本帖最后由 Jorge 于 2015-4-6 14:31 编辑破解入门-第一章-前言 好多哥们儿说看教程跟老大的书都看不太明白,所以,我尽量把话说到最容易理解的份上,本文写给那些刚入门和尚未入门的朋友们...
目录
no.1------------------前言(说明一下)
no.2------------------汇编语言
no.3------------------Windows程序
no.4------------------调试器及相关工具入门
no.5------------------破解原理
no.6------------------初级破解实践,强暴一个软件
no.7------------------中级破解实践,找到注册码及写内存注册机
no.8------------------高级破解实践,分析软件算法,编写注册机
常见的修改方法有两种,我给你举例说明:
no.1
在某软件中,这样来进行注册:
00451239 CALL 00405E02(关键CALL,用来判断用户输入的注册码是否正确)
0045123D JZ 004572E6 (!!!<--此为关键跳转,如果用户输入的注册码正确,就跳向成功处,即004572E6处)
0045XXXX YYYYYYYYYY
XXXXXXXX YYYYYYYYYY
XXXXXXXX YYYYYYYYYY
XXXXXXXX 执行到此处,就提示用户注册失败
...提示用户注册码不正确等相关信息
...
004572E6 ...<--(注册成功处!!!)
...提示用户注册成功等相关信息
呵呵,看明白了吗?没有的话,我来给你讲一下。在软件执行到00451239处的时候,CALL置0045E02处来进行注册码判断。接着回来后就来一个跳转语句,即如果用户输入的注册码正确就跳到004572E6处,跳到此处,就算是注册成功了。如果用户输入的注册码不正确的话,那么就不会在 0045123D处进行跳转,而一直执行下去。在下面等它的,是注册失败部分。
想明白了吗?嘿嘿...没错,我们只要把那个关键跳转JZ给改为JNZ(如果用户输入的注册码错误,就注册成功,输入正确则注册失败)。当然你也可以将JNZ修改为Jmp,这样的话,你输入的注册码无论正确与否。都可以注册成功。
no.2
我们再来讲一下另外的一种情况:
00451239 CALL 00405E02(关键CALL,用来判断用户输入的注册码是否正确)
0045123D JNZ 004572E6 (!!!<--此为关键跳转,如果用户输入的注册码不正确,就跳向失败处,即004572E6处)
0045XXXX YYYYYYYYYY
XXXXXXXX YYYYYYYYYY
XXXXXXXX YYYYYYYYYY
XXXXXXXX 执行到此处,就提示用户注册成功
...提示用户注册成功等相关信息
...
004572E6 ...<--(注册失败处!!!)
...提示用户注册码不正确等相关信息
这次我相信,并且深信不疑。你一定明白了。我还是不明白...倒...
你一定看出跟第一种情况不同的地方了吧。没错!它与第一种不同的,就是第一种情况是如果注册码正确,就跳到注册成功处,如果没有跳走,就会执行到失败处。而这一种情况则是如果注册码不正确,就跳到注册失败处,否则将执行到注册成功处。
这种情况的修改,除了把JNZ改为JZ外,还可以将其改为Nop,Nop这个指令没有任何意义,将该条指令修改为Nop后,便可随意输入注册码来进行注册了。
原理以经给你讲了,下面我们再来讲一下具体的修改办法吧。(我假设你以经明白了我所说的工具的使用方法)
先说一下虚拟地址和偏移量转换的问题,在SoftICE和W32Dasm下显示的地址值是所谓的内存地址(memory offset),或称之为虚拟地址(Virual Address,VA)。而十六进制工具里,如:Hiew、Hex Workshop等显示的地址就是文件地址,称之为偏移量(File offset) 或物理地址(RAWoffset)。
所以当我们要通过那些十六进制工具来对可执行文件中的相应指令进行修改的话,先要找到它的Fileoffset。我们没有必要去使用那些专门的转换工具,在W32Dasm中就有这个功能,比如说你W32Dasm中来到0045123D处,在 W32Dasm界面下方的状态栏中就会出现该条指令的虚拟地址和偏移地址,即@:0045123D@offset 0005063Dh 后面的这个0005063Dh就是相应的偏移地址。我们得到该地址后,便可用UltraEdit等十六进制工具来对可执行文件进行修改了。比如使用UltraEdit,你先用UltraEdit打开该可执行文件,然后按Ctrl+G,接着输入你得到的偏移地址,就可以来到其相应的机器码处。
再给你讲一下机器码,所谓的机器码。就是你看到的那些个十六进制数据了。还记的它们与汇编指令是一一对应的吗?
以下这几个是爆破时要用到的,其它的如果感兴趣,可自行查看相关资料:
JZ=74;JNZ=75;JMP=EB;Nop=90
爆破的时候,只要对以上机器码进行相应的修改就行了,比如第一种情况的时候,可以将74修改为EB,即将JZ修改为JMP。而第二种情况,责需将75修改为90,即将JNZ修改为Nop。
由于本章只讲原理,具体一点的。如怎样找到关键跳转等,我们在下一章中再讲。(一个砖头飞了上来!嘿嘿,这次被俺接到了)
上边讲了爆破的原理,你需要明白的是。爆破只是你学习Crack的开始,是很简单的手段。刚入门的时候可以玩玩儿,但希望你不要就此不前!
(嘿嘿,再说了。人家的软件中不是都说了嘛,不准对其进行逆向修改。你动了人家的身子,怎么能不买帐呢? )
偶就不喜欢爆破,做不出注册机也要找出注册码。否则我就不会去注册这个软件,既然想不掏钱,就要靠你自己的本事。(等以后我有钱了,会考虑去注册那些优秀的共享软件的 )。所以,从某种意义上来说,我是一个正人君子
其实要找到注册码并不是一件多么难的事,我是指你所针对的软件不太那个的时候 不过你无需惧怕。
刚才我们说爆破的时候不提到过关键CALL吗?一般情况下,这个关键CALL就是对两个注册码(一个是软件自身通过你的注册名或机器什么的计算出来的正确的注册码,令一个就是你输入的错误的注册码)进行比较。我前边提到过,CALL之前一般会把所用到的数据先放到一个地方,CALL过去的时候再从这些地方把先前放入的数据取出来,进行相应的处理。这个关键CALL也是这样,在CALL之前,一般会把那两个注册码放到堆栈或某个寄存器中。嘿嘿,我们只要在调试器中,单步执行到该CALL,在未进去之前通过CALL之前的指令判断其将正确的和不正确的注册码放到哪里了。然后再用相应指令进行查看就成了,我说过不难的。
下面列出两个最常见的情况(可参考相关教程):
no.1
moveax [ ]这里可以是地址,也可以是其它寄存器
movedx [ ]同上,该条指令也可以是pop edx
call 00?????? 关键call
test eax eax
jz(jnz)或jne(je)关键跳转
看明白了吧,在关键CALL之前,软件会把两个注册码分别放入eax和edx中,你只要在CALL处下d eax或d edx就能看到正确的注册码了。
no.2
moveax [ ]这里可以是地址,也可以是其它寄存器
movedx [ ]同上,该条指令也可以是pop edx
call 00?????? 关键call
jne(je) 关键跳转
以上两种情况最为常见,而那些个不太常见的情况,我们这里就不再提了。到下下一章的时候,我会给你讲相关方法的...
关于查找软件注册码的部分,就到这里。具体内容,下下一章咱们再说。(不是说了吗?我以经可以接到你的砖头了,干嘛还要丢呢? )
最后,再来说最后的所谓的高级阶段,如果你相信自己。并且热爱Crack,那么你一定会熬到这个阶段的,只是时间因人而异。
其实分析软件的算法,是有好多技巧在里面的。呵呵,最起码我刚开始的时候就摸不着头脑,那么多CALL,每个看起来,都很重要,都追一遍?结果连好多API 都被追了进去。等你自己真正用心分析了一个软件的算法,并写出了注册机后。你就会明白其中的道理了,我们下下下一章再说。(大哥,你不是吧,连你家太阳能都丢过来了)
<本章完>
第六章--爆破软件
爆破其实很简单,最起码比你能一下把你家的牙膏给全挤出来要容易多了。你只要先到大街上买几根雷管,然后放到你的显示器上再点着就OK了(不难吧,记的点着后跑远点儿)
爆破的原理我也说过了,相信你很容易就能理解了。我们今天就具体讲一下如何找到那个关键跳转以及如何才能买到即便宜又好用的雷管...
爆破一个软件一般只需要很少的几个步骤,首先先看一下其有无加壳,有的话是用何工具加的壳,知道了以后用相应的工具将其脱掉或进行手工脱壳,参考以有教程。接着我们就可以对脱过壳之后的软件来开刀了。你有两种选择,用W32Dasm或调试器,一般如果你遇上的是那种很菜的软件的话,用W32Dasm就可以搞定了。如果遇上的不是那种比较菜的,就买股票吧,因为股票是你如胶似漆的妻子!当!快醒醒啊...哦,一般如果你遇上的不是那种很菜的软件的话,就用调试器吧。先来说W32Dasm:我们首先用W32Dasm来进行反汇编(废话!)之后在串式参考中找到错误提示信息或可能是正确的提示信息双击鼠标左键来到相应的地址处。在W32Dasm的主窗口中分析相应汇编代码,找出关键跳转和关键call。绿色光条停在关键跳转,在W32Dasm主窗口底部找到关键跳转的偏移地址(实际修改地址)。用ultraedit找到偏移地址(实际修改地址)修改机器码(或放上一根雷管),保存(点火)!而用调试器也同样简单,等会儿会详细说明。
道理废话了那么多,来实例动手说明吧:
首先讲解用W32Dasm来进行爆破:
【软件名称】中华压缩(ChinaZip)
【软件版本】7.0
【文件大小】1041KB
【适用平台】Win9x/Me/NT/2000
【软件简介】ChinaZip(中华压缩)是一款压缩、解压各种压缩文档的工具软件,它支持包括ZIP格式文件在内的各种常见压缩格式如:ARJ、CAB、GZIP、JAR、LHA、TAR、ZOO、ARC、LZH、Pak等等。
软件的出处是电脑报2001年的合订本配套光盘,7.0时的保护做的很那个,目前最新版应该好多了...
好的,我们开始吧,首先第一步是你得把它装上(引来野狼N头),之后先随便找个字符串填上去注册一下,会看到一个错误对话框,提示"注册码不正确,无法注册 "。接着我们用FI来看一下它用的是什么壳。ASPack 2.001,caspr出场。脱过壳后我们用W32Dasm花上半分钟或半小时的时间来对它进行反汇编。我们以经反汇编完毕。之后在串式参考中(字符串数据参考)中找刚才你看到的那个错误提示,找到之后双击几次,发现其只有一处调用。我们会来到004F0E64处,我把具体代码给贴上(请你从代码的最下边开始看):
:004F4DD1E84EE1F3FF call 00432F24
:004F4DD68B55F0 mov edx, dword ptr
:004F4DD98D4DF4 lea ecx, dword ptr
:004F4DDC8BC3 mov eax, ebx
:004F4DDEE8C9010000 call 004F4FAC
:004F4DE3 8B55F4 mov edx, dword ptr
:004F4DE658 pop eax
:004F4DE7E830F3F0FF call 0040411C
:004F4DEC7576 jne004F4E64 <--这个就是传说中的男人,Stop!这个就是传说中的关键跳转
:004F4DEEB201 mov dl, 01
:004F4DF0A158254500 mov eax, dword ptr * Referenced by a(U)nconditional or (C)onditional Jump at Address:
|:004F4D86(C)
|
:004F4DF5E85ED8F5FF call 00452658
:004F4DFA8945FC mov dword ptr , eax
:004F4DFD33C0 xor eax, eax
:004F4DFF55 push ebp
:004F4E00685D4E4F00 push 004F4E5D
:004F4E0564FF30 push dword ptr fs:
:004F4E08648920 mov dword ptr fs:, esp
:004F4E0BB101 mov cl, 01* Possible StringData Reffrom Code Obj ->"Software\XDZHAN\ChinaZip"
|
:004F4E0DBAA84E4F00 mov edx, 004F4EA8
:004F4E128B45FC mov eax, dword ptr
:004F4E15E822DAF5FF call 0045283C* Possible StringData Reffrom Code Obj ->"Real Programmers Use Pascal!"
|
:004F4E1AB9CC4E4F00 mov ecx, 004F4ECC* Possible StringData Reffrom Code Obj ->"Key"
|
:004F4E1FBAF44E4F00 mov edx, 004F4EF4
:004F4E248B45FC mov eax, dword ptr
:004F4E27E854DEF5FF call 00452C80* Possible StringData Reffrom Code Obj ->"软件注册成功,谢谢您的支持!" <--我们向上看会在这里发现注册成功后的正确信息。正确信息处向上找第一个跳转就是我们要找的关键跳转。
|
:004F4E2CB8004F4F00 mov eax, 004F4F00
:004F4E31E8563DF6FF call 00458B8C
:004F4E36A16C305000 mov eax, dword ptr
:004F4E3B8B00 mov eax, dword ptr * Possible StringData Reffrom Code Obj ->"中华压缩(ChinaZip)-注册版"
|
:004F4E3DBA244F4F00 mov edx, 004F4F24
:004F4E42 E80DE1F3FF call 00432F54
:004F4E4733C0 xor eax, eax
:004F4E495A pop edx
:004F4E4A59 pop ecx
:004F4E4B59 pop ecx
:004F4E4C648910 mov dword ptr fs:, edx
:004F4E4F686E4E4F00 push 004F4E6E* Referenced by a(U)nconditional or (C)onditional Jump at Address:
|:004F4E62(U)
|
:004F4E548B45FC mov eax, dword ptr
:004F4E57E868E2F0FF call 004030C4
:004F4E5C C3 ret
:004F4E5DE9C2E9F0FF jmp 00403824
:004F4E62EBF0 jmp 004F4E54* Referenced by a(U)nconditional or (C)onditional Jump at Address:
|:004F4DEC(C)
|* Possible StringData Ref from Code Obj ->"注册码不正确,无法注册!"<--这个就是出错的信息了,那正确信息也就在附近,上下看看。
|
:004F4E64B8484F4F00 mov eax,004F4F48 <--双击来到这里
:004F4E69E81E3DF6FF call 00458B8C
:004F4E6E33C0 xor eax, eax
:004F4E705A pop edx
:004F4E7159 pop ecx
:004F4E7259 pop ecx
:004F4E73648910 mov dword ptr fs:, edx
:004F4E76689B4E4F00 push 004F4E9B
你可能有点不明白,为什么我说它就是关键跳转呢?还记的在破解原理中我举的例子吗?
我再给你讲一遍好了,通常我们会遇到两种关键跳转,我分别举例说明:
(1)
je (jne,jz,jnz) 19870219
........XXXXXXXXXX
........XXXXXXXXXX
........软件注册正确的相关信息
...
...
19870219 软件的出错信息
.......
.......
也就是说这第一种情况是先判断注册码是否正确,如果不正确就跳到19870219处,正确的话就不跳转,一直执行下去,直至注册正确处。
对于这种情况,我们要找的关键跳转,就是正确信息上面的第一个跳转。我们可能对其作相应修改或将其给nop掉就万事OK了。
(2)
je (jne,jz,jnz) 19870219
........XXXXXXXXXX
........XXXXXXXXXX
........软件的出错信息
...
...
19870219 软件注册正确的相关信息
.......
.......
而这第二种情况就是先判断注册码正确与否,如果正确就跳到19870219处,不正确的话就不跳转,一直执行下去,直至出错处。
对于这种情况,我们要找的关键跳转就是出错信息上面的第一个跳转。将其做相应修改或改为jmp后我们就可以为所欲为了
呵呵,道理也都给你讲明白了,我们来改一下试试吧。我们在W32Dasm中选中关键跳转,在右下角的状态栏中看到相应的偏移地址为000F41EC。好的,我们用UltraEdit来打开它。Ctrl+G,接着输入0xF41EC,回车后便会跳到相应的位置。相应的机器码是75(jne),我们将其改为74 (jz)后存盘退出。
好了,运行一下看看,我们来随便输入一个注册码注册一下试试。呵呵,注册成功!
用W32Dasm我们就讲到这里,呵呵,很简单的,你下去之后自己找些保护简单的软件上上手吧。
我们接着来讲用调试器来进行爆破。
如果你真的试图用W32Dasm去爆破几个软件的话,用不了多少时间你就会发现一些问题。比如说有的软件你用W32Dasm反汇编后串式参考根本就不能用。或者串式参考中没有出错或正确的信息。还有就是有的软件就算你通过串式参考来到了相应的地方,刚想去找关键跳转你就会发现眼前的东西比你想像中的要乱的多...虽然你有可能通过认真仔细地找,仍会找到,但我不认为那是一件聪明的事情。毕竟,有一些动静是只有在程序执行期间才能看出来的。好的,如果你用 W32Dasm遇到了找不到关键跳转的软件,就去用调试器吧!(你用调试器前可先用W32Dasm打开一遍看个先,如果很容易就让你找到了。那就没必要了)
在开始之前我们有必要讲一下用调试器来爆破的步骤(我知道你一定会用调试器的 ):首先,我们当然还是要把你要Crack的软件给装上(我挡我挡我挡,不要乱丢东西嘛!)然后来到输入注册码的地方,仍旧随便输入一个,接着不要按确定,待我们把调试器叫出来先。还记的我前面跟你讲的API的事情吗?软件要得到你输入的注册码,就一定会调用某个API函数来达到目的。我们就在调试器中用相应的API来做断点,这样的话,只要一有程序调用这个API,就会被调试器给拦截下来。
GetDlgItemInt、 GetDlgItemText、GetDlgItemTextA这三个函数可能会有用。但是如果你用的是98,那为什么不用hmemcpy呢?那真的是一个不错的主意。当我们下完断点后就返回到你要注册的那个软件中,点确定这类的按钮。如果被调试器给断了下来,就说明你刚才下的断点有用,如果没有被断下来,就换个断点试试。接下来我们在调试器中来取消刚才你下的那个断点,我们以TRW2000为例(SoftICE与其操作大体相同)取消断点用bc *指令。然后我们就输入pmodule指令来返回到程序的领空(而在SoftICE中由于没有相应指令,呵呵,狂按F12吧)。现在我们把话题岔开一下,什么是领空呢?举个例子吧,你的程序要得到你输入的那个注册码,就会去调用相应的函数。比如调用GetDlgItemTextA,而GetDlgItemTextA本身又会去调用Hmemcpy这个函数,而这些函数都是存在于系统中的某个DLL 文件中的。那么当这个程序调用相应的API函数的话,程序的领空就会转到这个相应的DLL文件中去执行这个API函数。(你就这样理解就行了)我前边也说过了,Hmemcpy这个函数应用程序本身并不直接调用,而是由其它的API函数来调用。那么,你就可以理解为你的程序调用了一个API函数,调用的同时程序的领空会转到这个API所在的DLL文件里,而这个API又调用了Hmemcpy函数,那么此时领空就会又转到了Hmemcpy所在的DLL文件中,之后当Hmemcpy执行完毕,就会返回到调用它的API的领空中去,而当这个API执行完毕的后就会返回到调用它的应用程序的领空中去。比如说我们用 Hmemcpy这个函数来当断点,当我们输入完注册码按确定后,程序就会去调用某个API来得到你输入的那些数据,而这“某个API”又会去调用 Hmemcpy,所以程序就被断到了。当然此时程序的领空也就不会在应用程序中了,但是当我们输入过pmodule指令之后我们就可以反回到应用程序本身的领空中去了。这样的话你看到的就是应用程序自身的代码了,而不是API的!好了,我接着刚才的说(到哪儿了来着?)当我们返回到程序自身的领空中去后就一直狂按F12吧,F12的作用是一直执行程序,直到遇上ret等指令。也就是一大坨一大坨地来执行程序^_^你一直按F12,直到程序出现注册错误对话框。然后记下刚才你按的次数,接着从头做起,这一次按F12的次数是你刚才按的次数-1,也就是说比上一次要少按一次。而后按键由F12换至F10(怎么没有F4?),还是一路狂按,直到软件提示出错,这次记下你按F10的次数。好的,再从头来一遍,我们再次按F10的时候,要一步一步慢慢来,一般你按 F10的次数离你上次按的次数相差五六步的时候,一般就会看见一个CALL,接着是一个跳转指令。你一步一步地来,看过了这个跳转指令之后会不会跳走,如果跳走了,那一般你不会再过两三步就应该出错了。当然也有可能是你没有跳走,而过了两三步就出错了。这个应该不难理解,因为基本上它和我前边跟你介绍过的是一个道理。然而另外一种情况是你一路按F10下来,到了最后会发现根本没什么跳转指令,呵呵,别害怕,这个很常见的。遇上这种情况,我们只要把F10的次数变换为上次按F10的次数-1,这样的话你一般就会停在一个CALL处,而这个CALL,就是程序中的关键CALL,我们之后要吃点儿苦,要按F8追进去分析它,程序注册的成功与失败,就在这个CALL中,也就是说我们要修改的关键跳转,也在这个CALL中。呵呵,其实也很好理解的,就是把我上边说的那些个判断什么地放到了一个CALL里面。我们按F8追进去之后便仍旧按F10来一步一步执行,过不了多长时间你就会发现关键跳转了,找关键跳转的方法跟我前边说的一样,即按F10的次数跟上一次差五六步的时候慢下来,就会看到了。
你应该明白,程序是很灵活的东西,并没有那么多公式化的东西在里边,大概的分析方法就是这个样子,一切都要靠你自己去掌握,别人跟你讲,也只是讲一个分析的方法而以,我相信随着你以后经验的提高,你慢慢地就能应付各种情况了。
现在,我们再用调试器来对CHINAZIP这个软件进行分析,希望你能够掌握这个并不难的方法。
首先,你要把刚才爆破过了的再改回来,或直接重装一遍。之后我们打开它,任意输入注册码,接着按Ctrl+N呼出TRW,下断点hmemcpy。下过后按F5退出(它就是不用F4,我也没办法^_^)然后我们点击确定。好的,程序被断了下来:
KERNEL?HMEMCPY
0147:9e62push bp
0147:9e63mov bp,sp
0147:9e65push ds
0147:9e66push edi
0147:9e68push esi
0147:9e6acld
0147:9e6bmov ecx,
0147:9e6fjcxz 9ee9
……以下N多代码省略……
我们输入bc *来取消断点,然后用pmodule来返回到程序的领空:
0167:00436d13mov ,eax
0167:00436d16mov eax,
0167:00436d18cmp eax,byte +0c
0167:00436d1bjnz 00436d38
0167:00436d1dmov edx,
0167:00436d20push edx
0167:00436d21mov ecx,
0167:00436d24mov edx,eax
0167:00436d26mov eax,esi
0167:00436d28call 00432b24
……N多代码仍旧省略……
按7 下F12另加1下F10来到0167:004f4dc4处,我们接着一下一下来按F10,大概按了10多下,就可以看到004f4dec处有一个跳转,我们执行到004f4dec处后果然跳走了。会跳到004f4e64处,我们跳过去之后按不了三下,程序就提示出错了。呵呵,明白过来了吧, 004f4dec处的那个跳转jnz 004f4e64就是关键跳转,嘿嘿,找到了之后不用我说了吧
0167:004f4dc4mov eax,
0167:004f4dc7push eax
0167:004f4dc8lea edx,
0167:004f4dcbmov eax,
0167:004f4dd1call 00432f24
0167:004f4dd6mov edx,
0167:004f4dd9lea ecx,
0167:004f4ddcmov eax,ebx
0167:004f4ddecall 004f4fac
0167:004f4de3mov edx,
0167:004f4de6pop eax
0167:004f4de7call 0040411c
0167:004f4decjnz 004f4e64 <--关键跳转!!
0167:004f4deemov dl,01
0167:004f4df0mov eax,
0167:004f4df5call 00452658
0167:004f4dfamov ,eax
0167:004f4dfdxor eax,eax
0167:004f4dffpush ebp
0167:004f4e00push dword 004f4e5d
0167:004f4e05push dword
0167:004f4e08mov ,esp
0167:004f4e0bmov cl,01
0167:004f4e0dmov edx,004f4ea8
0167:004f4e12mov eax,
0167:004f4e15call 0045283c
0167:004f4e1amov ecx,004f4ecc
0167:004f4e1fmov edx,004f4ef4
0167:004f4e24mov eax,
0167:004f4e27call 00452c80
0167:004f4e2cmov eax,004f4f00
0167:004f4e31call 00458b8c
0167:004f4e36mov eax,
0167:004f4e3bmov eax,
0167:004f4e3dmov edx,004f4f24
0167:004f4e42call 00432f54
0167:004f4e47xor eax,eax
0167:004f4e49pop edx
0167:004f4e4apop ecx
0167:004f4e4bpop ecx
0167:004f4e4cmov ,edx
0167:004f4e4fpush dword 004f4e6e
0167:004f4e54mov eax,
0167:004f4e57call 004030c4
0167:004f4e5cret
0167:004f4e5djmp 00403824
0167:004f4e62jmp short 004f4e54
0167:004f4e64mov eax,004f4f48 <---由上面的0167:004f4dec处跳来,出错!;
0167:004f4e69call 00458b8c
0167:004f4e6exor eax,eax
再来给你举另一个例子:
【软件名称】天网防火墙
【软件版本】2.46 Beta
【文件大小】1289KB
【适用平台】Win9x/Me/NT/2000
【软件简介】天网防火墙个人版是一套给个人电脑使用的网络安全程序,它可以帮你抵挡网络入侵和攻击,防止信息泄露,并可与我们的网站相配合,根据可疑的攻击信息,来找到攻击者。同时天网防火墙个人版把网络分为本地网和互联网,可以针对来自不同网络的信息,来设置不同的安全方案,它适合于在拨号上网的用户,也适合通过网络共享软件上网的用户。
该软件仍旧是我从电脑报2001年合订本的配套光盘中找的,软件的注册码可以到其网站免费获得...
我们还是要先把它装上(某民工:你小子敢再说一句废话试试!^_^)之后我们用FI看一下它有没有加壳,呵呵,BC++编译,没有加壳,爽!运行它,在注册对话框中随便输入点什么,比如说这星期又出了几部新电影,都叫什么名字等等...
好的,我们接下来请TRW2000出场。先胡乱输入两个字符串,比如第一个输入“英雄的导演是?”第二个输入“可能是赵本山”:)
接下来就按Ctrl+N把TRW2K叫出来,下bpx hmemcpy,之后按F5退出。
接着可以按确定就成了,程序会被TRW2K断掉,我们紧接着输入bc *以及pmodule。
下面可以开始按F12了,一共按8下程序就会报错,我们第二次就按7下然后开始按F10,按70下F10程序就又报错了(呵呵,一定要有耐心哦)。
好的,我把反汇编后的代码给你贴出来:
0167:0041c617lea edx, <--7下F12后按一下F10来到这里
0167:0041c61amov ecx,
0167:0041c620mov eax,
0167:0041c622mov eax,
0167:0041c628add eax,byte +2c
0167:0041c62bcall 00517740
0167:0041c630dec dword
0167:0041c633lea eax,
0167:0041c636mov edx,02
0167:0041c63bcall 00517710
0167:0041c640mov word ,14
0167:0041c646lea eax,
0167:0041c649call 00401d60
0167:0041c64emov edx,eax
0167:0041c650inc dword
0167:0041c653mov ecx,
0167:0041c656mov eax,
0167:0041c65ccall 004b9f14
0167:0041c661lea edx,
0167:0041c664mov ecx,
0167:0041c66amov eax,
0167:0041c66cmov eax,
0167:0041c672add eax,byte +30
0167:0041c675call 00517740
0167:0041c67adec dword
0167:0041c67dlea eax,
0167:0041c680mov edx,02
0167:0041c685call 00517710
0167:0041c68alea eax,
0167:0041c68dcall 00401d60
0167:0041c692mov edx,eax
0167:0041c694inc dword
0167:0041c697mov ecx,
0167:0041c69amov eax,
0167:0041c6a0call 004b9f14
0167:0041c6a5lea edx,
0167:0041c6a8push dword
0167:0041c6aamov word ,20
0167:0041c6b0lea eax,
0167:0041c6b3call 00401d60
0167:0041c6b8mov edx,eax
0167:0041c6bainc dword
0167:0041c6bdmov ecx,
0167:0041c6c0mov eax,
0167:0041c6c6call 004b9f14
0167:0041c6cblea edx,
0167:0041c6cemov edx,
0167:0041c6d0mov eax,
0167:0041c6d5mov eax,
0167:0041c6d7pop ecx
0167:0041c6d8call 0040525c
0167:0041c6ddmov ,al
0167:0041c6e0dec dword
0167:0041c6e3lea eax,
0167:0041c6e6mov edx,02
0167:0041c6ebcall 00517710
0167:0041c6f0dec dword
0167:0041c6f3lea eax,
0167:0041c6f6mov edx,02
0167:0041c6fbcall 00517710
0167:0041c700cmp byte ,00
0167:0041c704jz 0041c750 <--按了60多下F10后会在这里发现一个跳转,嘿嘿,就是它了!!!
0167:0041c706mov ecx,
0167:0041c70cmov eax,
0167:0041c70emov eax,
0167:0041c714call 00411fd0
0167:0041c719mov word ,2c
0167:0041c71fmov edx,00521b50
0167:0041c724lea eax,
0167:0041c727call 005175b0
0167:0041c72cinc dword
0167:0041c72fmov eax,
0167:0041c731call 004b41b0
0167:0041c736dec dword
0167:0041c739lea eax,
0167:0041c73cmov edx,02
0167:0041c741call 00517710
0167:0041c746mov eax,
0167:0041c749call 004a81d0
0167:0041c74ejmp short 0041c77d
0167:0041c750mov word ,38
0167:0041c756mov edx,00521b6b
0167:0041c75blea eax,
0167:0041c75ecall 005175b0
0167:0041c763inc dword
找到了关键跳转之后就别闲着了,呵呵,放雷管吧!(你可以用W32Dasm打开这个文件,然后按Shift+F12,之后输入0041c704,这样就可以在右下角看到相应的偏移地址了)
小技巧:在TRW中,如果你觉的某处可能是关键跳转的话,可以用r fl z这个指令来进行测试,该指令可使以成立的条件取反,比如说本来JZXXXXXXXX成立,可以跳走了,用r fl z指令后该条指令就不成立了,即就不会跳走了。以上也是,你可以在0041c704处输入r fl z,呵呵,再执行几步看看,是不是成功了?还有就是如果你只是想达到注册软件的目的,且该软件只在注册的时候验证一次的话,用这个方法就可以代替雷管了!
呵呵,最后还是要说一句,爆破只是一些雕虫小技。刚入门时玩几次就够了,切莫就此不前...
后话:你可能慢慢就会发现,有一些软件其实并没有你想象中那么简单,你甚至连找到它的关键跳转都找不到。这很正常,你要做的便是多动手多练习,慢慢你就会明白过来的。我今天之所以给你举这两个例子,就是因为它们两个都比较简单,且能说明重点,给你讲那些比较那个的软件的爆破,反而会让你看的一头雾水...第七章-寻找软件的注册码
我们来寻找软件真正的注册码!
寻找软件的注册码就像你小时玩的躲猫猫一样,简单又有趣,虽然后来你会不这样觉的
好的,我们开始。
我不知道你有没有明白我前面在原理中讲的那些东西,如果没明白,我就再说一遍
软件通过你输入的用户名或者机器码什么的生成一个正确的注册码来与你输入的注册码进行比较,如果两个相同,也就是说你输入的注册码是正确的话,那软件就会完成注册。如果你输入的不正确,嘿嘿,当然就不会注册成功。
好的,现在你已经知道软件会有一个比较两个注册码的过程,这就是关键所在。一般如果你遇到的是那种明码比较的软件,这会是一件非常另人愉快的事情的
软件会先计算出正确的注册码然后再与你输入的那个进行比较,也就是说正确的注册码会被软件自己算出来!嘿嘿,搜身你会吗?虽然法律以及道德不允许我们去搜身,但…
我接着说,虽然现在的软件已经比以前要厉害上许多,但,那种用明码比较的,还是大有人在的。所谓明码比较,就是说软件先算出正确的注册码,然后放到内存或你家的沙发下面,之后再得到你输入的那个注册码,接着就比较了。呵呵,好理解吧,我们只要找到那个比较的地方,看一下软件把注册码放到内存的哪里了,再到相应的内存处瞧一瞧,就万事OK了!
还记的对你说过的那些常见的(也是最菜的)比较吗?我捡其中最简单的一个来给你再解释一下:
moveax [ ] 这里可以是地址,也可以是其它寄存器 该条指令也可以是moveax [ ]
movedx [ ] 同上 通常这两个地址就储存着重要信息 该指令也可以是 pop edx
call 00?????? 关键call
jz(jnz)或jne(je)关键跳转
第一条mov eax [ ]指令是将一个内存地址或另外一个寄存器(该寄存器中装的是内存地址)装入eax中。第二条指令与其相同,是将一个内存地址或另外一个寄存器中的内存地址装入edx中。而这两条指令是干什么的呢?嘿嘿嘿嘿…
这两条指令就是用来存放真假两个注册码的地址的,也就是说eax和edx这两个寄存器中此时一个装的是正确的注册码的内存地址,一个是你输入的那个错误的注册码的内存地址。软件在比较注册码前将两个注册码的内存地址分别装入到两个寄存器中,然后就是关键Call出场。在这个关键Call中对注册码进行比较时,软件会从相应的寄存器中取出两个注册码来比较,接着出来就是一个关键跳转,通过上面Call中的比较结果来做相应的跳转…
你应该已经想到什么了吧!没错,我们只要找到软件的关键Call,然后在关键Call处来查看相应的内存地址就可以找到正确的注册码了 而这一切,都可以通过调试器来完成。从某种意义上来说,如果你能自己一个人把你家的微波炉修好,那你就绝对会用调试器我们在调试器中,只要一步一步执行到关键Call处,然后用d eax和d edx就可以查看两个地址中放的两个注册码,如果你发现其中的一个是你自己刚才输入的,那么另一条就是正确的
而所谓的内存注册机呢?我这里就不再多说了,它的原理就是自动在软件注册的时候中断到相应的地方,并显示相应内存处的值,当然它是需要配置的... 此类软件有CRACKCODE2000和注册机编写器keymake,具体用法你可以参考软件的联机帮助^_^
我们剩下的问题就是如何来找个这关键Call了,基本上来说你就用前边给你讲爆破时的那种方法就可以了,很简单的
但是就像你家后门的玻璃可能永远擦不干净一样,我们家后门的玻璃也从来没擦干净过 导演:NG!重说,就像所有事情都有例外一样,有些软件的关键Call会比较难找一点,但如果你掌握了适当的方法,同样也会很好找的...
我们就来玩玩吧:
首先,我们还来用CHINAZIP这个软件上上手^_^
它已经是我们的老朋友了,所以就不用再介绍它了吧
好的,我们先装上它(嘿嘿,偶就是喜欢说废话,你打偶偶也要说^_^)接着我们点帮助-注册,输入Name:Suunb,Code:19870219
然后请出我们的老伙计TRW2000,下bpx hmemcpy 按F5点确定被拦:
KERNEL?HMEMCPY
0147:9e62push bp
0147:9e63mov bp,sp
0147:9e65push ds
0147:9e66push edi
0147:9e68push esi
0147:9e6acld
0147:9e6bmov ecx,
0147:9e6fjcxz 9ee9
...省略N多代码...
输入bc *,删除断点。pmodule ,直接跳到程序领空:
0167:00436d13mov ,eax
0167:00436d16mov eax,
0167:00436d18cmp eax,byte +0c
0167:00436d1bjnz 00436d38
0167:00436d1dmov edx,
0167:00436d20push edx
0167:00436d21mov ecx,
0167:00436d24mov edx,eax
0167:00436d26mov eax,esi
0167:00436d28call 00432b24
...省略N多代码...
按8 下F12就会提示出错,我们第二次就按7次接着我们再来按F10,按16下就会报错,好的,我们再来:这一次我们按F10的时候,就按我前边说过的方法,到与上次按的次数相差五六次的时候就慢下来。好的,我们按十来下的时候就慢下来仔细瞅瞅,呵呵,一下子就看到004f4dec处的那个跳转以及它上面的关键CALL了我们按F10单步执行到004f4de7处(即关键CALL处)后下指令d edx就可看到真正的注册码,而d eax则可以看到我刚才输入的19870219代码给你:
0167:004f4dc4mov eax, <---7下F12,1下F10就来到这里(此时ebp-08处放的是刚才输入的注册码19870219)
0167:004f4dc7push eax <---将EAX压栈;
0167:004f4dc8lea edx,
0167:004f4dcbmov eax,
0167:004f4dd1call 00432f24 <---该CALL用来得到用户输入的用户名,其实就是某个API函数,嘿嘿,好奇的话可以追进去看看
0167:004f4dd6mov edx, <---将得到的用户名放入EDX;
0167:004f4dd9lea ecx,
0167:004f4ddcmov eax,ebx
0167:004f4ddecall 004f4fac <---该CALL用来计算出真正的注册码;
0167:004f4de3mov edx, <---将计算出的真.注册码放入EDX,在下条指令时可用D EDX查看;
0167:004f4de6pop eax <---先前压入的注册码出栈;
0167:004f4de7call 0040411c <---该CALL用来比较两个注册码,罪魁祸首啊!;
0167:004f4decjnz 004f4e64 <---不相等则跳,跳必死,暴破将75改为74或EB,当然90也行;
0167:004f4deemov dl,01
0167:004f4df0mov eax,
0167:004f4df5call 00452658
0167:004f4dfamov ,eax
0167:004f4dfdxor eax,eax
0167:004f4dffpush ebp
0167:004f4e00push dword 004f4e5d
0167:004f4e05push dword
0167:004f4e08mov ,esp
0167:004f4e0bmov cl,01
0167:004f4e0dmov edx,004f4ea8
0167:004f4e12mov eax,
0167:004f4e15call 0045283c
0167:004f4e1amov ecx,004f4ecc
0167:004f4e1fmov edx,004f4ef4
0167:004f4e24mov eax,
0167:004f4e27call 00452c80
0167:004f4e2cmov eax,004f4f00
0167:004f4e31call 00458b8c
0167:004f4e36mov eax,
0167:004f4e3bmov eax,
0167:004f4e3dmov edx,004f4f24
0167:004f4e42call 00432f54
0167:004f4e47xor eax,eax
0167:004f4e49pop edx
0167:004f4e4apop ecx
0167:004f4e4bpop ecx
0167:004f4e4cmov ,edx
0167:004f4e4fpush dword 004f4e6e
0167:004f4e54mov eax,
0167:004f4e57call 004030c4
0167:004f4e5cret
0167:004f4e5djmp 00403824
0167:004f4e62jmp short 004f4e54
0167:004f4e64mov eax,004f4f48 <---由上面的0167:004f4dec处跳来,挂!;
0167:004f4e69call 00458b8c
0167:004f4e6exor eax,eax
整理:
Name:Suunb
Code:SCCG5296
可以真接在TRW2000中下断点bpx 004f4de6,中断后用D EDX来查看真.注册码。
另附:CRACKCODE2000的CRACKCODE.INI
CommandLine=CHINAZIP.exe
Mode=2
First_Break_Address=4f4de7
First_Break_Address_Code=E8
First_Break_Address_Code_Lenth=5
Second_Break_Address=404123
Second_Break_Address_Code_Lenth=2
Save_Code_Address=EDX
呵呵,是不是很简单?我说过了嘛,其实并不难的
我不知道你有没有发现,其实上面的软件的关键CALL还是很好找的,相信你用W32Dasm就中以找出来,那为什么不用呢?对于那些比较简单的软件,何必非请出调试器呢?
给你贴个用W32Dasm找关键CALL的:
【软件名称】e族百变桌面
【软件版本】4.0
【文件大小】1316KB
【适用平台】Win9x/Me/NT/2000
【软件简介】提供25种变换桌面的方式,让你的桌面焕然一新。操作简单,无需费力学习。支持多种Internet流行图片格式。将壁纸文件打包,方便存储、转发。将壁纸包展开,还原图片文件。
嘿嘿,我也懒的去折腾我的小猫了,咱们就还用电脑报2001年合订本配套光盘上的软件吧(2002年的偶没有买)
首先装上它(嘿嘿,你习惯了?为什么不丢东西了? ^_^)运行一下该软件先,该软件自动生成了相应的机器码,并停留在注册项上,输入注册码19870219,点确定,挂!
用fi检查,该软件为Delphi编译,没加壳。
用W32DASM打开该执行文件,参考-串式参考,在最下边,见到了刚才弹出的"注册码不正确,请联系作者"。
用鼠标双击,发现只有一处调用,在00488E97处,接着在串式参考对话框中在"注册码不正确,请联系作者"处向上找,找到"感谢您支持国产软件,祝您好运"(说的我都不好意思了)
用鼠标双击,仍旧只有一处调用,在00488DF7处:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00488DCD(U)
|
:00488DD98B45FC mov eax, dword ptr
:00488DDC8B8020040000 mov eax, dword ptr
:00488DE235280BB61E xor eax, 1EB60B28
:00488DE7 3B45F8 cmp eax, dword ptr <---关键比较,? EAX来查看软件正确的注册码;
:00488DEA0F85A0000000 jne00488E90 <---关键跳转,不相等就跳,跳必挂!
:00488DF06A40 push 00000040* Possible StringData Reffrom Code Obj ->"注册成功"
|
:00488DF268D48E4800 push 00488ED4* Possible StringData Reffrom Code Obj ->"感谢您支持国产软件,祝您好运!"
|
:00488DF768E08E4800 push00488EE0 <---双击串式参考便跳到此行,我们向上找第一个跳转处就是关键跳转,关键跳转上面就是关键比较;
:00488DFC8B45FC mov eax, dword ptr
:00488DFFE81CD2FBFF call 00446020
:00488E0450 push eax
...省略代码若干...
向上看,00488DEA处有一跳转,不相等便跳到00488E90处,跳必挂!还记的00488E97处的出错对话框吧! 罪魁祸首啊!
在向上一行,看00488DE7处:cmp eax, dword ptr ,此为关键比较。可用? EAX查看软件正确的注册码。
整理:
打开该软件,在注册码处输入19870219,打开TRW2000,下断点bpx 00488DE7,点注册被拦。输入? EAX得到软件正确的注册码。
机器码:533226313
注册码:25061473
用注册机编写器keymake编写该软件的注册机:
点其它-另类注册机(F8),软件名称输入ePaper.exe,注册码选寄存器方式 EAX 十进制。
添加断点,中断地址:00488DE7,中断次数:1,第一字节:3B,指令长度:3。
生成注册机后完工,万事OK!
嘿嘿,现在是不是觉的找软件的注册码越来越像小时候玩的躲猫猫了?可惜偶小时候没有青梅竹马那种类型的伙伴...
好的,我们这次讲个有点儿名气的软件,WinZIP8.1,这个软件相信大家都用过吧,反正偶是喜欢用RAR,不过也多少用过几天这玩意儿...
如果你没听说过,那看介绍好了
【软件名称】WinZIP
【软件版本】8.1 Beta 2
【文件大小】1757KB
【适用平台】Win9x/Me/NT/2000
【软件简介】一个强大并且易用的压缩实用程序,支持ZIP、CAB、TAR、GZIP、MIME,以及更多格式的压缩文件。其特点是紧密地与Windows资源管理器拖放集成,不用离开资源管理器而进行压缩、解压缩。
不用我说了吧,出处仍旧是电脑报2001年合订本的配套光盘
我之所以先择它,是因为觉得它的关键CALL没有前边那两个那样好找(其实也就那样了^_^)极具代表性,而且通过它可以让你感受一下Ollydbg这个魅力比你家的荼几还大的调试器
这里之所以提到Ollydbg,是觉的它真是一个非常非常棒的调试器...强烈建议你多玩几次...(MP3好听吗? ^_^)
我们来吧,首先当然还是要装上它(左闪术,右闪术),然后用Ollydbg来载入,此时界面会被分成四个部分,左上方是软件反汇编后的代码,右上方是寄存器开会的地方,左下方是内存区,右下方显示的则是堆栈的信息。
我们来下断点,按Alt+F4,之后选USER32,然后再鼠标右键-->搜索-->当前模块中的名称,然后在那一大堆函数中找到GetDlgItemTextA,按F2来下断点,它会提示你错误,并说无法设置中断点,是不是很过瘾?(呜呜呜...大哥,我错了,再也不敢了...)
呵呵,这个我也不知道什么原因,明明是用了这个函数嘛,就是不让断,其实我对Ollydbg也不是太那个(关键是讨厌它的下断方式)看来还是用我们的万能断点吧,输入注册名Suunb,输入注册码 19870219,然后用TRW2000下断bpx hmemcpy,断到之后,pmodule返回领空后一次F12就会出错,看来所有的东东就在这里了...
我们用TRW2000再断一下,返回领空之后记着第一条指令的地址0040bd5f,呜呜呜...上条指令明明是调用GetDlgItemTextA,为什么在Ollydbg中不让下呢?
没关系,我们记下这个地址后仍旧用Ollydbg来加载程序,之后在反汇编窗口中找到0040bd5f处,然后按下F2来下断(会变为红色),下断之后便按 F9来运行程序,接着输入注册名Suunb,注册码19870219后按确定,程序会被Ollydbg给断到:
0040BD5F|.57 PUSHEDI
0040BD60|. E8 F34A0500 CALL WINZIP32.00460858
0040BD65|.57 PUSHEDI ; /Arg1
0040BD66|. E8 164B0500 CALLWINZIP32.00460881 ; \WINZIP32.00460881
0040BD6B|.59 POPECX
0040BD6C|. BE 1CCA4C00 MOV ESI,WINZIP32.004CCA1C
0040BD71|.59 POPECX
0040BD72|. 6A 0B PUSH0B ; /Count = B (11.)
0040BD74|.56 PUSHESI ; |Buffer => WINZIP32.004CCA1C
0040BD75|. 68 810C0000 PUSH0C81 ; |ControlID = C81 (3201.)
0040BD7A|.53 PUSHEBX ; |hWnd
0040BD7B|. FF15 F4C54A00CALL DWORD PTRDS:[<&USER32.GetDlgItemTe>; \GetDlgItemTextA
0040BD81|.56 PUSHESI
0040BD82|. E8 D14A0500 CALL WINZIP32.00460858
0040BD87|.56 PUSHESI
0040BD88|. E8 F44A0500 CALL WINZIP32.00460881
0040BD8D|. 803D F0C94C00 >CMP BYTE PTR DS:,0
0040BD94|.59 POPECX
0040BD95|.59 POPECX
0040BD96|. 74 5F JE SHORT WINZIP32.0040BDF7
0040BD98|. 803D 1CCA4C00 >CMP BYTE PTR DS:,0
0040BD9F|. 74 56 JE SHORT WINZIP32.0040BDF7
0040BDA1|. E8 31F9FFFF CALLWINZIP32.0040B6D7 <--关键CALL,等会儿进去玩玩
0040BDA6|. 84C0 TESTAL,AL <--根据关键CALL中比较的结果来做相应的测试
0040BDA8|. 74 4D JE SHORTWINZIP32.0040BDF7 <--跳走就没戏!
0040BDAA|.57 PUSHEDI
0040BDAB|. 68 08DE4B00 PUSHWINZIP32.004BDE08 ;ASCII "Name"
0040BDB0|. FF35 1CC74A00PUSH DWORD PTRDS: ;WINZIP32.004BDDEC
0040BDB6|. E8 8AFA0400 CALL WINZIP32.0045B845
0040BDBB|.56 PUSHESI
0040BDBC|. 68 C8EB4B00 PUSHWINZIP32.004BEBC8 ;ASCII "SN"
0040BDC1|. FF35 1CC74A00PUSH DWORD PTRDS: ;WINZIP32.004BDDEC
0040BDC7|. E8 79FA0400 CALL WINZIP32.0045B845
0040BDCC|. FF35 18C74A00PUSH DWORD PTRDS: ; |Arg4 = 004BDDF4 ASCII "winzip32.ini"
0040BDD2|. 6A 00 PUSH0 ; |Arg3 = 00000000
0040BDD4|. 6A 00 PUSH0 ; |Arg2 = 00000000
0040BDD6|. 68 14DE4B00 PUSHWINZIP32.004BDE14 ; |Arg1 = 004BDE14 ASCII "rrs"
0040BDDB|. E8 4CFA0400 CALLWINZIP32.0045B82C ; \WINZIP32.0045B82C
0040BDE0|. A1 A8914C00 MOV EAX,DWORD PTR DS:
0040BDE5|. 83C4 28 ADD ESP,28
0040BDE8|.85C0 TEST EAX,EAX
0040BDEA|. 74 07 JE SHORT WINZIP32.0040BDF3
0040BDEC|.50 PUSHEAX ; /hObject => 000013F4 (font)
0040BDED|. FF15 80C04A00CALL DWORD PTRDS:[<&GDI32.DeleteObject>>; \DeleteObject
0040BDF3|> 6A01 PUSH 1
0040BDF5|. EB 30 JMP SHORT WINZIP32.0040BE27
0040BDF7|> E8 C3020000 CALL WINZIP32.0040C0BF
0040BDFC|. 68 8E020000 PUSH 28E
0040BE01|. E8 61470500 CALL WINZIP32.00460567
0040BE06|.50 PUSHEAX ; |Arg3
0040BE07|.53 PUSHEBX ; |Arg2
0040BE08|. 6A 3D PUSH3D ; |Arg1 = 0000003D
0040BE0A|. E8 C8050400 CALL WINZIP32.0044C3D7 ; \WINZIP32.0044C3D7我们用Ollydbg断到之后,可以像在TRW2000中一样通过F8(这个调试器跟我一样,也不喜欢F4^_^)来单步执行程序,我们按32下F8后程序就会出错,那我们在第二遍载入时按F8按到20多下时就仔细看看有没有可疑的地方,你一眼就可以看到0040BDA1处的这个关键CALL,我们只要追到这里时追进去就有可能看到软件正确的注册码
那还等什么呢?我们就进去吧...
按F7 跟进后你会看的眼花眼花缭乱,到处都是PUSH跟POP,到底哪个才是呢?现在知道我为什么让你用Ollydbg了吧(偶起初也是要用TRW2000的,但临时改变主意 ^_^)用Ollydbg的一个最大好处就是可以真接看到寄存器中的值,特别是你通过F8来单步执行的时候,在反汇编代码的下边,会有一个小窗体,在那里可以显示相关指令中所使用的寄存器的值,爽吧!
我们按76下F8之后,在0040B803处就可以第一次看到正确的注册码了,呵呵,我这边儿是71C20EDC,然后你还会再陆续看到几次,爽?
另外我还发现一个有趣的事情,在WinZIP8.1中,一个注册名可以有两个注册码,呵呵,不知道是不是还有为特别用户准备的特别注册码以用来和普通的做区别当程序通过比较,发现你输入的注册码不正确后竟然会再次算出另一个注册码来再比较一次,嘿嘿,我的第二个注册码是25170288
追入关键CALL里的代码:
0040B6D7/$55 PUSHEBP
0040B6D8|.8BEC MOV EBP,ESP
0040B6DA|. 81EC 0C020000SUB ESP,20C
0040B6E0|. 8065 FF 00 AND BYTE PTR SS:,0
0040B6E4|. 803D F0C94C00 >CMP BYTE PTR DS:,0
0040B6EB|.53 PUSHEBX
0040B6EC|.56 PUSHESI
0040B6ED|.57 PUSHEDI
0040B6EE|. 0F84 FB000000JE WINZIP32.0040B7EF
0040B6F4|. 8D45 E8 LEAEAX,DWORD PTR SS:
0040B6F7|.50 PUSHEAX
0040B6F8|. 68 C0E84B00 PUSH WINZIP32.004BE8C0
0040B6FD|. E8 DE61FFFF CALL WINZIP32.004018E0
0040B702|. 8D45 E8 LEAEAX,DWORD PTR SS:
0040B705|.50 PUSHEAX
0040B706|. E8 F57C0800 CALL WINZIP32.00493400
0040B70B|. 83C4 0C ADD ESP,0C
0040B70E|. 83F8 14 CMP EAX,14
0040B711|. 72 11 JB SHORT WINZIP32.0040B724
0040B713|. BF 20C74A00 MOVEDI,WINZIP32.004AC720 ;ASCII "auth.c"
0040B718|. 6A 21 PUSH 21
0040B71A|.57 PUSHEDI
0040B71B|. E8 86F60000 CALL WINZIP32.0041ADA6
0040B720|.59 POPECX
0040B721|.59 POPECX
0040B722|. EB 05 JMP SHORT WINZIP32.0040B729
0040B724|> BF 20C74A00 MOVEDI,WINZIP32.004AC720 ;ASCII "auth.c"
0040B729|> 8D85 F4FDFFFFLEA EAX,DWORD PTR SS:
0040B72F|. BB F0C94C00 MOVEBX,WINZIP32.004CC9F0 ;ASCII "Suunb"
0040B734|.50 PUSHEAX
0040B735|.53 PUSHEBX
0040B736|. E8 50030000 CALL WINZIP32.0040BA8B
0040B73B|. 8D85 F4FDFFFFLEA EAX,DWORD PTR SS:
0040B741|.50 PUSHEAX
0040B742|. E8 B97C0800 CALL WINZIP32.00493400
0040B747|. BE C8000000 MOV ESI,0C8
0040B74C|. 83C4 0C ADD ESP,0C
0040B74F|.3BC6 CMP EAX,ESI
0040B751|. 72 0A JB SHORT WINZIP32.0040B75D
0040B753|. 6A 23 PUSH 23
0040B755|.57 PUSHEDI
0040B756|. E8 4BF60000 CALL WINZIP32.0041ADA6
0040B75B|.59 POPECX
0040B75C|.59 POPECX
0040B75D|> 8D85 F4FDFFFFLEA EAX,DWORD PTR SS:
0040B763|.50 PUSHEAX
0040B764|. 8D45 E8 LEAEAX,DWORD PTR SS:
0040B767|.50 PUSHEAX
0040B768|. E8 03300900 CALL WINZIP32.0049E770
0040B76D|.59 POPECX
0040B76E|.85C0 TEST EAX,EAX
0040B770|.59 POPECX
0040B771|. 75 04 JNZ SHORT WINZIP32.0040B777
0040B773|. C645 FF 01 MOV BYTE PTR SS:,1
0040B777|> 8D45 E8 LEAEAX,DWORD PTR SS:
0040B77A|.50 PUSHEAX
0040B77B|. 68 D0E84B00 PUSH WINZIP32.004BE8D0
0040B780|. E8 5B61FFFF CALL WINZIP32.004018E0
0040B785|. 8D45 E8 LEAEAX,DWORD PTR SS:
0040B788|.50 PUSHEAX
0040B789|. E8 727C0800 CALL WINZIP32.00493400
0040B78E|. 83C4 0C ADD ESP,0C
0040B791|. 83F8 14 CMP EAX,14
0040B794|. 72 0A JB SHORT WINZIP32.0040B7A0
0040B796|. 6A 27 PUSH 27
0040B798|.57 PUSHEDI
0040B799|. E8 08F60000 CALL WINZIP32.0041ADA6
0040B79E|.59 POPECX
0040B79F|.59 POPECX
0040B7A0|> 8D45 E8 LEAEAX,DWORD PTR SS:
0040B7A3|.50 PUSHEAX
0040B7A4|.53 PUSHEBX
0040B7A5|. E8 C62F0900 CALL WINZIP32.0049E770
0040B7AA|.59 POPECX
0040B7AB|.85C0 TEST EAX,EAX
0040B7AD|.59 POPECX
0040B7AE|. 75 0E JNZ SHORT WINZIP32.0040B7BE
0040B7B0|. FF15 F0C14A00CALL DWORD PTRDS:[<&KERNEL32.GetTickCou>; [GetTickCount
0040B7B6|. A8 01 TEST AL,1
0040B7B8|. 74 04 JE SHORT WINZIP32.0040B7BE
0040B7BA|. C645 FF 01 MOV BYTE PTR SS:,1
0040B7BE|> 6A14 PUSH 14
0040B7C0|. 8D45 E8 LEAEAX,DWORD PTR SS:
0040B7C3|. 6A 00 PUSH 0
0040B7C5|.50 PUSHEAX
0040B7C6|. E8 75820800 CALL WINZIP32.00493A40
0040B7CB|.56 PUSHESI
0040B7CC|. 8D85 F4FDFFFFLEA EAX,DWORD PTR SS:
0040B7D2|. 6A 00 PUSH 0
0040B7D4|.50 PUSHEAX
0040B7D5|. E8 66820800 CALL WINZIP32.00493A40
0040B7DA|. 83C4 18 ADD ESP,18
0040B7DD|. 807D FF 00 CMP BYTE PTR SS:,0
0040B7E1|. 74 13 JE SHORT WINZIP32.0040B7F6
0040B7E3|. E8 D7080000 CALL WINZIP32.0040C0BF
0040B7E8|. 8025 EDBF4C00 >AND BYTE PTR DS:,0
0040B7EF|>32C0 XOR AL,AL
0040B7F1|. E9 F5000000 JMP WINZIP32.0040B8EB
0040B7F6|> 8D85 BCFEFFFFLEA EAX,DWORD PTR SS:
0040B7FC|.50 PUSHEAX
0040B7FD|.53 PUSHEBX
0040B7FE|. E8 ED000000 CALLWINZIP32.0040B8F0 <--参与计算软正确的注册码
0040B803|. 8D85 BCFEFFFFLEA EAX,DWORD PTRSS: <--在这里第一次发现软件正确的注册码
0040B809|.50 PUSHEAX
0040B80A|. E8 F17B0800 CALL WINZIP32.00493400
0040B80F|. BE 2C010000 MOV ESI,12C
0040B814|. 83C4 0C ADD ESP,0C
0040B817|.3BC6 CMP EAX,ESI
0040B819|. 72 0A JB SHORT WINZIP32.0040B825
0040B81B|. 6A 39 PUSH 39
0040B81D|.57 PUSHEDI
0040B81E|. E8 83F50000 CALL WINZIP32.0041ADA6
0040B823|.59 POPECX
0040B824|.59 POPECX
0040B825|> BF 1CCA4C00 MOVEDI,WINZIP32.004CCA1C ;ASCII"19870219" <--将刚才输入的错误的注册码放入EDI
0040B82A|. 8D85 BCFEFFFFLEA EAX,DWORD PTRSS: <--EAX中装入正确的注册码所在的地址
0040B830|.57 PUSHEDI <--用户输入的注册码入栈
0040B831|.50 PUSHEAX <--软件计算出的正确的注册码入栈
0040B832|. E8 392F0900 CALLWINZIP32.0049E770 <--关键CALL,用于比较用户输入的注册码
0040B837|.F7D8 NEG EAX
0040B839|.1AC0 SBB AL,AL
0040B83B|.59 POPECX
0040B83C|.FEC0 INC AL
0040B83E|.59 POPECX
0040B83F|. A2 EDBF4C00 MOV BYTE PTR DS:,AL
0040B844|. 0F85 8A000000JNZ WINZIP32.0040B8D4
0040B84A|. 8D85 BCFEFFFFLEA EAX,DWORD PTR SS:
0040B850|.50 PUSHEAX
0040B851|.53 PUSHEBX
0040B852|. E8 33010000 CALLWINZIP32.0040B98A <--参与计算软件的第二个注册码
0040B857|. 8D85 BCFEFFFFLEA EAX,DWORD PTRSS: <--此时软件会再算出另
外一个注册码
0040B85D|.50 PUSHEAX
0040B85E|. E8 9D7B0800 CALL WINZIP32.00493400
0040B863|. 83C4 0C ADD ESP,0C
0040B866|.3BC6 CMP EAX,ESI
0040B868|. 72 0E JB SHORT WINZIP32.0040B878
0040B86A|. 6A 3E PUSH 3E
0040B86C|. 68 20C74A00 PUSHWINZIP32.004AC720 ;ASCII "auth.c"
0040B871|. E8 30F50000 CALL WINZIP32.0041ADA6
0040B876|.59 POPECX
0040B877|.59 POPECX
0040B878|> 8D85 BCFEFFFFLEA EAX,DWORD PTRSS: <--软件计算出的第二个注册码装入EAX中
0040B87E|.57 PUSHEDI <--用户输入的注册码入栈
0040B87F|.50 PUSHEAX <--软件计算出的第二个注册码入栈
0040B880|. E8 EB2E0900 CALLWINZIP32.0049E770 <--另一个关键CALL,用于比较第二次生成的注册码
0040B885|.F7D8 NEG EAX
0040B887|. 1AC0 SBB AL,AL
0040B889|.59 POPECX
0040B88A|.FEC0 INC AL
0040B88C|.59 POPECX
0040B88D|. A2 EDBF4C00 MOV BYTE PTR DS:,AL
0040B892|. 75 40 JNZ SHORT WINZIP32.0040B8D4
0040B894|. 8D85 C0FEFFFFLEA EAX,DWORD PTR SS:
0040B89A|. 6A 04 PUSH 4
0040B89C|.50 PUSHEAX
0040B89D|.57 PUSHEDI
0040B89E|. E8 DD690900 CALL WINZIP32.004A2280
0040B8A3|. 83C4 0C ADD ESP,0C
0040B8A6|. 85C0 TEST EAX,EAX
0040B8A8|. 75 23 JNZ SHORT WINZIP32.0040B8CD
0040B8AA|. 8D85 BCFEFFFFLEA EAX,DWORD PTR SS:
0040B8B0|. 6A 04 PUSH 4
0040B8B2|.50 PUSHEAX
0040B8B3|. 68 20CA4C00 PUSH WINZIP32.004CCA20 ;ASCII "0219"
0040B8B8|. E8 C3690900 CALL WINZIP32.004A2280
0040B8BD|. 83C4 0C ADD ESP,0C
0040B8C0|.85C0 TEST EAX,EAX
0040B8C2|. 75 09 JNZ SHORT WINZIP32.0040B8CD
0040B8C4|. C605 EDBF4C00 >MOV BYTE PTR DS:,1
0040B8CB|. EB 07 JMP SHORT WINZIP32.0040B8D4
0040B8CD|> 8025 EDBF4C00 >AND BYTE PTR DS:,0
0040B8D4|>56 PUSHESI
0040B8D5|. 8D85 BCFEFFFFLEA EAX,DWORD PTR SS:
0040B8DB|. 6A 00 PUSH 0
0040B8DD|.50 PUSHEAX
0040B8DE|. E8 5D810800 CALL WINZIP32.00493A40
0040B8E3|. A0 EDBF4C00 MOV AL,BYTE PTR DS:
0040B8E8|. 83C4 0C ADD ESP,0C
0040B8EB|>5F POPEDI
0040B8EC|. 5E POP ESI
0040B8ED|.5B POPEBX
0040B8EE|.C9 LEAVE
0040B8EF\.C3 RETN整理一下:
注册名:Suunb
注册码:71C20EDC or 25170288
其实如果你坐在那里肯花上一杯茶的功夫来仔细想一下,就会知道,其实一点儿也不难,只是有一点点麻烦而以
这一章也就到这里吧,我现在巨困无比...
最后说一下的是,现在有仍有N多的软件用的是明码的比较方法,所以,要想找一两个软件练练手还是挺容易的
这一章本来还打算讲一下那些非明码比较的软件的,但忽然发现,如果通过非明码比较的软件能找到注册码的话,那应该也就把它的算法给搞的差不多了,所以,到下一章,分析软件的注册算法时再讲吧...第八章--注册码是怎样炼成的
你应该明白的是,并不是所有的软件作者都像你想象并希望的那笨 没有人愿意自己的软件被别人在调试器中用一条d指令就能找到正确的注册码...要是那样的话还出来搞什么?
前边儿我们讲的查找软件注册码的方法是有针对性的,必须保证的是该软件使用的是明码比较,这样的话,我们只需找对地方,一个d指令就成了。那既然有明码比较这个词,就不难猜出还有相应的非明码比较...非明码比较也比较容易理解,就是软件比较两个注册码的方法不同而以,并不是计算出正确的注册码后就与用户输入的进行比较,它可能会采用每计算出一位就与注码中的相应位比较一次,一但发现与用户输入的不同,就提示出错等等等等...
遇到这样的软件,我们其实也可以找到其相应的注册码,但有点儿惨,要一位一位的计下来...但是如果人家不给你面子,一但计算出某位不正确就跳走的话,那你怎么办?所以,国民想致富,种树是根本...NG!所以遇到这种软件,我们就只有对其算法进行分析,并做出注册机才是唯一的方法(如果你想写注册机的话)...
你要明白,就算我们能找到那些采用明码比较的软件的注册码,原因也仅仅是因为其采用的是明码比较,所以我们没有什么值的高兴的地方,我们真正要做的,并不是找到一个注册码而以...当然如果你刚入门,那对你的提高还是很有帮助的。我们Crack一个软件的最终目的,是对其进行相应的分析,搞懂它的注册算法并写出注册机,这样才算是成功的Crack了一个软件,成功后的心情是难以表达的!就像你便秘了多天后一下子排了出来一样 ^_^,呵呵这个比喻虽然粗俗,但是你可以想象一下,对一个软件进行仔细的分析,最后一下把它的算法给搞明白了,那种感觉...我深信不疑的认为有一天你也能体会的到,偶等你
相信你以前看过那些高人大虾的关于软件注册算法分析的文章,同时也相信你有过试图跟踪分析某软件的举动,虽然后来的结果另人不太满意
其实分析一个软件的注册算法,这其中包括了一些技巧性方面的东西以及必要的经验,很难想象一个连调试器的使用都还没掌握的人试图去分析一个软件会是怎样一个场面...嘿嘿,偶是见过的 使用调试器并不难,但那并不意味着你就能去分析一个软件了,见CALL就追这样的举动可不是偶一个人有过的经历,本章我尽量给你说明适当的分析方法。
相信大家都有不在父母陪同下独自使用调试器的能力以及看懂大部分汇编指令的能力了吧,那就够了!我们开始...
正式开始今天的正题,我来举两个例子,相信这两个例子都有足够的表达能力,最起码比我们家楼下那个卖油条的表达能力要强多了...
好的,首先,我们还是请出我们的那位老朋友吧 嘿嘿,在此,偶向CHINAZIP(中华压缩)v7.0的作者表示我内心最真诚的歉意!相信我用这个老版本的中华压缩不会给您带来经济上的麻烦...
通过前边儿两章的讲解,我们已经把这个软件大体上给搞明白了,并且也追出了其相应的注册码。而我们今天的目的是对其注册算法进行分析,并写出注册机!这个软件的注册算法其实也比较简(并且存在Bug)用它来当例子,很能说明情况...
好的,我们开始,前边儿追注册码的时候我们就已经知道了其用于计算正确注册码的关键CALL的所在位置为004f4dde,我们用TRW2000来对其进行分析!(鉴于目前大部分教程中仍以TRW2000为主,而且这个是大多数菜鸟都会用的调试器,偶就用这个调试器来做具体讲解)
先启动CHINAZIP,帮助--注册(所以我才说这个软件非常适合写教程用嘛,注册后仍然中以再次注册)输入注册名Suunb,注册码19870219。之看按Ctrl+N呼出TRW2000,下断点bpx 004f4dde,F5返回。
接着就按确定吧,呵呵,被TRW2000拦到了。通过前边两章的分析,我们以经知道了004f4dde处的这个CALL用于计算正确的注册码,所以我们直接按F8跟进吧!注册码的算法,就包涵在这个CALL中,把它给分析透了,我们也就能弄明白软件的注册码是怎样生成的了。但是要怎么分析呢?这是一个比较严肃的问题,面对那一堆堆的指令,我不知道你是怎么想的,反正我第一次时是觉的找不着北,我怎么哪些重要哪些不重要呢?再说了,里面又包涵了那么多CALL,我还要一个一个地追进去看看?
呵呵,这就是我说的技巧所在了。其实也没什么可怕的,只要你汇编不是问题,就行了。我们首先可以先把这个计算注册码的CALL从头到尾执行一遍,搞明白其中大概的跳转以及其中某些CALL的作用,hehe~~你可以执行过一个CALL后就看一下各个寄存器的变化情况(如果寄存器中的值改变了,颜色就会变)如果某寄存器的值在CALL过之后改变了,我们就可以看一下其包含的值是何类型,如是内存地址就用d指令看一下,如是数值就看一下是不是得到你输入注册名或注册码的位数等等,这样的话就可以淘汰下来一大部分的CALL,因为有许多CALL的作用只是把注册名或注册码装入到内存中的某个地址或者得到注册名(注册码)的位数或注册码某一位的ASCII码,对与这些,我们不必深究。还是推荐你用Ollydbg,执行过一条指令后很多信息都可以看到 好的,我接着说,按F8追入CALL之后先大概走一遍...我给出追入后的反汇编代码,并给出注释,相应的分析看后面...
0167:004f4fac push ebp <--F8跟入后的第一条指令
0167:004f4fad mov ebp,esp
0167:004f4faf push byte +00
0167:004f4fb1 push byte +00
0167:004f4fb3 push byte +00
0167:004f4fb5 push byte +00
0167:004f4fb7 push byte +00
0167:004f4fb9 push byte +00
0167:004f4fbb push byte +00
0167:004f4fbd push ebx
0167:004f4fbe push esi
0167:004f4fbf push edi
0167:004f4fc0 mov ,ecx
0167:004f4fc3 mov ,edx
0167:004f4fc6 mov eax,
0167:004f4fc9 call 004041c0
0167:004f4fce xor eax,eax
0167:004f4fd0 push ebp
0167:004f4fd1 push dword 004f5097
0167:004f4fd6 push dword
0167:004f4fd9 mov ,esp
0167:004f4fdc xor esi,esi
0167:004f4fde lea eax,
0167:004f4fe1 mov edx,
0167:004f4fe4 call 00403e24 <--此CALL过后用于得到用户输入的注册名
0167:004f4fe9 mov eax, <--将得到的注册名的地址装用eax寄存器
0167:004f4fec call 0040400c <--此CALL用于得到用户输入的注册名的位数,并将其放入eax中
0167:004f4ff1 mov edi,eax <--将注册名的位数装入edi中
0167:004f4ff3 test edi,edi <--对edi进行测试
0167:004f4ff5 jng 004f5051 <--如果edi中的值为0就会跳走
0167:004f4ff7 mov ebx,01 <--ebx置1,用于后面的运算
0167:004f4ffc mov eax, <--ebp-0c中装的是注册名的内存地址,此时将其付于eax
0167:004f4fff mov al, <--eax中此时装的是注册名的内存地址,加上ebx中的值再减去01,用于得到注册码中的相应位的字符,比如说我们第一次执行到这里的时候ebx中装入的是01,再减去01后得到的值其实还是eax本身,这样就能得到注册名中的第一个字符了,而执行到后边再跳回来时ebx会加上1,所以就能得到下一个字符了...
0167:004f5003 call 004f4f60 <--这个CALL很重要,后面会说明我们是怎样知道它很重要的
0167:004f5008 test al,al <--在这里我们会发现一个测试运算,对象是al,而al在前边CALL之前刚装入了注册名中的某一个字符,所以我们可以断定上面的那个CALL会对得到的字符做上一些手脚,待会儿我们再跟入...
0167:004f500a jz 004f5031 <--如果al中装的是0就跳到004f5031处,而al中的值会被004f5003处的那个CALL所改变
0167:004f500c lea eax,
0167:004f500f mov edx, <--ebp-0c中装的是注册名的内存地址,此时装入edx中
0167:004f5012 mov dl, <--跟前边儿004f4fff处的指令道理相同,得到注册码中的当前参加运算的字符
0167:004f5016 call 00403f34 <--不重要!!
0167:004f501b mov eax,
0167:004f501e lea edx,
0167:004f5021 call 004088ac <--不重要!!
0167:004f5026 mov edx,
0167:004f5029 lea eax,
0167:004f502c call 00404014 <--该CALL同样比较重要,其作用是这样的,如果当前参加运算的字符在前边004f5003的CALL里进行运算之后符合了要求(符合要求后al会被置非0值)那么在004f500a处的跳转将会失去作用,而执行到这里后该CALL会将当前的这个符合要求的字符保存到00D3B3C4处(内存)!!后边儿会再详细说明
0167:004f5031 cmp ebx,byte +01 <--用此时ebx中装的值减去1
0167:004f5034 jz 004f5040 <--如果为零,也就是说此时计算的是注册名中的第一个字符的话就跳到004f5040处
0167:004f5036 mov eax, <--ebp-0c中装的是注册名的内存地址,该指令将注册名的内存地址装入eax中
0167:004f5039 movzx eax,byte <--用于得到上一个参加运算的字符
0167:004f503e jmp short 004f5046 <--无条件跳转到004f5046处
0167:004f5040 mov eax, <--ebp-0c中装的是注册名的内存地址
0167:004f5043 movzx eax,byte <--得到注册名的第一个字符
0167:004f5046 lea esi, <--!!!这一条指令就是关键所在,后面会说明的!!!此指令先得到本轮参加运算的字符的ASCII码,然后乘以6,之后再加上a8(即十进制数168,呵呵,可以理解)同时再将这个字符计算得到的值与前面已经运算过的字符的值的和相加!
0167:004f504d inc ebx <--ebx加1,用于得到注册码的下一个字符
0167:004f504e dec edi <--edi减1,edi中装的是注册码的位数
0167:004f504f jnz 004f4ffc <--不为零就跳到004f4ffc处开始对下一个字符进行运算...也就是说每计算完一个字符就将edi减去1,直到其为0也就是所有的字符全参加过运算为止。
0167:004f5051 lea edx, <--把装注册码后半部分的地址装入edx,传给下面的CALL
0167:004f5054 mov eax,esi <--将前面计算的注册码的后半部分的值装入eax中
0167:004f5056 call 00408c70 <--将前面计算得到的注册码后半部分的值转换为十进制,并装入ebp-1c中
0167:004f505b mov ecx, <--epb-1c中装的是注册码的后半部分
0167:004f505e lea eax,
0167:004f5061 mov edx, <--ebp-10中装的是注册码的前半部分
0167:004f5064 call 00404058 <--该CALL用于将前后两部分注册码合并置一起,合并后的注册码会存放置ebp-0c处
0167:004f5069 mov eax,
0167:004f506c mov edx,
0167:004f506f call 00403de0
0167:004f5074 xor eax,eax
0167:004f5076 pop edx
0167:004f5077 pop ecx
0167:004f5078 pop ecx
0167:004f5079 mov ,edx
0167:004f507c push dword 004f509e
0167:004f5081 lea eax,
0167:004f5084 mov edx,05
0167:004f5089 call 00403db0
0167:004f508e lea eax,
0167:004f5091 call 00403d8c
呵呵,看了我加了注释后的代码是不是好理解多了?你也许会问,你怎么知道那些CALL是做什么的?我前边儿不是说过方法了吗?我们先大概地过上一遍,看一下各个跳转,然后再大大概的看一下各个CALL的作用...你以为上面这些注释是我过一遍之后就能写出来的?你多过几遍,心中就会有了个大概...
你现在在想些什么?众人:站着说话不腰痛...我晕~~
呵呵,我尽量说的仔细一些:
其实很好理解的,我们追了进来,之后大概的看一下那些个CALL,其中一些稍有经验的一看就知道是用来得到注册名或长度什么的...之后我们再从头跟一遍...跟到004f4ff3处,会发现其会对注册名的位数进行一个比较,看用户是否输入了注册名...(也就是说如果edi中装的注册名的位数不大于0,即没输入就跳走,一会儿我会在后面说一下关于这点儿的Bug)而后在004f4ffc处我们会发现软件会得到注册名的内存地址,接下来的一条指令一看就知道是用来得到注册名中的各个字符的,嘿嘿,见到这类指令,马上就向下看吧,找一下下边儿哪条指令会再跳回到004f4ffc处...呵呵,我们会在004f504f处发现目标,好了,现在我们就知道了从004f4ffc到004f504f之间的那些个指令会对注册名中的每一个字符进行计算...
呵呵,也就是说软件从004f4ffc处开始先是得到注册名中的第N位字符,然后进行一系列的运算,之后执行到了004f504e处时把先前先到的注册名的位数减去1然后看其是否为0,不为0就再跳到004f4ffc处,然后得以注册名的N+1位再来进行计算。此举的目的就是为了看注册名的各位是否都被计算过了,如果不为0就说明还没有计算完,呵呵,很简单的道理嘛,edi中装的是注册名的位数,第计算过一位后就将其减1,减完了,注册名的各位也就都参加了运算...
好的,我们再来看具体的算法部分:
在004f4ff5的跳转,如果你输入了注册名,其就不会跳走...偶输入的是Suunb,好的,此时会继续执行到004f4ff7处,该指令对ebx进行初始化...给它付1,然后在004f4ffc处时会将ebp-0c中装的注册名的内存地址装入eax中,接着的004f4fff处用于得到注册名的第一个字符,并将其装入al。想象一下,eax中装的是注册名的内存地址,从该地址开始连续10个内存单元是我们输入的注册名S u u n b [ C C G ] 呵呵,明白了吗?eax中装的内存地址就是注册名在内存中的首地址,第一次执行到这里时ebx中装的是1,eax+ebx-01后得到的还是注册名的首地址,也就是S。而等到后面004f504f处的跳转指令跳转回来之前,会在004f504d处有一条inc指令会给ebx加1,这样的话再执行到这里时就会得到注册名中的第2个字符u了,嘿嘿,第三次来之前会再给ebx加上1,明白了吗?总知你可以把ebx中的值理解为当前参加运算的字符在注册名中的位数,即ebx是1就是得到注册名的第一位(S),如果ebx是2就是得到注册名的第2位(u).
而后紧接着在004f5003处会有一个CALL等着我们,呵呵,这个CALL比较关键,注册码的一部份由它来决定,要发现它的重要性并不难,因为在004f5003处下面会有一个跳转,跳转之前会对al进行测试,嘿嘿,而al在CALL之前装入的是当前参与运算的字符...并且你用调试器过一下这个CALL就会发现其对al进行了修改,呵呵,这个CALL会对al做一些处理,而处理的结果直接影响了后面部分的流程,所以,对于它,我们一定要跟进...最好能派出两个人在边路对其进行防守,并找专门的后位对其盯梢...
我们待会儿再跟进它,现在还是要先搞明白软件大体上的算法。好的,我接着说,在004f5008处对al进行了测试之后会有一个跳转,即如果al中此时装的值为0就跳到004f5031处去...你可以理解为这个CALL会对字符进行一些运算,如果符合了要求,al就会被置0或1什么的,出来后的测试用来判断当前字符是否符合要求,如果符合就跳或不符合就跳...
继续,由于我输入的注册名的第一个字符是S,而S刚好能通过004f5003处的那个CALL的计算 所以就没有跳走,我继续按F10进行单步执行...接下来的004f500c、004f500f、004f5012这三条指令跟前边儿的得到注册码第N位字符的指令道理是一样的,你看注释好了...而后面从004f5016到004f5029处的这几条指令也没什么好讲的,对中间的两个CALL好奇的话可以进去大概看一下。得不到什么实质性的东西...而004f502c处的这个CALL嘛,就很重要了,呵呵,它的作用是什么呢?还记的我刚才说过的004f5003处的那个CALL吧,它执行过后会使al发生变化,它下面的跳转指令会根据al的值做相应跳转,即如果al为0,就跳到004f5031处,刚好就跳过了004f502c处的这个CALL...而我输入的第一个字符是S,刚好符合了004f5003处那个CALL的要求,所以没有跳走,于是就执行到了这里,你可以追进去看一下,里面并不复杂,只是将当前参加运算的字符装入内存的00D3B3C4处(如果当前参加运算的字符在004f5003处没有通过,就不会执行到这里,呵呵,明白过来了吧,这个CALL用于收集注册名中所有符合004f5003处那个CALL要求的字符)
HOHOHO~~(请模仿周星星式的笑声...)现在我们已经明白了一半了...好的,我们继续...
不管你是从004f500a处跳到004f5031处的,还是一步步执行到这里的,总知,不管你输入的注册名中参加当前运算的那一个字符符不符合004f5003处的那个CALL的要求,总知都会执行到这里...这条指令用来干什么呢?还记的ebx中装的是参加运算的字符在注册名中的相应的位数吗?cmp ebx,byte +01 就是用ebx减去1,该条指令的用途也就是看一下当前参加运算的字符是不是注册名中的第一个字符,如果是就跳到 004f5040处,否则继续... 我们先看004f5040处,当执行到此处时,ebp-0c中装的其实是注册名的内存地址(前边就已经说过了)在这里将其装入eax中,而后面004f5043处的指令的用途就是得到注册名的第一个字符...好了,我们再拐回来看004f5036处,如果当前参加运算的字符不是注册名中的第一个字符,就不会跳走,而执行到这里时同样将ebp-0c中装的注册名的内存地址放入eax中,而004f5039处的eax,byte 嘛,呵呵,很好理解,eax+ebx-01得到的是当前参加运算的字符的内存地址,而这里的eax+ebx-02得到的就是当前参加运算的字符的前面的那个字符,了解?
我们接着看004f5046处的那条指令吧,这个同样非常重要,它的作用是计算注册码的后半部分!
我相信你很容易就能理解它的意思了,当执行到这里时,eax中装的或者是注册码中的第一个字符,或者是当前参加运算的字符的前一个字符(注:字符在内存或寄存器中是以ASCII码来表示的,如S在eax中会显示为00000053,而S的ASCII码便是53,十进制为83)...我们第一次执行到这里时,esi中的值为0(即00000000)eax*4+a8的意思就是用当前参加运算的字符的ASCII码乘以4,再用积加上a8(也就是十进制数168,一路发?)再用这个和与esi相加,我已经说过了,第一次执行到这里时esi中的值为0...而当第二次执行到这里时,esi中装的便是注册名的第一个字符的ASCII码乘以4再加一路发的和...
你会问你为什么知道它是计算注册码的后半部分的?猜的!!呵呵,当然不是,我们可以看到,在004f5054处,程序会将前面计算的结果装用eax中,后边儿紧接着就是一个CALL,嘿嘿,光天化日之下,这也太明显了吧,我们追进去大概看一下就知道它的作用是将十六进制的数转换为十进制的...并将转换后的结果装入edx中装的内存地址处,在CALL之前我们会看到edx中的值以由004f5051处装入,即ebp-1c,呵呵,CALL过之后你用d ebp-1c看一下,就会看到你注册码的后半部分了...
而后程序会在004f505b将注册码后半部分装入ecx中,在004f505e处时会将一个内存地址ebp-0c装入eax处(它的作用就是起一个传递参数的作用,在待会儿的CALL中会用eax中装入的值来存放结果)之后的004f5061处会将ebp-10装入edx中,ebp-10处装的是什么呢?我们用d ebp-10指令看一下就会知道它的地址为00D3B3C4,嘿嘿,你的嗅觉敏感吗?不敏感的话我就再说一遍,还记的004f502c处的那个CALL吗?它的作用就是收集符合004f5003处的那个CALL的要求的字符...
嘿嘿,你明白过来了吗?
这个软件的注册算法是这样的:首先得到注册码的位数,看其是否大于0,不大于0就跳到004f5051处...好的,我们输入了Suunb这个注册名,此时的注册码位数就是10,所以不会跳走,之后我们会来到004f4fff处,第一次执行到这里时会将注册名的第一个字符S装入al中,第二次来时会将注册名中的第二个字符(即u)装入al中,它的作用就是将当前参加运算的字符装入al中,之后紧接着就是一个CALL,这个CALL会对当前参加运算的字符进行计算...接着出来会有一个跳转,看al中装的是不是0,如果是就跳到004f5031处,如果不是非0值就说明当前这个字符符合了要求,那么就会执行到004f502c处,这里的CALL会将其存放置内存的00D3B3C4处...而后到了004f5031处会有一个比较,作用是看当前参加运算的字符是不是注册名中的第一个字符,是的话就跳到004f5040处,在此将注册名的第一个字符装入eax,用来参加004f5046处的计算。如果当前参加运算的不是注册名的第一个字符,那么就会在执行到004f5039处时得到当前参加运算的字符前面的那个字符,将其装入eax后就无条件跳到004f5046处来参加运算。了解?也就是说你输入的注册名的第一个字符会参加两次计算,而最后一个字符不会参加计算(想想看,如果当前参加运算的字符是注册名中的第一个字符,它会参加计算,如果是第二个,就取前边的一个,即第一个又会参加一次计算,到了第三个的时候取第二个,到了第四个的时候取第三个...而当最后一个字符来到这里时会取前边的那个字符来参加运算,而这之后就循环就结束了,所以,最后一个不会被计算入内)等到注册名中的所有字符都参加过了运算,就会来到004f5056处,在这里将前面004f5046处的计算结果转换为十进制...而后会在后面的004f5064处的那个CALL里,将其与先前装入00D3B3C4处的所有符合004f5003处的CALL要求的字符合并到一起,这个结果,嘿嘿,就是真正的注册码了!
也就是说,真正的注册码是由以下部分组成的:
你输入的注册名中的所有符合004f5003处的那个CALL要求的字符+((注册名中的第一个字符的ASCII码*4+168)*2+(除第一位和最后一位外的所有字符)*4+168的和的和)
现在我们也知道注册码是怎样炼成了的 那么我们要写注册机,就一定要把004f5003处的那个CALL给搞明白,这样的话,我们才能对注册名中的字符进行筛选...
好的,我们再来:
Ctrl+N呼出TRW2000,下bpx 004f5003,F5退出点确定被拦后便按F8跟进,呵呵,这个就没什么好说的了,看我给出的注释吧:
0167:004f4f60 push ebp
0167:004f4f61 mov ebp,esp
0167:004f4f63 push ecx
0167:004f4f64 push ebx
0167:004f4f65 push esi
0167:004f4f66 mov ,al <--将字符装入内存ebp-01处
0167:004f4f69 mov byte ,02 <--ebp-03处装入02
0167:004f4f6d mov byte ,01 <--ebp-02处装入01
0167:004f4f71 mov cl, <--将参加运算的字符装入cl
0167:004f4f74 dec ecx <--cl减1
0167:004f4f75 sub cl,02 <--cl再减去2
0167:004f4f78 jc 004f4fa4 <--有进位就跳转,你不用担心,一般都不会跳走的啦
0167:004f4f7a inc ecx <--ecx加1,也就是cl加1
0167:004f4f7b mov bl,02 <--bl装入02
0167:004f4f7d xor eax,eax <--eax做异或运算,即将eax置0
0167:004f4f7f mov al, <--al装入参加运算的字符
0167:004f4f82 xor edx,edx <--edx置0
0167:004f4f84 mov dl,bl <--将bl中的值付给dl
0167:004f4f86 mov esi,edx <--再付给esi
0167:004f4f88 xor edx,edx <--edx置0
0167:004f4f8a div esi <--用eax中装的参加运算的字符的ASCII码除以当前esi的值
0167:004f4f8c test edx,edx <--测试edx,edx中装的是上刚才除法计算后的余数
0167:004f4f8e jnz 004f4f93 <--不为0就跳到004f4f93处
0167:004f4f90 inc byte <--ebp-03处的值加1
0167:004f4f93 cmp byte ,02 <--用ebp-03处的值减去02
0167:004f4f97 jna 004f4f9f <--不大于就跳到004f4f9f处
0167:004f4f99 mov byte ,00 <--ebp-02装入00
0167:004f4f9d jmp short 004f4fa4 <--无条件跳转到004f4fa4处
0167:004f4f9f inc ebx <--ebx加1
0167:004f4fa0 dec cl <--cl减1
0167:004f4fa2 jnz 004f4f7d <--不为0就跳到004f4f7d处再来一遍
0167:004f4fa4 mov al, <--将ebp-02处的值装入al后返回
0167:004f4fa7 pop esi
0167:004f4fa8 pop ebx
0167:004f4fa9 pop ecx
0167:004f4faa pop ebp
不知道你看不看的明白,我大概给你说明一下,大体上就是这样的:
先得到这个字符的ASCII码,然后用其减去2,并将bl置值02...然后用eax中装的减了2的ASCII码除以esi中装的bl中的值,之后就看edx中装的余数是否为0,如果为0就将ebp-03处的值加1,你应该知道ebp-03处在初始化的时候被付值为2,如果其被加了1,那就大于了2,这样的话后面在004f4f97处就不会跳走,如果不跳走,在004f4f99处,ebp-02就会被装入00,之后就会无条件跳转到004f4fa4处,在那里就会把ebp-02的值,也就是00装入al,明白过来了吧...但如果edx中装的余数不为0,那么在004f4f8e处就会跳走,到了004f4f93处时由于ebp-03中装的是02,所以条件就会成立,从而可以跳到004f4f9f处去继续执行程序...而到了004f4f9f处后ebx(也就是bl)会被加上1,而cl在后面会被减去1,如果cl不为0的话就再跳到004f4f7d处,再来一遍,直到cl变为零为止...
上面这个过程在Delphi中可以这样表示:
(变量S中装的是当前参加运算的字符,Code变量用来收集符合要求的字符,变量的声明我没有写明)
N:=Ord(S);
for i:=2 to N-1 do
begin
modz:=(N-i) mod i;
if modz=0 then Break;
end;
if modz<>0 then
Code:=Code+S;
呵呵,这就起到了与前面汇编代码相同的作用了
下面我给你写一个函数,该函数可以用来得到注册码中的所有符合要求的字符:
function GetKeyChar(Name: String): String;
var
i,ASC,sh,modz:integer;
Code:String;
begin
for i:=1 to Length(Name) do
begin
ASC:=Ord(Name);
for sh:=2 to ASC-1 do
begin
modz:=(ASC-sh) mod sh;
if modz=0 then Break;
end;
if modz<>0 then
Code:=Code+Name;
end;
Result:=Code;
end;
你可以这样来用:
var
S1,S2:String;
begin
S1:=Edit1.text; //Edit1用来输入注册名;
S2:=GetKeyChar(S1); //此时S2中得到的便是注册名中所有符合要求的字符了;
end;
嘿嘿,你现在是不是很想知道都有哪些字符能符合要求?嘿嘿,其实CHINAZIP自己就可以告诉我们,你只要在输入注册名的时候把所有的可用字符全填上,然后在用d指令看一下注册码的前半部(即非数字部分),就可以知道了,当然你也可以自己写一个程序来试试,用Delphi的话可以直接用我上面给的函数...告诉你好了,在所有的ASCII字符中,只有以下几个符合要求:
CGIOSYaegkmq5=%)+;/
不信的话你可以试试,正确的注册码中的字符只能是这几个...嘿嘿,看来还是比较尊重我们CCG的嘛
好了,我又废话了这么多,把完整的注册机给你贴出来吧,这并不难,只要加上后半部分注册码的计算就OK了:
你可以在Delphi中声明以下函数,便可直接使用:
function GetKey(Name: String): String;
var
N:String;
i,sh,ci:integer;
Si:integer;
ASC,modz:integer;
begin
i:=Length(Name);
if i=0 then Result:='请输入注册名...'
else
begin
for sh:=1 to i do
begin
ASC:=Ord(Name);
for ci:=2 to ASC-1 do
begin
modz:=(ASC-ci) mod ci;
if modz=0 then Break;
end;
if modz<>0 then N:=N+Name
end;
Si:=Ord(Name)*4+168;
for sh:=1 to i-1 do
begin
Si:=Si+Ord(Name)*4+168;
end;
N:=UpperCase(N+inttostr(Si));
Result:=N;
end;
end;
最后顺便说一下,如果你稍微留意一下,就会发现,在刚开始的004f4ff3处会对注册名的位数进行测试,即如果位数为0就会在下一条指令时跳至004f5051处,如果你稍微有一点儿经验,就会发觉,通常如果程序发现注册名的位数为0,就会直接跳到失败处,而这个软件却没有!004f5051处是什么呢?晕~~具然是要得到注册码的后半部分,呵呵,我们以到00D3B3C4处看看,会看到一堆0,你现在在想什么呢?既然我们没有输入注册名,那么就不可能有注册码的前半部分,而后边便会有CALL来合并前后两部分的注册码 你重新启动一下软件,注册名不填,把注册码填为0注册一下看看...HOHO~~(请仍旧模仿周星星式的笑声)这个粗心的作者啊,造成这样的原因很简单,软件根本就没有判断注名是否为空并在软件初始化的时候把用于计算注册码后半部分的integer变量付了初始值0,否则的话00D3B3C4处的内存应该为空值..(难不成到时连0都不用输就能注册?)
所以说,Crack并不是一件坏事,像这种情况你完全可以告诉作者的嘛,到时不但交了一个朋友而且说不准还会得到个免费的注册码....(不知道有没有白帽子Cracker?嘿嘿,CCC刚好也可以是注册码的前半部分哦~~)我希望你明白,对于这种注册算法简单且存在Bug的软件(通常也说明其作者还没什么经验 ^_^),我们不应该为能提供它注册机而感到高兴,如果能帮助其作者改善算法或去掉Bug,又何尝不是一件好事呢?毕竟软件上面加的有中华两个字,你忍心???
我不知道上面给你讲的中华压缩注册分析你是否看懂了,我个人认为我讲的还是比较详细的了(几乎每条指令都加了注释且又再三在后面说明)但如果你仍然看不懂的话,请务必相信是本人写的文章不好,不要放弃啊哥们儿~~!
好了,我再来给你举另外一个例子...通过它来给你讲一下另外一种比较常见的注册码计算方法,即将运算的结果与一个表中的字符进行转换,也就是常说的密码表啦^_^
本来是想用网际快车FlashGet的,可是在看雪已经有人贴了最新的1.40版的破文&注册机,正好前些天的时候网友啥也不是在后面跟贴说要帮他看一下语音界面2.0这个软件,down下来后大概看了一下,呵呵,发现这个正是我想要的,注册码计算的过程中采用了密码表并且也不难...hehe~~后来HMILY老哥看到了啥也不是的另一个贴子,也写个注册机和破文,你可以参考一下,嘿嘿,HMILY跟偶是自己人,所以偶不怕他...
我们开始吧...
首先运算一下这个软件,其会自动生成机器码,在我这边儿是xn2urkeUMwpNv5xZ。
这一章,我会用调试器Ollydbg来作讲解,它真的很好用...我们开始吧:
偶不知道你是否喜欢Ollydbg的下断方式,总知偶是不喜欢,从那么多API里面先(字好小),再说了,偶还是喜欢用Hmemcpy来断,除非断不到或在2K/XP下,否则偶才不要去跑API呢,往往要三四次才断到,多累啊 我们还是先请临时演员TRW2000出出一下场吧(把你的MP3先暂停一下 ),下bpx hmemcpy点确定后会被拦,pmodule后返回到0040432f处,我们就从这里开始吧 导演:"Stop!换吴孟达出场" 嘿嘿,继续你的MP3,请同时打开Ollydbg
我们用Ollydbg载入,在反汇编代码处(即左上方那个子窗口中)按Ctrl+G,输入0040432f,回车后便来到了这里。我们大概看看,有经验的话很容易就会看出此地便是了(这次运气比较好,一下就能找到软件计算注册码的地方 ^_^)
好吧,我们按F2在这里下断,接着按F9来运行程序,在注册处输入CHINA Cracking Group Suunb后按确定会被Ollydbg断下来,大概跑跑看看吧 我贴出反汇编代码:
0040432F |. 8D4C24 10 LEA ECX,DWORD PTR SS:
00404333 |. 6A 05 PUSH 5
00404335 |. 51 PUSH ECX
00404336 |. 68 E8030000 PUSH 3E8
0040433B |. 8BCE MOV ECX,ESI
0040433D |. E8 10050000 CALL <JMP.&MFC42.#3092>
00404342 |. 8BC8 MOV ECX,EAX
00404344 |. E8 7D060000 CALL <JMP.&MFC42.#3873>
00404349 |. 8D5424 18 LEA EDX,DWORD PTR SS:
0040434D |. 6A 05 PUSH 5
0040434F |. 52 PUSH EDX
00404350 |. 68 E9030000 PUSH 3E9
00404355 |. 8BCE MOV ECX,ESI
00404357 |. E8 F6040000 CALL <JMP.&MFC42.#3092>
0040435C |. 8BC8 MOV ECX,EAX
0040435E |. E8 63060000 CALL <JMP.&MFC42.#3873>
00404363 |. 8D4424 20 LEA EAX,DWORD PTR SS:
00404367 |. 6A 05 PUSH 5
00404369 |. 50 PUSH EAX
0040436A |. 68 EA030000 PUSH 3EA
0040436F |. 8BCE MOV ECX,ESI
00404371 |. E8 DC040000 CALL <JMP.&MFC42.#3092>
00404376 |. 8BC8 MOV ECX,EAX
00404378 |. E8 49060000 CALL <JMP.&MFC42.#3873>
0040437D |. 8D4C24 28 LEA ECX,DWORD PTR SS:
00404381 |. 6A 05 PUSH 5
00404383 |. 51 PUSH ECX
00404384 |. 68 EB030000 PUSH 3EB
00404389 |. 8BCE MOV ECX,ESI
0040438B |. E8 C2040000 CALL <JMP.&MFC42.#3092>
00404390 |. 8BC8 MOV ECX,EAX
00404392 |. E8 2F060000 CALL <JMP.&MFC42.#3873>
00404397 |. 8B7C24 68 MOV EDI,DWORD PTR SS:
0040439B |. 33DB XOR EBX,EBX
0040439D |. 33C9 XOR ECX,ECX
0040439F |. 8D04BF LEA EAX,DWORD PTR DS:
004043A2 |. 8D0480 LEA EAX,DWORD PTR DS:
004043A5 |. 8D3480 LEA ESI,DWORD PTR DS: <--上面的这些你都不需要管,因为它们帮不了我们什么忙
004043A8 |. C1E6 02 SHL ESI,2 <--执行后ESI的值为5DC,及十进制数1500
004043AB |> 0FBE440C 50 /MOVSX EAX,BYTE PTR SS: <--ESP+ECX+50就是机器码在内存中的地址(首次执行到这里明ECX为0,得到的就是机器码的第一位,第二次到这里时ECX会加上1,得到的是第二位...)
004043B0 |. 03C6 |ADD EAX,ESI <--与ESI相加,也就是加上1500
004043B2 |. BD 3E000000 |MOV EBP,3E <--EBP置3E,及十进制数62
004043B7 |. 99 |CDQ <--扩展...
004043B8 |. F7FD |IDIV EBP <--EAX中装的机器码的第1 or 2 or 3 or 4位与1500的和与62相除
004043BA |. 0FBE440C 54 |MOVSX EAX,BYTE PTR SS: <--ESP+ECX+54得到机器码的第5位(还记的ESP+ECX+50中装的是第一位吗?首次执行到这里明ECX为0,得到的就是机器码的第5位,第二次到这里时ECX会加上1,得到的是第6位...)
004043BF |. 03C6 |ADD EAX,ESI <--同样加上1500
004043C1 |. 8A92 E4704000 |MOV DL,BYTE PTR DS: <--重要的地方来了!此时EDX中装的是前面的第1 or 2 or 3 or 4位机器码加上1500后再除以62的余数,那4070E4处是什么呢?如果在TRW2000中,我们用d 004070E4就可以看到,在Ollydbg中,我们可以在左下角处按Ctrl+G来输入相应的内存地址,这样的话就可以看到了。我们会发现从4070E4开始,装的是一串字符,依次是0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ。呵呵明白什么意思了吗?4070E4处指的是0,那4070E4加上edx中装的余数后的内存地址中装的便是当前机器码所对应的注册码。(如余数为5,那么从4070E4处的0开始往后数第5个字符就是了)该条指令执行过后就会把相应的注册码装入dl中
004043C7 |. 88540C 30 |MOV BYTE PTR SS:,DL <--将机器码的第1 or 2 or 3 or 4所对应的注册码装入ESP+ECX+30处
004043CB |. 99 |CDQ <--前边儿得到的第5 or 6 or 7 or 8位机器码扩展
004043CC |. F7FD |IDIV EBP <--同样除以62
004043CE |. 8A82 E4704000 |MOV AL,BYTE PTR DS: <--与004043C1处作用相同,不用我多说了吧,就是得到当前机器码的对应注册码
004043D4 |. 88440C 38 |MOV BYTE PTR SS:,AL <--装入ESP+ECX+38处
004043D8 |. 0FBE440C 58 |MOVSX EAX,BYTE PTR SS: <--得到机器码的第9 or 10 or 11 or 12位
004043DD |. 03C6 |ADD EAX,ESI <--与1500相加
004043DF |. 99 |CDQ <--扩展....
004043E0 |. F7FD |IDIV EBP <--除以62
004043E2 |. 0FBE440C 5C |MOVSX EAX,BYTE PTR SS: <--得到机器码的第13 or 14 or 15 or 16位
004043E7 |. 03C6 |ADD EAX,ESI <--与1500相加
004043E9 |. 8A92 E4704000 |MOV DL,BYTE PTR DS: <--前边的第9 or 10 or 11 or 12位所对应的注册码
004043EF |. 88540C 40 |MOV BYTE PTR SS:,DL <--装入ESP+ECX+40处
004043F3 |. 99 |CDQ <--扩展
004043F4 |. F7FD |IDIV EBP <--除以62
004043F6 |. 41 |INC ECX <--ECX加1
004043F7 |. 83F9 04 |CMP ECX,4 <--看ECX是否为4(前边儿是一次计算四位的嘛,第一次计算第1、5、9、13位,第二次是2、6、10、14...)
004043FA |. 8A82 E4704000 |MOV AL,BYTE PTR DS: <--得到前边的第13 or 14 or 15 or 16位机器码所对应的注册码
00404400 |. 88440C 47 |MOV BYTE PTR SS:,AL <--装入ESP+ECX+47处
00404404 |.^7C A5 \JL SHORT LIAOCACH.004043AB <--ECX小于4就从头再来一遍(直到16位机器码都计算完为止)
00404406 |. 8B35 AC524000 MOV ESI,DWORD PTR DS:[<&MSVCRT.atoi>] ;MSVCRT.atoi
0040440C |. 8D4C24 10 LEA ECX,DWORD PTR SS:
00404410 |. 51 PUSH ECX ; /s
00404411 |. 885C24 38 MOV BYTE PTR SS:,BL ; |
00404415 |. 885C24 40 MOV BYTE PTR SS:,BL ; |
00404419 |. 885C24 48 MOV BYTE PTR SS:,BL ; |
0040441D |. 885C24 50 MOV BYTE PTR SS:,BL ; |
00404421 |. FFD6 CALL ESI ; \atoi
00404423 |. 83C4 04 ADD ESP,4
00404426 |. 83F8 01 CMP EAX,1
00404429 |. 75 3C JNZ SHORT LIAOCACH.00404467
0040442B |. 8D5424 18 LEA EDX,DWORD PTR SS:
0040442F |. 52 PUSH EDX
00404430 |. FFD6 CALL ESI
00404432 |. 83C4 04 ADD ESP,4
00404435 |. 83F8 01 CMP EAX,1
00404438 |. 75 2D JNZ SHORT LIAOCACH.00404467
0040443A |. 8D4424 20 LEA EAX,DWORD PTR SS:
0040443E |. 50 PUSH EAX
0040443F |. FFD6 CALL ESI
00404441 |. 83C4 04 ADD ESP,4
00404444 |. 83F8 01 CMP EAX,1
00404447 |. 75 1E JNZ SHORT LIAOCACH.00404467
00404449 |. 8D4C24 28 LEA ECX,DWORD PTR SS:
0040444D |. 51 PUSH ECX
0040444E |. FFD6 CALL ESI
00404450 |. 83C4 04 ADD ESP,4
00404453 |. 83F8 01 CMP EAX,1
00404456 |. 75 0F JNZ SHORT LIAOCACH.00404467
00404458 |. 5F POP EDI
00404459 |. 5E POP ESI
0040445A |. 5D POP EBP
0040445B |. B8 FEFFFFFF MOV EAX,-2
00404460 |. 5B POP EBX
00404461 |. 83C4 54 ADD ESP,54
00404464 |. C2 0400 RETN 4
00404467 |> 8D7424 30 LEA ESI,DWORD PTR SS: <--正确的注册码的前4位的地址装入ESI中,嘿嘿,执行到这里时我们就可以看到正确的注册的前4位了,在TRW2000 or SoftICE中可以用d ESP+30来查看而在Ollydbg中什么都不用做就可以在左上方反汇编代码区与左下内存区中间的那个小窗体中看见 在TRW2000中下过D指令后按Alt+上下键翻几下,就可以看到所有的注册码了(它们并没有分太开嘛0063F5E0-0063F5E3是前4位,0063F5E8-0063F5EB是5-8位,0063F5F0-0063F5F3是9-12位,0063F5F8-0063F5FB是最后4位,而你输入的注册码的内存地址:0063F5C0-0063F5C3是前4位,0063F5C8-0063F5CB是5-8位,0063F5D0-0063F5D3是9-12位,0063F5D8-0063F5DB是最后4位,机器码存放的地址是0063F6000-0063F60F)
0040446B |. 8D4424 10 LEA EAX,DWORD PTR SS: <--你输入的注册码的前4位的地址装入EAX中
0040446F |> 8A10 /MOV DL,BYTE PTR DS: <--得到你输入的注册码的第1位或第3位(EAX中的值到了后边儿会加上2,这样再执行到这里时得到的就是第3位了)
00404471 |. 8ACA |MOV CL,DL <--传入cl中
00404473 |. 3A16 |CMP DL,BYTE PTR DS: <--与正确的注册码的第1位或第3位比较(ESI中的值会与EAX中的值一起改变)
00404475 |. 75 1C |JNZ SHORT LIAOCACH.00404493 <--不相等就跳走
00404477 |. 3ACB |CMP CL,BL <--CL与BL比较,BL中的值为00000000(也就是空啦),这条指令有什么用呢?其实很简单了,每4位注册码的后面都会再跟一个空值,也就是如你在内存中可以看到1234.那个.就是空值,明白过来了吧,等到前4位都被测试过了,cl中就会装入.也就是00000000,到时就可以在后面跳走了
00404479 |. 74 14 |JE SHORT LIAOCACH.0040448F <--如果CL中的值为零(即4位已经全部比较过了),就跳走
0040447B |. 8A50 01 |MOV DL,BYTE PTR DS: <--EAX+1后得到的会是你输入的注册码的第2位或者第4位(视EAX的值而定)
0040447E |. 8ACA |MOV CL,DL <--传入CL
00404480 |. 3A56 01 |CMP DL,BYTE PTR DS: <--与正确的注册码的第2位或第4位比较(ESI的值会与EAX一起改变)
00404483 |. 75 0E |JNZ SHORT LIAOCACH.00404493 <--不相等就跳走
00404485 |. 83C0 02 |ADD EAX,2 <--EAX加上2,这样的话待会儿再跳到0040446F处时,再得到的就是你输入的注册码的第3位了
00404488 |. 83C6 02 |ADD ESI,2 <--同上,ESI加上2后再跳到0040446F处重新再来一遍时就会得到正确的注册码的第3位
0040448B |. 3ACB |CMP CL,BL <--再次比较CL是否为空
0040448D |.^75 E0 \JNZ SHORT LIAOCACH.0040446F <--不为空就再跳到0040446F处,来继续比较前4位中的1、3两位
0040448F |> 33C0 XOR EAX,EAX <--1-4位全部比较完后会跳到这里
00404491 |. EB 05 JMP SHORT LIAOCACH.00404498
00404493 |> 1BC0 SBB EAX,EAX
00404495 |. 83D8 FF SBB EAX,-1
00404498 |> 3BC3 CMP EAX,EBX
0040449A |. 0F85 AB000000 JNZ LIAOCACH.0040454B
004044A0 |. 8D7424 38 LEA ESI,DWORD PTR SS: <--与上面的大体相同嘛,将正确注册码的5-8位的内存地址装入ESI中
004044A4 |. 8D4424 18 LEA EAX,DWORD PTR SS: <--你输入的注册码的5-8位的内存地址装入EAX中
004044A8 |> 8A10 /MOV DL,BYTE PTR DS: <--得到你输入的注册码的第5 or 7位(道理我相信你一定已经明白了)
004044AA |. 8ACA |MOV CL,DL <--再装入CL中
004044AC |. 3A16 |CMP DL,BYTE PTR DS: <--与正确的注册码的第5 or 7位比较
004044AE |. 75 1C |JNZ SHORT LIAOCACH.004044CC <--不相等就跳走
004044B0 |. 3ACB |CMP CL,BL <--与BL中的00000000比较,看5-8位是否已经全部比较完毕
004044B2 |. 74 14 |JE SHORT LIAOCACH.004044C8 <--是的话就跳走
004044B4 |. 8A50 01 |MOV DL,BYTE PTR DS: <--得到你输入的注册码的第6 or 8位
004044B7 |. 8ACA |MOV CL,DL <--装入CL
004044B9 |. 3A56 01 |CMP DL,BYTE PTR DS: <--与正确的注册码的第6 or 8位比较
004044BC |. 75 0E |JNZ SHORT LIAOCACH.004044CC <--不正确就跳走
004044BE |. 83C0 02 |ADD EAX,2 <--EAX加2,这样做的目的相信你已经知道了吧
004044C1 |. 83C6 02 |ADD ESI,2 <--ESI也加上2
004044C4 |. 3ACB |CMP CL,BL <--比较CL是否为空
004044C6 |.^75 E0 \JNZ SHORT LIAOCACH.004044A8 <--不是就跳回去再来一遍
004044C8 |> 33C0 XOR EAX,EAX <--5-8位全部比较完后全跳到这里
004044CA |. EB 05 JMP SHORT LIAOCACH.004044D1
004044CC |> 1BC0 SBB EAX,EAX
004044CE |. 83D8 FF SBB EAX,-1
004044D1 |> 3BC3 CMP EAX,EBX
004044D3 |. 75 76 JNZ SHORT LIAOCACH.0040454B
004044D5 |. 8D7424 40 LEA ESI,DWORD PTR SS: <--将正确的注册码的9-12位的内存地址装入ESI
004044D9 |. 8D4424 20 LEA EAX,DWORD PTR SS: <--你输入的
004044DD |> 8A10 /MOV DL,BYTE PTR DS: <--得到你输入的注册码的第9 or 11位
004044DF |. 8ACA |MOV CL,DL <--装入CL
004044E1 |. 3A16 |CMP DL,BYTE PTR DS: <--与正确的注册码的第9 or 11位比较
004044E3 |. 75 1C |JNZ SHORT LIAOCACH.00404501 <--不对便跳走
004044E5 |. 3ACB |CMP CL,BL <--看CL是否为空,即看9-12位是否全部比较完毕
004044E7 |. 74 14 |JE SHORT LIAOCACH.004044FD <--是的话跳走
004044E9 |. 8A50 01 |MOV DL,BYTE PTR DS: <--得到你输入的注册码的第10 or 12位
004044EC |. 8ACA |MOV CL,DL <--装入CL
004044EE |. 3A56 01 |CMP DL,BYTE PTR DS: <--与正确的注册码的第10 or 12位比较
004044F1 |. 75 0E |JNZ SHORT LIAOCACH.00404501 <--不相等就跳走
004044F3 |. 83C0 02 |ADD EAX,2 <--EAX加2
004044F6 |. 83C6 02 |ADD ESI,2 <--ESI加2
004044F9 |. 3ACB |CMP CL,BL <--看是否全部比较完毕
004044FB |.^75 E0 \JNZ SHORT LIAOCACH.004044DD <--没有就跳回去再来一遍
004044FD |> 33C0 XOR EAX,EAX <--9-12位全部比较完毕后会跳到这里
004044FF |. EB 05 JMP SHORT LIAOCACH.00404506
00404501 |> 1BC0 SBB EAX,EAX
00404503 |. 83D8 FF SBB EAX,-1
00404506 |> 3BC3 CMP EAX,EBX
00404508 |. 75 41 JNZ SHORT LIAOCACH.0040454B
0040450A |. 8D7424 48 LEA ESI,DWORD PTR SS: <--嘿嘿,都讲了三遍了,你一定明白了吧,所以我把这最后一段留给你自己来看吧,从这里到00404530处我相信你猜也猜的出来 (众人:鄙视你!)
0040450E |. 8D4424 28 LEA EAX,DWORD PTR SS:
00404512 |> 8A10 /MOV DL,BYTE PTR DS:
00404514 |. 8ACA |MOV CL,DL
00404516 |. 3A16 |CMP DL,BYTE PTR DS:
00404518 |. 75 1C |JNZ SHORT LIAOCACH.00404536
0040451A |. 3ACB |CMP CL,BL
0040451C |. 74 14 |JE SHORT LIAOCACH.00404532
0040451E |. 8A50 01 |MOV DL,BYTE PTR DS:
00404521 |. 8ACA |MOV CL,DL
00404523 |. 3A56 01 |CMP DL,BYTE PTR DS:
00404526 |. 75 0E |JNZ SHORT LIAOCACH.00404536
00404528 |. 83C0 02 |ADD EAX,2
0040452B |. 83C6 02 |ADD ESI,2
0040452E |. 3ACB |CMP CL,BL
00404530 |.^75 E0 \JNZ SHORT LIAOCACH.00404512
00404532 |> 33C0 XOR EAX,EAX <--全部通过后来到这里
00404534 |. EB 05 JMP SHORT LIAOCACH.0040453B
00404536 |> 1BC0 SBB EAX,EAX
00404538 |. 83D8 FF SBB EAX,-1
0040453B |> 3BC3 CMP EAX,EBX
0040453D |. 75 0C JNZ SHORT LIAOCACH.0040454B
0040453F |. 8BC7 MOV EAX,EDI
00404541 |. 5F POP EDI
00404542 |. 5E POP ESI
00404543 |. 5D POP EBP
00404544 |. 5B POP EBX
00404545 |. 83C4 54 ADD ESP,54
00404548 |. C2 0400 RETN 4
我的注释写的还算清楚吧 ^_^,我再大概给你讲解一下:
软件的注册码是这样计算出来的,机器码中的各个字符的ASCII码加上1500后除以62的余数在密码表中对应的字符,就是相应的注册码。
比如说我这里的机器码为xn2urkeUMwpNv5xZ,x的ASCII码为78(十进制120) 78+5DC的值为654(即1620) 接着用1620除以3E(62)得商26余8,好的,我们从“密码表”0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ的开始处向后数8下,就会到了8这个字符,嘿嘿,这就是x对应的注册码。
好的,我给出Delphi的注册机(我仍将其写为函数的形式):
function KeyGen(Name: String): String;
var
S:String;
P:String;
Key:String;
i,N,Z:integer;
begin
P:='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
if Length(Name)<16 then
Result:='机器码必须为16位...'
else
begin
S:=Name;
for i:=1 to 16 do
begin
N:=Ord(S);
N:=N+1500;
Z:= N mod 62;
Z:=Z+1;
Key:=Key+P;
end;
Result:=Key;
end;
end;
呵呵,这一章就是最后一章了,现在也写完了.... 打个Kiss~~
如何破解加密狗硬件加密锁,俗程“加密狗”,对于加密狗的破解大致可以分为三种方法,一种是通过硬件克隆或者复制,一种是通过SoftICE等Debug工具调试跟踪解密,一种是通过编写拦截程序修改软件和加密狗之间的通讯。
硬件克隆复制主要是针对国产芯片的加密狗,因为国产加密狗公司一般没有核心加密芯片的制造能力,因此有些使用了市场上通用的芯片,破解者分析出芯片电路以及芯片里写的内容后,就可以立刻复制或克隆一个完全相同的加密狗。不过国外的加密狗就无法使用这种方法,国外加密狗硬件使用的是安全性很好的自己研制开发的芯片,通常很难进行复制,而且现在国内加密狗也在使用进口的智能卡芯片,因此这种硬件克隆的解密方法用处越来越少。
对于Debug调试破解,由于软件的复杂度越来越高,编译器产生的代码也越来越多,通过反汇编等方法跟踪调式破解的复杂度已经变得越来越高,破解成本也越来越高,目前已经很少有人愿意花费大量精力进行如此复杂的破解,除非被破解的软件具有极高的价值。
目前加密锁(加密狗)的解密破解工作主要集中在应用程序与加密动态库之间的通讯拦截。这种方法成本较低,也易于实现,对待以单片机等芯片为核心的加密锁(加密狗)具有不错的解密效果。
由于加密锁(加密狗)的应用程序接口(API)基本上都是公开的,因此从网上可以很容易下载到加密狗的编程接口API、用户手册、和其它相关资料,还可以了解加密狗技术的最新进展。
例如,某个国内知名的美国加密狗提供商的一款很有名的加密狗,其全部编程资料就可以从网上获取到,经过对这些资料的分析,我们知道这个加密锁(加密狗)有64个内存单元,其中56个可以被用户使用,这些单元中的每一个都可以被用为三种类型之一:算法、数据值和计数器。
数据值比较好理解,数据值是用户存储在可读写的单元中的数据,就和存储在硬盘里一样,用户可以使用Read函数读出存储单元里面的数据,也可以使用Write函数保存自己的信息到存储单元。
计数器是这样一种单元,软件开发商在其软件中使用Decrement函数可以把其值减一,当计数器和某种活动的(active)算法关联时,计数器为零则会封闭(deactive)这个算法。
算法单元较难理解一些,算法(algorithm)是这样一种技术,你用Query(queryData)函数访问它,其中queryData是查询值,上述函数有一个返回值,被加密的程序知道一组这样的查询值/返回值对,在需要加密的地方,用上述函数检查狗的存在和真伪。对于被指定为算法的单元,软件上是无法读和修改的,即使你是合法的用户也是如此,我理解这种技术除了增加程序复杂性以外,主要是为了对付使用模拟器技术的破解。
此加密锁(加密狗)的所有API函数调用都会有返回值,返回值为0的时候表示成功。
因此,破解思路就出来了,就是使用我们自己的工具(如VB、VC等)重新编写构造一个和加密狗API一样的DLL动态库文件,里面也包含Read、Write等全部API中包含的函数,使用的参量及返回值和原来的函数一样,所有函数返回零。然后对Query、Read函数进行处理,返回应用软件需要的数值即可。
这个新的DLL文件编写成功后,直接替换掉原来的DLL文件,这时候再运行应用软件,软件访问加密狗的操作就全部会被拦截,拦截程序永远会返回正确的数据给软件,从而实现了模拟加密狗的运行。
以上是目前破解软件加密狗(加密锁)的一些常见思路,对于这种破解,软件开发者还是有相应的一些对策的,下一回我将在《软件加密锁编程技巧》一文中具体介绍一下软件开发者将如何编写安全可靠的代码,使得这种类似的破解方法失效。
我要破解的软件:网络填表终结者
破解需要的软件(点击下载):
侦壳 language.exe
脱壳AspackDie.exe
反编译 W32Dasm黄金中文版
16进制编辑器 UltraEdit.rar 在破解之前先复习一下基础知识:
一.破解的等级
初级,修改程序,用ultraedit修改exe文件,称暴力破解,简称爆破
中级,追出软件的注册码
高级,写出注册机 二.用w32dasm破解的一般步骤:
1.看软件的说明书,软件注册与不注册在功能上有什么区别,如何注册
2.运行此软件,试着输入你的姓名和任意注册码去注册,有什麽错误提示信息,将错误提示信息记下来
3.侦测有无加壳(第一课).若加壳,脱壳(第二课)
4.pw32dasmgold反汇编
5.串式参考中找到错误提示信息或可能是正确的提示信息双击鼠标左键
6.pw32dasmgold主窗口中分析相应汇编,找出关键跳转和关键call
7.绿色光条停在关键跳转,在pw32dasmgold主窗口底部找到关键跳转的偏移地址(实际修改地址)
8.用ultraedit找到偏移地址(实际修改地址)修改机器码,保存
壳的概念:版权信息需要保护起来,不想让别人随便改动,exe可执行文件压缩,最常见的加壳软件ASPACK ,UPX,PEcompact 脱壳:拿到一个软件,侦测它的壳,然后我们要把它的壳脱去,还原它的本来面目.若它没有加壳,就省事不用脱壳了.脱壳软件unaspack,caspr,upx,unpecompact,procdump 实际修改地址(偏移地址)和行地址(虚拟地址)pw32dasmgold反汇编出来的代码由三列组成
第一列 行地址(虚拟地址)
第二列 机器码(最终修改时用ultraedit修改)
第三列 汇编指令 第一列 第二列 第三列
:0041BE38 2B45F0 sub eax, dword ptr
:0041BE3B 6A42 push 00000042
:0041BE3D 50 push eax
:0041BE3E FF75F4 push
:0041BE41 FF75F0 push
:0041BE44 FF35A8AB4400 push dword ptr
两种不同情况的不同修改方法
1.修改为jmp
je(jne,jz,jnz) =>jmp相应的机器码EB(出错信息向上找到的第一个跳转)jmp的作用是绝对跳,无条件跳,从而跳过下面的出错信息 2.修改为nop
je(jne,jz,jnz) =>nop相应的机器码90(正确信息向上找到的第一个跳转) nop的作用是抹掉这个跳转,使这个跳转无效,失去作用,从而使程序顺利来到紧跟其后的正确信息处。好了,下面开始我们的破解之旅。。。。。。。。。。 1,侦壳:先打开侦壳language.exe,选择打开----找到要破解的网络填表终结者:FormGhost.exe,点确定,如图1。language.exe便显示出软件的壳是:Aspack,如图2。file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image001.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image003.jpg2,脱壳:双击脱壳AspackDie.exe,出现一个对话框,选择网络填表终结者:FormGhost.exe,打开。如图3。出现图4框,点确定脱壳完成。在网络填表终结者:FormGhost.exe同目录下生成一个unpacked.exe文件,这就是脱壳后的FormGhost.exe。file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image004.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image005.jpg3,运行脱壳后的unpacked.exe,点帮助----注册,图9。注册名称,注册码随便添。图10。点注册,提示:“注册码错误”图11,好了记住这5个字。关了它。file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image006.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image008.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image009.jpg4,开始反汇编:打开 反编译 W32Dasm黄金中文版,选择反汇编----打开脱壳后的unpacked.exe,变开始加载。如图5。图6。file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image010.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image011.jpg返汇编之后如图7。点击上面的参考----串式参考如图8,file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image012.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image013.jpg出现这个对话框图12。找到 “注册码错误”,双击它,汇编主程序便来到这里:图13。file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image015.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image017.jpg(注意:正确注册信息在错误信息之上)关闭串式参考框。看主程序:图14。从注册码错误向上找到第一个跳转(关键跳,除了jmp的其它跳:je,jne,jz,jnz),来到这里图15。file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image019.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image020.jpg(它上面的call叫关键call。),双击关键跳,看软件最下面有一行字:Line:379267 Pg 7586 of 7626 Code Data@004ACB4B@Offset 00ACB4BH in File:unpacked.exe.其中@Offset 00ACB4BH就是偏移地址,记住00ACB4B(后面的h代表16进制,不用管他),图16。file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image022.jpg5,开始修改软件:打开16进制编辑器 UltraEdit.rar,(有点慢)图17。打开脱壳后的unpacked.exe,直接按ctrl+g,出现对话框,输入0xacb4b(即偏移地址,不要前面的000)图18。点确定,来到图19file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image023.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image025.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image026.jpg前面说过正确注册信息在错误信息之上,所以这里将of85改为of84。图20。(如果正确注册信息在错误信息之下,这里改为eb)。将光标移到5上直接输入数字4即可,其他地方不要动。好了,改好只后左上角的文件---另存为unpacked222.exefile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image027.jpg6,关闭所以软件,运行另存的unpacked222.exe,点帮助---注册,注册名称,注册码随便添,点确定,提示注册完成。图21。回到软件界面看看,帮助,注册一项已经变为灰色了,图22
7,破解全部完成file:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image028.jpgfile:///C:/DOCUME~1/ADMINI~1/LOCALS~1/Temp/msohtml1/01/clip_image029.jpg转字<该页无法显示>博客
-----------------------------------------------------------------------------------
只要六步破解软件时间限制大家一定碰到过有些软件有时间限制,没关系我们破了他:
第一破解时间限制软件原理:一般地共享软件要达到计算机用户使用次数或时间的目的,通常是在安装时将当前的时间标志或者用户使用软件的次数记录,隐蔽的存放在注册表或某个文件中。每次使用软件时都会提醒还可以使用软件多少次。如果我们能够找出软件从注册表中调用隐蔽的标志和记录位置,将时间标志和使用次数修改,就可以达到无限用得目的了.
第二注册表监视软件:如何从注册表中找到软件的时间标志或者使用次数记录呢?我们只要使用一款名为RegSnap的软件,在软件运行前后对注册表各作一次快照,通过对比两次注册表快照,来判断出软件的时间标志或者使用次数的记录是哪一个键值,更改这个标志和记录,就可以实现破解共享软件使用时间和次数的限制了.
第三各位随便找一个软件就可以了. 现在开始.
第一步:建立一个注册表快照 运行RepSnap后,点击菜单“文件” “新建”,在弹出的保存快照对话框中选择快照项目为“仅注册表”,并输入快照说明文字以便后面区分(例如输入:使用50次)然后点击“确定”按纽,就可以开始扫描并保存注册表内容了.扫描完毕后,点击菜单“文件” “保存”命令,将当前快照保存。
第二步:建立第二个快照 运行你要破解的那个软件,可以运行多次,当软件提示可用次数发生变化后,再用上面同样的方法,保存一次注册表快照。
第三步:比较注册表快照 这一步很重要,现在需要对比两个注册表快照,找出注册表中的不同之处,这可是破解使用次数限制的关键。当然我们不会去手工对照.可以直接使用RepSnap的快照比较功能。 点击菜单“文件” “比较”命令打开快照比较对话框。RepSnap会自动将最近两次保存的快照调如进行比较。在报告选项中可以选择显示修改过得键名,也可以显示键名和键值,想得到详细的比较内容的话就选择第二项“显示修改过得键名和键值”吧接下来,点击“确定”按纽后,即可开始比较两个注册表快照内容的不同之处.完成后显示详细报告信息
第四步:找到次数记录 从报告中可以看到注册表中有11个键值发生了变化。经过仔细的查看,发现一处重要的注册表更改项目(大家要仔细找)其中“49”和“48”不正是软件剩余的使用次数.
第五步:确定次数记录位置在RepSnap中点击工具栏上的“加载注册表编辑器”按钮,打开系统中的注册表编辑器,展开注册项目“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IE4\Setup\”找到键值“KEYFSTIMES”。先关闭我们要修改那个软件,然后再次运行,返回到注册表中,刷新刚才的键值,可以看到该键值也减少了1,因此可以肯定此处就是记录软件剩余次数的关键了.
第六步:修改注册表(石头最怕的)先尝试修改注册表键值“KEYFSTIMES”,改为最初的50次,如果正确的话在重启就可以了. 重中之重来了.有种软件很坏的.记录的文件有两个地方.那么接着查看快照对比结果,在刚才的键值下面发现了两处修改信息:“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Prefetcher\TracesProcessed新:DWORD:6 (0乘31)旧:DWORD:5 (0乘c)HKEY_LOCAL_MACHIND\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Prefetcher\TracesSuccessful新:DWORD:6 (0乘e) 旧:DWORD:5 (0乘9) 而这两处键值对应得正好就是我们已使用了的软件次数.也就是说我们还要更改这两处键值,才可以达到完全突破软件的使用次数限制。以后当我们使用了该软件50次后无法使用时,我们就可以将“KEYFSTIMES”键值改为50次,另两个键值改为0就可以使用了.
常用的破解工具有哪些 剑客离不开剑,破解高手也离不开破解工具,合适的工具使你事半功倍,文章主要是介绍几种破解工具。
1.调试工具softice
2.调试工具Trw2000
3.反汇编工具Wdasm8.93
4.Hiew
5.Visual Basic程序调试工具Smartcheck
6.十六进制编辑器(如:Ultraedit、WinHex、Hex Workshop 等)
7.注册表监视工具RegShot、regmon或RegSnap
8.侦测文件类型工具TYP、gtw或FileInfo等
9. 脱壳工具PROCDUMP
10.调试工具IceDump
11.注册机制作crackcode2000
12.备份windows配制文件工具ERU
13.文件监视工具 filemon
14.资源修改器 EXESCOPE
15.Frogsice
Soft-ICE 是目前公认最好的跟踪调试工具。 使用Soft-ICE可以很容易的跟踪一个软件、或是监视软件产生的错误进行除错。你甚至可以用他来替代C语言的调试器--如果你不喜欢使用C语言自己的调试器的话。主意其有几种平台的版本,DOS,WINDOW3.1,WIN95/98/2000/,NT,所以别搞错了。
Trw2000 中国人自己编写的调试软件,完全兼容SOFTICE各种指令,但现在许多软件能检测SOFTICE存在,而TRW2000在这方面就好多了。TRW2000有它自己的独特方面,是针对破解软件优化的,Windows下的跟踪调试程序,跟踪功能更强;可以设置各种断点,只是断点种类更多;它可以象一些脱壳工具一样完成对加密外壳的去除,自动生成EXE文件,只是留给用户更多的选择;在DOS下的版本为TR。
Wdasm8.93 反汇编的极品工具。可方便反汇编程序,它能静态分析程序流程,也可动态分析程序,操作简单、破解必备!
Hiew 不用多说,是一个十六进制工具,它除了普通十六进制的功能外,它还有个特色,能反汇编文件,并可以汇编指令修改程序,是不是够酷的!
Smartcheck VB程序执行时从本质上讲是解释执行,它们只是调用 VBRUNxxx.DLL 中的函数 ,VB 的 exe 是伪代码,程序都在 vbXXX.dll 里面执行,你只能在 vbdll 里面用SOFTICE 打转转,什么都改不成,而且代码质量不高,结构还颇复杂。当然只要了解其特点用SOFTICE也可破解 ,但SmartCheck的出现,大大方便了我们,它可将VB程序执行的操作完全记录下来,使我们轻而易举的破解大部分VB程序。
十六进制编辑器 HIEW就是一种是十六进制工具,但其是DOS界面,因此有必要再准备一款windows下的工具,这样的工具很多,如:Ultraedit、WinHex、Hex Workshop 等,其中Hex Workshop比较有特色,操作方便,但遗憾的是没有汉化版。
注册表监视工具 注册表是Windows 95及Windows 98的核心数据库,表中存放着各种参数,直接控制着Windows的启动、硬件驱动程序的装载以及一些Windows应用程序运行的正常与否。而应用软件安装时,有可能在注册表中注册,将一些必要的信息放进去,如安装时间,使用次数等。RegShot、regmon或RegSnap就是一种监视注册表变化的工具,以了解应用程序在注册表何处修改了,以协助破解。
侦测文件类型工具 这样的工具有TYP、gtw或FileInfo等。这是一个能侦测你的软件是被哪一种「壳」给加密了 (就好像侦测你的文件档是被zip、rar、arj哪一个给压缩了一样,如果连被哪种软体加了壳都不晓得,那要剥壳就难很多)。一般配合PROCUDUMP使用。
PROCDUMP 脱壳工具,可剥许多壳,你使用的许多软件都是压缩过的,用该工具很方便把它们还原,然后再修改,并可自己编写脚本文件,以便能脱壳新版的壳。它是也一款优秀的PE格式修改工具,脱壳必备!
IceDump 是配合SOFTICE而使用的,可抓取内存的数据,以重建EXE文件,脱壳必备。并可在SOFTICE下边调试边听mp3哟!具体参考其readme.
crackcode2000 一种全新的注册机工具,它可以从另一进程的内存中取出你想要的注册码,它可以令水平不高的你一夜之间成为破解高手,有了它,很多软件可以用二十秒时间写出注册机来,而你不需要会任何的语言,因为它只是一个工具,一个操作很简单的工具,它的参数只有四行,实在简单到不能再简单了,它的体积也很少,只有11K,如果再用其它压缩软件压一下一定 会小于10K,所以用它是可以做出很优秀的注册机。
ERU 这是windows安装盘自带的小工具,备份注册表等一些windows重要的配制文件,强烈推荐,在你破解一软件前,最好备份一下系统,因为你在破解某些软件的过程中,寻找关键点时,在这时改动一下以验证自己的判断,结果正确注册成功,此时你再想回到那里看一究竟,重装该软件都没用,哈哈!永远是注册版版,除非你重装系统。此时你只要还原注册表和配制文件,再重装该软件,又可注册了,这次你就可好好研究它一下了......,当然这种情况不多见,但破解某些软件前备份一下注册表,还是有必要的。
filemon 文件监视工具 ,可监视系统文件运行状况,如哪个文件打开,哪个文件关闭,在哪个文件读取了数据等,破解时非常有用,以便了解程序在启动、关闭或验证注册码是做了哪些手脚。
EXESCOPE 资源修改器 eXeScope 可以说是 EXE 及 DLL 等执行文件的解析终结工具, 它有执行文件(EXE, DLL等)的解析与显示功能;提取资源到外部文件 ;资源的重新写入;记录文件的记录及其再编辑(成批编辑)等功能。是汉化软件的常用工具,当然破解软件时也很有用。
Frogsice 最好的 SOFT-ICE 加强软件!它并不是简单的将 SICE 隐藏,而是让你可以配合 SICE 避过现在流行的各种加密、保护软件里面的各种防止 SICE 的陷阱。有了它,你再也不用怕在装入一个程序准备调试的时候,程序告诉你发现SICE 的存在而终止运行,或者干脆把你的机器从新启动,又甚至触发更残酷的报复手段。
手把手教你如何破解软件写在破解之前:::
软件破解的目的是
:::有些需要注册的软件,可是找不到注册码,将其破解之后,输入任何注册码都会提示注册成功。
我要破解的软件:万事通.exe
破解需要的软件:侦壳language.exe 脱壳AspackDie.exe
反编译 W32Dasm黄金中文版 16进制编辑器 UltraEdit.rar
在破解之前先复习一下基础知识:
一.破解的等级
初级,修改程序,用ultraedit修改exe文件,称暴力破解,简称爆破
中级,追出软件的注册码
高级,写出注册机
二.用w32dasm破解的一般步骤:
1.看软件的说明书,软件注册与不注册在功能上有什么区别,如何注册
2.运行此软件,试着输入你的姓名和任意注册码去注册,有什麽错误
提示信息,将错误提示信息记下来
3.侦测有无加壳(第一课).若加壳,脱壳(第二课)
4.pw32dasmgold反汇编
5.串式参考中找到错误提示信息或可能是正确的提示信息双击鼠标左键
6.pw32dasmgold主窗口中分析相应汇编,找出关键跳转和关键call
7.绿色光条停在关键跳转,在pw32dasmgold主窗口底部找到关键跳转
的偏移地址(实际修改地址)
8.用ultraedit找到偏移地址(实际修改地址)修改机器码,保存
壳的概念:版权信息需要保护起来,不想让别人随便改动,exe可执行文件压缩,最常见的加壳软件ASPACK,UPX,PEcompact
脱壳:拿到一个软件,侦测它的壳,然后我们要把它的壳脱去,还原它的
本来面目.若它没有加壳,就省事不用脱壳了.脱壳软件
unaspack,caspr,upx,unpecompact,procdump
实际修改地址(偏移地址)和行地址(虚拟地址)
pw32dasmgold反汇编出来的代码由三列组成
第一列 行地址(虚拟地址)
第二列 机器码(最终修改时用ultraedit修改)
第三列 汇编指令
第一列第二列 第三列
:0041BE38 2B45F0 sub eax, dword ptr
:0041BE3B 6A42 push 00000042
:0041BE3D 50 push eax
:0041BE3E FF75F4 push
:0041BE41 FF75F0 push
:0041BE44 FF35A8AB4400 push dword ptr
常见修改(机器码)
74=>75 74=>90 74=>EB
75=>74 75=>90 75=>EB
jnz->nop
75->90(相应的机器码修改)
jnz -> jmp
75 -> EB(相应的机器码修改)
jnz -> jz
75->74 (正常) 0F 85-> 0F 84
两种不同情况的不同修改方法
1.修改为jmp
je(jne,jz,jnz) =>jmp相应的机器码EB (出错信息向上找到的第一个跳转)jmp的作用是绝对跳,无条件跳,从而跳过下面的出错信息
2.修改为nop
je(jne,jz,jnz) =>nop相应的机器码90 (正确信息向上找到的第一个跳转) nop的作用是抹掉这个跳转,使这个跳转无效,失去作用,从而使程序顺利来到紧跟其后的正确信息处
好了,下面开始我们的破解之旅。。。。。。。。。。
1,侦壳:先打开侦壳language.exe,选择打开----找到要破解的"万事通.exe":点确。language.exe便显示出软件的壳又是:Aspack,
2,脱壳:双击脱壳AspackDie.exe,出现一个对话框,选择万事通.exe,打开。点确定脱壳完成。在万事通.exe:同目录下生成一个unpacked.exe文件,这就是脱壳后的万事通.exe
3,运行脱壳后的unpacked.exe,点帮助----注册,注册名称,注册码随便添。。点注册,提示:“注册码不符”,好了记住这5个字。关了它。
4,开始反汇编:打开 反编译 W32Dasm黄金中文版,选择反汇编----打开脱壳后的unpacked.exe,变开始加载。。返汇编之后。点击上面的参考----串式参考,出现这个对话框。找到
“注册码不符”,双击它,汇编主程序便来到这里:图1。(注意:正确注册信息在错误信息之下)关闭串式参考框。看主程序:。从注册码错误向上找到第一个跳转(关键跳,除了jmp的其它跳:je,jne,jz,jnz),来到这里。(它上面的call叫关键call。),双击关键跳,看软件最下面有一行字的后面:@Offset000b6fe8H in File:unpacked.exe.其中@Offset 000b6fe8H就是偏移地址,记住000b6fe8(后面的h代表16进制,不用管他),
5,开始修改软件:打开16进制编辑器 UltraEdit.rar,。打开脱壳后的unpacked.exe,直接按ctrl+g,出现对话框,输入0xb6fe8(即偏移地址,不要前面的000)。点确定,来到图2,说过正确注册信息在错误信息之下,所以这里将74改为eb。图2.3。。将光标移到74上直接输入数字eb即可,其他地方不要动。好了,改好只后左上角的文件---另存为unpacked222.exe。
6,关闭所以软件,运行另存的unpacked222.exe,点帮助---注册,注册名称,注册码随便添,点确定,提示注册完成。。回到软件界面看看,帮助,注册一项已经没有了。
7,破解全部完成。 (本博客还有其他破解相关文章,在网络分类里面!需要的可查看) 找不到练手软件下载地址。。。给个地址吧 Jorge 发表于 2015-4-6 09:07
重点是看练手的软件!
你的听众日益见长啊, 我记得我是第二个听众,哈哈 好长呀!! 想用一篇文章带新手入门,实属不易,俺学习了半天,还是云里雾里,看来俺的基础不牢固,还需努力,谢谢楼主!辛苦了 好帖,支持 各位有兴趣的新手把帖子顶起来啊! 本帖太长,有人不想看。那我直接放出本帖的练手软件。
【软件名称】中华压缩(ChinaZip)
【软件版本】7.0
【文件大小】1041KB
【软件名称】天网防火墙
【软件版本】2.46 Beta
【文件大小】1289KB
【软件名称】e族百变桌面
【软件版本】4.0
【文件大小】1316KB
【软件名称】WinZIP
【软件版本】8.1 Beta 2
【文件大小】1757KB
【软件名称】网络填表终结者 本帖最后由 Jorge 于 2015-4-6 09:07 编辑
七、本版块对于转载优秀脱文,破文,算法分析类者也将给予适当奖励
@Hmily 这个能加分吗? 表示那么长 不看了 唯殇 发表于 2015-4-6 09:06
表示那么长 不看了
重点是看练手的软件! 附上软件和图片就完美了