一般情况下共享软件破解的层次大概有三:爆破、穷追注册码和制作注册机。爆破由于它的简单性,不需要对软件注册算法有很好了解,所以很适合破解初学者练习,如果掌握好暴破的方法,我们一样可以搞定大部分的共享软件,下面介绍一下我自己在爆破方面的一点体会,仅作为自己学习之目的和供初学破解的朋友参考,如果大家觉得软件不错,可以购买正版。
我们今天要“开刀”的软件是:家庭卡拉OK 2.4中文版和全能音频转换通1.2,这两个小工具都是戴维的作品,可以在作者的主页下载得到:http://davidsoft.nease.net/。(特别声明,很对不起作者,不是我故意和您过不去,实在是因为我水平菜,您的软件很适合我练习,还请您原谅啊。)
首先介绍一下这两款小工具的功能:
1.家庭卡拉OK,从名字上我们就可以看出是用来唱卡拉OK的,用这款小工具加上麦克和MP3歌曲就能实现您的“歌星”梦想,还是相当方便的,并且它还是一款多媒体播放工具,支持常见的音频及视频格式,内置消原唱功能,可以把MP3等歌曲中的原唱剔除,也支持VCD的伴唱功能,同时支持麦克风演唱、音频录制与合成以及歌词同步显示,LRC歌词同步显示+MP3和VCD消原唱功能+麦克风演唱功能+录音功能+MP3合成功能=完美的家庭卡拉OK梦想!同时该软件还附送四个小工具:MP3换名器、LRC管理器、LRC编辑器和MP3到WMA转换器。当然没注册的用户功能是很受限制的,比如不能使用附加的这四个工具,每次启动软件都有扰人的提示注册框,还倒计时,而且不能保存伴奏合成处理过的MP3。
2.全能音频转换通是一款音视频文件格式转换软件。它支持目前所有流行的媒体文件格式(MP3/MP2/OGG/APE/WAV/WMA/AVI/RM/RMVB/ASF/MPEG/DAT),并能批量转换。更为强大的是,该软件能从视频文件中分离出音频流,转换成完整的音频文件。典型的应用如WAV转MP3,MP3转WMA,WAV转WMA,RM(RMVB)转MP3,AVI转MP3,RM(RMVB)转WMA等。并且可以从整个媒体中截取出部分时间段,转成一个音频文件,或者将几个不同格式的媒体转换并连接成一个音频文件。但是,没有注册只能使用五次!
好了,工具介绍完了,我们开始讨论如何破解,当然我们最终的目的就是去掉所有功能限制,在不穷追注册算法的前提下如果能达到和注册后相同的情况就算我们爆破成功了。我们先来复习一下爆破的思路,一般情况下,软件在注册码验证过程中会对我们输入的注册码和它本身注册算法得到的注册码进行比较(不管是不是明文),在比较之后会有一个关键性跳转,即如果两者相同就运行注册版部分的程序,如果不相同则跳到未注册版部分。我们常用的爆破手法就是找到这一关键性跳转,然后更改跳转指令,达到我们预期的目的。基本的跳转指令有哪些呢?看看论坛里可是有不少这样的教程呢。经典的比较注册码的关键部分大致如下:
CALL ******
TEST EAX,ECX
JNZ ******(或JZ *****)
Call部分就是调用验证子程序,Test部分就是比较子程序返回值的,JNZ和JZ(包括JNE,JE)则是不相等(结果不为0)或者相等(结果为0)时进行跳转。 我们只要反向更改跳转部分,让它本来不跳的时候跳或者本来跳的时候不跳就可以达到暴力破解的目的,当然有时候我们还会用到JMP(不管是否相等都强制跳)和NOP(不管不问)。
原理先复习到这,我们请出破解必备三剑客开始破解之旅吧,它们就是:
OllyDbg——动(静)态跟踪“超级武器”
W32Dasm——静态反汇编“利刃”
WinHex——16进制文件编辑与磁盘编辑“小刀”
当然有时候,我们还需要检测壳软件以便判断程序是否加壳,今天我们的破解很幸运,这也是我为什么选它练习的原因之一,两款工具都未加壳,所以侦壳工具省了。
先拿家庭卡拉OK练习,安装好软件后,我们先自己注册一下,随便输入注册码:777888456,程序会提示注册码已经录入,下次启动后检测,注意了,看来程序不是在输入注册码时进行验证的,这就告诉我们在录入注册码时我们没办法下断截获,程序注册码比对是在启动时候完成的,某些“注册失败”的对话框也不会出现了,有些难度哦!不过,我们可以想出办法来,这种验证方法通常会有以下几种情况:一是从注册表中查询相关注册键值,二是从固定的文件中导入注册码(比如INI文件、KEY文件等)。那我们今天的目标是哪种情况呢?看看安装目录,有个DSMiniOK.ini文件,打开一看,
[App]
AppPath=C:\Program Files\家庭卡拉OK\
EverydayTip=0
AppWord=777888456
APPCode=
原来我们的注册码被保存到了这里。好了,我们利用W32Dasm载入该软件,点击菜单上的“参考”,选择“串式数据参考”,下拉滚动条,我们找一下关键字符串“DSMiniOK.ini”这个字符串,双击来到“00442E27”。好,接下来用OllyDbg载入家庭卡拉OK软件,在前往表达中,输入“00442E27”确定后在此处设置断点。接下来运行,自动中断在我们下断处了,嘿嘿,肯定它要在这以后进行注册码的比较的,我们先F8初跟踪一下,我们可以看到:
00442E2C . E8 E1690000 CALL <JMP.&MFC42.#537_??0CString@@QAE>
00442E31 . 8BCE MOV ECX, ESI ; |
00442E33 . E8 A8010000 CALL 家庭卡拉.00442FE0 ; \家庭卡拉.00442FE0
00442E38 . 8BCE MOV ECX, ESI
00442E3A . E8 01030000 CALL 家庭卡拉.00443140
00442E3F . 85C0 TEST EAX, EAX
00442E41 . 8986 C4000000 MOV DWORD PTR DS:[ESI+C4], EAX
00442E47 . 0F85 8E000000 JNZ 家庭卡拉.00442EDB
00442E4D . 50 PUSH EAX
怎么样,发现最后一段的经典比较了吧,先不管00442E3A这个Call是不是注册码验证子程序,那个JNZ跳往何处我们得关心一下。我们发现来到这里时,程序并没有跳转,下面的代码中又有N个Call,而如果跳到后面的话,会来到这里:
00442EF5 . E8 06080000 CALL 家庭卡拉.00443700
00442EFA . 6A 0A PUSH 0A ; /Arg4 = 0000000A
00442EFC . 6A 01 PUSH 1 ; |Arg3 = 00000001
00442EFE . 68 84DF4700 PUSH 家庭卡拉.0047DF84 ; |Arg2 = 0047DF84 ASCII "EverydayTip"
00442F03 . 68 88D64700 PUSH 家庭卡拉.0047D688 ; |Arg1 = 0047D688 ASCII "App"
00442F08 . B9 B0F24700 MOV ECX, 家庭卡拉.0047F2B0 ; |
00442F0D . E8 AE93FFFF CALL 家庭卡拉.0043C2C0 ; \家庭卡拉.0043C2C0
呵呵,有个每日提示,这说明已经进入主程序了,最起码开始出来的提示注册对话框没了。为了证实我们的猜测,我们先强行让它跳过去看看,不出所料,果然直接进去了,不跳就会出现提示对话框。。但进去后我们发现还是提示未注册,看来注册码比较应该在这一跳的前边。重新来过,这次F7跟进00442E3A这个Call,果然仔细研究正是注册码验证子程序,具体算法我们不管了,00443187 |. /0F85 F4000000 JNZ 家庭卡拉.00443281这个跳我们先关心一下,程序来到这里是要跳的,我们的注册码肯定是假的,先让它别跳,一番跟下去,会来到这里:
00443274 |. DED9 FCOMPP
00443276 |. DFE0 FSTSW AX
00443278 F6C4 40 TEST AH, 40
0044327B |. 0F85 5A040000 JNZ 家庭卡拉.004436DB
这个跳有很大的跨度性,前面部分既然是比较注册码部分,这里很可能是胜利之巅。暂且记下,如果不跳会来到这:
00443281 |> 68 44ED4700 PUSH 家庭卡拉.0047ED44
00443286 |. 68 8CD64700 PUSH 家庭卡拉.0047D68C ; ASCII "AppWord"
0044328B |. 8D4C24 18 LEA ECX, DWORD PTR SS:[ESP+18]
0044328F |. 68 88D64700 PUSH 家庭卡拉.0047D688 ; ASCII "App"
00443294 |. 51 PUSH ECX
00443295 |. B9 B0F24700 MOV ECX, 家庭卡拉.0047F2B0
0044329A |. E8 618CFFFF CALL 家庭卡拉.0043BF00
0044329F |. 8B5424 10 MOV EDX, DWORD PTR SS:[ESP+10]
004432A3 |. 8B35 081C4500 MOV ESI, DWORD PTR DS:[<&MSVCRT._mbs>; msvcrt._mbscmp
004432A9 |. 68 44ED4700 PUSH 家庭卡拉.0047ED44 ; /s2 = ""
004432AE |. 52 PUSH EDX ; |s1
004432AF |. C78424 940000>MOV DWORD PTR SS:[ESP+94], 0 ; |
004432BA |. FFD6 CALL NEAR ESI ; \_mbscmp
004432BC |. 83C4 08 ADD ESP, 8
004432BF |. 85C0 TEST EAX, EAX
004432C1 |. 0F84 C1030000 JE 家庭卡拉.00443688
004432C7 |. 8B4424 10 MOV EAX, DWORD PTR SS:[ESP+10]
004432CB |. 68 30EB4700 PUSH 家庭卡拉.0047EB30 ; ASCII "CrackersDead"
004432D0 |. 50 PUSH EAX
004432D1 |. FFD6 CALL NEAR ESI
004432D3 |. 83C4 08 ADD ESP, 8
004432D6 |. 85C0 TEST EAX, EAX
004432D8 |. 0F84 E9030000 JE 家庭卡拉.004436C7
004432DE |. 6A 02 PUSH 2
这里刚好是00443187跳过来的地方,看来前面的胜利之巅就是了,一定得跳。返回去,重新来一边,在0044327B处强跳,结果程序运行后显示已注册了。暂且记下两处关键性跳转:
1.00443187 |. /0F85 F4000000 JNZ 家庭卡拉.00443281,此处不跳,我们利用Winhex把0F85F4000000改成909090909090。
2.0044327B |. 0F85 5A040000 JNZ 家庭卡拉.004436DB,此处强跳,我们利用Winhex把0F855A040000改成90E95A040000。
OK,再次运行程序,注册成功了吧,可惜,那四个小工具运行时候不行,提示要注册,我们利用W32Dasm很容易可以找到关键性“字符串”,在前面的关键性跳转指令处修改一下令其强行跳转,具体更改的部分是:
1.LRCEditor.exe——> 利用WinHex搜索75176840C04000改为EB176840C04000
2.LRCManager.exe——>利用WinHex搜索75246840504000改为EB246840504000
3.Mp3Rename.exer——>利用WinHEx搜索75246844404000改为EB246844404000
4.MP3toWMA.exe——> 利用WinHEx搜索7517686C654000改为EB17686C654000
OK了,功能都可以用了。到此,这个程序应该算破解完了,但大家肯定会注意到
AppWord=777888456
APPCode=
为什么还有一个Appcode?而且00443286这后部分的比较是干什么用的呢?最重要的是004432CB |. 68 30EB4700 PUSH 家庭卡拉.0047EB30 ; ASCII "CrackersDead",这里有个单词吸引了我,“CrackersDead”,嘿嘿,戴维还curse了我们一下,后来我发现appcode处自己如果随便写出一串数字的话,00443187就自然不跳了。而在004432CB部分程序会用“CrackersDead”来和我们输入的注册码比较,相同就会跳到004436C7,嘿嘿也是胜利的彼岸啊,难道CrackersDead是万能注册码?打开程序输入它,HOHO,注册成功,原来CrackersDead就是万能注册码,用它注册完,连那四个小工具不用破都能使用!不过“CrackersDead”很不爽啊,改成“CrackersBest”多好啊,好,利用WinHex搜索“CrackersDead”,找到后改为“CrackersBest”,保存,怎么样,再输入我们自己的万能注册码是不是也可以成功了!(注:不适用四个小工具)
后记,该软件还有一处“破解盗版”的部分,具体的我没调试,大家不放心可以在这部分之前的跳转改一下,让它怎么都跳不到这里来就行了。修改部分是利用WinHex搜索743D8D4C2418改为90908D4C2418。
接下来我们继续练习下一个软件全能音频转换通,上面我们主要利用了OllyDbg,这次我们主要利用W32Dasm,别看它是静态反汇编工具,一样调试没问题的。我们首先可以想到既然是同一作者同一时期的作品,注册验证过程很可能相似,我们先看看吧,安装好程序,运行注册,填入注册码:77788956,注册一下,果然提示注册验证是在下次,打开程序目录下面的Media.INI文件,可以看到:
[App]
AppPath=C:\Program Files\全能音频转换通\
AppNum=77788956
好了,基本上和前一个软件相似,可以用同样的方法来破解,但这次我们用另外一种思维并用W32Dasm来研究一下它的爆破方法,大家请看:(为了方便,我还是用了OllyDbg拷贝下面的代码)
004068CA . 68 DCB84A00 PUSH 全能音频.004AB8DC ; ASCII "Media.ini"
004068CF . E8 F4B70700 CALL 全能音频.004820C8
004068D4 . 8BCE MOV ECX, ESI ; |
004068D6 . E8 35070000 CALL 全能音频.00407010 ; \全能音频.00407010
004068DB . 6A 0A PUSH 0A ; /Arg4 = 0000000A
004068DD . 53 PUSH EBX ; |Arg3
004068DE . 68 D4B84A00 PUSH 全能音频.004AB8D4 ; |Arg2 = 004AB8D4 ASCII "AppLan"
004068E3 . 68 D0B84A00 PUSH 全能音频.004AB8D0 ; |Arg1 = 004AB8D0 ASCII "App"
004068E8 . B9 C84B4B00 MOV ECX, 全能音频.004B4BC8 ; |
004068ED . 899E C4000000 MOV DWORD PTR DS:[ESI+C4], EBX ; |
004068F3 . E8 D8B60100 CALL 全能音频.00421FD0 ; \全能音频.00421FD0
004068F8 . 3BC3 CMP EAX, EBX
004068FA . 75 2A JNZ SHORT 全能音频.00406926
004068FC . FF15 B4434900 CALL NEAR DWORD PTR DS:[<&KERNEL32.Ge>; [GetSystemDefaultLangID
00406902 . 25 FF030000 AND EAX, 3FF
00406907 . 66:3D 0400 CMP AX, 4
0040690B . 74 3D JE SHORT 全能音频.0040694A
0040690D . 68 C4B84A00 PUSH 全能音频.004AB8C4 ; /FileName = "EngRes.dll"
00406912 . FF15 B8434900 CALL NEAR DWORD PTR DS:[<&KERNEL32.Lo>; \LoadLibraryA
00406918 . 8BF8 MOV EDI, EAX
0040691A . 3BFB CMP EDI, EBX
0040691C . 89BE C4000000 MOV DWORD PTR DS:[ESI+C4], EDI
00406922 . 74 26 JE SHORT 全能音频.0040694A
00406924 . EB 1C JMP SHORT 全能音频.00406942
00406926 > 83F8 02 CMP EAX, 2
00406929 . 75 1F JNZ SHORT 全能音频.0040694A
0040692B . 68 C4B84A00 PUSH 全能音频.004AB8C4 ; /FileName = "EngRes.dll"
00406930 . FF15 B8434900 CALL NEAR DWORD PTR DS:[<&KERNEL32.Lo>; \LoadLibraryA
00406936 . 8BF8 MOV EDI, EAX
00406938 . 3BFB CMP EDI, EBX
0040693A . 89BE C4000000 MOV DWORD PTR DS:[ESI+C4], EDI
00406940 . 74 08 JE SHORT 全能音频.0040694A
00406942 > E8 15450800 CALL 全能音频.0048AE5C
00406947 . 8978 0C MOV DWORD PTR DS:[EAX+C], EDI
0040694A > 8BCE MOV ECX, ESI
0040694C . E8 87410800 CALL 全能音频.0048AAD8
00406951 . 8D4C24 14 LEA ECX, DWORD PTR SS:[ESP+14]
00406955 . E8 E6BF0100 CALL 全能音频.00422940
0040695A . 51 PUSH ECX
0040695B . 899C24 B82900>MOV DWORD PTR SS:[ESP+29B8], EBX
00406962 . 8BCC MOV ECX, ESP
00406964 . 896424 1C MOV DWORD PTR SS:[ESP+1C], ESP
00406968 . 68 B0B84A00 PUSH 全能音频.004AB8B0 ; ASCII "MediaConvert.dav"
0040696D . E8 56B70700 CALL 全能音频.004820C8
00406972 . 6A 05 PUSH 5 ; |Arg1 = 00000005
我们看到:
004068F3 . E8 D8B60100 CALL 全能音频.00421FD0 ; \全能音频.00421FD0
004068F8 . 3BC3 CMP EAX, EBX
004068FA . 75 2A JNZ SHORT 全能音频.00406926
这里有一段经典比较结构,如果不跳,之后还会有多处比较和验证,但它们有一个共同的地方就是跳往0040694A处,而这之后会看到载入MediaConvert.dav,初步估计如果跳到这里,程序应该是正常运行了。我们先点击W32Dasm菜单栏中的“跳转”,然后“到代码位置”处输入004068F3,确定后来到这里,我们再点击“调试”——>加载进程——>载入,弹出了调试窗口,不去管它,重新点跳转到代码位置(004068F3),确定后,按F2在此处下断。好,按F9运行一下程序,刚好中断在我们的断点处,我们点击“步进”,跟进去看看,接下来是“自动步进至结束”,看看程序会最终执行了哪些部分的代码(标记为红色),最后程序弹出了注册提示对话框,而最终红色代码处是“004069B7”这处有个Call,看来是它调用了提示对话框,而这部分已经在00406968 . 68 B0B84A00 PUSH 全能音频.004AB8B0 ; ASCII "MediaConvert.dav"之后了,看来前面我们设置的断点处还不是真正注册码比较部分,向上翻翻,原来004069B7是从00406992处跳转过来后来到这里的,那如果它不跳到这里不就行了,接着来到00406992处,
00406981 . E8 EA070000 CALL 全能音频.00407170
00406986 3BC3 CMP EAX, EBX
00406988 . 8986 C0000000 MOV DWORD PTR DS:[ESI+C0], EAX
0040698E . 75 65 JNZ SHORT 全能音频.004069F5
00406990 . 3BFB CMP EDI, EBX
00406992 . 74 0D JE SHORT 全能音频.004069A1
我们可以看到“00406981”处有一个Call,之后有个比较和Mov指令,如果结果不等就会跳往004069F5,否则就会来到00406992处的跳转,而我们就是从这里跳过来的,最后弹出了注册对话框,这就告诉我们如果在0040698E处强跳就可以躲过注册提示了,我们终止调试窗口,重新来一遍,这次我们选择在0040698E处下断,清除以前的断点,方法如前所述按F2在0040698E下断后,F9运行,来到我们下的断点了,我们点一下调试窗口的“代码补丁”,输入新指令:Jmp 004069F5,回车后,点击应用,关闭后一切都选“是”,接下来我们再点击“自动步进结束”,哈哈,怎么样,程序正常运行了,但还是提示未注册,而且使用次数为“-N”次,这是我们强行修改使程序计数器发生计算为负的结果,本来结果为0(使用完5次后)就不会来到这里了,可是我们强制来到这里,所以结果当然为负了。好了,接下来其实我们修改的方法很简单了,只要我们利用WinHex搜索75653BFB改为“EB653BFB”就可以了,然后利用资源修改工具,比如reshacker或者PE Explorer把未注册(使用还剩N次)的字符串改成“已注册(孤风飘影破解)”就OK了,还可以屏蔽“注册按钮”,怎么样,是不是一个比较帅的想法。
当然,我们还是会觉得这样破解起来总是有些暇疵,我们可以想想既然0040698E处的跳转为关键性跳转,前面00406981处的Call就是注册码验证子程序,我们可以跟进去看看,果然如此,之后是比较和数据传送指令,我们再来看看这个Call到底是怎么一回事,进入这个Call后我们来到00407170处,
00407170 /$ 56 PUSH ESI
00407171 |. 6A 0A PUSH 0A ; /Arg4 = 0000000A
00407173 |. 6A 00 PUSH 0 ; |Arg3 = 00000000
00407175 |. 68 0CB94A00 PUSH 全能音频.004AB90C ; |Arg2 = 004AB90C ASCII "AppNum"
0040717A |. 68 D0B84A00 PUSH 全能音频.004AB8D0 ; |Arg1 = 004AB8D0 ASCII "App"
0040717F |. B9 C84B4B00 MOV ECX, 全能音频.004B4BC8 ; |
00407184 |. E8 47AE0100 CALL 全能音频.00421FD0 ; \全能音频.00421FD0
00407189 |. 8BC8 MOV ECX, EAX
0040718B |. BE E8030000 MOV ESI, 3E8
00407190 |. 99 CDQ
00407191 |. F7FE IDIV ESI
00407193 |. 8D04D5 000000>LEA EAX, DWORD PTR DS:[EDX*8]
0040719A |. 2BC2 SUB EAX, EDX
0040719C |. 8D0440 LEA EAX, DWORD PTR DS:[EAX+EAX*2]
0040719F |. 8D7442 10 LEA ESI, DWORD PTR DS:[EDX+EAX*2+10]
004071A3 |. B8 D34D6210 MOV EAX, 10624DD3
004071A8 |. F7E9 IMUL ECX
004071AA |. C1FA 06 SAR EDX, 6
004071AD |. 8BCA MOV ECX, EDX
004071AF |. 33C0 XOR EAX, EAX
004071B1 |. C1E9 1F SHR ECX, 1F
004071B4 |. 03D1 ADD EDX, ECX
004071B6 3BD6 CMP EDX, ESI
004071B8 |. 5E POP ESI
004071B9 |. 0F94C0 SETE AL
004071BC \. C3 RETN
我们先不管程序注册验证算法是什么样的,我们看最后面几段代码,不管如何计算最后程序会比较EDX和ESI的值,然后会有一个SETE条件设置指令来判断条件是否为真,如果为真,程序返回的值就是判断已注册的标志而自动在0040698E处跳转,如果为假,就判断未注册在0040698E不予跳转。那我们可以这样想我们通过修改指令使条件返回永远为真不就行了。条件比较是什么呢?比较EDX和ESI的值是否相同,我们让它成为CMP ESI,ESI,结果肯定相同,条件就为真了!怎么改呢,我们还是得返回去利用原先的方法,在004071B6处下断,然后修改代码补丁,改为“CMP ESI,ESI”机器码3BD6就变成了3BF6,记下。应用后我们自动步进结束。哈哈,怎么样,程序正常运行了吧,而且是“已注册”哦,那我们只需要利用WinHex搜索3BD65E改为3BF65E就可以实现完美爆破了!剩下的我们利用Keymaker等补丁制作工具制作一个破解补丁就可以发布了!破解任务到此完成。
总结:
1.对于输入注册码后程序提示下次启动后检测的,我们输入的注册码往往保存在程序预先指定的文件中(INI或者是Key文件),或者保存在注册表中,对于保存在文件中的,我们应该首先在程序安装目录中寻找,如果没找到的,也可以利用BPX ReadFile下断。
2.我们应该灵活使用Ollydbg和W32DASM这两款工具,前者动态跟踪更加灵活,后者静态反汇编能力强,字符串搜索效率高,特别是针对中文比前者要好。而且后者也可以调试跟踪程序运行的,如果善于利用我们甚至不需要Ollydbg就可以用W32DASM完美完成破解练习。
3.对于爆破,找到关键性跳转是最核心的,但有时候强行跳转和“反向”不能取得很好效果时,我们可以修改其他指令使程序判断条件永远成立,这样程序就会按照注册一样对待从而实现完美爆破了!
4.爆破也是需要细心和反复调试的,我们只要有信心反复试验总会有所收获的。