第 3 节
作者:雨来不躲      更新:2022-08-10 08:35      字数:5296
  离线浏览器自动引导web browser进入每个页面,每进入一个页面,都通过web browser控件获取客户端HTML源代码及页面元素,包括图片、css、js、flash等。
  采用这种方法实现的离线浏览器,由于使用web browser控件,因此可以维持客户端session,抓取到动态网页。虽然网页抓取下来就成了静态的,但是对离线浏览来说应该不成问题,对付收费的网上教育等网站正好合适。
  2。3 HLP格式
  这种格式出现得比较早,在16位Windows(Windows 95以前的各Windows版本)下曾是标准的帮助文件格式,因此大概也算是Windows下出现得最早的电子书格式之一了。
  由于这种格式比较流行,国外研究的也比较多,不过公开源代码的我似乎只见过一个HELPDECO v2。1。这个软件是一个控制台程序,因此有人做了一个GUI外壳DuffOS对它进行封装。国内有人对HELPDECO进行过汉化,到汉化新世纪搜索一下就可以找到,包括全部源代码。
  在UnEBook中使用了HELPDECO的源代码,实现对HLP文件的批量反编译。不过从我使用的情况看,原版HELPDECO有一个小小的不足:反编译出来的RTF文件没有指定字符集。这对英文RTF来说没有任何影响,但是对中文RTF来说,其影响足够强到使您打开RTF后看到的是一堆乱码。它的修正方法有两个:
  用文本编辑器打开反编译出来的RTF文件,手工指定中文字符集。这个是一种比较累的方法。
  修改HELPDECO源代码,加上字符集修正,这个是一劳永逸的办法。但是不知道为什么,在汉化新世纪推出的汉化版上,我看到的还是原版的HELPDECO。看来汉化者只是用它反编译过英文HLP,没有反编译过中文HLP。
  另外这份源代码还有一个不知道算不算是严重的问题:变量没有统一初始化、释放,因此不仅在程序退出的时候,VC++会报告有内存漏洞,而且就象当年的DOS内核一样,几乎没有可重入性。我曾经试图修复这个bug,但是在经过一个下午的奋斗后,有两处泄漏死活找不到。最后我还是决定向DuffOS学习:将HELPDECO代码封装成一个独立的DLL,每反编译一个HLP文件,都动态加载、释放一次DLL。这样一方面可以利用Windows本身的DLL管理机制,弥补HELPDECO产生的内存漏洞,一方面解决不可重入问题。收费的“耶书制造”软件提供的HLP反编译功能也是用DLL文件实现的,因此我严重怀疑它的作者可能也曾遇到过相同的烦恼,嘿嘿嘿……
  从HLP文件反编译出来的RTF文件,一般包含大量书签、分页符等与实际文本内容无关的东西,有必要转换成纯文本格式。这个实现倒是比较简单:
  创建一个Windows标准的RichEdit控件,当然没有必要在用户界面上显示出来。
  按SF_RTF格式,StreamIn原RTF文件内容。
  按SF_TEXT格式,StreamOut文本内容。
  UnEBook提供的从RTF到TXT的批量转换功能,就是按照上面的方法实现的。
  2。4 小说网/小说世界(ebx/XReader)
  这两家网站提供的电子书使用的是同一个阅读器,只不过小说网出现得比较早,提供的电子书多半不需要验证码,而小说世界出现得比较晚,提供的电子书多半需要输入验证码。
  这种电子书分两种:ebx和EXE格式。ebx格式的电子书需要用专用浏览器XReader才能浏览,EXE文件的内容其实就是XReader + ebx包构成。
  国内Cyu曾经推出过反编译这种EXE格式的工具--xReader Unpacker。从我试用的情况来看,这个工具的实现应该是基于对EXE文件格式的辛苦分析,果然勤劳善良的中国人什么时候都有啊!不过从我试用的结果看,这个工具也存在下列问题:
  一次只能反编译一个文件,不能批量反编译,使用起来略有不便。
  反编译出来的文件用左侧目录树中对应的节点命名,完全失去了文件的先后顺序。
  在反编译某些文件,如《血酬定律中国历史中的生存游戏》的时候,会出错退出。我个人猜想可能是因为对书中多级目录处理不当。
  奇怪得很,只能对EXE文件进行反编译,不能对ebx文件反编译,其实这两种文件本是两位一体的。
  当然,我试用的只是最初版本的xReader Unpacker,后来听说作者又进行了更新,这些问题都解决了也说不定。
  在考虑反编译这种格式的电子书的时候,因为我已经在思考针对IE内核的通用反编译方法,因此从一开始我就没打算对文件格式进行分析,而是打算从界面元素入手,看看有没有什么后面可走:
  先用IECracker抓一下窗口,发现根本就不是基于IE内核的东西。这个时候首先想到的就是:软件作者会不会向起点中文网学习,将内容转换成图片,然后再显示?但是很快就否定了这个可能,一方面是因为XReader提供了文字放大、缩小功能,另一方面是因为启动金山词霸后,将光标往窗口上一放,词霸显示出了抓词内容。这个时候脑袋里一闪念间,也曾出现过一个反编译方案:干脆向金山词霸学习,做一个API hook,抓它的显示内容算了,哈哈……
  在确定XReader显示的东西不是图片后,我就启动SPY++,打算看看XReader的显示窗口用的是什么东西。但是查看的结果令人惊奇:每启动一次XReader,显示窗口的class name就会变化一次,是一个完全随机的字符串,从上面根本看不出这个窗口使用了什么控件。
  再多看几本电子书后,我发现所有电子书都有一个特点:完全没有图片,清一色都是纯文本,但是鼠标放到窗口上的时候,光标不会变成通常文本窗口的插入光标(一条竖线),还是箭头光标。到这个时候,我已经开始准备相信软件作者完全继承了国人勤劳善良的光荣传统,自己写了一个文本输出控件了。……且慢,为什么在打开这个大文件的时候光标会闪一下,从竖线变成箭头?再前后动动鼠标滚轮看看,每次不多不少,正好滚动3行,这个不是RichEdit控件的特性之一吗?!
  立刻启动SPY++,这次不看class name了,改看消息流。果然每次点击左侧目录树,都会向右侧显示窗口发送一堆RichEdit控件的消息:EM_SETBKGNDCOLOR(设置窗口背景色)、EM_SETCHARFORMAT(设置光标形状)、EM_SETMARGINS(设置左右页边距)、EM_STREAMIN(导入显示内容)。
  既然已经确定右侧显示区用的是一个标准的RichEdit控件,而左侧目录树是一个标准的TreeCtrl控件,那么反编译方案其实也就出来了:周游左侧目录树,依次选中每个节点,然后拦截右侧RichEdit控件的输出,写入文件即可。
  不过在搞清楚XReader的原理后,我也产生了一个疑问:RichEdit控件本身是可以同时显示文本、图片的(RTF格式),但是为什么XReader只显示纯文本,不显示图片呢?要知道这样可是会使做出来的电子书增色不少。开始我以为是为了保密,象我自己一开始不也差点误入歧途?如果不是偶然看到光标闪烁,再动动鼠标滚轮,可能我一时也想不起来他用的是标准RichEdit控件。后来在看到早期版本的XReader后,我想更大的可能是为了兼容:早期版本用WM_SETTEXT传递显示信息,只能显示纯文本,后来才改用EM_STREAMIN的。
  总结一下,XReader中采取了下列措施防拷贝、防反编译:
  随机更改RichEdit控件的class name,防止被人识破。
  对光标形状进行设置,一方面防止被人识破使用的是RichEdit,一方面避免用鼠标选择、复制内容。
  对WM_COPY、WM_GETTEXT、EM_STREAMOUT等等消息进行了过滤,因此直接从窗口获得文本内容就不要想了。
  可惜,微软提供的RichEdit控件是用于开放环境的,一旦被识破,用微软本身提供的接口就足以搞到所需的内容了。
  后来看到小说网早期放出来的EXE格式电子书,才发现XReader这个软件也是不断发展的,而版本升级的目的主要就是为了加强安全性,ebx格式本身却没有什么变化,一直很稳定,新的ebx文件也可以用老的XReader打开:
  早期版本的XReader支持用命令行参数的方式,传入需要打开的ebx文件路径,这样容易被人利用,实现文件自动打开。后来版本的XReader就只能通过菜单或工具条,点“打开电子书”才能打开文件。当然这个限制也不是不可以突破,不过毕竟没有用命令行参数传递这么方便。
  早期版本的XReader其实就使用WM_SETTEXT消息显示文本。如果早点看到这个版本的电子书,说不定我还可以少费点周折。后来版本改用EM_STREAMIN,估计一方面是为了保密,另一方面是为了速度和性能:在显示大文件的时候,EM_STREAMIN比WM_SETTEXT快得多;EM_STREAMIN可以显示RTF文件,而WM_SETTEXT只能显示文本文件;EM_STREAMIN可以显示大型文件,而WM_SETTEXT支持的文件长度是有限的。
  3。 结论
  就像信息安全中的攻与防一样,电子书的编译与反编译之间的斗争也将是一个永无止境的死循环。我相信不论电子书反编译技术如何发展,都不会导致电子书的绝迹,毕竟有实际的需要。但是本文的发表,毫无疑问将会刺激电子书制作软件和制作技术的新一轮升级。那么我的文章和软件会不会随之升级呢?我自己是没什么自信啦,毕竟我的自由时间越来越少,而如果没有其他人愿意象我这样研究反编译技术和软件(收费的免谈),我想最终胜利的一定是有商业利益支撑的电子书制作软件。
  先分析电子书的详细文件格式,再有针对性推出专用反编译器的方法,在初期确实是一个不错的方法,但是随着电子书格式的增多,如果每一种都要去分析一遍,早晚会累死。
  电子书制作软件其实也是人开发的,开发者当然也会有人类的通病——懒!只要有现成的东西可用,很少有人会再花力气去修练自己的独门功夫。而目前Windows下的东西,开放性的考虑要比安全性的考虑更多一些,如果能够找到这些东西的突破口,即可突破同一类使用这些东西的电子书。
  利用现成控件的接口或漏洞,实现通用电子书反编译,这其实也是程序员懒惰的一种体现。这种方法虽然比老老实实分析、跟踪电子书简单许多,但是也有其天然缺陷:只能反编译显示到控件中的内容。通俗一点说,如果电子书是加密码保护的,那么这种方法并不能在不知道密码的情况下,反编译出电子书的内容。
  附录 基于IE内核电子书的实现方式探讨
  电子书看多了,有时候我也会想,如果是我自己做一个电子书制作工具,我会采用什么样的技术加以实现?考虑到现在HTML格式文档的普遍性,在有人开放出新的HTML render之前,我的想法还是只能围绕IE内核打转。下面就是我想到的一些思路。
  1、基于res协议
  res协议是IE内核提供的一种非常简单的协议,允许将需要浏览的页面存放在EXE或DLL的资源(resource)中,IE根据URL定位EXE或DLL,装载其中的资源。下面这个URL就是这种协议的一个例子:
  res://C:WINNTsystem32shdoclc。dll/http_404。htm
  如果您在IE中要浏览的页面不存在,IE就会通过这个URL,打开C:WINNTsystem32shdoclc。dll,查找其中名为http_404。htm的资源,找到后提取、显示出来,您看到的就是一个提示页面不存在的网页。
  从上面这个页面的源代码可以看到,除HTML代码外,res协议还允许在页面中包含图片等内容,如上面这个页面就显示了一个名为pagerror。gif的图片,其绝对URL为res://C:WINNTsystem32shdoclc。dll/pagerror。gif。
  虽然res协议非常简单,基本上不需要额外的编程,但是我目前还没有看到有人用它做电子书,最多只看到有人用它显示软件的About信息。仔细想想,可能是因为这种协议太不保密了:随便找一个资源编辑器,就可以直接获取、替换资源内容了。
  2、基于文件方式
  这种方式的思路其实非常简单:需要显示网页的时候,先将网页解压缩到临时目录,然后用IE控件显示,退出的时候删除临时文件。
  这种方式我早就知道,但是因为它实在是太简单了,所以连我自己都不相信有人真的会用它做电子书,直到我见到雄风网的电子书:这个网站早期发行的电子书,虽然要求用户输入密码进行验证,但是在密码输对以后,就会把全部内容解压缩到temp目录下,然后用IE控件打开文件进行浏览。虽然temp目录下的文件属性被设置为隐藏,但是这点小伎俩实在不值一提,所以只要破解了认证密码,电子书本身就已经提供了完整的反?