常見電子書格式及其反編譯思路分析
更新時間:2008年07月17日 23:41:04 作者:
本文僅僅從技術角度討論電子書反編譯問題,請勿將之用于侵犯版權等等非法目的,或損害他人利益。如果您對此感到失望,請勿繼續(xù)閱讀。
從HLP文件反編譯出來的RTF文件,一般包含大量書簽、分頁符等與實際文本內容無關的東西,有必要轉換成純文本格式。這個實現(xiàn)倒是比較簡單:
創(chuàng)建一個Windows標準的RichEdit控件,當然沒有必要在用戶界面上顯示出來。
按SF_RTF格式,StreamIn原RTF文件內容。
按SF_TEXT格式,StreamOut文本內容。
UnEBook提供的從RTF到TXT的批量轉換功能,就是按照上面的方法實現(xiàn)的。
2.4 小說網/小說世界(ebx/XReader)
這兩家網站提供的電子書使用的是同一個閱讀器,只不過小說網出現(xiàn)得比較早,提供的電子書多半不需要驗證碼,而小說世界出現(xiàn)得比較晚,提供的電子書多半需要輸入驗證碼。
這種電子書分兩種:ebx和EXE格式。ebx格式的電子書需要用專用瀏覽器XReader才能瀏覽,EXE文件的內容其實就是XReader + ebx包構成。
國內Cyu曾經推出過反編譯這種EXE格式的工具--xReader Unpacker。從我試用的情況來看,這個工具的實現(xiàn)應該是基于對EXE文件格式的辛苦分析,果然勤勞善良的中國人什么時候都有??!不過從我試用的結果看,這個工具也存在下列問題:
一次只能反編譯一個文件,不能批量反編譯,使用起來略有不便。
反編譯出來的文件用左側目錄樹中對應的節(jié)點命名,完全失去了文件的先后順序。
在反編譯某些文件,如《血酬定律--中國歷史中的生存游戲》的時候,會出錯退出。我個人猜想可能是因為對書中多級目錄處理不當。
奇怪得很,只能對EXE文件進行反編譯,不能對ebx文件反編譯,其實這兩種文件本是兩位一體的。
當然,我試用的只是最初版本的xReader Unpacker,后來聽說作者又進行了更新,這些問題都解決了也說不定。
在考慮反編譯這種格式的電子書的時候,因為我已經在思考針對IE內核的通用反編譯方法,因此從一開始我就沒打算對文件格式進行分析,而是打算從界面元素入手,看看有沒有什么后面可走:
先用IECracker抓一下窗口,發(fā)現(xiàn)根本就不是基于IE內核的東西。這個時候首先想到的就是:軟件作者會不會向起點中文網學習,將內容轉換成圖片,然后再顯示?但是很快就否定了這個可能,一方面是因為XReader提供了文字放大、縮小功能,另一方面是因為啟動金山詞霸后,將光標往窗口上一放,詞霸顯示出了抓詞內容。這個時候腦袋里一閃念間,也曾出現(xiàn)過一個反編譯方案:干脆向金山詞霸學習,做一個API hook,抓它的顯示內容算了,哈哈……
在確定XReader顯示的東西不是圖片后,我就啟動SPY++,打算看看XReader的顯示窗口用的是什么東西。但是查看的結果令人驚奇:每啟動一次XReader,顯示窗口的class name就會變化一次,是一個完全隨機的字符串,從上面根本看不出這個窗口使用了什么控件。
再多看幾本電子書后,我發(fā)現(xiàn)所有電子書都有一個特點:完全沒有圖片,清一色都是純文本,但是鼠標放到窗口上的時候,光標不會變成通常文本窗口的插入光標(一條豎線),還是箭頭光標。到這個時候,我已經開始準備相信軟件作者完全繼承了國人勤勞善良的光榮傳統(tǒng),自己寫了一個文本輸出控件了?!衣?,為什么在打開這個大文件的時候光標會閃一下,從豎線變成箭頭?再前后動動鼠標滾輪看看,每次不多不少,正好滾動3行,這個不是RichEdit控件的特性之一嗎?!
立刻啟動SPY++,這次不看class name了,改看消息流。果然每次點擊左側目錄樹,都會向右側顯示窗口發(fā)送一堆RichEdit控件的消息:EM_SETBKGNDCOLOR(設置窗口背景色)、EM_SETCHARFORMAT(設置光標形狀)、EM_SETMARGINS(設置左右頁邊距)、EM_STREAMIN(導入顯示內容)。
既然已經確定右側顯示區(qū)用的是一個標準的RichEdit控件,而左側目錄樹是一個標準的TreeCtrl控件,那么反編譯方案其實也就出來了:周游左側目錄樹,依次選中每個節(jié)點,然后攔截右側RichEdit控件的輸出,寫入文件即可。
不過在搞清楚XReader的原理后,我也產生了一個疑問:RichEdit控件本身是可以同時顯示文本、圖片的(RTF格式),但是為什么XReader只顯示純文本,不顯示圖片呢?要知道這樣可是會使做出來的電子書增色不少。開始我以為是為了保密,象我自己一開始不也差點誤入歧途?如果不是偶然看到光標閃爍,再動動鼠標滾輪,可能我一時也想不起來他用的是標準RichEdit控件。后來在看到早期版本的XReader后,我想更大的可能是為了兼容:早期版本用WM_SETTEXT傳遞顯示信息,只能顯示純文本,后來才改用EM_STREAMIN的。
總結一下,XReader中采取了下列措施防拷貝、防反編譯:
隨機更改RichEdit控件的class name,防止被人識破。
對光標形狀進行設置,一方面防止被人識破使用的是RichEdit,一方面避免用鼠標選擇、復制內容。
對WM_COPY、WM_GETTEXT、EM_STREAMOUT等等消息進行了過濾,因此直接從窗口獲得文本內容就不要想了。
可惜,微軟提供的RichEdit控件是用于開放環(huán)境的,一旦被識破,用微軟本身提供的接口就足以搞到所需的內容了。
后來看到小說網早期放出來的EXE格式電子書,才發(fā)現(xiàn)XReader這個軟件也是不斷發(fā)展的,而版本升級的目的主要就是為了加強安全性,ebx格式本身卻沒有什么變化,一直很穩(wěn)定,新的ebx文件也可以用老的XReader打開:
早期版本的XReader支持用命令行參數的方式,傳入需要打開的ebx文件路徑,這樣容易被人利用,實現(xiàn)文件自動打開。后來版本的XReader就只能通過菜單或工具條,點“打開電子書”才能打開文件。當然這個限制也不是不可以突破,不過畢竟沒有用命令行參數傳遞這么方便。
早期版本的XReader其實就使用WM_SETTEXT消息顯示文本。如果早點看到這個版本的電子書,說不定我還可以少費點周折。后來版本改用EM_STREAMIN,估計一方面是為了保密,另一方面是為了速度和性能:在顯示大文件的時候,EM_STREAMIN比WM_SETTEXT快得多;EM_STREAMIN可以顯示RTF文件,而WM_SETTEXT只能顯示文本文件;EM_STREAMIN可以顯示大型文件,而WM_SETTEXT支持的文件長度是有限的。3. 結論
就像信息安全中的攻與防一樣,電子書的編譯與反編譯之間的斗爭也將是一個永無止境的死循環(huán)。我相信不論電子書反編譯技術如何發(fā)展,都不會導致電子書的絕跡,畢竟有實際的需要。但是本文的發(fā)表,毫無疑問將會刺激電子書制作軟件和制作技術的新一輪升級。那么我的文章和軟件會不會隨之升級呢?我自己是沒什么自信啦,畢竟我的自由時間越來越少,而如果沒有其他人愿意象我這樣研究反編譯技術和軟件(收費的免談),我想最終勝利的一定是有商業(yè)利益支撐的電子書制作軟件。
先分析電子書的詳細文件格式,再有針對性推出專用反編譯器的方法,在初期確實是一個不錯的方法,但是隨著電子書格式的增多,如果每一種都要去分析一遍,早晚會累死。
電子書制作軟件其實也是人開發(fā)的,開發(fā)者當然也會有人類的通病——懶!只要有現(xiàn)成的東西可用,很少有人會再花力氣去修練自己的獨門功夫。而目前Windows下的東西,開放性的考慮要比安全性的考慮更多一些,如果能夠找到這些東西的突破口,即可突破同一類使用這些東西的電子書。
利用現(xiàn)成控件的接口或漏洞,實現(xiàn)通用電子書反編譯,這其實也是程序員懶惰的一種體現(xiàn)。這種方法雖然比老老實實分析、跟蹤電子書簡單許多,但是也有其天然缺陷:只能反編譯顯示到控件中的內容。通俗一點說,如果電子書是加密碼保護的,那么這種方法并不能在不知道密碼的情況下,反編譯出電子書的內容。
附錄 基于IE內核電子書的實現(xiàn)方式探討
電子書看多了,有時候我也會想,如果是我自己做一個電子書制作工具,我會采用什么樣的技術加以實現(xiàn)?考慮到現(xiàn)在HTML格式文檔的普遍性,在有人開放出新的HTML render之前,我的想法還是只能圍繞IE內核打轉。下面就是我想到的一些思路。
1、基于res協(xié)議
res協(xié)議是IE內核提供的一種非常簡單的協(xié)議,允許將需要瀏覽的頁面存放在EXE或DLL的資源(resource)中,IE根據URL定位EXE或DLL,裝載其中的資源。下面這個URL就是這種協(xié)議的一個例子:
res://C:\WINNT\system32\shdoclc.dll/http_404.htm
如果您在IE中要瀏覽的頁面不存在,IE就會通過這個URL,打開C:\WINNT\system32\shdoclc.dll,查找其中名為http_404.htm的資源,找到后提取、顯示出來,您看到的就是一個提示頁面不存在的網頁。
從上面這個頁面的源代碼可以看到,除HTML代碼外,res協(xié)議還允許在頁面中包含圖片等內容,如上面這個頁面就顯示了一個名為pagerror.gif的圖片,其絕對URL為res://C:\WINNT\system32\shdoclc.dll/pagerror.gif。
雖然res協(xié)議非常簡單,基本上不需要額外的編程,但是我目前還沒有看到有人用它做電子書,最多只看到有人用它顯示軟件的About信息。仔細想想,可能是因為這種協(xié)議太不保密了:隨便找一個資源編輯器,就可以直接獲取、替換資源內容了。
2、基于文件方式
這種方式的思路其實非常簡單:需要顯示網頁的時候,先將網頁解壓縮到臨時目錄,然后用IE控件顯示,退出的時候刪除臨時文件。
這種方式我早就知道,但是因為它實在是太簡單了,所以連我自己都不相信有人真的會用它做電子書,直到我見到雄風網的電子書:這個網站早期發(fā)行的電子書,雖然要求用戶輸入密碼進行驗證,但是在密碼輸對以后,就會把全部內容解壓縮到temp目錄下,然后用IE控件打開文件進行瀏覽。雖然temp目錄下的文件屬性被設置為隱藏,但是這點小伎倆實在不值一提,所以只要破解了認證密碼,電子書本身就已經提供了完整的反編譯功能了。
該網站后來發(fā)行的電子書雖然經過升級,但還是延續(xù)了這種模式,只不過在temp目錄里存放的是加過密的HTML文件,但是圖像文件卻是不加密的,因此我猜測他們可能改用MIME Filter技術了。
3、基于流或document.write方法
用流往IE控件中寫入內容的方法,在MSDN和CSDN中都有詳細的討論,連源代碼都有。有需要的到MSDN搜索“Loading HTML content from a Stream”即可。
document.write在動態(tài)網頁中比較常用,很多網頁加密工具都是使用這招來實現(xiàn)網頁源代碼的隱藏。對于VC、Delphi等來說,這招不過是換成了IHTMLDocument2::write,效果是一樣的。
使用這種方法做電子書的雖然不多,不過畢竟還是有的,我見過的就是讀寫網。由于打開這個網站的電子書后,IE主頁就會自動設置為這個網站的URL,所以在這里就不給出這個網站的URL了,以免各位受到意外傷害。破解這種電子書的收費驗證的方法,已經有人在紫宸殿網絡論壇的技術區(qū)貼出來過,有興趣的可以去看看。
在MSDN中對這種基于流的方法的局限性說得很清楚:
頁面不能太復雜,如果頁面包含的tag太多,顯示出來的就不是解析后生成的頁面,而是原始的HTML代碼。大概就是因為這個原因,所以讀寫網放出來的電子書清一色都只有純文本,加背景色。
當前頁面的URL永遠不變(讀寫網的永遠都是about:blank),因此IE內核沒有辦法從相對URL自動構造出絕對URL。就是因為這個原因,讀寫網早期的電子書在頁面中使用jpg文件作為背景,就只能將這個背景圖片寫到temp目錄下,然后在網頁中使用絕對URL引用這個圖片。也正是因為這個原因,所以在頁面中不能包含“上一頁”、“下一頁”、“回目錄”等鏈接,只能自己在左側放一棵目錄樹,讓用戶一頁、一頁去點。
由于這種電子書的頁面沒有自己的URL,因此不能用KillEBook進行反編譯,只能用IECracker或CtrlN,一頁、一頁手工抓取。
4、采用MIME Filter
與基于流的方法相比,這種方法不僅支持包含眾多tag的復雜HTML頁面,而且可以從相對URL構造絕對URL,因此支持頁面之間的鏈接,實現(xiàn)也不復雜,MSDN上就有現(xiàn)成的例子可供參考。
不過這種方法的缺點也很明顯:不能對圖像等內容進行加密處理。下面說的協(xié)議插件方法就比這種方法強些。
5、基于web服務器
對于不懂行的人來說,“web服務器”聽起來可能是一個很了不起的東東,但是對于懂行的人來說,實現(xiàn)其實很簡單:
起一個監(jiān)聽線程,對本地80或任何一個指定的端口進行監(jiān)聽。
每監(jiān)聽到一個連接請求,起一個服務線程,根據請求內容,按照HTTP協(xié)議,返回內容。
在codeguru和codeproject上,有很多現(xiàn)成的web server代碼,直接拿來用就好,自己只要考慮怎么填寫返回內容即可。VC 6自帶的MSDN光盤上,也帶了一個名為HTTPSVR的例子,說明如何用MFC和WinSock創(chuàng)建web server。
使用這種方法雖然簡單、直截了當,而且只要愿意,差不多能夠模擬一個真正web server的功能(就算想實現(xiàn)app server也并非不可能,不過要花點功夫),但是也有問題:
基本上沒有什么保密性可言,服務器起來后,本機其它進程很輕松就能下載到需要的內容。
如果本機上其它進程也提供TCP/IP服務,可能會產生端口沖突。
6、協(xié)議插件(Asynchronous Pluggable Protocols)
這個是微軟專門為IE擴展的東西。
在互聯(lián)網上,常見的應用層協(xié)議包括http、FTP等。出于種種原因,微軟允許用戶在標準的應用層協(xié)議之外,擴展自己的協(xié)議,稱為Asynchronous Pluggable Protocol。到MSDN、codeguru和codeproject上搜索這幾個關鍵字,從理論到源代碼都能找出一堆,在這里我就不羅嗦了。
Asynchronous Pluggable Protocol可以指定對所有進程有效,這個在注冊表的HKEY_CLASSES_ROOT\PROTOCOLS\Handler下注冊一下就好;也可以指定只在某個進程內有效,以增加保密性,不過這個時候微軟就不叫它Asynchronous Pluggable Protocol了,而是Pluggable Namespace Handler。
由于Asynchronous Pluggable Protocol具有一定的保密性,實現(xiàn)起來又有例子可參考,而且差不多與架設web server一樣,能夠對網頁顯示提供全面的支持,因此在電子書中得到了廣泛的應用,我見過的就有mk(chm)、ada99(eBook Workshop)、wc2p(Web Compiler 2000)、ic32pp(Web Compiler 2000—exe防反編譯格式)、e-book(E-Book Creator)、mec(E-ditor eBook Compiler)等。不過這種技術如果使用不好,可能會在注冊表中產生垃圾,或產生垃圾文件(插件本身是一個COM控件,一般用DLL實現(xiàn),使用前必須在注冊表中注冊)。
7、最后一招
即使使用Asynchronous Pluggable Protocol,由于在IE內核中還存在可顯示的HTML源代碼,因此還是存在被導出的可能,這個就是上面正文里討論了半天的東西。
我想到的最后一招制作防反編譯的電子書的辦法就是:在制作的時候,將所有頁面內容全部轉換成圖片,然后再打包。將網頁轉換成圖片的源代碼參見這里:
http://www.codeproject.com/internet/htmlimagecapture.asp
使用這種方法,在拿到一本制作好的電子書后,想得到原始文本信息的方法大概只有兩個:OCR和key in。這個也可以用起點中文網的方法來對付:使用手寫體,加水印,故意增加錯別字或替換標點符號等。據傳說,起點就是根據用戶ID,生成錯別字和錯誤標點的,因此如果是原樣key in或OCR,就可能被查出來。
但是回頭一想,如果哪個電子書制作工具真的走到了這一步,大概也就離消亡不遠了,用戶還不如直接去做PDF:
所有動態(tài)效果全部沒有,頁面上的鏈接也全部失效,大概又只能靠在左側放一棵目錄樹才能導航了。
頁面大小、字符大小基本固定,顯示的時候很難放大、縮小,尤其是放大的時候,要么速度比較慢,要么必須忍受難看的鋸齒。
文件尺寸大增。對于以收藏為目的的電子書來說,這是一個必須以嚴肅的態(tài)度,認真地加以考慮的問題。
相關文章
linux Shell學習筆記最后一節(jié),溫故與知新
linux Shell學習筆記最后一節(jié),這節(jié)是對前面章節(jié)的小結,學習shell編程的朋友可以參考下。2010-12-12在InstallShield中引用WINSOCK 的示例代碼
在InstallShield中引用WINSOCK 的示例代碼...2007-03-03