[转载]菜鸟破解从头学

信息来源:霏凡论坛(bbs.crsky.com)(停止注册)
文章作者:小航

大家好,我是新人,我是借朋友的ID来这里看看的。
我想在这注册,可现在要有邀请码才行。
我看过上面 菜鸟破解从头学(全教程)这个贴子,看到里面不完整,
所以我就发过新一点的。

附破解常用工具:
(转帖,忘了在那收集的,如下载链接错误,请用google找寻)

所謂工欲善其事,必先歷其器!不過做什麼,工具都是非常重要的.不借助工具,我們將寸步難行!下面我就把破解者最常用的工具介紹一下,希望對初學者有點幫助!當然,我不可能給每個工具給出詳細的使用說明,這裡只是告訴大家有什麼工具可以利用,以及到哪裡可以找到這些工具.具體到各種工具的使用,就要大家自己慢慢摸索了:)

1)文件查看

拿到一個程序,破解的第一步是什麼?"知己知彼,百戰不殆",首先當然應該了解敵人的一舉一動.對我們破解者來說,利用文件查看工具主要是弄清楚程序使用哪種編譯器編譯,是否加殼,何種加殼軟件加的殼等等.

1>FileInfo
FileInfo可以检测出常见的各种壳,非常方便。看雪網站上有說FI是各类查壳工具中性能最强的。

版本:3.01
作者:Michael Hering(herinmi@tu-cottbus.de)
下載地址:http://www.pediy.com/tools/unpac ... ers/Fileinfo/fi.rar

2>peid

上面介紹的FileInfo確實很強大,不過是命令行的(其實我越來越喜歡命令行的東東了),對於初學者可能不太友善.所以再推薦這款GUI的工具.
版本:0.9

官方網站:http://www.mesa-sys.com/~snaker/peid/
下載地址:http://www.mesa-sys.com/~snaker/peid/PEid.zip

2)脫殼加殼

1>ASProtect
这个壳在pack界当选老大是毫无异议的,当然这里的老大不仅指它的加密强度,而是在于它开创了壳的新时代,seh和各种流行的 anti,bpm断点的清除都出自这里,更为有名的当属rsa的使用,使得demo版无法被crack成完整版本,code_dips也源于这里。

版本:1.23

官方網站:http://www.aspack.com/
下載地址:http://www.aspack.com/files/asprotect123.zip


相應的脫殼工具

AsprStripper 2.03

可以全自动脱ASProtect1.2x的壳,支持EXE和DLL文件,工作平台Windows 2000/XP

官方網站:http://www.is.svitonline.com/syd/
下載地址:http://www.is.svitonline.com/syd/stripper_v203_public.rar


CASPR v1.10

ASProtect与Aspack的克星!仅对ASProtect1.2以前版本有效。

下載地址:http://www.pediy.com/tools/unpack/CASPR/Caspr110.zip

2>ASPack

一款非常强大的win 32压缩工具。

版本:2.12

官方網站:http://www.aspack.com/

下載地址:http://www.aspack.com/files/aspack212.zip


相應的脫殼工具

Aspackdie1.41

可以解压缩 自 Aspack 2000 以后的任何 Aspack 版本

官方網站:y0da.cjb.net

下載地址:http://www.pediy.com/tools/unpac ... ie/AspackDie141.zip


3>UPX

壓縮比非常大的一款加殼工具

版本:1.90

官方網站:http://upx.sourceforge.net/
下載地址:http://upx.sourceforge.net/download/unstable/upx190w.zip


相應的脫殼工具:

Upxfix
UPX的壳可以用其自身命令脱: upx -d 文件名
但对于处理过的UPX壳,此命令就不好用了。这时,可以用upxfix工具来修复文件,再用unxfix自带的upx来脱。

作者:upxfix@yahoo.com
下載地址:http://www.pediy.com/tools/unpack/UPX/UPXFIX/upxfix.zip


注:由於加殼工具版本眾多,每一種版本都需要相應版本的脫殼工具,而在這裡我只是提到最新版的工具,如果你需要其他版本的,請到http://www.exetools.com找找看.


3)靜態反匯編

1>W32DASM

静态分析中文软件的利器!絕大部分破解教程里都提到了它,作為破解者,它是必備品。强烈推荐!(已停止開發)

版本:8.93

下載地址:http://www.pediy.com/tools/Disassemblers/W32Dasm/W32dsm8.93.rar

2>IDA Pro

它是一个极好的反汇编工具,它的功能大大的胜过了w32dasm。如果你想進一步從破解者編成逆向工程的專家,選擇它吧!

版本:4.6

官方網站;http://www.datarescue.com/idabase/
下載地址:http://www.cnxhacker.com/download/down.asp?id=111&no=1

4)動態調試

1>SoftICE

調試工具的極品。功能強大到無所不能:)如果你能熟練運用它,你就能成為傳說中的高手喔!現在已經成為 DriverStudio 2.7的一部分。最新已有 DriverStudio 3.0beta2,但考慮到穩定性,這裡提供DriverStudio 2.7版。

版本: DriverStudio 2.7

官方網站:http://www.softice.net/
下載地址:http://www.21ele.com/down_view.asp?action=download&id=14

2>TRW2000

國產利器。Windows9x与Windows Me下的跟踪调试程序,跟踪功能更强。

版本:1.23

下載地址:http://www.pediy.com/tools/Debuggers/TRW2000/TRW1.2X/trw1.23.zip


3>OllyDbg

一款新興的調試工具,工作在ring3。最近人氣很好,很多人都開始使用它了。

版本:1.09D

官方網站:http://home.t-online.de/home/Ollydbg/
下載地址:http://home.t-online.de/home/Ollydbg/odbg109d.zip

5)編輯工具

1>Hiew

强大的十六进制编辑工具 ,相当的好的反汇编功能,破解利器。强烈推荐!


版本:6.83

大小:700KB

官方網站:http://www.serje.net/sen/
下載地址:http://www.serje.net/sen/files/hiew683.zip

2>Winhex

一款优秀的十六进制编辑工具,其内存编辑功能值得称道。許多共享軟件的註冊碼會在內存中出現,利用winhex的內存編輯功能就能很輕鬆的找到這類軟件的註冊碼喔!

版本:11.14

大小:718KB

官方網站:http://www.sf-soft.de/
下載地址:http://www.winhex.com/winhex.zip(多語言版)


6)補丁工具

1>KeyMake

國產的註冊機製作工具,使用十分簡單,很容易上手的。

版本:1.73
大小:1.00MB
下載地址:http://www.pediy.com/tools/Patchers/KEYMAKE/keymake1.73.zip


7)輔助工具

1>File Monitor
文件監視工具,可以監視系統中所有關於文件的事件,是破解某些利用keyfile保護的好幫手!

版本:6.07

官方網站:http://www.sysinternals.com
下載地址:
http://www.sysinternals.com/files/NTFILMON.ZIP (For NT/2000/Xp)
http://www.sysinternals.com/files/FILEMON.ZIP (For 9X/Me)


2>REGSHOT ver
TiANWEi力作,比较注册表变化的软件,这个版本完善了一些功能,加上了一篇教学。

版本:1.05a
官方網站:http://regshot.ist.md/
下載地址:http://www.pediy.com/tools/spy tools/RegShot/RGST150A.ZIP

第一章--前言

第一章--前言
好多哥们儿说看教程跟老大的书都看不太明白,所以,我尽量把话说到最容易理解的份上,本文写给那些刚入门和尚未入门的朋友们...
目录
no.1------------------前言(说明一下)
no.2------------------汇编语言
no.3------------------Windows程序
no.4------------------调试器及相关工具入门
no.5------------------破解原理
no.6------------------初级破解实践,强暴一个软件
no.7------------------中级破解实践,找到注册码及写内存注册机
no.8------------------高级破解实践,分析软件算法,编写注册机
由于现在网吧,临时写来,所以,今天只写个前言吧,呵呵...
本章只作一些说明,现在也说了这么多了,没别的了,卖个广告,推荐几本书吧。
首先,力荐看雪老大《加密与解密--软件保护技术及完全解决方案》,绝对物超所值,要的抢先了...(汗~~俺都没看过,看来要落伍了)。当然,还有看雪精华一、二、三、四以及将要出来的五,足够带你上路,还有风飘雪大虾的《风飘雪破解教程》等等等等(其它一些,没说到的就请自行搜集吧),还有就是常到论坛来转转 ;=》
另外,我觉的你真的很有必要学一门编程语言以及掌握一些Win32程序的知识...


课后FAQ
Q:哪些人可以学习破解?
A:任何会启动电脑并运行软件同时又想学习破解的人。我说的全是实话,如果你既不会启动电脑又不会运行软件,那么我教你一个更高深的吧--破解电脑,呵呵,很简单,到大街上随便抡个板砖什么的,回去慢慢破解吧 记得关电源)
Q:有没有什么办法可以使我快速入门并成为高手?
A:有。但你得是个MM(P不PL无所谓),然后找个离你家最近的破解达人,什么也不用做,眨个眼放个电之类的会吧(现在连初中的小女生都会这个),然后就成了,呵呵,想破什么的话,让高手帮忙吧,到时说成是自己破的就成了 MM问为什么?因为那些高手大都奇丑无比,呵呵,有了头脑就没了长相,男的也是这样,而且越是高手,长的就是越丑。据说一次市里到CCG考察奶牛们的出乳情况,看到大哥Sun某的时候,说了句“这奶牛个儿这么小啊,中午大家吃涮锅” (众大哥:大家准备好家伙,我们一会儿要去械斗)。呵呵,玩笑开到这里,其实我说这么多,只是想告诉你,学习破解跟其它技术一样,请你不要试图投机取巧,要想学,就脚踏实地,多看教程多动手实践积累经验,不要经常POSE那种弱智问题“我不懂XX,请问我能学破解吗?”,答案是不能,你问的同时,不也正在学吗?想知道重要吗?那我告诉你好了,凡是看雪教程上要求掌握的,你全要掌握,这还不算,要想成为高手就必须精通,如果你不想一直只停留在入门阶段的话。不要想偷机取巧,谁一开始也不是什么都会的,但你只要花一些时间和一小部分精力,那么没有什么你学不会的,知识是要积累的,你知道自己不会却不去学,而在那儿问重不重要,人家会觉的你这个人并不想认真学破解,而是报有侥幸心理在浪费时间,请不要做浪费时间的人。不要刚开始学就想马上成为高手,没有高手,你没必要立下超越的目标,只把学知识放在首位就够了,欲速则不达,请不要做急于求成的人。
Q:学破解对我来说有什么好处?
A:这个问题应该你自己来回答,呵呵,你为什么要学?“我想免费使用共享软件”倒...那多少也算是个目的,但我希望你不要只报这种目的(目前国内共享软件业还有待发展)。我只是想说给那些只是因为一时冲动才学习破解的人,请将你们当初的冲动继续维持下去,你需要明白,学习破解的目的不只在于破解软件这个词,也许后来你会变为软件分析,随着学习时间的增加,对你的编程水平,相信会有相当大的提高。学习别人好的思想,并化为已用 就我个人来说,学习破解可以把我的汇编的基础给打好,呵呵,俺对操作系统这玩意儿感兴趣,到时候还想写出来个玩玩儿呢,所以汇编这关必须要过....
Q:我很笨,那些大虾的教程我大都看不明白,我能学会吗?
A:永远不要说你笨,你只是学的比人家晚而已,太高深的看不懂,那你就捡能看懂的看,别人能入门,你也能,不得要领只是暂时,大虾与你,也许差的就是一两年时间的问题。

答网友问
Q:寄存器可以随便用么,有没有什么限制?写个程序的时候那些变量什么的可以放在任意的寄存器么?
A:呵呵,我现在就来回答楼上朋友的问题。
寄存器有它的使用机制,及各个寄存器都有着明确的分工。
如小翠儿 如数据寄存器(EAX-EDX),它们都是通用寄存器,及在软件中,任何数据都可存放于此。但是除此之外,它们又可以都可以用于各自的专用目的。
例如:
EAX可以作为累加器来使用,所以它是算术运算的主要寄存器。在乘除法等指令中指定用来存放操作数。比如在乘法中,你可以用AL或AX或EAX来装被乘数,而AX或DX:AX或EAX或EDX:EAX则用来装最后的积。
EBX一般在计算存储器地址时,它经常用作基址寄存器。
ECX则常用来保存计数值,如在移位指令它用来装位移量、循环和串处理指令中作隐含的计数器。
最后就剩下四大天王中的黎明了,近一段时间来,他总是比较低调...(你别打我了,我去撞墙好了)最后就剩下EDX了,一般在作双字长运算时把DX和AX组在一起存放一个双字长数(你还记的什么是双字长吧,举个例子,比如说有一个数二进制数据01101000110101000100100111010001,你要把它寄存起来,就可以把0110100011010100(即高十六位)放在DX中,把0100100111010001(即低十六位)放在AX中,这个数表示为DX:AX)当然完全可以用一个EDX就把这个数给装下。所以,还可以用EDX:EAX来装一个64位数据,这个你会推断出来吧。
而ESP、EBP、EDI、ESI,我上边儿以经大概介绍的差不多了,所以这里不说它们了。
当然还有其它的一些限制,因为我们只是要看程序的汇编代码(人家写好了的,肯定不会犯错误吧),而不是要去写,所以可以不必掌握。有性趣的话,去看相关书籍。
另外再说一下你的最后一个问题“写个程序的时候那些变量什么的可以放在任意的寄存器么? ”这句话我不明白你要问的是什么。我想你可能是把一些关点给搞错了,变量这词通常都是出现在高级语言中的,而你用高级语言写程序的话,完全不用理解那些寄存器什么的,这些都跟高级语言没什么关系。但是最终,高级语言也还是把你写的程序转换为对寄存器、内部存储器的操作。
<本章完>

第三章—Windows程序
这一章我都不知道该如何写了,呵呵~~
毕竟,Win32是一个非常深奥的系统,目前还容不得我这种小辈在这儿说三道四,不过,我既然是要写给那些入门阶段的朋友们看的,又不是写给那些搞程序设计老鸟看的,所以,我也犯不着怕被人背后指着骂 本章的名字就叫《Windows程序》而不是《Windows程序设计》所以,我只是讲一些关于Windows程序运作的原理:
Windows为什么叫Windows,相信所有用过的朋友都可以明白,那桌面上一个一个的窗口,就是它名字的由来。也就是这一个又一个窗口的出现,使计算机的使用一下子简单了巨多。几年前接触过电脑的朋友一定知道DOS吧,不知道的话,去问加解密工具下载版的版主老哥,让他跟你解释 你还记的DOS下那黑乎乎的窗口吧,没见过的哥们儿可以在开始菜单中找出来看看。DOS通过一系列的命令来进行相应的操作,如进入一个目录,删除一个目录等等等等。那种工作方式就叫做命令提示符方式,也即命令行。
现在国内不懂电脑的人还老爱说要想学电脑,必须要英语过关。(就是这个,吓跑了多少仅仅是想学习一些基本操作的朋友)可能也就是源自DOS的原因吧。
后来,随着硬件的支持以及技术上的提高,当然还有为了使电脑更方便的服务与人,慢慢的就有了所谓的视图操作系统,从此,你不用再记忆那些大堆的指令了,而且操作上,也有了相大的提高,可以说操作系统发展到今天的份儿上,操作已经够简单了,去看看那些在网吧里一把鼻涕的小孩子们吧…
当然,就像当年DOS之于命令提示行一样,今天的Windows仍和当年一样,占据着大部分的用户群。
(场外:一观众扔来一烂柿饼,你是唐僧啊,这么多废话)
马上转入正题,Windows之所以好用,除了不用背N多的命令外,一个原因就是因为它本身提供了大量的标准Windows GUI函数。所以对于用户,面对的是同一套标准的窗口,对这些窗口的操作都是一样的,所以使用不同的应用程序时无须重新学习操作。不用像当年在DOS下面那样一安装新程序,就要马上看帮助,看说明。
而Windows GUI函数,只不过是微软提供给程序开发人员的API(Application Programming Interface 应用编程接口)中的一小部分而以。Windows API是一大组功能强大的函数,它们本身驻扎在 Windows 中供人们随时调用。这些函数的大部分被包含在几个动态链接库(DLL)中,譬如:kernel32.dll、 user32.dll 和 gdi32.dll。 Kernel32.dll中的函数主要处理内存管理和进程调度;user32.dll中的函数主要控制用户界面;gdi32.dll中的函数则负责图形方面的操作等等。
你可能多多少少听说过API函数,如果你不太清楚到底是怎么一回事的话,我尽量给你解释的清楚一点。
不知道你有没有想过,Windows中的那一个又一个窗口是怎么画出来的呢?呵呵,你可能用VB、Delphi编过程序,你有没有想过你写的程序中的那些窗口是怎么形成的?是控件变成的。倒...呵呵,相信你当初学VB或Delphi的时候,所看的书上一定对可视化编程环境大肆赞扬了一番吧,是不是也提到过比VC++怎么怎么方便?怎么怎么不用再为生成程序的界面而花费大量无用时间了等等。
(台下上来一东北民工:小子,你找抽啊,还讲不讲了)
马上开说,其实我只是想告诉你,所有你用的Windows下的程序,都是通过调用一个又一个的Windows API来执行相应任务的,没有API,你的程序什么也做不了。用VB、Delphi以及MFC的朋友也许会说我根本没有调用什么API啊!其实这些API都是由你所用的开发环境自动进行相应的转换的。比如说你用Delphi新建一程序,什么也不用动就直接按F9来运行它,是不是出现一个空白的窗体?这就是个标准的Windows程序,它有Windows程序所具有的一切特征,如最大化按钮、最小化按钮、关闭按钮…你可以通过鼠标来移动它。
但是如果你想用VC++或MASM32来写这样一个程序,那么你有两种方法,在VC++中,你可以用MFC或直接调用API,而在MASM32中,你就只有直接调用API这一种方法。所谓直接调用API,就是指所有的操作都通过最原始的API来完成。通过直接调用API来生成这样一个程序,你必须要先注册窗口类(除非您使用 Windows 预定义的窗口类,如 MessageBox 或 dialog box);然后产生窗口;然后在桌面显示窗口(除非您不想立即显示它); 然后刷新窗口客户区;
麻烦吧,如果你想真正的让这个程序能正常地运行下来,还要再加入以下步骤:
1.你要得到您应用程序的句柄。2.窗体显示后就进入无限的获取窗口消息的循环。3. 如果有消息到达,由负责该窗口的窗口回调函数处理。4. 如果用户关闭窗口,进行退出处理。
上面这此步骤,都需要调用相应的API来完成。比如说得到程序的句柄用GetModuleHandle注册窗口类用RegisterClass或RegisterClassEx;注册后,还要用CreateWindowEx函数来生成相应窗口,而后用ShowWindow来显示它,之后还会用UpdateWindow 来更新客户区等等等等。这些还都不算呢,如果你真通过直接调用API去写一个稍大一点儿的程序的话,你会发现那是一个多么不令人愉快的事情。
上面说的这些,只不过是API中的一小小小小小小小小小小….部分,这才几个,真正的API有成百上千个,包括对系统各个方面进行的操作。没有API,你的程序什么也干不了。比如说你的程序中有一个Edit控件,VB中应该叫做Text控件吧,你想将用户输入到里面的信息放到一个变量中去,那么Delphi中可以用Str:=Edit1.text来实现。VB中应该是Str=Text1.Text;但是如果你用API,想要得到Edit输入框里的文本内容,就要调用GetDlgItemInt(Edit中输入的值当做数值来用)GetDlgItemText、GetDlgItemTextA(Edit中输入的值当做字符串来用)。而上面我说的VB、Delphi得到编辑框中输入的内容的方法,最终在编译成可执行文件的时候,也会由编译器自动对其进行相应的转换。你只要明白一件事就好了,那就是你所用的程序,无时无刻都在调用着系统中的各种各样的API函数。
其实Windows中的API,就相当于当年DOS系统中的系统功能调用,及中断21。只不过在数量上和功能上,都是DOS系统功能调用所不及的。
如果你还是看不明白,那我不怪你,可能是我讲的不清楚,所以,还是给你推荐老牛写的书吧。力推《Windows程序设计》,看过之后你会内力大增的,那时候你所知道的知识就不止是API而以了。
其实话说回来,我这篇文章不是教你编程的,所以关于Windows程序的原理,没有必要说那么多,我之所以跟你讲API,是想让你知道Windows程序的运行机制。免的到时候用调试器下断点的时候问什么是API。(众人(十分愤怒地)冲上台来:“拉下去PK!把我们当什么了!”)
(我再次来到台上,镜头切向脸的一侧,来个特写。只见上面有若干处大小不同的伤口)可能还有些重点的地方我没有提到,欢迎指正。如果你有什么不明白的地方,欢迎跟贴提问。只要别太那个,比如说“你能把所有的API给我列出来让我回去背背好吗?”
附上几个常用的API函数吧。相信你此时因该以经对API有个大概的了解了。
MessageBox 显示一信息对话框
MessageBoxEx 显示一信息对话框
MessageBoxIndirect 显示一定制信息对话框
(以上这三个,可以用来中断那些错误提示,比如说你注册码输入错误了,程序就可能通过这几个函数中的一个,来提示你错误)
GetDlgItemInt 得指定输入框整数值
GetDlgItemText 得指定输入框输入字符串
GetDlgItemTextA 得指定输入框输入字符串
(软件可以用这三个来得到用户输入的注册码)
GetLocalTime 得当前本地时间
GetSystemTime 得当前系统时间
(软件可以用这两个来判断软件是否过期)
RegQueryvalueA 获取一个项的设置值
RegQueryvalueExA 获取一个项的设置值
RegSetvalueA 设置指定项或子项的值
RegSetvalueExA 设置指定项的值
(如果软件用注册表存储注册信息的话,那么这几个也许会有用)
上面讲的,只是几个平时比较常见的,更多请参见看雪以前的教程或Windows开发人员手册。
最后,我们还要隆重介绍一个重量级函数,你可能不知道API是什么,但你只要用过调试器,就一定知道它的名字。你可以不知道美国现任的总统是谁,但是你一定要知道这个函数。我虽然知道现任美国总统是鲍威尔 但我同时也知道这个函数是谁。
它就是----吴孟达!(导演:NG)重新说。它就是hmemcpy。
这个函数是干什么的?
它是一个非常简单的函数。只完成一项非常非常基本的任务,就是把数据从一个地方复制到另一个地方。应用程序本身并不调用它,理由很简单,它很低级(汇编:谁敢说跟我一样?)。但是大部分API函数却非常频繁地调用它。所以,它也叫万能函数。平时你可能都不知道有这么个东西,但是断起程序来却非常管用。但目前到了2K跟Xp下,却没有这个函数了,与之相应的是一个叫memcpy的函数,虽然功能与其相同,但是基本上已经是个废人了 总知,你用memcpy根本就断不下什么来。所以,这么一个好使的函数只能在98下使用了。这就像美国的总统一样,再好使也只能使八年,不好使的就别说了。说不定明年就把他踢飞
别的我也不多说什么了,这章你就知道API是什么就成了。
如果你觉的有什么不妥的地方或有什么问题,并且想文明一点地表代出来的话,就请在回复。如果想野蛮一点的话,就拿鸡蛋往你显示器上丢吧
<本章完>
 
第四章--调试器及相关工具入门
在写这章之前,我看了一下看雪以往的教程。本来想参考一下,可忽然发现,写这样的一章,是一件非常愚蠢的事情,因为我觉的关于这些工具的使用教程。看雪教程中已经写的够详细的了,我并不认为你会看不懂。所以我不想做浪费时间的人,本章就此搁浅。
推荐看《Crack Tutorial 2001》,推荐看《看雪论坛精华一、二、三、四》,推荐看《加密与解密--软件保护技术及完全解决方案》,推荐看一切与之有关的教程。
本章补遗:
要想上路,你最少应该熟练掌握以下工具:
SoftICE:目前公认最好的跟踪调试工具。(由于我使用的分辩率的关系,从没有用过它)
Trw2000: 国人骄傲,其中有我最喜欢的pmodule命令。(河南老乡,殷墟旧人)
W32Dasm8.93或其它任意版本:反汇编的极品工具。
Hiew 或者Ultra Edit或者其它:十六进制工具。爆破时使用,DOS下使用Hiew,Windows下使用Ultra Edit、WinHex、Hex Workshop等,我个人喜欢用Ultra Edit。
侦测文件类型工具:比如TYP、gtw或FileInfo等。这是一个能侦测你的软件是被哪一种「壳」给加密了。
PROCDUMP与其它N多的脱壳软件。
EXESCOPE:拥有执行文件(EXE, DLL等)的解析与显示功能;提取资源到外部文件 ;资源的重新写入;记录文件的记录及其再编辑(成批编辑)等功能。是汉化软件的常用工具,当然破解软件时也很有用。
其它许多......(等你入了门后再学也不迟)
(作者注:以上工具的使用方法,大都可在看雪以有的教程中找到,故不愿复之)

第五章--破解原理
从本章开始,我们来一步一步学习Crack软件(80%读者昏死过去,且不省人世...另有20%在寻找附近可以用来打人的东西)
不可不说一下学习破解的三个阶段:
初级,修改程序,用ultraedit等工具修改exe文件,称暴力破解,简称爆破
中级,追出软件的注册码
高级,写出注册机
先说这爆破。所谓爆破,就是指通过修改可执行文件的源文件,来达到相应的目的。你不明白?呵呵,举个例子好了,比如说某共享软件,它比较用户输入的注册码,如果用户输入的,跟它通过用户名(或其它)算出来的注册码相等的话(也就是说用户输入的注册码正确了),那么它就会跳到注册成功的地方去,否则就跳到出错的地方去。
明白过来了吧,我们只要找到这个跳转指令,把它修改为我们需要的“造型”,这样,我们是不是就可以为所欲为了?(某软件双手放在胸口,你要干嘛?)
常见的修改方法有两种,我给你举例说明:
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) 或物理地址(RAW offset)。
所以当我们要通过那些十六进制工具来对可执行文件中的相应指令进行修改的话,先要找到它的File offset。我们没有必要去使用那些专门的转换工具,在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
mov eax [ ] 这里可以是地址,也可以是其它寄存器
mov edx [ ] 同上,该条指令也可以是pop edx
call 00?????? 关键call
test eax eax
jz(jnz)或jne(je) 关键跳转
看明白了吧,在关键CALL之前,软件会把两个注册码分别放入eax和edx中,你只要在CALL处下d eax或d edx就能看到正确的注册码了。
no.2
mov eax [ ] 这里可以是地址,也可以是其它寄存器
mov edx [ ] 同上,该条指令也可以是pop edx
call 00?????? 关键call
jne(je) 关键跳转
以上两种情况最为常见,而那些个不太常见的情况,我们这里就不再提了。到下下一章的时候,我会给你讲相关方法的...
关于查找软件注册码的部分,就到这里。具体内容,下下一章咱们再说。(不是说了吗?我以经可以接到你的砖头了,干嘛还要丢呢? )
最后,再来说最后的所谓的高级阶段,如果你相信自己。并且热爱Crack,那么你一定会熬到这个阶段的,只是时间因人而异。
其实分析软件的算法,是有好多技巧在里面的。呵呵,最起码我刚开始的时候就摸不着头脑,那么多CALL,每个看起来,都很重要,都追一遍?结果连好多API都被追了进去。等你自己真正用心分析了一个软件的算法,并写出了注册机后。你就会明白其中的道理了,我们下下下一章再说。(大哥,你不是吧,连你家太阳能都丢过来了 )
<本章完>

第六章--爆破软件
爆破其实很简单,最起码比你能一下把你家的牙膏给全挤出来要容易多了。你只要先到大街上买几根雷管,然后放到你的显示器上再点着就OK了(不难吧,记的点着后跑远点儿)
爆破的原理我也说过了,相信你很容易就能理解了。我们今天就具体讲一下如何找到那个关键跳转以及如何才能买到即便宜又好用的雷管...
爆破一个软件一般只需要很少的几个步骤,首先先看一下其有无加壳,有的话是用何工具加的壳,知道了以后用相应的工具将其脱掉或进行手工脱壳,参考以有教程。接着我们就可以对脱过壳之后的软件来开刀了。你有两种选择,用W32Dasm或调试器,一般如果你遇上的是那种很菜的软件的话,用W32Dasm就可以搞定了。如果遇上的不是那种比较菜的,就买股票吧,因为股票是你如胶似漆的妻子!当!快醒醒啊...哦,一般如果你遇上的不是那种很菜的软件的话,就用调试器吧。先来说W32Dasm:我们首先用W32Dasm来进行反汇编(废话!)之后在串式参考中找到错误提示信息或可能是正确的提示信息双击鼠标左键来到相应的地址处。在W32Dasm的主窗口中分析相应汇编代码,找出关键跳转和关键call。绿色光条停在关键跳转,在W32Dasm主窗口底部找到关键跳转的偏移地址(实际修改地址)。用ultraedit找到偏移地址(实际修改地址)修改机器码(或放上一根雷管),保存(点火)!而用调试器也同样简单,等会儿会详细说明。
道理废话了那么多,来实例动手说明吧:
首先讲解用W32Dasm来进行爆破:
【软件名称】中华压缩(ChinaZip)
【软件版本】7.0
【文件大小】1041KB
【适用平台】W.x/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处,我把具体代码给贴上(请你从代码的最下边开始看):
:004F4DD1 E84EE1F3FF call 00432F24
:004F4DD6 8B55F0 mov edx, dword ptr [ebp-10]
:004F4DD9 8D4DF4 lea ecx, dword ptr [ebp-0C]
:004F4DDC 8BC3 mov eax, ebx
:004F4DDE E8C9010000 call 004F4FAC
:004F4DE3 8B55F4 mov edx, dword ptr [ebp-0C]
:004F4DE6 58 pop eax
:004F4DE7 E830F3F0FF call 0040411C
:004F4DEC 7576 jne 004F4E64 <--这个就是传说中的男人,Stop!这个就是传说中的关键跳转
:004F4DEE B201 mov dl, 01
:004F4DF0 A158254500 mov eax, dword ptr [00452558]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004F4D86(C)
|
:004F4DF5 E85ED8F5FF call 00452658
:004F4DFA 8945FC mov dword ptr [ebp-04], eax
:004F4DFD 33C0 xor eax, eax
:004F4DFF 55 push ebp
:004F4E00 685D4E4F00 push 004F4E5D
:004F4E05 64FF30 push dword ptr fs:[eax]
:004F4E08 648920 mov dword ptr fs:[eax], esp
:004F4E0B B101 mov cl, 01

* Possible StringData Ref from Code Obj ->\"Software\\XDZHAN\\ChinaZip\"
|
:004F4E0D BAA84E4F00 mov edx, 004F4EA8
:004F4E12 8B45FC mov eax, dword ptr [ebp-04]
:004F4E15 E822DAF5FF call 0045283C

* Possible StringData Ref from Code Obj ->\"Real Programmers Use Pascal!\"
|
:004F4E1A B9CC4E4F00 mov ecx, 004F4ECC

* Possible StringData Ref from Code Obj ->\"Key\"
|
:004F4E1F BAF44E4F00 mov edx, 004F4EF4
:004F4E24 8B45FC mov eax, dword ptr [ebp-04]
:004F4E27 E854DEF5FF call 00452C80

* Possible StringData Ref from Code Obj ->\"软件注册成功,谢谢您的支持!\" <--我们向上看会在这里发现注册成功后的正确信息。正确信息处向上找第一个跳转就是我们要找的关键跳转。
|
:004F4E2C B8004F4F00 mov eax, 004F4F00
:004F4E31 E8563DF6FF call 00458B8C
:004F4E36 A16C305000 mov eax, dword ptr [0050306C]
:004F4E3B 8B00 mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->\"中华压缩(ChinaZip)-注册版\"
|
:004F4E3D BA244F4F00 mov edx, 004F4F24
:004F4E42 E80DE1F3FF call 00432F54
:004F4E47 33C0 xor eax, eax
:004F4E49 5A pop edx
:004F4E4A 59 pop ecx
:004F4E4B 59 pop ecx
:004F4E4C 648910 mov dword ptr fs:[eax], edx
:004F4E4F 686E4E4F00 push 004F4E6E

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004F4E62(U)
|
:004F4E54 8B45FC mov eax, dword ptr [ebp-04]
:004F4E57 E868E2F0FF call 004030C4
:004F4E5C C3 ret


:004F4E5D E9C2E9F0FF jmp 00403824
:004F4E62 EBF0 jmp 004F4E54

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004F4DEC(C)
|

* Possible StringData Ref from Code Obj ->\"注册码不正确,无法注册!\" <--这个就是出错的信息了,那正确信息也就在附近,上下看看。
|
:004F4E64 B8484F4F00 mov eax, 004F4F48 <--双击来到这里
:004F4E69 E81E3DF6FF call 00458B8C
:004F4E6E 33C0 xor eax, eax
:004F4E70 5A pop edx
:004F4E71 59 pop ecx
:004F4E72 59 pop ecx
:004F4E73 648910 mov dword ptr fs:[eax], edx
:004F4E76 689B4E4F00 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:9e62 push bp
0147:9e63 mov bp,sp
0147:9e65 push ds
0147:9e66 push edi
0147:9e68 push esi
0147:9e6a cld
0147:9e6b mov ecx,[bp+06]
0147:9e6f jcxz 9ee9
……以下N多代码省略……
我们输入bc *来取消断点,然后用pmodule来返回到程序的领空:
0167:00436d13 mov [ebx+0c],eax
0167:00436d16 mov eax,[ebx]
0167:00436d18 cmp eax,byte +0c
0167:00436d1b jnz 00436d38
0167:00436d1d mov edx,[ebx+08]
0167:00436d20 push edx
0167:00436d21 mov ecx,[ebx+04]
0167:00436d24 mov edx,eax
0167:00436d26 mov eax,esi
0167:00436d28 call 00432b24
……N多代码仍旧省略……
按7下F12另加1下F10来到0167:004f4dc4处,我们接着一下一下来按F10,大概按了10多下,就可以看到004f4dec处有一个跳转,我们执行到004f4dec处后果然跳走了。会跳到004f4e64处,我们跳过去之后按不了三下,程序就提示出错了。呵呵,明白过来了吧,004f4dec处的那个跳转jnz 004f4e64就是关键跳转,嘿嘿,找到了之后不用我说了吧
0167:004f4dc4 mov eax,[ebp-08]
0167:004f4dc7 push eax
0167:004f4dc8 lea edx,[ebp-10]
0167:004f4dcb mov eax,[ebx+02e0]
0167:004f4dd1 call 00432f24
0167:004f4dd6 mov edx,[ebp-10]
0167:004f4dd9 lea ecx,[ebp-0c]
0167:004f4ddc mov eax,ebx
0167:004f4dde call 004f4fac
0167:004f4de3 mov edx,[ebp-0c]
0167:004f4de6 pop eax
0167:004f4de7 call 0040411c
0167:004f4dec jnz 004f4e64 <--关键跳转!!
0167:004f4dee mov dl,01
0167:004f4df0 mov eax,[00452558]
0167:004f4df5 call 00452658
0167:004f4dfa mov [ebp-04],eax
0167:004f4dfd xor eax,eax
0167:004f4dff push ebp
0167:004f4e00 push dword 004f4e5d
0167:004f4e05 push dword [fs:eax]
0167:004f4e08 mov [fs:eax],esp
0167:004f4e0b mov cl,01
0167:004f4e0d mov edx,004f4ea8
0167:004f4e12 mov eax,[ebp-04]
0167:004f4e15 call 0045283c
0167:004f4e1a mov ecx,004f4ecc
0167:004f4e1f mov edx,004f4ef4
0167:004f4e24 mov eax,[ebp-04]
0167:004f4e27 call 00452c80
0167:004f4e2c mov eax,004f4f00
0167:004f4e31 call 00458b8c
0167:004f4e36 mov eax,[0050306c]
0167:004f4e3b mov eax,[eax]
0167:004f4e3d mov edx,004f4f24
0167:004f4e42 call 00432f54
0167:004f4e47 xor eax,eax
0167:004f4e49 pop edx
0167:004f4e4a pop ecx
0167:004f4e4b pop ecx
0167:004f4e4c mov [fs:eax],edx
0167:004f4e4f push dword 004f4e6e
0167:004f4e54 mov eax,[ebp-04]
0167:004f4e57 call 004030c4
0167:004f4e5c ret
0167:004f4e5d jmp 00403824
0167:004f4e62 jmp short 004f4e54
0167:004f4e64 mov eax,004f4f48 <---由上面的0167:004f4dec处跳来,出错!;
0167:004f4e69 call 00458b8c
0167:004f4e6e xor eax,eax
再来给你举另一个例子:
【软件名称】天网防火墙
【软件版本】2.46 Beta
【文件大小】1289KB
【适用平台】W.x/Me/NT/2000
【软件简介】天网防火墙个人版是一套给个人电脑使用的网络安全程序,它可以帮你抵挡网络入侵和攻击,防止信息泄露,并可与我们的网站相配合,根据可疑的攻击信息,来找到攻击者。同时天网防火墙个人版把网络分为本地网和互联网,可以针对来自不同网络的信息,来设置不同的安全方案,它适合于在拨号上网的用户,也适合通过网络共享软件上网的用户。
该软件仍旧是我从电脑报2001年合订本的配套光盘中找的,软件的注册码可以到其网站免费获得...
我们还是要先把它装上(某民工:你小子敢再说一句废话试试!^_^)之后我们用FI看一下它有没有加壳,呵呵,BC++编译,没有加壳,爽!运行它,在注册对话框中随便输入点什么,比如说这星期又出了几部新电影,都叫什么名字等等...
好的,我们接下来请TRW2000出场。先胡乱输入两个字符串,比如第一个输入“英雄的导演是?”第二个输入“可能是赵本山”:)
接下来就按Ctrl+N把TRW2K叫出来,下bpx hmemcpy,之后按F5退出。
接着可以按确定就成了,程序会被TRW2K断掉,我们紧接着输入bc *以及pmodule。
下面可以开始按F12了,一共按8下程序就会报错,我们第二次就按7下然后开始按F10,按70下F10程序就又报错了(呵呵,一定要有耐心哦)。
好的,我把反汇编后的代码给你贴出来:
0167:0041c617 lea edx,[ebp-04] <--7下F12后按一下F10来到这里
0167:0041c61a mov ecx,[0052ae7c]
0167:0041c620 mov eax,[ecx]
0167:0041c622 mov eax,[eax+0318]
0167:0041c628 add eax,byte +2c
0167:0041c62b call 00517740
0167:0041c630 dec dword [ebp-20]
0167:0041c633 lea eax,[ebp-04]
0167:0041c636 mov edx,02
0167:0041c63b call 00517710
0167:0041c640 mov word [ebp-2c],14
0167:0041c646 lea eax,[ebp-08]
0167:0041c649 call 00401d60
0167:0041c64e mov edx,eax
0167:0041c650 inc dword [ebp-20]
0167:0041c653 mov ecx,[ebp-40]
0167:0041c656 mov eax,[ecx+02e0]
0167:0041c65c call 004b9f14
0167:0041c661 lea edx,[ebp-08]
0167:0041c664 mov ecx,[0052ae7c]
0167:0041c66a mov eax,[ecx]
0167:0041c66c mov eax,[eax+0318]
0167:0041c672 add eax,byte +30
0167:0041c675 call 00517740
0167:0041c67a dec dword [ebp-20]
0167:0041c67d lea eax,[ebp-08]
0167:0041c680 mov edx,02
0167:0041c685 call 00517710
0167:0041c68a lea eax,[ebp-10]
0167:0041c68d call 00401d60
0167:0041c692 mov edx,eax
0167:0041c694 inc dword [ebp-20]
0167:0041c697 mov ecx,[ebp-40]
0167:0041c69a mov eax,[ecx+02e0]
0167:0041c6a0 call 004b9f14
0167:0041c6a5 lea edx,[ebp-10]
0167:0041c6a8 push dword [edx]
0167:0041c6aa mov word [ebp-2c],20
0167:0041c6b0 lea eax,[ebp-0c]
0167:0041c6b3 call 00401d60
0167:0041c6b8 mov edx,eax
0167:0041c6ba inc dword [ebp-20]
0167:0041c6bd mov ecx,[ebp-40]
0167:0041c6c0 mov eax,[ecx+02d4]
0167:0041c6c6 call 004b9f14
0167:0041c6cb lea edx,[ebp-0c]
0167:0041c6ce mov edx,[edx]
0167:0041c6d0 mov eax,[0052ae7c]
0167:0041c6d5 mov eax,[eax]
0167:0041c6d7 pop ecx
0167:0041c6d8 call 0040525c
0167:0041c6dd mov [ebp-45],al
0167:0041c6e0 dec dword [ebp-20]
0167:0041c6e3 lea eax,[ebp-10]
0167:0041c6e6 mov edx,02
0167:0041c6eb call 00517710
0167:0041c6f0 dec dword [ebp-20]
0167:0041c6f3 lea eax,[ebp-0c]
0167:0041c6f6 mov edx,02
0167:0041c6fb call 00517710
0167:0041c700 cmp byte [ebp-45],00
0167:0041c704 jz 0041c750 <--按了60多下F10后会在这里发现一个跳转,嘿嘿,就是它了!!!
0167:0041c706 mov ecx,[0052ae7c]
0167:0041c70c mov eax,[ecx]
0167:0041c70e mov eax,[eax+0318]
0167:0041c714 call 00411fd0
0167:0041c719 mov word [ebp-2c],2c
0167:0041c71f mov edx,00521b50
0167:0041c724 lea eax,[ebp-14]
0167:0041c727 call 005175b0
0167:0041c72c inc dword [ebp-20]
0167:0041c72f mov eax,[eax]
0167:0041c731 call 004b41b0
0167:0041c736 dec dword [ebp-20]
0167:0041c739 lea eax,[ebp-14]
0167:0041c73c mov edx,02
0167:0041c741 call 00517710
0167:0041c746 mov eax,[ebp-40]
0167:0041c749 call 004a81d0
0167:0041c74e jmp short 0041c77d
0167:0041c750 mov word [ebp-2c],38
0167:0041c756 mov edx,00521b6b
0167:0041c75b lea eax,[ebp-18]
0167:0041c75e call 005175b0
0167:0041c763 inc dword [ebp-20]
找到了关键跳转之后就别闲着了,呵呵,放雷管吧!(你可以用W32Dasm打开这个文件,然后按Shift+F12,之后输入0041c704,这样就可以在右下角看到相应的偏移地址了)
小技巧:在TRW中,如果你觉的某处可能是关键跳转的话,可以用r fl z这个指令来进行测试,该指令可使以成立的条件取反,比如说本来JZ XXXXXXXX成立,可以跳走了,用r fl z指令后该条指令就不成立了,即就不会跳走了。以上也是,你可以在0041c704处输入r fl z,呵呵,再执行几步看看,是不是成功了?还有就是如果你只是想达到注册软件的目的,且该软件只在注册的时候验证一次的话,用这个方法就可以代替雷管了!
呵呵,最后还是要说一句,爆破只是一些雕虫小技。刚入门时玩几次就够了,切莫就此不前...
后话:你可能慢慢就会发现,有一些软件其实并没有你想象中那么简单,你甚至连找到它的关键跳转都找不到。这很正常,你要做的便是多动手多练习,慢慢你就会明白过来的。我今天之所以给你举这两个例子,就是因为它们两个都比较简单,且能说明重点,给你讲那些比较那个的软件的爆破,反而会让你看的一头雾水...







初学破解人的口诀和指令


cmp  a,b  // 比较a与b
mov  a,b  // 把b值送给a值,使a=b
ret     // 返回主程序
nop     // 无作用,英文(no operation)简写,意思“do nothing”(机器码90)
       (ultraedit打开编辑exe文件看到90相当汇编语句的nop)
call    // 调用子程序,子程序以ret结尾
je或jz    // 相等则跳(机器码是74或84)
jne或jnz  // 不相等则跳(机器码是75或85)
jmp     // 无条件跳(机器码是EB)
jb     // 若小于则跳
ja     // 若大于则跳
jg     // 若大于则跳
jge     // 若大于等于则跳
jl     // 若小于则跳
pop xxx  // xxx出栈
push xxx  // xxx压栈

        爆破无敌口诀

      一条(跳)就死,九筒(90)就胡
      (对应上面的2--修改为nop)
      一条(跳)就胡,一饼(EB)伺候
      (对应上面的1--修改为jmp)
       (74) 变(75)
       (84) 变 (85)
大家不懂不要紧,一定要先牢记,以后慢慢的理解。

写给新手 - 浅谈脱壳方法

[转]写给新手 - 浅谈脱壳方法


【标  题】写给新手 - 浅谈脱壳方法
【作  者】xIkUg[CCG][BCG][DFCG][DCM][CZG][D.4s]
【日  期】2004-12-18
【使用工具】OllyDBG, ImportREC
【主  页】http://bbs.xp-program.com
【平  台】WinXP sp1
【目标程序】轻轻松松学开车 6.6
【下载地址】http://www.sharebank.com.cn/soft/soft_view.php?id=10506
【作者声明】只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

【正  文】
我很少写破文, 最近看到一些新手常问查壳工具查不出是什么壳,末知壳如何脱...我这里就简单的用一个示例程序谈谈脱壳
方法. 算是给新手打打气.

一般这种没有公开的壳不会太猛(除了hying, vcasm, jingulong等这些圈内人的壳哈), 大多是自己土制的壳, 有的还伪装一
下, 致使查壳工具查不出或查出什么Aspack, UPX的壳. 碰到这种壳不用太怕, 认真跟踪分析一下一般都没多大问题.

一般加壳后的程序运行时大多是用各种方法AntiDebugger, 其中夹杂很多花指令和LJ指令, 然后解码,
又是一堆AntiDebugger, 可能又解码, 恢复IAT, 又是一堆AntiDebugger...最后再跳到程序真正的OEP处, 对付这种壳一般的方
法是先找到OEP, 再修复IAT

在壳跳到OEP的时候一般是个跨段跳转, 跳转方法有很多, 如JMP XXXXXXXX, JMP [XXXXXXXX], JE [XXXXXXXX],
PUSH XXXXXXXX RET, CALL XXXXXXXXX, CALL [XXXXXXXX], CALL EAX...还有的是在SEH中直接指定EIP等等, 找到这个跳转地址,
然后在相应地址上设上断点, F9运行, 就到达OEP处了, 此时就是最好的Dump时机

修复IAT一般用ImportREC, 填写好OEP的RVA, 先点IATAutoSearch, 再点GetImport, 如果找到的API全部有效就可以点
Fix Dump了, 如果有无效的就需要修复, 先点Show Invalid, 再对这些无效的API点右键, 共有3个修复级别, 分别是Disasm,
HOOK, Trap Flag, 可以一个一个试, 全部API有效或只有一两个API无效时就可以点Fix Dump了, 如果修复不了就只有用手工
修复了.

手工修复IAT的方法是, 一般壳在运行的时候会恢复IAT或破坏IAT, 你可以在恢复IAT后或破坏IAT之前DUMP出完好的IAT,
再用16进制编辑器, 把完整的IAT复制到Dump出来的文件中, 多做做练习就不难了

还是看看目标程序"轻轻松松学开车 6.6", 用PEiD查一下, ASPack 2.12 -> Alexey Solodovnikov
用OD载入, 提示入口点在代码外部(以后别再问如何判断程序是否加壳了, 用OD载入如果有这个提示就表示程序是加了壳的),
点确定, 问是否分析, 点否, 来到入口处

006AF001 D> 60        pushad         ; 壳代码入口
006AF002  E8 03000000     call DrvStudy.006AF00A     ; 有花指令, F7跟进
006AF007  - E9 EB045D45     jmp 45C7F4F7
006AF00C  55        push ebp
006AF00D  C3        retn
006AF00E  E8 01000000     call DrvStudy.006AF014
006AF013  EB 5D        jmp short DrvStudy.006AF072

在006AF002处call DrvStudy.006AF00A, 代码中没有006AF00A, 是因为花指令让OD错误的分析了代码, 用F7跟进就能来到
006AF00A处, 像这种近距离的Call, 其实是变形的Jmp, 都要用F7跟进, 如果F8跳过的话可以会碰到里面的陷阱


006AF00A  5D        pop ebp         ; DrvStudy.006AF007, 跳到这里
006AF00B  45        inc ebp         ; ebp + 1
006AF00C  55        push ebp         ; 变形跳转到ebp的地址处
006AF00D  C3        retn

来到
006AF008  /EB 04        jmp short DrvStudy.006AF00E  ; 来到这里
006AF00A  |5D        pop ebp
006AF00B  |45        inc ebp         ; ebp + 1
006AF00C  |55        push ebp         ; 变形跳转到ebp的地址处
006AF00D  |C3        retn
006AF00E  \E8 01000000     call DrvStudy.006AF014     ; 变形跳转, F7跟进

006AF014  5D        pop ebp
006AF015  BB EDFFFFFF     mov ebx,-13
006AF01A  03DD        add ebx,ebp
006AF01C  81EB 00F02A00     sub ebx,2AF000        ; 代码重定位
006AF022  83BD 22040000 00    cmp dword ptr ss:[ebp+422],0  ; 变量ebp+422是存放的基址
006AF029  899D 22040000     mov dword ptr ss:[ebp+422],ebx
006AF02F  /0F85 65030000     jnz DrvStudy.006AF39A     ; 这里不跳
006AF035  |8D85 2E040000     lea eax,dword ptr ss:[ebp+42E]  ; "kernel32.dll"
006AF03B  |50        push eax         ; 参数入栈
006AF03C  |FF95 4D0F0000     call dword ptr ss:[ebp+F4D]  ; kernel32.GetModuleHandleA
006AF042  |8985 26040000     mov dword ptr ss:[ebp+426],eax  ; kernel32.dll的句柄存入ebp+426处
006AF048  8BF8        mov edi,eax        ; kernel32.77E40000
006AF04A  8D5D 5E      lea ebx,dword ptr ss:[ebp+5E]  ; "VirtualAlloc"
006AF04D  53        push ebx
006AF04E  50        push eax         ; Kernel32.dll句柄
006AF04F  FF95 490F0000     call dword ptr ss:[ebp+F49]  ; GetProcAddress
006AF055  8985 4D050000     mov dword ptr ss:[ebp+54D],eax  ; 把VirtualAlloc的函数地址存入ebp+54D处
006AF05B  8D5D 6B      lea ebx,dword ptr ss:[ebp+6B]  ; "VirtualFree"
006AF05E  53        push ebx
006AF05F  57        push edi         ; Kernel32.dll句柄入栈
006AF060  FF95 490F0000     call dword ptr ss:[ebp+F49]  ; GetProcAddress
006AF066  8985 51050000     mov dword ptr ss:[ebp+551],eax  ; 把VirtualFree的函数地址存入ebp+511处
006AF06C  8D45 77      lea eax,dword ptr ss:[ebp+77]  ; 跳转地址载入eax
006AF06F  FFE0        jmp eax         ; 跳到eax指向的地方

006AF08A  8B9D 31050000     mov ebx,dword ptr ss:[ebp+531]  ; 来到这里, ebx=0
006AF090  0BDB        or ebx,ebx
006AF092  /74 0A        je short DrvStudy.006AF09E    ; ebx==0,跳
006AF094  |8B03        mov eax,dword ptr ds:[ebx]
006AF096  |8785 35050000     xchg dword ptr ss:[ebp+535],eax
006AF09C  |8903        mov dword ptr ds:[ebx],eax
006AF09E  \8DB5 69050000     lea esi,dword ptr ss:[ebp+569]  ; 跳到这里, esi指向一标志
006AF0A4  833E 00      cmp dword ptr ds:[esi],0
006AF0A7  /0F84 21010000     je DrvStudy.006AF1CE     ; 不为0, 不跳
006AF0AD  6A 04        push 4
006AF0AF  68 00100000     push 1000
006AF0B4  68 00180000     push 1800
006AF0B9  6A 00        push 0
006AF0BB  FF95 4D050000     call dword ptr ss:[ebp+54D]  ; 分配内存
C语言描述为
VirtualAlloc(NULL, 0x1800, MEM_COMMIT, PAGE_READWRITE);
006AF0C7  8B46 04      mov eax,dword ptr ds:[esi+4]
006AF0CA  05 0E010000     add eax,10E
006AF0CF  6A 04        push 4
006AF0D1  68 00100000     push 1000
006AF0D6  50        push eax
006AF0D7  6A 00        push 0
006AF0D9  FF95 4D050000     call dword ptr ss:[ebp+54D]  ; 再次分配内存, eax为所需内存大小
006AF0DF  8985 52010000     mov dword ptr ss:[ebp+152],eax  ; 分配的第2块内存锯柄存入ebp+152处
006AF0E5  56        push esi
006AF0E6  8B1E        mov ebx,dword ptr ds:[esi]
006AF0E8  039D 22040000     add ebx,dword ptr ss:[ebp+422]
006AF0EE  FFB5 56010000     push dword ptr ss:[ebp+156]  ; 0x401000
006AF0F4  FF76 04      push dword ptr ds:[esi+4]
006AF0F7  50        push eax
006AF0F8  53        push ebx
006AF0F9  E8 6E050000     call DrvStudy.006AF66C     ; 解压代码
006AF0FE  B3 01        mov bl,1
006AF100  80FB 00      cmp bl,0
006AF103  75 5E        jnz short DrvStudy.006AF163
006AF105  FE85 EC000000     inc byte ptr ss:[ebp+EC]
006AF10B  8B3E        mov edi,dword ptr ds:[esi]
006AF10D  03BD 22040000     add edi,dword ptr ss:[ebp+422]
006AF113  FF37        push dword ptr ds:[edi]     ; 保护0x401000处的代码
006AF115  C607 C3      mov byte ptr ds:[edi],0C3    ; 把0x401000处的代码改为RET
006AF118  FFD7        call edi         ; LJ调用
006AF11A  8F07        pop dword ptr ds:[edi]     ; 恢复0x401000处的代码

F8单步到下面一点点, 来到
006AF12D  0BC9        or ecx,ecx
006AF12F  74 2E        je short DrvStudy.006AF15F
006AF131  78 2C        js short DrvStudy.006AF15F
006AF133  AC        lods byte ptr ds:[esi]
006AF134  3C E8        cmp al,0E8
006AF136  74 0A        je short DrvStudy.006AF142
006AF138  EB 00        jmp short DrvStudy.006AF13A
006AF13A  3C E9        cmp al,0E9
006AF13C  74 04        je short DrvStudy.006AF142
006AF13E  43        inc ebx
006AF13F  49        dec ecx
006AF140  ^ EB EB        jmp short DrvStudy.006AF12D
006AF142  8B06        mov eax,dword ptr ds:[esi]    ; 在这里设置一个断点

这里找opcode为e8或e9的地方, F9运行后断下, ebx=1FE, eax=[esi]的内容, 紧接着会比较esi指向的地方

006AF144  /EB 00        jmp short DrvStudy.006AF146
006AF146  \803E 36      cmp byte ptr ds:[esi],36    ; 比较第2个字节的opcode是否为36
006AF149  ^ 75 F3        jnz short DrvStudy.006AF13E  ; 是就不跳, 这里为36不会跳
006AF14B  24 00        and al,0
006AF14D  C1C0 18      rol eax,18        ; 解码
006AF150  2BC3        sub eax,ebx        ; 解码
006AF152  8906        mov dword ptr ds:[esi],eax    ; 解码后的代码存入esi指向的地方
006AF154  83C3 05      add ebx,5
006AF157  83C6 04      add esi,4
006AF15A  83E9 05      sub ecx,5
006AF15D  ^ EB CE        jmp short DrvStudy.006AF12D  ; 向上跳

可以判断出上面的这段代码是解码的, C30000处的代码会解码, 在006AF15D的下一个指令设好断点, F9运行, 断下
006AF15F  5B        pop ebx         ; 断下, 解码完毕
006AF160  5E        pop esi
006AF161  59        pop ecx
006AF162  58        pop eax
006AF163  EB 08        jmp short DrvStudy.006AF16D  ; 跳

006AF16D  8BC8        mov ecx,eax        ; 来到这里
006AF16F  8B3E        mov edi,dword ptr ds:[esi]    ; 代码段偏移
006AF171  03BD 22040000     add edi,dword ptr ss:[ebp+422]  ; 基地址+偏移, 指向代码段
006AF177  8BB5 52010000     mov esi,dword ptr ss:[ebp+152]  ; 解码后的正确代码地址
006AF17D  C1F9 02      sar ecx,2
006AF180  F3:A5        rep movs dword ptr es:[edi],dword >; 填充正确的代码
006AF182  8BC8        mov ecx,eax
006AF184  83E1 03      and ecx,3
006AF187  F3:A4        rep movs byte ptr es:[edi],byte pt>; 填充正确的代码
006AF189  5E        pop esi
006AF18A  68 00800000     push 8000
006AF18F  6A 00        push 0
006AF191  FFB5 52010000     push dword ptr ss:[ebp+152]
006AF197  FF95 51050000     call dword ptr ss:[ebp+551]  ; VirtualFree
006AF19D  83C6 08      add esi,8
006AF1A0  833E 00      cmp dword ptr ds:[esi],0    ; 解码完成?没完成就跳
006AF1A3  ^ 0F85 1EFFFFFF     jnz DrvStudy.006AF0C7     ; 又跳到上面

因此可以确定这一大段006AF0C7 - 006AF1A3都是解码的代码, 在006AF1A3处的下1条指令设置一个断点, F9运行, 断下

006AF1A9  68 00800000     push 8000        ; 断下
006AF1AE  6A 00        push 0
006AF1B0  FFB5 56010000     push dword ptr ss:[ebp+156]
006AF1B6  FF95 51050000     call dword ptr ss:[ebp+551]  ; VirtualFree
释放内存了

006AF1BC  8B9D 31050000     mov ebx,dword ptr ss:[ebp+531]  ; ebx=0
006AF1C2  0BDB        or ebx,ebx
006AF1C4  74 08        je short DrvStudy.006AF1CE    ; ebx==0,跳
006AF1C6  8B03        mov eax,dword ptr ds:[ebx]
006AF1C8  8785 35050000     xchg dword ptr ss:[ebp+535],eax
006AF1CE  8B95 22040000     mov edx,dword ptr ss:[ebp+422]  ; 跳到这里, ebx=0x400000, 基地址
006AF1D4  8B85 2D050000     mov eax,dword ptr ss:[ebp+52D]  ; eax=0x400000
006AF1DA  2BD0        sub edx,eax
006AF1DC  74 79        je short DrvStudy.006AF257    ; ecx==0, 跳

下面就是恢复IAT了

006AF257  8B95 22040000     mov edx,dword ptr ss:[ebp+422]  ; 跳到这里, edx=0x400000, 基地址
006AF25D  8BB5 41050000     mov esi,dword ptr ss:[ebp+541]  ; esi=0
006AF263  0BF6        or esi,esi
006AF265  74 11        je short DrvStudy.006AF278    ; esi==0, 跳
006AF267  03F2        add esi,edx
006AF269  AD        lods dword ptr ds:[esi]
006AF26A  0BC0        or eax,eax
006AF26C  74 0A        je short DrvStudy.006AF278
006AF26E  03C2        add eax,edx
006AF270  8BF8        mov edi,eax
006AF272  66:AD        lods word ptr ds:[esi]
006AF274  66:AB        stos word ptr es:[edi]
006AF276  ^ EB F1        jmp short DrvStudy.006AF269
006AF278  BE 00001E00     mov esi,1E0000        ; 跳到这里, esi=1e0000
006AF27D  8B95 22040000     mov edx,dword ptr ss:[ebp+422]  ; edx=基地址
006AF283  03F2        add esi,edx        ; esi=51e0000
006AF285  8B46 0C      mov eax,dword ptr ds:[esi+C]  ; 指向下一个dll文件名的RVA
006AF288  85C0        test eax,eax        ; 不为空就不跳
006AF28A  0F84 0A010000     je DrvStudy.006AF39A
006AF290  03C2        add eax,edx        ; 得到下一个dll文件名
006AF292  8BD8        mov ebx,eax
006AF294  50        push eax
006AF295  FF95 4D0F0000     call dword ptr ss:[ebp+F4D]  ; 取kernel32.dll的句柄
006AF29B  85C0        test eax,eax        ; 成功, 跳
006AF29D  75 07        jnz short DrvStudy.006AF2A6
006AF29F  53        push ebx
006AF2A0  FF95 510F0000     call dword ptr ss:[ebp+F51]
006AF2A6  8985 45050000     mov dword ptr ss:[ebp+545],eax  ; 跳到这里, kernel32.dll句柄存入ebp+545
006AF2AC  C785 49050000 00000000  mov dword ptr ss:[ebp+549],0  ; [ebp+549]=0
006AF2B6  8B95 22040000     mov edx,dword ptr ss:[ebp+422]  ; edx=基地址
006AF2BC  8B06        mov eax,dword ptr ds:[esi]    ; eax=0
006AF2BE  85C0        test eax,eax
006AF2C0  75 03        jnz short DrvStudy.006AF2C5  ; eax==0, 不跳
006AF2C2  8B46 10      mov eax,dword ptr ds:[esi+10]  ; IAT的FirThunk基地址
006AF2C5  03C2        add eax,edx
006AF2C7  0385 49050000     add eax,dword ptr ss:[ebp+549]  ; 指向下1个API
006AF2CD  8B18        mov ebx,dword ptr ds:[eax]
006AF2CF  8B7E 10      mov edi,dword ptr ds:[esi+10]
006AF2D2  03FA        add edi,edx
006AF2D4  03BD 49050000     add edi,dword ptr ss:[ebp+549]
006AF2DA  85DB        test ebx,ebx
006AF2DC  0F84 A2000000     je DrvStudy.006AF384
006AF2E2  F7C3 00000080     test ebx,80000000
006AF2E8  75 04        jnz short DrvStudy.006AF2EE
006AF2EA  03DA        add ebx,edx
006AF2EC  43        inc ebx         ; 取函数名
006AF2ED  43        inc ebx         ; 取函数名
006AF2EE  53        push ebx
006AF2EF  81E3 FFFFFF7F     and ebx,7FFFFFFF
006AF2F5  53        push ebx         ; 函数名入栈
006AF2F6  FFB5 45050000     push dword ptr ss:[ebp+545]  ; kernel32.dll句柄入栈
006AF2FC  FF95 490F0000     call dword ptr ss:[ebp+F49]  ; GetProcAddress
006AF302  85C0        test eax,eax
006AF304  5B        pop ebx
006AF305  75 6F        jnz short DrvStudy.006AF376  ; 跳

取API函数地址成功后跳到下面的地方
006AF376  8907        mov dword ptr ds:[edi],eax    ; API地址存入edi指向地址
006AF378  8385 49050000 04    add dword ptr ss:[ebp+549],4  ; 取下一个API
006AF37F  ^ E9 32FFFFFF     jmp DrvStudy.006AF2B6     ; 跳
006AF384  8906        mov dword ptr ds:[esi],eax
006AF386  8946 0C      mov dword ptr ds:[esi+C],eax
006AF389  8946 10      mov dword ptr ds:[esi+10],eax
006AF38C  83C6 14      add esi,14
006AF38F  8B95 22040000     mov edx,dword ptr ss:[ebp+422]
006AF395  ^ E9 EBFEFFFF     jmp DrvStudy.006AF285     ; 跳去恢复下个导入dll中的函数

这个大循环完成后IAT就恢复完成了...这个IAT是没有被破坏的, 根据一般经验, 壳在运行时都会有这么一个大循环来恢复IAT,
有的是破坏, 因此当在你一个循环中碰到GetModuleHandleA, LoadLibraryA, GetProcAddress, 时就要小心了, 记下它,
有可能ImportRec找不回API函数的时候, 需要手工修复IAT时就要用到它

循环完后,来到这里
006AF39A  B8 08CF1C00     mov eax,1CCF08        ; OEP的RVA
006AF39F  50        push eax
006AF3A0  0385 22040000     add eax,dword ptr ss:[ebp+422]  ; OEP值
006AF3A6  59        pop ecx
006AF3A7  0BC9        or ecx,ecx
006AF3A9  8985 A8030000     mov dword ptr ss:[ebp+3A8],eax  ; 修改[ebp+3A8]处的代码
006AF3AF  61        popad
006AF3B0  75 08        jnz short DrvStudy.006AF3BA  ; 跳
006AF3B2  B8 01000000     mov eax,1
006AF3B7  C2 0C00      retn 0C
006AF3BA  68 08CF5C00     push DrvStudy.005CCF08     ; 变形跳转
006AF3BF  C3        retn          ; ^_^ 飞向光明之颠

这里就是典型的Delphi程序的OEP处代码
005CCF08  55        push ebp         ; 停在这里
005CCF09  8BEC        mov ebp,esp
005CCF0B  83C4 F0      add esp,-10
005CCF0E  53        push ebx
005CCF0F  B8 80CA5C00     mov eax,DrvStudy.005CCA80
005CCF14  E8 B3A7E3FF     call DrvStudy.004076CC

现在就可在005CCF08处Dump程序了, 用OD的OllyDump插件, Dump出程序, 启动ImportREC, 填入OEP的RVA值
先点IATAutoSearch, 再点GetImport, 找到的API全部有效, 点Fix Dump, 修复IAT指针

运行程序, 提示系统数据错误, 这是因为程序有自校验, 发现自己被脱壳后拒绝运行, 去除程序的自校验我就不说了...用爆破
的方法就能搞定...

附件: ASXP_v135自动脱壳 http://www.chinadforce.com/attachment.php?aid=186834

附件: fi脱壳工具 http://www.chinadforce.com/attachment.php?aid=186835

附件: Krykiller加壳 http://www.chinadforce.com/attachment.php?aid=186836

附件: BW2K02找壳点工具 http://www.chinadforce.com/attachment.php?aid=186837

附件: 黑客实用工具 http://www.chinadforce.com/attachment.php?aid=186838

附件: vfpkill150脱壳 http://www.chinadforce.com/attachment.php?aid=186839

看过全文的朋友不要忘了帮我顶住它哦,谢啦

一定要顶住这个贴子哦




寻找软件的注册码

第七章-寻找软件的注册码
我们来寻找软件真正的注册码!
寻找软件的注册码就像你小时玩的躲猫猫一样,简单又有趣,虽然后来你会不这样觉的
好的,我们开始。
我不知道你有没有明白我前面在原理中讲的那些东西,如果没明白,我就再说一遍
软件通过你输入的用户名或者机器码什么的生成一个正确的注册码来与你输入的注册码进行比较,如果两个相同,也就是说你输入的注册码是正确的话,那软件就会完成注册。如果你输入的不正确,嘿嘿,当然就不会注册成功。
好的,现在你已经知道软件会有一个比较两个注册码的过程,这就是关键所在。一般如果你遇到的是那种明码比较的软件,这会是一件非常另人愉快的事情的
软件会先计算出正确的注册码然后再与你输入的那个进行比较,也就是说正确的注册码会被软件自己算出来!嘿嘿,搜身你会吗?虽然法律以及道德不允许我们去搜身,但…
我接着说,虽然现在的软件已经比以前要厉害上许多,但,那种用明码比较的,还是大有人在的。所谓明码比较,就是说软件先算出正确的注册码,然后放到内存或你家的“我是头号大傻瓜”下面,之后再得到你输入的那个注册码,接着就比较了。呵呵,好理解吧,我们只要找到那个比较的地方,看一下软件把注册码放到内存的哪里了,再到相应的内存处瞧一瞧,就万事OK了!
还记的对你说过的那些常见的(也是最菜的)比较吗?我捡其中最简单的一个来给你再解释一下:
mov eax [ ] 这里可以是地址,也可以是其它寄存器 该条指令也可以是mov eax [ ]
mov edx [ ] 同上 通常这两个地址就储存着重要信息 该指令也可以是 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[CCG],Code:19870219
然后请出我们的老伙计TRW2000,下bpx hmemcpy 按F5点确定被拦:
KERNEL?HMEMCPY
0147:9e62 push bp
0147:9e63 mov bp,sp
0147:9e65 push ds
0147:9e66 push edi
0147:9e68 push esi
0147:9e6a cld
0147:9e6b mov ecx,[bp+06]
0147:9e6f jcxz 9ee9
...省略N多代码...
输入bc *,删除断点。pmodule ,直接跳到程序领空:
0167:00436d13 mov [ebx+0c],eax
0167:00436d16 mov eax,[ebx]
0167:00436d18 cmp eax,byte +0c
0167:00436d1b jnz 00436d38
0167:00436d1d mov edx,[ebx+08]
0167:00436d20 push edx
0167:00436d21 mov ecx,[ebx+04]
0167:00436d24 mov edx,eax
0167:00436d26 mov eax,esi
0167:00436d28 call 00432b24
...省略N多代码...
按8下F12就会提示出错,我们第二次就按7次 接着我们再来按F10,按16下就会报错,好的,我们再来:这一次我们按F10的时候,就按我前边说过的方法,到与上次按的次数相差五六次的时候就慢下来。好的,我们按十来下的时候就慢下来仔细瞅瞅,呵呵,一下子就看到004f4dec处的那个跳转以及它上面的关键CALL了 我们按F10单步执行到004f4de7处(即关键CALL处)后下指令d edx就可看到真正的注册码,而d eax则可以看到我刚才输入的19870219 代码给你:
0167:004f4dc4 mov eax,[ebp-08] <---7下F12,1下F10就来到这里(此时ebp-08处放的是刚才输入的注册码19870219)
0167:004f4dc7 push eax <---将EAX压栈;
0167:004f4dc8 lea edx,[ebp-10]
0167:004f4dcb mov eax,[ebx+02e0]
0167:004f4dd1 call 00432f24 <---该CALL用来得到用户输入的用户名,其实就是某个API函数,嘿嘿,好奇的话可以追进去看看
0167:004f4dd6 mov edx,[ebp-10] <---将得到的用户名放入EDX;
0167:004f4dd9 lea ecx,[ebp-0c]
0167:004f4ddc mov eax,ebx
0167:004f4dde call 004f4fac <---该CALL用来计算出真正的注册码;
0167:004f4de3 mov edx,[ebp-0c] <---将计算出的真.注册码放入EDX,在下条指令时可用D EDX查看;
0167:004f4de6 pop eax <---先前压入的注册码出栈;
0167:004f4de7 call 0040411c <---该CALL用来比较两个注册码,罪魁祸首啊!;
0167:004f4dec jnz 004f4e64 <---不相等则跳,跳必死,暴破将75改为74或EB,当然90也行;
0167:004f4dee mov dl,01
0167:004f4df0 mov eax,[00452558]
0167:004f4df5 call 00452658
0167:004f4dfa mov [ebp-04],eax
0167:004f4dfd xor eax,eax
0167:004f4dff push ebp
0167:004f4e00 push dword 004f4e5d
0167:004f4e05 push dword [fs:eax]
0167:004f4e08 mov [fs:eax],esp
0167:004f4e0b mov cl,01
0167:004f4e0d mov edx,004f4ea8
0167:004f4e12 mov eax,[ebp-04]
0167:004f4e15 call 0045283c
0167:004f4e1a mov ecx,004f4ecc
0167:004f4e1f mov edx,004f4ef4
0167:004f4e24 mov eax,[ebp-04]
0167:004f4e27 call 00452c80
0167:004f4e2c mov eax,004f4f00
0167:004f4e31 call 00458b8c
0167:004f4e36 mov eax,[0050306c]
0167:004f4e3b mov eax,[eax]
0167:004f4e3d mov edx,004f4f24
0167:004f4e42 call 00432f54
0167:004f4e47 xor eax,eax
0167:004f4e49 pop edx
0167:004f4e4a pop ecx
0167:004f4e4b pop ecx
0167:004f4e4c mov [fs:eax],edx
0167:004f4e4f push dword 004f4e6e
0167:004f4e54 mov eax,[ebp-04]
0167:004f4e57 call 004030c4
0167:004f4e5c ret
0167:004f4e5d jmp 00403824
0167:004f4e62 jmp short 004f4e54
0167:004f4e64 mov eax,004f4f48 <---由上面的0167:004f4dec处跳来,挂!;
0167:004f4e69 call 00458b8c
0167:004f4e6e xor eax,eax
整理:
Name:Suunb[CCG]
Code:SCCG5296
可以真接在TRW2000中下断点bpx 004f4de6,中断后用D EDX来查看真.注册码。
另附:CRACKCODE2000的CRACKCODE.INI
[Options]
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
【适用平台】W.x/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)
|
:00488DD9 8B45FC mov eax, dword ptr [ebp-04]
:00488DDC 8B8020040000 mov eax, dword ptr [eax+00000420]
:00488DE2 35280BB61E xor eax, 1EB60B28
:00488DE7 3B45F8 cmp eax, dword ptr [ebp-08] <---关键比较,? EAX来查看软件正确的注册码;
:00488DEA 0F85A0000000 jne 00488E90 <---关键跳转,不相等就跳,跳必挂!
:00488DF0 6A40 push 00000040

* Possible StringData Ref from Code Obj ->\"注册成功\"
|
:00488DF2 68D48E4800 push 00488ED4

* Possible StringData Ref from Code Obj ->\"感谢您支持国产软件,祝您好运!\"
|
:00488DF7 68E08E4800 push 00488EE0 <---双击串式参考便跳到此行,我们向上找第一个跳转处就是关键跳转,关键跳转上面就是关键比较;
:00488DFC 8B45FC mov eax, dword ptr [ebp-04]
:00488DFF E81CD2FBFF call 00446020
:00488E04 50 push eax
...省略代码若干...
向上看,00488DEA处有一跳转,不相等便跳到00488E90处,跳必挂!还记的00488E97处的出错对话框吧! 罪魁祸首啊!
在向上一行,看00488DE7处:cmp eax, dword ptr [ebp-08],此为关键比较。可用? 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
【适用平台】W.x/Me/NT/2000
【软件简介】一个强大并且易用的压缩实用程序,支持ZIP、CAB、TAR、GZIP、MIME,以及更多格式的压缩文件。其特点是紧密地与Windows资源管理器拖放集成,不用离开资源管理器而进行压缩、解压缩。
不用我说了吧,出处仍旧是电脑报2001年合订本的配套光盘
我之所以先择它,是因为觉得它的关键CALL没有前边那两个那样好找(其实也就那样了^_^)极具代表性,而且通过它可以让你感受一下Ollydbg这个魅力比你家的荼几还大的调试器
这里之所以提到Ollydbg,是觉的它真是一个非常非常棒的调试器...强烈建议你多玩几次...(MP3好听吗? ^_^)
我们来吧,首先当然还是要装上它(左闪术,右闪术),然后用Ollydbg来载入,此时界面会被分成四个部分,左上方是软件反汇编后的代码,右上方是寄存器开会的地方,左下方是内存区,右下方显示的则是堆栈的信息。
我们来下断点,按Alt+F4,之后选USER32,然后再鼠标右键-->搜索-->当前模块中的名称,然后在那一大堆函数中找到GetDlgItemTextA,按F2来下断点,它会提示你错误,并说无法设置中断点,是不是很过瘾?(呜呜呜...大哥,我错了,再也不敢了...)
呵呵,这个我也不知道什么原因,明明是用了这个函数嘛,就是不让断,其实我对Ollydbg也不是太那个(关键是讨厌它的下断方式)看来还是用我们的万能断点吧,输入注册名Suunb[CCG],输入注册码19870219,然后用TRW2000下断bpx hmemcpy,断到之后,pmodule返回领空后一次F12就会出错,看来所有的东东就在这里了...
我们用TRW2000再断一下,返回领空之后记着第一条指令的地址0040bd5f,呜呜呜...上条指令明明是调用GetDlgItemTextA,为什么在Ollydbg中不让下呢?
没关系,我们记下这个地址后仍旧用Ollydbg来加载程序,之后在反汇编窗口中找到0040bd5f处,然后按下F2来下断(会变为红色),下断之后便按F9来运行程序,接着输入注册名Suunb[CCG],注册码19870219后按确定,程序会被Ollydbg给断到:
0040BD5F |. 57 PUSH EDI
0040BD60 |. E8 F34A0500 CALL WINZIP32.00460858
0040BD65 |. 57 PUSH EDI ; /Arg1
0040BD66 |. E8 164B0500 CALL WINZIP32.00460881 ; \\WINZIP32.00460881
0040BD6B |. 59 POP ECX
0040BD6C |. BE 1CCA4C00 MOV ESI,WINZIP32.004CCA1C
0040BD71 |. 59 POP ECX
0040BD72 |. 6A 0B PUSH 0B ; /Count = B (11.)
0040BD74 |. 56 PUSH ESI ; |Buffer => WINZIP32.004CCA1C
0040BD75 |. 68 810C0000 PUSH 0C81 ; |ControlID = C81 (3201.)
0040BD7A |. 53 PUSH EBX ; |hWnd
0040BD7B |. FF15 F4C54A00 CALL DWORD PTR DS:[<&USER32.GetDlgItemTe>; \\GetDlgItemTextA
0040BD81 |. 56 PUSH ESI
0040BD82 |. E8 D14A0500 CALL WINZIP32.00460858
0040BD87 |. 56 PUSH ESI
0040BD88 |. E8 F44A0500 CALL WINZIP32.00460881
0040BD8D |. 803D F0C94C00 >CMP BYTE PTR DS:[4CC9F0],0
0040BD94 |. 59 POP ECX
0040BD95 |. 59 POP ECX
0040BD96 |. 74 5F JE SHORT WINZIP32.0040BDF7
0040BD98 |. 803D 1CCA4C00 >CMP BYTE PTR DS:[4CCA1C],0
0040BD9F |. 74 56 JE SHORT WINZIP32.0040BDF7
0040BDA1 |. E8 31F9FFFF CALL WINZIP32.0040B6D7 <--关键CALL,等会儿进去玩玩
0040BDA6 |. 84C0 TEST AL,AL <--根据关键CALL中比较的结果来做相应的测试
0040BDA8 |. 74 4D JE SHORT WINZIP32.0040BDF7 <--跳走就没戏!
0040BDAA |. 57 PUSH EDI
0040BDAB |. 68 08DE4B00 PUSH WINZIP32.004BDE08 ; ASCII \"Name\"
0040BDB0 |. FF35 1CC74A00 PUSH DWORD PTR DS:[4AC71C] ; WINZIP32.004BDDEC
0040BDB6 |. E8 8AFA0400 CALL WINZIP32.0045B845
0040BDBB |. 56 PUSH ESI
0040BDBC |. 68 C8EB4B00 PUSH WINZIP32.004BEBC8 ; ASCII \"SN\"
0040BDC1 |. FF35 1CC74A00 PUSH DWORD PTR DS:[4AC71C] ; WINZIP32.004BDDEC
0040BDC7 |. E8 79FA0400 CALL WINZIP32.0045B845
0040BDCC |. FF35 18C74A00 PUSH DWORD PTR DS:[4AC718] ; |Arg4 = 004BDDF4 ASCII \"winzip32.ini\"
0040BDD2 |. 6A 00 PUSH 0 ; |Arg3 = 00000000
0040BDD4 |. 6A 00 PUSH 0 ; |Arg2 = 00000000
0040BDD6 |. 68 14DE4B00 PUSH WINZIP32.004BDE14 ; |Arg1 = 004BDE14 ASCII \"rrs\"
0040BDDB |. E8 4CFA0400 CALL WINZIP32.0045B82C ; \\WINZIP32.0045B82C
0040BDE0 |. A1 A8914C00 MOV EAX,DWORD PTR DS:[4C91A8]
0040BDE5 |. 83C4 28 ADD ESP,28
0040BDE8 |. 85C0 TEST EAX,EAX
0040BDEA |. 74 07 JE SHORT WINZIP32.0040BDF3
0040BDEC |. 50 PUSH EAX ; /hObject => 000013F4 (font)
0040BDED |. FF15 80C04A00 CALL DWORD PTR DS:[<&GDI32.DeleteObject>>; \\DeleteObject
0040BDF3 |> 6A 01 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 PUSH EAX ; |Arg3
0040BE07 |. 53 PUSH EBX ; |Arg2
0040BE08 |. 6A 3D PUSH 3D ; |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 PUSH EBP
0040B6D8 |. 8BEC MOV EBP,ESP
0040B6DA |. 81EC 0C020000 SUB ESP,20C
0040B6E0 |. 8065 FF 00 AND BYTE PTR SS:[EBP-1],0
0040B6E4 |. 803D F0C94C00 >CMP BYTE PTR DS:[4CC9F0],0
0040B6EB |. 53 PUSH EBX
0040B6EC |. 56 PUSH ESI
0040B6ED |. 57 PUSH EDI
0040B6EE |. 0F84 FB000000 JE WINZIP32.0040B7EF
0040B6F4 |. 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
0040B6F7 |. 50 PUSH EAX
0040B6F8 |. 68 C0E84B00 PUSH WINZIP32.004BE8C0
0040B6FD |. E8 DE61FFFF CALL WINZIP32.004018E0
0040B702 |. 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
0040B705 |. 50 PUSH EAX
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 MOV EDI,WINZIP32.004AC720 ; ASCII \"auth.c\"
0040B718 |. 6A 21 PUSH 21
0040B71A |. 57 PUSH EDI
0040B71B |. E8 86F60000 CALL WINZIP32.0041ADA6
0040B720 |. 59 POP ECX
0040B721 |. 59 POP ECX
0040B722 |. EB 05 JMP SHORT WINZIP32.0040B729
0040B724 |> BF 20C74A00 MOV EDI,WINZIP32.004AC720 ; ASCII \"auth.c\"
0040B729 |> 8D85 F4FDFFFF LEA EAX,DWORD PTR SS:[EBP-20C]
0040B72F |. BB F0C94C00 MOV EBX,WINZIP32.004CC9F0 ; ASCII \"Suunb[CCG]\"
0040B734 |. 50 PUSH EAX
0040B735 |. 53 PUSH EBX
0040B736 |. E8 50030000 CALL WINZIP32.0040BA8B
0040B73B |. 8D85 F4FDFFFF LEA EAX,DWORD PTR SS:[EBP-20C]
0040B741 |. 50 PUSH EAX
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 PUSH EDI
0040B756 |. E8 4BF60000 CALL WINZIP32.0041ADA6
0040B75B |. 59 POP ECX
0040B75C |. 59 POP ECX
0040B75D |> 8D85 F4FDFFFF LEA EAX,DWORD PTR SS:[EBP-20C]
0040B763 |. 50 PUSH EAX
0040B764 |. 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
0040B767 |. 50 PUSH EAX
0040B768 |. E8 03300900 CALL WINZIP32.0049E770
0040B76D |. 59 POP ECX
0040B76E |. 85C0 TEST EAX,EAX
0040B770 |. 59 POP ECX
0040B771 |. 75 04 JNZ SHORT WINZIP32.0040B777
0040B773 |. C645 FF 01 MOV BYTE PTR SS:[EBP-1],1
0040B777 |> 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
0040B77A |. 50 PUSH EAX
0040B77B |. 68 D0E84B00 PUSH WINZIP32.004BE8D0
0040B780 |. E8 5B61FFFF CALL WINZIP32.004018E0
0040B785 |. 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
0040B788 |. 50 PUSH EAX
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 PUSH EDI
0040B799 |. E8 08F60000 CALL WINZIP32.0041ADA6
0040B79E |. 59 POP ECX
0040B79F |. 59 POP ECX
0040B7A0 |> 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
0040B7A3 |. 50 PUSH EAX
0040B7A4 |. 53 PUSH EBX
0040B7A5 |. E8 C62F0900 CALL WINZIP32.0049E770
0040B7AA |. 59 POP ECX
0040B7AB |. 85C0 TEST EAX,EAX
0040B7AD |. 59 POP ECX
0040B7AE |. 75 0E JNZ SHORT WINZIP32.0040B7BE
0040B7B0 |. FF15 F0C14A00 CALL DWORD PTR DS:[<&KERNEL32.GetTickCou>; [GetTickCount
0040B7B6 |. A8 01 TEST AL,1
0040B7B8 |. 74 04 JE SHORT WINZIP32.0040B7BE
0040B7BA |. C645 FF 01 MOV BYTE PTR SS:[EBP-1],1
0040B7BE |> 6A 14 PUSH 14
0040B7C0 |. 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
0040B7C3 |. 6A 00 PUSH 0
0040B7C5 |. 50 PUSH EAX
0040B7C6 |. E8 75820800 CALL WINZIP32.00493A40
0040B7CB |. 56 PUSH ESI
0040B7CC |. 8D85 F4FDFFFF LEA EAX,DWORD PTR SS:[EBP-20C]
0040B7D2 |. 6A 00 PUSH 0
0040B7D4 |. 50 PUSH EAX
0040B7D5 |. E8 66820800 CALL WINZIP32.00493A40
0040B7DA |. 83C4 18 ADD ESP,18
0040B7DD |. 807D FF 00 CMP BYTE PTR SS:[EBP-1],0
0040B7E1 |. 74 13 JE SHORT WINZIP32.0040B7F6
0040B7E3 |. E8 D7080000 CALL WINZIP32.0040C0BF
0040B7E8 |. 8025 EDBF4C00 >AND BYTE PTR DS:[4CBFED],0
0040B7EF |> 32C0 XOR AL,AL
0040B7F1 |. E9 F5000000 JMP WINZIP32.0040B8EB
0040B7F6 |> 8D85 BCFEFFFF LEA EAX,DWORD PTR SS:[EBP-144]
0040B7FC |. 50 PUSH EAX
0040B7FD |. 53 PUSH EBX
0040B7FE |. E8 ED000000 CALL WINZIP32.0040B8F0 <--参与计算软正确的注册码
0040B803 |. 8D85 BCFEFFFF LEA EAX,DWORD PTR SS:[EBP-144] <--在这里第一次发现软件正确的注册码
0040B809 |. 50 PUSH EAX
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 PUSH EDI
0040B81E |. E8 83F50000 CALL WINZIP32.0041ADA6
0040B823 |. 59 POP ECX
0040B824 |. 59 POP ECX
0040B825 |> BF 1CCA4C00 MOV EDI,WINZIP32.004CCA1C ; ASCII \"19870219\" <--将刚才输入的错误的注册码放入EDI
0040B82A |. 8D85 BCFEFFFF LEA EAX,DWORD PTR SS:[EBP-144] <--EAX中装入正确的注册码所在的地址
0040B830 |. 57 PUSH EDI <--用户输入的注册码入栈
0040B831 |. 50 PUSH EAX <--软件计算出的正确的注册码入栈
0040B832 |. E8 392F0900 CALL WINZIP32.0049E770 <--关键CALL,用于比较用户输入的注册码
0040B837 |. F7D8 NEG EAX
0040B839 |. 1AC0 SBB AL,AL
0040B83B |. 59 POP ECX
0040B83C |. FEC0 INC AL
0040B83E |. 59 POP ECX
0040B83F |. A2 EDBF4C00 MOV BYTE PTR DS:[4CBFED],AL
0040B844 |. 0F85 8A000000 JNZ WINZIP32.0040B8D4
0040B84A |. 8D85 BCFEFFFF LEA EAX,DWORD PTR SS:[EBP-144]
0040B850 |. 50 PUSH EAX
0040B851 |. 53 PUSH EBX
0040B852 |. E8 33010000 CALL WINZIP32.0040B98A <--参与计算软件的第二个注册码
0040B857 |. 8D85 BCFEFFFF LEA EAX,DWORD PTR SS:[EBP-144] <--此时软件会再算出另外一个注册码
0040B85D |. 50 PUSH EAX
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 PUSH WINZIP32.004AC720 ; ASCII \"auth.c\"
0040B871 |. E8 30F50000 CALL WINZIP32.0041ADA6
0040B876 |. 59 POP ECX
0040B877 |. 59 POP ECX
0040B878 |> 8D85 BCFEFFFF LEA EAX,DWORD PTR SS:[EBP-144] <--软件计算出的第二个注册码装入EAX中
0040B87E |. 57 PUSH EDI <--用户输入的注册码入栈
0040B87F |. 50 PUSH EAX <--软件计算出的第二个注册码入栈
0040B880 |. E8 EB2E0900 CALL WINZIP32.0049E770 <--另一个关键CALL,用于比较第二次生成的注册码
0040B885 |. F7D8 NEG EAX
0040B887 |. 1AC0 SBB AL,AL
0040B889 |. 59 POP ECX
0040B88A |. FEC0 INC AL
0040B88C |. 59 POP ECX
0040B88D |. A2 EDBF4C00 MOV BYTE PTR DS:[4CBFED],AL
0040B892 |. 75 40 JNZ SHORT WINZIP32.0040B8D4
0040B894 |. 8D85 C0FEFFFF LEA EAX,DWORD PTR SS:[EBP-140]
0040B89A |. 6A 04 PUSH 4
0040B89C |. 50 PUSH EAX
0040B89D |. 57 PUSH EDI
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 BCFEFFFF LEA EAX,DWORD PTR SS:[EBP-144]
0040B8B0 |. 6A 04 PUSH 4
0040B8B2 |. 50 PUSH EAX
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:[4CBFED],1
0040B8CB |. EB 07 JMP SHORT WINZIP32.0040B8D4
0040B8CD |> 8025 EDBF4C00 >AND BYTE PTR DS:[4CBFED],0
0040B8D4 |> 56 PUSH ESI
0040B8D5 |. 8D85 BCFEFFFF LEA EAX,DWORD PTR SS:[EBP-144]
0040B8DB |. 6A 00 PUSH 0
0040B8DD |. 50 PUSH EAX
0040B8DE |. E8 5D810800 CALL WINZIP32.00493A40
0040B8E3 |. A0 EDBF4C00 MOV AL,BYTE PTR DS:[4CBFED]
0040B8E8 |. 83C4 0C ADD ESP,0C
0040B8EB |>