一本电子书引出的故事
                                       kflnig
你试过用PEID扫描IDA或者OD吗? 没有,那么我来告诉你答案!borland c++写的,当在这个微软visual c++盛行的时候,是不是很惊奇啊!我也是,所以我想去了解borland c++好在何处。 所以,我去"中华电脑书库"下了一个"C++ Builder 3核心编程技术"的电子书,想学习一下。还是wdl格式的,一并去下了一个wdl阅读器。安装等此处不提。
故事便是从这里开始了……

打开,看到如图一所示的东西

 
图一

一员猛将!虽然说我并不是要修改它,但是每次都看到这么一个东西,从心理上来讲,都不爽!
^_^,这难道不是考验我的crack水准吗?

好,我们的目标是去除它的密码防改写密码!否则我学习borland c++的热情都没有了。
给大家推荐一个好工具:OD,当然不是原版的,而是fixdbg diy crack team,好东西,绝对物超所值啊!
载入看Dlview32.exe(就是那个wdl阅读器了,当然要载入它了,电子书是要通过它我们才可以看到嘛。)
OD没有说话,我是懒人,懒人往往不希望多做事情,所以我也就省去了PEID扫壳这一步,因为一般加壳的东东OD载入之后都会提示说可能被加密了等。
当然这也有一个坏处是无法看到那些程序是什么语言写的。但我相信,有朝一日你可以看着代码就知道是什么语言编写的了。
二话不说,全部下断GetWindowTextA(如果是DELPHI的,不可以下这个断点,当然这个不是DELPHI写的) 
然后在框里输入123789。
然后确定,
/*4ECC6F*/  CALL DWORD PTR DS:[<&USER32.GetWindowTextA>],在此处断下了!经过这个之后eax中的值变为6,6是什么,我们的伪码的位数啊。
/*4ECC75*/  JMP SHORT Dlview32.004ECC89
没有办法,跳就跳吧!经过一个retn之后……感觉到了重点地区!然后谨慎的走啊走……
00445DF5  |.  50            PUSH EAX                         ; /Arg1 = 0012D6F8 ASCII "123789"
00445DF6  |.  8B4D 98       MOV ECX,DWORD PTR SS:[EBP-68]    ; |
00445DF9  |.  83C1 60       ADD ECX,60                       ; |
00445DFC  |.  E8 8FD3FCFF   CALL Dlview32.00413190           ; \Dlview32.00413190
00445E01  |.  85C0          TEST EAX,EAX
00445E03  |.  75 0D         JNZ SHORT Dlview32.00445E12

当来到这里的时候OD自动给出的注释中出现了伪码,在加上
call 地址1
test eax,eax
jnz 地址2
这个经典的句型,不用我多说了吧,^_^
00445DFC这里99.9%是重点啊!好了进去吧!
这个call里面的东西好少啊!

00413190  /$  55            PUSH EBP
00413191  |.  8BEC          MOV EBP,ESP
00413193  |.  51            PUSH ECX
00413194  |.  894D FC       MOV DWORD PTR SS:[EBP-4],ECX
00413197  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]
0041319A  |.  50            PUSH EAX                         ; /Arg2
0041319B  |.  8B4D FC       MOV ECX,DWORD PTR SS:[EBP-4]     ; |
0041319E  |.  8B11          MOV EDX,DWORD PTR DS:[ECX]       ; |
004131A0  |.  52            PUSH EDX                         ; |Arg1
004131A1  |.  E8 0A000000   CALL Dlview32.004131B0           ; \Dlview32.004131B0
004131A6  |.  83C4 08       ADD ESP,8
004131A9  |.  8BE5          MOV ESP,EBP
004131AB  |.  5D            POP EBP
004131AC  \.  C2 0400       RETN 4

当我走到这里的时候代码下面的窗口如此提示:
堆栈 SS:[0012D6E4]=0012D6F8, ASCII123789")EAX=0012D6F8, (ASCII "123789")
那么那么上面类似的MOV DWORD PTR SS:[EBP-4],ECX中会是什么呢?对了也许就是密码!
命令框中输入d ecx
0012DE94  4C CD D7 01看到这个,看着分明就是又一个地址,c语言中不是又指向指针的指针的吗?
咱们在d 01D7CD4C
01D7CD4C  59 52 4C 00 30 04 8D 00                          YRL.0 ?>
看到吗?59 52 4C YRL这个尤其引起了我的注意,那么它是密码吗?答案是的。到此第一步密码找到。
现在让我们进入第二步来看看它是怎么处理密码比较的
004131A1肯定就是这里了,因为前面不是在push吗?到这个里面才有用吗!代码就在不远处

/*4131B0*/  PUSH EBP
/*4131B1*/  MOV EBP,ESP
/*4131B3*/  MOV EAX,DWORD PTR SS:[EBP+C]
/*4131B6*/  PUSH EAX
/*4131B7*/  MOV ECX,DWORD PTR SS:[EBP+8]
/*4131BA*/  PUSH ECX
/*4131BB*/  CALL Dlview32.004D6C00
/*4131C0*/  ADD ESP,8
/*4131C3*/  POP EBP
/*4131C4*/  RETN

看来还没有到关键的处理的地方,但是此刻的寄存器的值值得我们注意(^_^,OD,的复制功能就是那么好,让我些文章都方便了不少,截图都省了)。不说了吧,什么都出来了。

EAX 0012D6F8 ASCII "123789"
ECX 0012DE94
EDX 01D7CD4C ASCII "YRL"
EBX 00000001
ESP 0012D6CC
EBP 0012D6DC
ESI 00528738 Dlview32.00528738
EDI 0012DE34
EIP 004131B0 Dlview32.004131B0

相信大家也知道了这里/*4131BB*/  CALL Dlview32.004D6C00才是我们要注意的里面,F7(单步)进去。
我把关键代码贴一下。

/*4D6C05*/  PUSH EBX
/*4D6C06*/  PUSH EBP
/*4D6C07*/  XOR EBP,EBP//这句重要,得会儿我会讲到
/*4D6C09*/  PUSH ESI
……
/*4D6C64*/  MOVZX CX,BYTE PTR DS:[EDI]
/*4D6C68*/  MOV EAX,ECX
/*4D6C6A*/  INC EDI
/*4D6C6B*/  AND EAX,0FF
/*4D6C70*/  MOV DWORD PTR SS:[ESP+18],ECX
/*4D6C74*/  TEST BYTE PTR DS:[EAX+5520D1],DL
/*4D6C7A*/  JE SHORT Dlview32.004D6C97
……
/*4D6C97*/  MOVZX BX,BYTE PTR DS:[ESI]
/*4D6C9B*/  MOV EAX,EBX
/*4D6C9D*/  INC ESI
/*4D6C9E*/  AND EAX,0FF
/*4D6CA3*/  TEST BYTE PTR DS:[EAX+5520D1],DL
/*4D6CA9*/  JE SHORT Dlview32.004D6CC0
……
/*4D6CC0*/  CMP CX,BX
/*4D6CC3*/  JNZ SHORT Dlview32.004D6CCC
/*4D6CC5*/  CMP CX,BP
/*4D6CC8*/  JE SHORT Dlview32.004D6CE6
/*4D6CCA*/  JMP SHORT Dlview32.004D6C64

首先说明:EDI中是真码的地址,ESI是伪码的地址。首先把真码的第一位放到CX中,然后EDI加上一,也就是EDI指向真码的第二位了,然后跳到处理伪码的地方,方法相同,相信如果你懂一些汇编的话可以看懂。
然后来到最后来比较CX与BX不相等就玩完。
先看看这个/*4D6C07*/  XOR EBP,EBP
和这个/*4D6C64*/  MOVZX CX,BYTE PTR DS:[EDI]
以及这个01D7CD4C  59 52 4C 00        YRL.
还有这个/*4D6CC5*/  CMP CX,BP
知道我想说什么了吗,在内存中密码最后一位的后面是00,bp早已清0,它是通过一直扫描密码下去,然后判断是否到了最后到最后就结束了。
看到这里,你可以告诉我这个程序是什么语言写的吗?也许你更愿意用PEID扫一下,但是我想说我可以告诉你这个家伙很可能是C++写的。
C规定:在每一个字符串的结尾加一个“字符串结束标志”,以便系统据此判断字符串是否结束。C规定以字符’\0’作为字符串结束标志’\0’是一个anscii码为0的字符。
基础的破解到此结束,但是作为一个cracker是永远都不会满足的。我们能否打造一个对密码免疫的wdl阅读器呢?let's go!
也许你会直接做一个内存注册机,把密码显示出来由于是明文,keymake就可以完美解决的。我这个人比较懒,我已经不是第一遍说了,当然懒人总有自己的办法。

00445DFC  |.  E8 8FD3FCFF   CALL Dlview32.00413190
00445E01  |.  85C0          TEST EAX,EAX
00445E03  |.  75 0D         JNZ SHORT Dlview32.00445E12

请读者诸君暂且不要说话,疑问随它有,看到最后就都解决了。
既然这只是对返回的EAX的值进行处理,那么我们只要把这里的EAX的值改成我们想要的就可以了。当然,这个方法只是治标不治本的,治本的方法是在软件检测到又密码的时候我们欺骗它说没有加密。怎么改,首先我们要确定只有EAX为0的时候才会OK,那么,我们该怎么改。是把JNZ改成JZ,真的?当然还有更好的方法。我们应该把TEST EAX,EAX改成SUB EAX,EAX。用OD直接保存我们的这个修改版为Dlview32++.exe。这个修改方法虽然技术含量不是很高但是也是一种汇编功底,也说明了你的思维活跃,因为一般教程都是教改跳转的。好处在哪?加入有一天你的运气是在非常的好,一不小心输对了密码?那么改成JZ的方法会错,而我的这个改法是万试万灵的。现在我们在弹出如图一时的对话框时直接确定就可以了,就可以直接进去了,然后点击文件--》发现现在文件密码设置是可选的,打开看看,点击变更,如图二所示,看到这里你有什么感想,修改密码竟然不用原来的密码。
 
 
图二

好了直接确定,密码就没有了。当然这个,有点巧合了!^_^
到此破解结束。
虽然破解结束了,但是小结还是要一个:在破解软件中要加强对代码的感知程度,还有破解的方法多种多样,也就是说条条大路通罗马,还有很重要的一点brain,这是一个无论从哪里你都买不到的一个重要工具,善于学习。
最后祝天下的cracker实力越来越强。我在成长,希望你们比我成长更快!
                                              浙江省绍兴县柯桥中学高二(3)班李宁