史萊姆論壇

返回   史萊姆論壇 > 教學文件資料庫 > 程式 & 網頁設計技術文件
忘記密碼?
論壇說明 標記討論區已讀

歡迎您來到『史萊姆論壇』 ^___^

您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的!

請點擊這裡:『註冊成為我們的一份子!』

Google 提供的廣告


 
 
主題工具 顯示模式
舊 2004-08-02, 02:28 PM   #1 (permalink)
榮譽會員
 
psac 的頭像
榮譽勳章
UID - 3662
在線等級: 級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時
註冊日期: 2002-12-07
住址: 木柵市立動物園
文章: 17381
現金: 5253 金幣
資產: 33853 金幣
預設 一般電子書格式及其反編譯思路

作者:馬健
版本:1.00
日期:2004.05.30

宣告:

本文可能夾雜大量技術術語,如果您對此感到不快,請勿繼續閱讀。
本文僅僅討論一些思路,不會提供相關來源碼,最多也只提供來源碼網站的連接。如果您對此有所不滿,請勿繼續閱讀。
本文僅僅從技術角度討論電子書反編譯問題,請勿將之用於侵犯版權等等非法目的,或損害他人利益。如果您對此感到失望,請勿繼續閱讀。
本文版權歸作者所有,轉載前請先徵得作者書面同意。
1. 前言
2. 一般電子書格式及其反編譯思路
2.1 PDF格式
2.2 關於IE內核的電子書
2.2.1 CHM格式
2.2.2 EXE格式
2.2.2.1 Web Compiler 1.67
2.2.2.2 Caislabs eBook Pack Express 1.6
2.2.2.3 通用反編譯思路
2.3 HLP格式
2.4 小說網/小說世界(ebx/XReader)
3. 結論
附錄 關於IE內核電子書的實現方式探討

1. 前言
本文所描述的電子書,指的是將原始的、可編輯的HTML、TXT、RTF、圖像文件等,打包成一個獨立的EXE,或其它只有專用瀏覽器才能讀取的文件,打包後的文件通常不可用一般工具進行編輯、全文檢索。

本文所描述的電子書反編譯,指的是將電子書中的內容提取出來,還原或轉換成標準的、可編輯的HTML、TXT、RTF及圖像文件等。

就像世間其它事物一樣,電子書編譯器和反編譯器的出現也都不是偶然的,都有其必然性。

在電子書編譯器這一方來說,大概從有電子我的文件那天開始,就有人琢磨著要對電子我的文件打包了。我個人認為這主要是從以下幾個方面進行考慮:

便於閱讀、管理。當年在DOS下閱讀文本文件,尤其是中文文件比較麻煩,因此出現了原有的中文字庫、原有的基本瀏覽(翻頁、滾動)功能的DOS電子書;由於需要在不同OS平台上獲得相同的閱讀效果,因此產生了跨平台的PDF格式電子書;隨著網際網路絡的發展,大量資訊以HTML格式出現,但是面對一大堆HTML文件,並不是每個人都知道該去雙按index.htm或default.htm的,而且文件太多,管理也成問題,因此出現了CHM格式和各種關於IE內核的EXE格式電子書。
便於保護知識產權、商業機密。這個問題的重要性相信大家現在都能理解了,不要說那些包含核心商業機密的東西,就算是區區一本小說,都會有些卑鄙小人把原始的HTML、TXT文件拿去加LOGO、打包,然後聲稱是自己「辛苦掃校的成果」,再堂而皇之地收取所謂「VIP費用」。因此PDF一直將我的文件安全性作為賣點之一,國內的各種獨門格式電子書也以防反編譯、防內容複製為首要目標。
而反對將通用格式打包成獨門格式的人,當然也有自己的道理:

便於全文檢索。如前所述,電子書一般不可用通常的檢索工具進行全文檢索,這就為資料的有效利用設定了障礙。我個人認為,藏書量在幾十本、上百本的時候,手工建立摘要、索引可能還可以接受;再多以後,我想要的就只是一個快速的全文檢索工具,就好像在網際網路環境下,對google的依賴一樣。
便於修改。俗話說:「金無足赤,人無完人」,電子書也是人做的,有時難免會出點什麼錯,或者因為資訊的發展,需要對原有內容加以修正、補充,這個時候如果面對的是一個不可編輯的EXE,您會有什麼感想?
節省時間和耐心。Windows在顯示文件列表的時候,需要讀取文件資訊,EXE文件還要讀取ICON等,如果裝有反病毒軟體,進入資料夾的時候,反病毒軟體一般還會自動對資料夾中的EXE文件進行自動檢查,而電子書大小一般都在MB級,因此開啟包含EXE格式電子書的時候,感覺速度巨慢,比較令人反感。
節省空間。一般EXE格式電子書的標準架構是:可執行體+內容+TOC。可執行體指的是電子書的執行程式碼部分,包括程序程式碼、插件程式碼、界面資源等。內容指的是電子書中真正包含的文本、圖像內容,一般使用某種壓縮、加密算法進行處理。TOC(Table Of Content)相當於目錄索引,作用是加速對內容的訪問。因此相對於直接用WinZip、WinRAR對原始內容進行壓縮,每一本EXE格式的電子書都會浪費一部分磁牒空間,以存儲執行體部分。電子書的軟體界面越花哨,這種浪費一般也越大,我見過最誇張的電子書比原始內容足足多出 1 MB多的東西。
避免垃圾。對於某些關於IE內核的電子書來說,由於實現技術的限制,可能會在註冊表和系統目錄下留下垃圾。
安全。如果說如今的網路社會是一個充滿惡意、毫無誠信的環境,可能有點誇張了,不過確實有人不知「做人要厚道」為何物。老實說,每次拿到一個來路不明的EXE格式的電子書的時候,我都在懷疑裡面有沒有什麼木馬、病毒,實在難受。
便於平台轉換,包括轉換到手持設備。EXE格式的電子書看起來可能很爽,但是畢竟只能在Windows下看,如果想在其它系統下看,尤其是在手持設備上看,唯一的出路就是反編譯了它。
當然,在反編譯後,也必須尋找合適的替代品,以繼續滿足原先的需要:

打包工具。建議選項Winzip或WinRAR,不僅使用方便,而且打包後文件也小,進入目錄還快。
閱讀工具。現在可以不解包就直接閱讀zip/rar文件內容的軟體不少,一搜一大把,我自己都做過一個MyReader,不僅可以直接從ZIP/RAR中讀取內容,還有自動定位index.htm、書籤、現場保護、資源瀏覽器右鍵表單擴展、zip/rar密碼自動記憶等功能。
全文檢索工具。可以直接在zip/rar中全文檢索的軟體也有不少,我自己也做過一個FindStr,支持加密zip/rar,這個工具還可以與MyReader整合,搜尋結果可以直接用MyReader直接開啟,不需解包。另外它還支持批量文本替換,所以也經常被我用來整理下載到的或反編譯出來的小說,包括去除廣告連接、絕對URL改成相對URL等。
對勞動成果的保護。這個直接用zip/rar的密碼保護就好。
2. 一般電子書格式及其反編譯思路
2.1 PDF格式
PDF格式是Adobe公司推出的一種跨平台電子我的文件格式,Adobe公司提供專用的我的文件瀏覽器,使用戶可以在不同平台下獲得相同的閱讀效果。

其實Adobe公司提供的PDF編輯工具--Adobe Acrobat本身,就已經支持將PDF文件另存為RTF格式,因此我對PDF的反編譯研究不多。不過這個功能似乎受到「我的文件安全性」的限制,好在我google了一下,破解PDF安全保護的軟體似乎不少。如果真的對批量轉換有興趣,在codeproject上也有一篇文章,提供將PDF轉換成純文本的來源碼。

從我使用的情況看,Adobe Acrobat本身輸出的RTF格式,對英文我的文件來說應該沒有什麼太大的問題,頂多是格式有點變化,但是在輸出中文我的文件的時候,偶爾會因為字串集程式碼錯誤,導致輸出的文件在Word、寫字板中開啟的時候,只能看到一堆亂碼。對於這種情況,手工替換一下字串集編碼即可解決。

出現亂碼還有一種可能就是PDF文件中使用了自訂的字庫,導致轉換出來後的文件無法正常顯示,這個比較麻煩。PDF文件原有的字庫有兩種方式:原有的一種完整的字庫,稱為font embedding;只原有的一種字庫中要用到的那幾個字串,稱為font subsetting。在e類出版物論壇的「圖書製作、閱讀工具區」對此有過討論,需要的可以自己去看。

不過有一次我試著用過一個叫PDF2Html的軟體,這個軟體的思想是將PDF文件的每一頁轉換成一個JPG文件,然後將JPG文件封裝到HTML文件裡,加上目錄、翻頁按鈕等,這樣在網路瀏覽的時候,連客戶端的Acrobat Reader及客戶端字體支持都可以省了。這個軟體的HTML文件範本做得怎樣先不去說它,最令我奇怪的是,轉換出來的圖像格式只能是JPG,不能是PNG。其實對於有大片白色背景的頁面來說,使用PNG格式不僅文件長度比JPG小,而且不會像JPG格式一樣,在文字、圖像邊緣產生許多細小的碎片(高次雜波)。

2.2 關於IE內核的電子書
隨著網際網路的發展,現在越來越多的網路我的文件內容是以HTML格式提供的,而微軟本身又以控件的形式提供了IE瀏覽器的內核,可以很方便地被幾乎所有Windows下的編程工具所使用,因此目前關於IE內核的電子書似乎佔據了主流位置。

2.2.1 CHM格式
CHM(發音為「chum」)的原意是Compiled HTML help file,是微軟作為HLP格式(16位Windows下的標準求助文件格式)的替代格式提出的,因此微軟自己不僅隨4.01以上版本的IE一起提供免費的瀏覽器,而且免費提供製作工具Microsoft HTML Help Workshop。

CHM文件內部使用ITS格式,這是一種非常優秀的壓縮格式,感覺壓縮比要比zip、rar大。

由於ITS格式的開放性,國外早就有人做出了CHM格式的獨立編譯、反編譯工具,並且公開了全部來源碼,需要的人可以到這裡看:

http://bonedaddy.net/pabs3/hhm/

這個網站除了提供CHM編譯、反編譯工具及其來源碼外,還提供CHM格式的詳細說明,當然是英文的。我做的UnEBook在開始的時候,就使用了其中chmdeco的來源碼,實現批量反編譯CHM的功能。如果這個網站不幸登入不了,google一下chmdeco就好,有很多制作備份站點的。chmdeco內部使用的是chmlib的來源碼,這份來源碼很有名,除chmdeco外,chmtools用的也是它。

不過在使用了一段時間後,我發現這份程式碼在反編譯某些CHM文件的時候,會出現陣列越界錯誤。這種錯誤出現的概率雖然不大,但是出現後還是比較心煩,因此最終放棄了這份程式碼。

現在UnEBook使用的CHM反編譯程式碼是從這裡改出來的:

http://www.codeproject.com/winhelp/htmlhelp.asp

這份程式碼使用了微軟未公開的ITS文件訪問接頭,直接對文件進行操作。由於使用的都是微軟的東西,不僅目標碼比較小,相容性也好得多,目前還沒有遇到反編譯不出來的CHM文件(唯一的一次例外,是那個CHM文件本身就打不開),記憶體漏洞什麼的也沒有發現。看來微軟的東西還是要由微軟來對付,方為王道。

另外某些人製作CHM電子書的時候,為了省事,沒有製作index.htm,而是單純依賴左側的目錄樹進行導航。對於這樣的電子書,在反編譯後,一般還需要根據產生的hcc文件,自動產生一個索引頁,以免看的時候不方便。hcc文件結構大致如下:

多級目錄通過<UL>控制,見到<UL>的時候往下走一級目錄,</UL>往回走一級。
目錄項以<OBJECT type="text/sitemap">開始,以</OBJECT>結束。以<PARAM NAME="Name" VALUE="xxx">存放項名稱,<PARAM NAME="Local" VALUE="xxx.html">存放項連接。
某些目錄項可能只有名稱,沒有連接。
在UnEbook中,不僅能夠根據hcc文件自動產生索引頁,還能自動產生框架頁,將索引頁和顯示頁嵌入框架中,以最大限度模仿CHM中的目錄效果。如果要完全模仿能夠動態伸縮的樹形目錄效果,則需要增加圖片、js、css等文件,實在得不償失。

2.2.2 EXE格式
除了CHM格式外,大量關於IE內核的電子書是以EXE格式提供的。製作EXE格式的電子書工具現在似乎已成為一個產業,養活了大批的程序員。雖然很多人認為這種格式的電子書很酷:一個文件就可以執行,界面也可以做得很漂亮,還可以帶密碼保護。但是我個人對這種格式的電子書是最最痛恨的:除了前面說到的安全性、速度、空間、檢索等問題外,我最心煩的一點是目前的EXE電子書都沒有好用的書籤功能,尤其是沒有能夠定位到頁面中任意位置的書籤功能,看長我的文件看到一半的時候被打斷會很麻煩,所以自從MyReader實現了書籤功能後,我就下定決心一定要解決反編譯問題。

2.2.2.1 Web Compiler 1.67
這種格式的電子書,因為其製作工具在國內出現得比較早,而且有非常徹底的漢化解密版,所以曾經比較流行,E書時空提供的很多電子書都是這種格式。不過也正因為它的流行,導致想反編譯它的人也多,引出了各種反編譯工具,所以現在用的人似乎已經不多了。

反編譯工具裡,收費的就不去說它了,國內RMH和Fbilo還聯合推出過免費的unwebcompiler,並且提供全套的Delphi來源碼,有需要的到google或百度搜尋一下unwebcompiler就有了。不過可能國內大多數軟體網站的管理員都不是開發人員出身,對來源碼不感興趣,所以收藏的都是212 KB的EXE,有來源碼的不多,需要仔細找一下。

在unwebcompiler的來源碼裡,RMH和Fbilo對Web Compiler 1.67產生的電子書的文件格式進行了詳細描述,在這裡我就不做無聊的重複,有興趣就自己去看吧。我做的UnEBook也使用了他們提供的來源碼,實現對Web Compiler 1.67產生的電子書的批量反編譯,不過被我將程式碼從Delphi改成了C,似乎長度縮短了一些(原程式碼中有一段在字串串和十六進制數之間轉換來、轉換去,看起來比較怪異,被我省了),不過LHA解壓縮部分改起來實在太麻煩,我直接在網上找了一段現成的C程式碼來用。

2.2.2.2 Caislabs eBook Pack Express 1.6
這個電子書製作工具也出過漢化版,所以在國內也有一定影響,不過這種影響似乎還沒有大到足以使反編譯工具滿天飛的程度,嘿嘿……

在分析這種格式的電子書的時候,我沒有使用任何反彙編工具,用UltraEdit32和系統監視工具就猜出來了:

文件標識:以十六進制串 00 F8 03 00 結尾。這個似乎是一種慣例,差不多所有EXE格式的電子書都有自己特殊的文件結尾。
目錄塊起始位址游標:0003F81C
目錄塊中目錄項結構:以0字串結尾的檔案名+4字元起始位址,檔案名起始字元為FF則目錄塊結束。
如果文件存放在子目錄裡,則檔案名首字串:02=../,01:第一個00變成/,直到遇到02。
文件內容實際起始位址:目錄項裡的4字元起始位址+9
文件內容長度:目錄項裡4字元起始位址所指內容,DWORD。
在分析出目錄結構後,我曾經想通過偵錯工具,分析文件加密算法,再反編譯出具體的文件內容,但是很快我就發現那樣干太累了,實在是得不償失。

不過在經過幾次嘗試後,我還是找到了一個偷懶的辦法:

通過安裝hook的方法,往電子書的行程空間注入一個DLL。
在這個DLL裡,用Windows標準的API函數URLDownloadToFile,就可以下載到指定的文件。文件的URL可以按前面說的方法,從目錄項得到相對路徑,再加上一個類BIOS前綴("file://Z:\\com_caislabs_ebk\\")構成絕對路徑。
UnEbook在批量反編譯這種格式的電子書的時候,就是按照上面的分析結果實現的。

不過到了更高版本的Caislabs eBook Pack Express的時候,似乎Caislabs公司也開始意識到文件內容保護的重要性,因此不僅對文件內容採用更強的加密算法,杜絕了可以用URLDownloadToFile下載的漏洞,連目錄塊的加密強度都強到足夠使我不想去分析了。幸好這個時候我已經有了更好的反編譯思路--與具體文件格式無關的,專門針對使用IE內核的電子書的通用反編譯思想。

2.2.2.3 通用反編譯思路
在分析過幾種電子書格式後,我開始領悟到一個真理:電子書內部文件結構的變化是無窮的,而我的時間和精力是有限的;把有限的時間和精力投入到對抗無窮的變數中去,早晚會有累死的一天。

有此認識後,我開始思考有沒有什麼通用的方法,可以解決大部分電子書的反編譯問題(我還沒有幼稚到相信這世上會有萬能藥的程度)。按照慣例(不可救藥的職業病),第一步當然是市場調查、產品定位,結論是目前大多數電子書都是關於IE內核的,但是根據我在開發MyReader時對IE內核的瞭解,這裡面明顯示記憶體在一個誤區:微軟以控件的形式提供IE內核,其目的就是希望通過控件接頭的開放性、方便性,吸引更多的人加入微軟的標準陣營,如果想在此基礎上增加加密、保護等等內容,恐怕與微軟的初衷不合(我說的是當時,以後微軟改主意了也說不定)。因此我相信IE內核一定有後門可走!經過一番努力,果然沒有令我失望。

1、基本原理

針對IE內核電子書的通用破解技術實現起來可能需要一些技術和技巧,但是原理卻很簡單,幾句話就可以說清楚:不論電子書在存儲的時候如何對內容進行加密,在將內容傳遞給IE內核進行顯示的時候,一定要將內容轉換成IE內核能夠識別的標準格式--HTML格式。而IE內核為了便於顯示、重新整理,在對HTML程式碼進行解析後,並不是立刻就把這些HTML程式碼拋棄,而是在記憶體裡儲存了一份制作備份。因此只要將這份制作備份從IE內核裡搞出來,就得到瞭解碼後的內容,也就是反編譯想得到的內容。

至於網頁中的其它內容,包括圖片、css、js、Flash文件等,就更簡單了:模擬IE內核,直接找電子書要就好。如果電子書分辨不出請求是來自IE內核還是來自其它地方,自然會乖乖把我們需要的東西雙手奉上!

雖然反編譯的原理幾句話就可以說清,但是要加以實現,還需要經過艱苦的探索和試驗,我自己就經過了長期的努力,IE內核的來源碼都翻來覆去看了好幾遍(吹的,別當真!)。而我思想的發展也大概經歷了兩個階段:第一個階段是在得到某份傳說中的來源碼(沒錯,就是那份展開後近700MB,被國內主流媒體形容為噱頭、無足輕重、充滿無聊垃圾的東西)之前,完全立足於微軟公開的IE內核接頭。當時我考慮將電子書內容按照HTML、圖像等分類,分別解決獲取問題。第二個階段是在得到那份來源碼之後,我突然發現其實對於所有文件,我都可以直接找電子書要,只要假裝是IE內核在要就行了。

由於某些東西比較敏感,因此下面敘述的主要是我第一個階段的想法,其中有些屬於基礎性的東西。第二個階段的實現恕我不便奉告。

2、獲取HTML來源碼的方法

從IE內核獲取HTML來源碼的方法不僅我一個人在想,從國內到國外,從CSDN(CSDN的VC/MFC區有一個欄目專門討論IE內核編程)到MSDN,早就有很多人討論過了,歸納起來,一般認為可以通過下列步驟實現:

不管是通過滑鼠點擊也好,通過EnumChildWindow也好,總之先找到IE內核的顯示視窗,也就是電子書顯示網頁內容的那個視窗。
通過這個視窗的句柄(HWND),取得這個視窗對應的IE內核我的文件接頭IHTMLDocument2的接頭游標。取得的方法目前認為有兩種,我個人認為這兩種需要結合使用,否則總有一些電子書會搞不定:一個是通過MSAA,一個是通過WM_HTML_GETOBJECT消息。至於具體的實現程式碼,在CSDN上都快被討論爛了,因此此處從略,有需要的自己到CSDN上找。不過這兩種方法都對平台有要求:XP下是完全沒有問題,2000下可能需要裝IE 6,98/Me/NT就不要想了。
在得到IHTMLDocument2接頭游標後,按照這個接頭提供的標準方法,即可獲得我的文件的HTML程式碼。具體實現程式碼見CSDN中的例子。
除了上面這種方法外,我自己還嘗試過一種方法:使用MIME Filter。

對於搞過網頁在線翻譯、網頁內容過濾的人來說,MIME Filter可是吃飯的本錢,它的作用和實現機理應該早就爛熟於心,但是對於其它人來說,可能還不是很熟,所以這裡簡單介紹一下:為了便於對IE內核的功能進行擴展,微軟規定在IE內核顯示某種標準格式(HTML、TEXT等)的內容之前,會先將要顯示的內容傳遞給這種格式的過濾器,即MIME Filter,由它先對內容進行預處理(如將英文翻譯成中文,將下流文字替換成星號等),然後再顯示。

按照這個原理,如果實現一個針對HTML格式的MIME Filter,即可攔截到最原汁原味的HTML程式碼。可惜,經過我的嘗試,這招對IE本身是靈的,對某些電子書也有效,但是對另一些無效。再加上使用IHTMLDocument2接頭游標的方法要比這種方法簡單得多,也可靠得多,所以後來在我開發的反編譯工具KillEBook、IECracker和CtrlN裡就沒有使用這種方法。不過這種方法也有一個好處:與平台無關,我在98/Me/2000/XP下都試過,當然都是在虛擬機下試的啦。

MIME Filter的作用機理、實現方法在MSDN裡有詳細說明,並提供了詳細的實例程式碼,有需要的可以到MSDN上搜「MIME Filter」。

3、獲取圖像的方法

與HTML程式碼相似,IE內核對圖像的處理也有一個「下載->解碼->顯示」的程序。考慮到顯示程式碼的抽像性,原來各種各樣的圖像格式,包括JPG、GIF、PNG、TIFF等,在解碼後都被統一表示成位圖格式,而原有格式資料在解碼後即被從記憶體中釋放,只在IE的cache中留有文件制作備份。如果指定不允許儲存本機cache,則連這個制作備份都沒有。在IE中通過右鍵表單選「圖片另存為...」的時候,其實就是將cache中的文件制作備份拷貝一份出來,如果cache中已經沒有制作備份,就只能儲存記憶體中的位圖(*.bmp)了。現在明白為什麼有些圖片明明是jpg格式,但是用IE卻只能儲存為「無標題.bmp」了吧?

因此,獲取圖像文件要比獲取HTML文件難得多。而且在MSDN裡說得很清楚,用IHTMLDocument2接頭只能得到圖像的連接,用MIME Filter也不能搞到網頁裡的圖像資料,因此需要另想辦法。我想過、試過的包括:

先將圖像複製到剪貼板,再從剪貼板裡獲取圖像資料,然後根據圖像文件副檔名(可以從圖像元素的URL裡解析),編碼成原始圖像格式,包括jpg、png、gif、tiff等。這個方法實現比較簡單,到MSDN KB裡搜尋Q293125,拷貝圖像到剪貼板的現成來源碼就有了,圖像編碼的來源碼則可以參考cximage,這個也是google一下就有的。不過這個方法遠非完美無缺:a). 對於png、gif等允許帶透明背景的格式,用這種方法處理後就不透明了。b). gif動畫處理後就動不起來了,只能顯示其中的某一畫格。c). 對於jpg這樣的有損壓縮格式來說,每壓縮一次就損失一次,多壓縮幾次可能就沒法看了。d). 在電子書裡,可以通過標準的Windows API函數,使剪貼板失效。
將IE內核導航到圖片,然後通過IViewObject接頭獲取圖片的拷貝。這個方法與上面的方法基本相同,不過不通過剪貼板,可以防止因為剪貼板被封鎖而搞不到圖像。
使用IE圖像解碼插件。IE內核在下載到某種格式的圖像文件後,會使用對應的解碼器,對圖像進行解碼(類似於MIME Filter)。為了便於擴充,解碼器是做成插件形式的。如果自己做一個圖像解碼器插件,對解碼請求進行攔截,即可獲得解碼前的原始圖像格式資料。解碼器的接頭、實現方法在微軟公開我的文件中沒有任何蛛絲馬跡,但是在那份傳說中的來源碼裡,不僅有詳細的接頭規範,而且有好幾個內嵌圖像解碼器的實現程式碼,可供借鑒。奇怪的是,雖然在MSDN中找不到,但是我在google上搜的時候,卻發現有一個日本人在自己的個人網站上,早就給出了詳細的圖像解碼器插件實現方法,一步一步說得很清楚,而且落款時間是2002年12月!看來這份來源碼的洩漏時間可能比想像的要早。當然這個日本人也可能本來就在微軟工作,或與微軟有合作關係,可以光明正大地檢視解碼器來源碼也說不定。
4、通用反編譯器的實現

在解決了HTML、頁面元素等的獲取方法後,通用反編譯器KillEBook的實現就很簡單了,其算法可以描述如下:

開啟電子書。
定位電子書的顯示視窗。
獲取當前顯示頁面的HTML程式碼。
解析頁面HTML程式碼,得到其中的所有連接。
獲取頁面上的所有元素內容,包括圖片等。
引導IE內核依次載入HTML連接頁面。
重複步驟3∼6,直到所有頁面及其中的元素都已獲取到。
5、進一步討論

在完成KillEBook後,我發現其實對它擴展一下,就可以成為一種新的離線瀏覽器,解決傳統離線瀏覽器(Offline Explorer Pro、Webzip等)面臨的一個問題:傳統離線瀏覽器多半與IE內核沒什麼瓜葛,因此在抓靜態網頁的時候都沒有什麼問題,但是在抓用session維持的動態網頁時,都有點問題,更不用說抓需要PKI證書驗證的HTTPS網站。

因此我考慮可以實現這樣一個離線瀏覽器:

提供一個位址欄供用戶輸入起始URL。
內嵌一個微軟web browser控件(IE內核),供用戶交互,包括在網頁上輸入用戶名/密碼、從IE證書庫中選項證書。
用戶登入成功、進入需要開始抓取的網頁後,設定遞回深度、URL過濾條件,點「開始」按鈕開始抓取。
離線瀏覽器自動引導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,但是在經過一個下午的奮鬥後,有兩處洩漏死活找不到。最後我還是決轉發IPDuffOS學習:將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:\WINNT\system32\shdoclc.dll/http_404.htm

如果您在IE中要瀏覽的頁面不存在,IE就會通過這個URL,開啟C:\WINNT\system32\shdoclc.dll,搜尋其中名為http_404.htm的資源,找到後提取、顯示出來,您看到的就是一個提示頁面不存在的網頁。

從上面這個頁面的來源碼可以看到,除HTML程式碼外,res傳輸協定還允許在頁面中包含圖片等內容,如上面這個頁面就顯示了一個名為pagerror.gif的圖片,其絕對URL為res://C:\WINNT\system32\shdoclc.dll/pagerror.gif。

雖然res傳輸協定非常簡單,基本上不需要額外的編程,但是我目前還沒有看到有人用它做電子書,最多只看到有人用它顯示軟體的About資訊。仔細想想,可能是因為這種傳輸協定太不保密了:隨便找一個資源編輯器,就可以直接獲取、替換資源內容了。

2、關於文件方式

這種方式的思路其實非常簡單:需要顯示網頁的時候,先將網頁解壓縮到臨時目錄,然後用IE控件顯示,退出的時候刪除臨時文件。

這種方式我早就知道,但是因為它實在是太簡單了,所以連我自己都不相信有人真的會用它做電子書,直到我見到雄風網的電子書:這個網站早期發行的電子書,雖然要求用戶輸入密碼進行驗證,但是在密碼輸對以後,就會把全部內容解壓縮到temp目錄下,然後用IE控件開啟文件進行瀏覽。雖然temp目錄下的文件內容被設定為隱藏,但是這點小伎倆實在不值一提,所以只要破解了認證密碼,電子書本身就已經提供了完整的反編譯功能了。

該網站後來發行的電子書雖然經過昇級,但還是延續了這種模式,只不過在temp目錄裡存放的是加過密的HTML文件,但是圖像文件卻是不加密的,因此我猜測他們可能改用MIME Filter技術了。

3、關於流或document.write方法

用流往IE控件中寫入內容的方法,在MSDN和CSDN中都有詳細的討論,連來源碼都有。有需要的到MSDN搜尋「Loading HTML content from a Stream」即可。

document.write在動態網頁中比較常用,很多網頁加密工具都是使用這招來實現網頁來源碼的隱藏。對於VC、Delphi等來說,這招不過是換成了IHTMLDocument2::write,效果是一樣的。

使用這種方法做電子書的雖然不多,不過畢竟還是有的,我見過的就是讀寫網。由於開啟這個網站的電子書後,IE主頁就會自動設定為這個網站的URL,所以在這裡就不給出這個網站的URL了,以免各位受到意外傷害。破解這種電子書的收費驗證的方法,已經有人在紫宸殿網路論壇的技術區貼出來過,有興趣的可以去看看。

在MSDN中對這種關於流的方法的局限性說得很清楚:

頁面不能太複雜,如果頁面包含的tag太多,顯示出來的就不是解析後產生的頁面,而是原始的HTML程式碼。大概就是因為這個原因,所以讀寫網放出來的電子書清一色都只有純文本,加背景色。
當前頁面的URL永遠不變(讀寫網的永遠都是about:blank),因此IE內核沒有辦法從相對URL自動構造出絕對URL。就是因為這個原因,讀寫網早期的電子書在頁面中使用jpg文件作為背景,就只能將這個背景影像寫到temp目錄下,然後在網頁中使用絕對URL引用這個圖片。也正是因為這個原因,所以在頁面中不能包含「上一頁」、「下一頁」、「回目錄」等連接,只能自己在左側放一棵目錄樹,讓用戶一頁、一頁去點。
由於這種電子書的頁面沒有自己的URL,因此不能用KillEBook進行反編譯,只能用IECracker或CtrlN,一頁、一頁手工抓取。

4、採用MIME Filter

與關於流的方法相比,這種方法不僅支持包含眾多tag的複雜HTML頁面,而且可以從相對URL構造絕對URL,因此支持頁面之間的連接,實現也不複雜,MSDN上就有現成的例子可供參考。

不過這種方法的缺點也很明顯:不能對圖像等內容進行加密處理。下面說的傳輸協定插件方法就比這種方法強些。

5、關於web伺服器

對於不懂行的人來說,「web伺服器」聽起來可能是一個很了不起的東東,但是對於懂行的人來說,實現其實很簡單:

起一個監聽線程,對本機80或任何一個指定的連接阜進行監聽。
每監聽到一個連接請求,起一個服務線程,根據請求內容,按照HTTP傳輸協定,返回內容。
在codeguru和codeproject上,有很多現成的web server程式碼,直接拿來用就好,自己只要考慮怎麼填寫返回內容即可。VC 6原有的的MSDN光碟上,也帶了一個名為HTTPSVR的例子,說明如何用MFC和WinSock新增web server。

使用這種方法雖然簡單、直截了當,而且只要願意,差不多能夠模擬一個真正web server的功能(就算想實現app server也並非不可能,不過要花點功夫),但是也有問題:

基本上沒有什麼保密性可言,伺服器起來後,本地機其它行程很輕鬆就能下載到需要的內容。
如果本地機上其它行程也提供TCP/IP服務,可能會產生連接阜衝突。
6、傳輸協定插件(Asynchronous Pluggable Protocols)

這個是微軟專門為IE擴展的東西。

在網際網路上,一般的套用層傳輸協定包括http、FTP等。出於種種原因,微軟允許用戶在標準的套用層傳輸協定之外,擴展自己的傳輸協定,稱為Asynchronous Pluggable Protocol。到MSDN、codeguru和codeproject上搜尋這幾個關鍵字,從理論到來源碼都能找出一堆,在這裡我就不囉嗦了。

Asynchronous Pluggable Protocol可以指定對所有行程有效,這個在註冊表的HKEY_CLASSES_ROOT\PROTOCOLS\Handler下註冊一下就好;也可以指定只在某個行程內有效,以增加保密性,不過這個時候微軟就不叫它Asynchronous Pluggable Protocol了,而是Pluggable Namespace Handler。

由於Asynchronous Pluggable Protocol具有一定的保密性,實現起來又有例子可參考,而且差不多與架設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實現,使用前必須在註冊表中註冊)。

7、最後一招

即使使用Asynchronous Pluggable Protocol,由於在IE內核中還存在可顯示的HTML來源碼,因此還是存在被匯出的可能,這個就是上面正文裡討論了半天的東西。

我想到的最後一招製作防反編譯的電子書的辦法就是:在製作的時候,將所有頁面內容全部轉換成圖片,然後再打包。將網頁轉換成圖片的來源碼參見這裡:

http://www.codeproject.com/internet/...agecapture.asp

使用這種方法,在拿到一本製作好的電子書後,想得到原始文本資訊的方法大概只有兩個:OCR和key in。這個也可以用起點中文網的方法來對付:使用手寫體,加水印,故意增加錯別字或替換標點符號等。據傳說,起點就是根據用戶ID,產生錯別字和錯誤標點的,因此如果是原樣key in或OCR,就可能被查出來。

但是回頭一想,如果哪個電子書製作工具真的走到了這一步,大概也就離消亡不遠了,用戶還不如直接去做PDF:

所有動態效果全部沒有,頁面上的連接也全部失效,大概又只能靠在左側放一棵目錄樹才能導航了。
頁面大小、字串大小基本類BIOS,顯示的時候很難放大、縮小,尤其是放大的時候,要麼速度比較慢,要麼必須忍受難看的鋸齒。
文件尺寸大增。對於以收藏為目的的電子書來說,這是一個必須以嚴肅的態度,認真地加以考慮的問題。
psac 目前離線  
送花文章: 3, 收花文章: 1631 篇, 收花: 3205 次
向 psac 送花的會員:
WCC1212 (2008-08-09)
感謝您發表一篇好文章
 


主題工具
顯示模式

發表規則
不可以發文
不可以回覆主題
不可以上傳附加檔案
不可以編輯您的文章

論壇啟用 BB 語法
論壇啟用 表情符號
論壇啟用 [IMG] 語法
論壇禁用 HTML 語法
Trackbacks are 禁用
Pingbacks are 禁用
Refbacks are 禁用


所有時間均為台北時間。現在的時間是 12:49 PM


Powered by vBulletin® 版本 3.6.8
版權所有 ©2000 - 2024, Jelsoft Enterprises Ltd.


SEO by vBSEO 3.6.1