【文章标题】: 电子书的相关破解
【文章作者】: kid
【软件名称】: 友益文书6.4.1
【下载地址】: 自己搜索下载
【加壳方式】: ASPack 2.12 -> Alexey Solodovnikov [Overlay]
【保护方式】: 自效验+不知名方式==
【编写语言】: VC2005
【使用工具】: OD
【操作平台】: XP
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
嘛,虽说这方面还算是新人,不过也想写点自己的心得,望各位大侠指点啊~~
 
原来电脑里有几本友益文书6.4.1制作的加密的电子书,可惜时间过期了,电脑也换新的了,原来的密码不能用了==
于是呼就想把它破掉,让任何电脑都能看。
 
用PEiD查壳为ASPack 2.12 -> Alexey Solodovnikov [Overlay]。附加数据在0x00075a00处,大小0x03690a98,就是电子书里的pdf数据了。
秒脱壳后,再查看是用Borland Delphi 4.0 - 5.0编写的,一运行就退出了,有自效验和日期限制么。此外这个软件还是稍稍有点麻烦的,作者做了一些手脚,程序一失去焦点就自动关闭;改了注册表的值,不能查看隐藏文件;断点设的不好就会报异常Fxx,联系作者什么的;效验不止一次等等==
 
OD载入,对CreateFile,ReadFile,SetFilePointer,GetFileSize下断点,很快就会找到放自效验值的位置,在exe文件的0x3a2处,这里的值是0x0f763ac5。当程序读入exe数据文件时,对数据下访问断点,就来到计算效验的地方了。这个程序的效验是对整个exe进行和效验。
 

代码:

  004E0F98  LEA EAX,DWORD PTR SS:[EBP-1020]            ; 存放数据的地址
  004E0F9E  XOR ECX,ECX
  004E0FA0  MOV CL,BYTE PTR DS:[EAX]
  004E0FA2  ADD DWORD PTR SS:[EBP-14],ECX              ; 逐字节累加
  004E0FA5  INC EAX
  004E0FA6  DEC EDX
  004E0FA7  JNZ SHORT 参考图.004E0F9E
  004E0FA9  DEC EBX
  004E0FAA  JNZ SHORT 参考图.004E0F72
  004E0FAC  SUB DWORD PTR SS:[EBP-14],7B
  004E0FB0  LEA EAX,DWORD PTR SS:[EBP-12B8]
  004E0FB6  CALL 参考图.0040663C
  004E0FBB  CALL 参考图.00402874
  004E0FC0  CMP DWORD PTR SS:[EBP-C],0
  004E0FC4  JNZ SHORT 参考图.004E0FE8
  004E0FC6  MOV EAX,DWORD PTR SS:[EBP-1C]              ; 原先读入的效验值
  004E0FC9  CMP EAX,DWORD PTR SS:[EBP-14]              ; 计算得到的效验值
  004E0FCC  JNZ SHORT 参考图.004E0FE1                  ; 不相同就挂了
  004E0FCE  MOV EBX,1
  004E0FD3  MOV EAX,DWORD PTR SS:[EBP-4]
  004E0FD6  INC BYTE PTR DS:[EAX+14534]

 
断在004E0FC6处,会发现原先读入的效验值并不等于一开始读入的,变成0x0f763c49。于是重来,读入效验值后设内存访问断点,到这里
 
代码:

  004E0DE5  XOR EAX,EAX
  004E0DE7  MOV AL,BYTE PTR SS:[EBP-20]
  004E0DEA  ADD EAX,DWORD PTR SS:[EBP-1C]              ;  加上效验值的每个字节
  004E0DED  XOR EDX,EDX
  004E0DEF  MOV DL,BYTE PTR SS:[EBP-1F]
  004E0DF2  ADD EAX,EDX
  004E0DF4  XOR EDX,EDX
  004E0DF6  MOV DL,BYTE PTR SS:[EBP-1E]
  004E0DF9  ADD EAX,EDX
  004E0DFB  XOR EDX,EDX
  004E0DFD  MOV DL,BYTE PTR SS:[EBP-1D]
  004E0E00  ADD EAX,EDX
  004E0E02  MOV DWORD PTR SS:[EBP-1C],EAX

 
这下明白了,exe文件的0x3a2处存放的效验值是后来加进去的,即原先这里为0的时候做的文件效验值。程序在运行时读取整个文件,就多加了这4个字节,所以要补上。
 
好,接下来破解日期限制。遗憾的是对GetLocalTime等下断,都没有截获,作者究竟是咋取得时间的呢?这时偶想到了参考字符串,函数可以变形,不过参数总不能变吧。搜索超级字符串参考,果然找到了yyyy-mm-dd,2006-08-10,2004-10-01,2006-07-10,2004-8-22。双击yyyy-mm-dd可以来到获取时间的地方。
 
代码:

  004C902F  ADD ESP,-8                                        ; /
  004C9032  FSTP QWORD PTR SS:[ESP]                           ; |Arg1 (8 字节)
  004C9035  WAIT                                              ; |
  004C9036  LEA EAX,DWORD PTR SS:[EBP-4]                      ; |
  004C9039  MOV EDX,参考图.004C9420                           ; |ASCII "yyyy-mm-dd"
  004C903E  CALL 参考图.0040B6AC                              ; \参考图.0040B6AC

 
 
单步执行后,EAX里返回存放日期的地址。崩管了,随便选个2006-08-10,就可到达判断的地方。
 
代码:

  004C90E1  MOV EAX,DWORD PTR SS:[EBP-4]
  004C90E4  MOV EDX,参考图.004C9434                              ;  ASCII "2006-08-10"
  004C90E9  CALL 参考图.0040405C
  004C90EE  JA SHORT 参考图.004C90FF                             ;  大于则挂
  004C90F0  MOV EAX,DWORD PTR SS:[EBP-4]
  004C90F3  MOV EDX,参考图.004C9448                              ;  ASCII "2004-10-01"
  004C90F8  CALL 参考图.0040405C
  004C90FD  JNB SHORT 参考图.004C9152                            ;  小于也挂
  

下面还有处判断就省略了。好,到这里应该是爆破成功了,修改后运行!结果连输入密码的对话框都没弹出,软件启动后变成制作模式,而非阅读模式了,无论加不加附加数据都这样。看了论坛里stasi转Lenus的浅谈脱壳中的附加数据问题(overlay)一文,改了疑似指向附加数据指针的地方,还是不行。看来只有用内存补丁了,这样连效验都可省了。
 
用dup2.14final先做个内存补丁,把上面两处日期判断的改了就行,一个nop掉,一个直接jmp,运行源exe后终于出现了输入密码对话框。为了爆破密码,还是得用OD,以上几处只有在OD里先手动改了。
机器码是在什么时候生成的呢?还是用偷懒的办法,输入密码窗口有机器码的字符,在字符串中搜索,然后对引用的地方下断,运行程序,输完第一个密码后程序就断下了(这本电子书有两到密码,一个是打开密码,一个是阅读密码,阅读密码是和机器码匹配的)。
 
代码:

  004CA590  MOV EAX,DWORD PTR SS:[EBP-4]
  004CA593  MOV ECX,DWORD PTR DS:[EAX+1003A4]                ; (初始 cpu 选择)
  004CA599  LEA EAX,DWORD PTR SS:[EBP-8]
  004CA59C  MOV EDX,参考图.004CAAE4                          ;   机器码:
  004CA5A1  CALL 参考图.00403F98

 
看寄存器窗口,ECX里放的正是机器码的地址,得来全不费功夫啊。换成旧电脑的机器码,运行,输入已知的密码,OK!终于看到久违了的电子书了~~
 
同样方法运行另一本电子书,发现每次存放机器码的地址都不一样,这样的话现成的内存补丁制作机就不好用了(ms都是改固定地址指令的)。那就自己做个loader吧。参看了密界宝典《软件加密 技术内幕》一书,做了个相当于针对此软件的小型调试程序。
 
创建debug的进程,在固定位置写入已改过的代码(只是日期那部分的判断就够了)。程序里没有判断什么时候壳解压完毕,而是在有DebugEvent事件时读取内存,如果是已解压后的代码,则改之,同时对第二道密码输入窗口下断点。当输入完第一道密码,在显示机器码之前,程序会断下,我们偷梁换柱,改成旧的机器码,在输入已知配对的密码,就大功告成了~~
 
到此应该算是Crack完毕,不过还有点缺陷。那么一长串的密码,要是能自动输入就好了。于是先用OD查看窗口,找到控件的类名:TEdit。在程序中用FindWindow、FindWindowEx找到句柄后发送WM_SETTEXT消息就搞定了。用自己做的loader运行电子书,连点两个确定后就可以阅读了,真爽~~ 
 
 
 
 
--------------------------------------------------------------------------------
【经验总结】
电子书之类的相关软件建议还是用内存补丁好了,毕竟有时候它的效验、密码和防破解手段还是比较麻烦的。如果有对内存、代码进行效验的话,还得找到存放这些效验值的地方,写入新的效验值。不知道程序用了哪些函数或找不到位置时,不妨试试找找它的参数,也许会事半功倍~~
 
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
 
2006年05月20日 14:25:41
 
 
附loader的源代码,平时潜水多了,还米上传附件权限,只好放MO上了==
下载地址:http://pickup.mofile.com/8668655597914286 1.82KB
 
 
 
 
PS1:本来是想把密码判断和机器码的生成算法也一起爆掉的,可是无论是设消息断点、run跟踪还是内存断点,停下后的代码都不好观察。不知是作者故意的还是Delphi编译后的程序就是这样,没有几处完整顺畅的代码,总是不停的call呀call,要不就是je、jnz等之类,弄的我头都晕了, 还是米弄清它是怎么判断的。不知有哪位大侠研究过这个软件的机器码生成和密码判断方式,还望指教啊。
 
PS2:后来又从另一方面入手,研究附加数据文件的打包、存储格式,做了个类似资源提取器的东东。附加数据的打包格式还是比较清楚的,文件都是用zlib压缩的,大于2mb的都分段压了(见图)
 
http://i146.photobucket.com/albums/r257/kidkid23/un.jpg
 
每个文件以00000000分割,0x30长度的文件名(作者打包时换成了一串无意义的数字==),我没找到放原始文件的地方,可能没有吧,所以提取出来的pdf文件名也是一串无意义的数字。