宝宝取名软件V17.0破解笔记

宝宝取名软件V17.0破解笔记

宝宝取名软件V17.0破解笔记

首先脱壳。ASPack的壳,VC++编写的程序。
运行后如图:
 
标题有文字“试用版”,于是我们查找字符串,在所有出现“试用版”的地方下断点,然后运行OD,断在这里:

004686D9   .  895D B8       MOV DWORD PTR SS:[EBP-48],EBX
004686DC   .  68 26275F00   PUSH Unpacked.005F2726                   ; / (试用版)
004686E1   .  8B5D B8       MOV EBX,DWORD PTR SS:[EBP-48]            ; |

然后拉到段首,下断,重新来跟一下。断首位置为:

004681F7   $  55            PUSH EBP
004681F8   .  8BEC          MOV EBP,ESP
004681FA   .  81EC 58000000 SUB ESP,58

单步走来到关键代码处:

0046834D   .  83C4 18       ADD ESP,18
00468350   .  E8 4193F9FF   CALL Unpacked.00401696                   ;  关键CALL
00468355   .  85C0          TEST EAX,EAX
00468357   .  0F84 6A030000 JE Unpacked.004686C7                     ;  关键跳,跳了就出错,EAX要为1才注册成功
0046835D   .  C705 4C938C00>MOV DWORD PTR DS:[8C934C],1
00468367   .  8B1D 2C928C00 MOV EBX,DWORD PTR DS:[8C922C]
0046836D   .  895D BC       MOV DWORD PTR SS:[EBP-44],EBX
00468370   .  8B1D 2C928C00 MOV EBX,DWORD PTR DS:[8C922C]
00468376   .  83C3 08       ADD EBX,8
00468379   .  895D B8       MOV DWORD PTR SS:[EBP-48],EBX
0046837C   .  68 46275E00   PUSH Unpacked.005E2746                   ; / (已注册)
00468381   .  8B5D B8       MOV EBX,DWORD PTR SS:[EBP-48]            ; |
00468384   .  FF33          PUSH DWORD PTR DS:[EBX]                  ; |Arg3
00468386   .  68 D6265E00   PUSH Unpacked.005E26D6                   ; | v

好,我们直接在关键CALL处下好断,重新来过,进入CALL看看。在CALL的最后几句分析了一下:

00401735  |.  50            PUSH EAX
00401736  |.  E8 950B0000   CALL Unpacked.004022D0                   ;  由下面分析得这里为关键算法CALL
0040173B  |.  8945 EC       MOV DWORD PTR SS:[EBP-14],EAX            ;  这里EAX给EBP-14
0040173E  |.  8B5D F0       MOV EBX,DWORD PTR SS:[EBP-10]
00401741  |.  85DB          TEST EBX,EBX
00401743  |.  74 09         JE SHORT Unpacked.0040174E
00401745  |.  53            PUSH EBX
00401746  |.  E8 76A60B00   CALL Unpacked.004BBDC1
0040174B  |.  83C4 04       ADD ESP,4
0040174E  |>  8B45 EC       MOV EAX,DWORD PTR SS:[EBP-14]            ;  这里EBP-14给EAX
00401751  |.  E9 00000000   JMP Unpacked.00401756
00401756  |>  8BE5          MOV ESP,EBP
00401758  |.  5D            POP EBP
00401759  \.  C3            RETN

这里要让EAX最后为1才能注册成功。观察最后的代码,发现最后决定EAX值的是这里“00401736  |.  E8 950B0000   CALL Unpacked.004022D0                   ;  由下面分析得这里为关键算法CALL
”,然后我们进去看看。

这个“004022D0”地址的算法CALL代码相当长,我刚开始跟的时候就跟得不耐烦了。
终于我们找到了段尾处:

00404142   > \8B5D C4       MOV EBX,DWORD PTR SS:[EBP-3C]
00404145   .  85DB          TEST EBX,EBX
00404147   .  74 09         JE SHORT Unpacked.00404152
00404149   .  53            PUSH EBX
0040414A   .  E8 727C0B00   CALL Unpacked.004BBDC1
0040414F   .  83C4 04       ADD ESP,4                                ;  ESP赋为4
00404152   >  58            POP EAX
00404153   .  8BE5          MOV ESP,EBP                              ;  又把EBP给ESP,故上面那个ESP=4没用
00404155   .  5D            POP EBP
00404156   .  C2 0800       RETN 8

分析后就把

0040414F   .  83C4 04       ADD ESP,4                                ;  ESP赋为4
00404152   >  58            POP EAX
00404153   .  8BE5          MOV ESP,EBP                              ;  又把EBP给ESP,故上面那个ESP=4没用

直接改成:

0040414F      B8 01000000   MOV EAX,1                                ;  直接让EAX为1
00404154      90            NOP

后面才发现,这样改是不行的,程序运行后就会出错。
然后我又尝试在算法CALL里面改代码,结果都不行,不管改哪都会使程序出错。

那就不改算法CALL了吧,直接改关键CALL里面。
 
这样改了之后,程序的第一次启动验证就OK了,标题已经显示为“已注册”,但是点击“注册”和其它的功能按钮后,程序依然会出错。

后来分析了一晚上,第二天早上才搞出来。原来这个软件有点变态,它的每一处都会有验证注册的代码。每一次都重新验证,而且还不是调用同一个地址的函数进行验证。

但是最终都是调用了算法CALL,关键不一样。于是我们选中算法CALL,右键->查找参考->调用目的地址。在每一处调用地方都下断点。在搜索出来的结果中右键->在每个命令上设置断点。

这时,运行起来。程序运行后会再次调用这个CALL以确定是否注册,如果没注册就弹出注册框。这个验证我们暂时不管,直接F9运行。当程序完全运行起来后,我们点击“生成”按钮,断下来后,执行到返回,来到如下代码:

0048B9AE  |> \E8 E35CF7FF   CALL Unpacked.00401696                   ;  关键CALL
0048B9B3  |.  85C0          TEST EAX,EAX
0048B9B5  |.  0F84 17000000 JE Unpacked.0048B9D2
0048B9BB  |.  E8 34D5F9FF   CALL Unpacked.00428EF4                   ;  关键CALL
0048B9C0  |.  8945 F8       MOV DWORD PTR SS:[EBP-8],EAX
0048B9C3  |.  837D F8 00    CMP DWORD PTR SS:[EBP-8],0
0048B9C7  |.  0F85 05000000 JNZ Unpacked.0048B9D2
0048B9CD  |.  E8 D755FFFF   CALL Unpacked.00480FA9
0048B9D2  |>  E8 BF5CF7FF   CALL Unpacked.00401696                   ;  关键CALL
0048B9D7  |.  85C0          TEST EAX,EAX
0048B9D9  |.  0F84 17000000 JE Unpacked.0048B9F6
0048B9DF  |.  E8 B3D5F8FF   CALL Unpacked.00418F97                   ;  关键CALL
0048B9E4  |.  8945 F8       MOV DWORD PTR SS:[EBP-8],EAX
0048B9E7  |.  837D F8 00    CMP DWORD PTR SS:[EBP-8],0
0048B9EB  |.  0F85 05000000 JNZ Unpacked.0048B9F6
0048B9F1  |.  E8 846CFAFF   CALL Unpacked.0043267A
0048B9F6  |>  E8 9B5CF7FF   CALL Unpacked.00401696                   ;  关键CALL
0048B9FB  |.  85C0          TEST EAX,EAX
0048B9FD  |.  0F84 17000000 JE Unpacked.0048BA1A
0048BA03  |.  E8 85D0FCFF   CALL Unpacked.00458A8D                   ;  关键CALL
0048BA08  |.  8945 F8       MOV DWORD PTR SS:[EBP-8],EAX
0048BA0B  |.  837D F8 00    CMP DWORD PTR SS:[EBP-8],0
0048BA0F  |.  0F85 05000000 JNZ Unpacked.0048BA1A
0048BA15  |.  E8 F619FDFF   CALL Unpacked.0045D410                   ;  关键CALL
0048BA1A  |>  E8 775CF7FF   CALL Unpacked.00401696
0048BA1F  |.  85C0          TEST EAX,EAX
0048BA21  |.  0F84 17000000 JE Unpacked.0048BA3E
0048BA27  |.  E8 3711FBFF   CALL Unpacked.0043CB63

发现这里一口气程序调用了好多次验证注册的算法CALL,每次关键CALL的地址都不一样,但都是调用了算法CALL。

不管它,直接运行,断下后,返回,再运行,一直来到如下代码:

0047BE6C  |.  E8 2558F8FF   CALL Unpacked.00401696                   ;  关键CALL
0047BE71  |.  85C0          TEST EAX,EAX
0047BE73  |.  0F84 DF1E0000 JE Unpacked.0047DD58                     ;  未注册就跳
0047BE79  |.  E8 FEFBFDFF   CALL Unpacked.0045BA7C

这里的JE不能让它跳。

同理,下面这个也不能让它跳:
0047BEAB  |.  3BC8          CMP ECX,EAX
0047BEAD  |.  0F8F 9D1E0000 JG Unpacked.0047DD50                     ;  不能跳
0047BEB3  |.  68 00000000   PUSH 0

一直执行到这里,这里有非常多的验证CALL与跳,非常多。多从来没有单步走完过。

 

分析到这里,就知道这个软件有非常多个,至少有一百多个重复验证注册的地址,每个验证的CALL都会调用算法CALL,算法CALL我们不能改,改了程序就不能运行。于是我们得在每一个关键CALL里面改,下面是一个关键CALL的改法。
 

由于所有的关键CALL结构类似,于是我们可以查找所有要改的地方 ,Ctrl+B,输入二进制“8B 45 EC E9”也就是
0047E4CF  |> \8B45 EC       MOV EAX,DWORD PTR SS:[EBP-14]            ;  把这里NOP掉
0047E4D2  |.  E9 00000000   JMP Unpacked.0047E4D7
这两句代码。
找到一个地方是这种结构的,就把MOV语句NOP掉,找完后再Ctrl+L继续找。这是个体力活,因为有相当多的这个要改。

这里改完后,再运行,来到有非常多的关键CALL与JNZ语句的那个地方,再单步,看是不是每个语句都改正确了,这时会发现有的CALL并没有修改到,这是因为它与我们上面查找的结构有点不同,它的结构为:
 
我们再通过搜索来找相应的所有类似的结构,搜索“8B 45 F4 E9”,找到所有的MOV 并NOP掉。

这样完成后,就达到完美破解了。

总结:查找“8B 45 F4 E9”与“8B 45 EC E9”,找到所有像:

00437F4A  |> \8B45 F4       MOV EAX,DWORD PTR SS:[EBP-C]
00437F4D  |.  E9 00000000   JMP Unpacked.00437F52
00437F52  |>  8BE5          MOV ESP,EBP
00437F54  |.  5D            POP EBP
00437F55  \.  C3            RETN

这种结构的地方,NOP掉MOV给EAX赋值的地方就OK了。
 

至于程序会弹出网站的问题,下断点“bp ShellExecuteA”,NOP掉函数调用就OK了。

破解后的程序图:

“生成”按钮的事件地址为:

0048B1A2  /.  55            PUSH EBP
0048B1A3  |.  8BEC          MOV EBP,ESP