常見電子書格式及其反編譯思路分析第2/3頁
更新時(shí)間:2008年07月17日 23:41:04 作者:
本文僅僅從技術(shù)角度討論電子書反編譯問題,請(qǐng)勿將之用于侵犯版權(quán)等等非法目的,或損害他人利益。如果您對(duì)此感到失望,請(qǐng)勿繼續(xù)閱讀。
2.2.2.1 Web Compiler 1.67
這種格式的電子書,因?yàn)槠渲谱鞴ぞ咴趪?guó)內(nèi)出現(xiàn)得比較早,而且有非常徹底的漢化解密版,所以曾經(jīng)比較流行,E書時(shí)空提供的很多電子書都是這種格式。不過也正因?yàn)樗牧餍?,?dǎo)致想反編譯它的人也多,引出了各種反編譯工具,所以現(xiàn)在用的人似乎已經(jīng)不多了。
反編譯工具里,收費(fèi)的就不去說它了,國(guó)內(nèi)RMH和Fbilo還聯(lián)合推出過免費(fèi)的unwebcompiler,并且提供全套的Delphi源代碼,有需要的到google或百度搜索一下unwebcompiler就有了。不過可能國(guó)內(nèi)大多數(shù)軟件網(wǎng)站的管理員都不是開發(fā)人員出身,對(duì)源代碼不感興趣,所以收藏的都是212 KB的EXE,有源代碼的不多,需要仔細(xì)找一下。
在unwebcompiler的源代碼里,RMH和Fbilo對(duì)Web Compiler 1.67生成的電子書的文件格式進(jìn)行了詳細(xì)描述,在這里我就不做無聊的重復(fù),有興趣就自己去看吧。我做的UnEBook也使用了他們提供的源代碼,實(shí)現(xiàn)對(duì)Web Compiler 1.67生成的電子書的批量反編譯,不過被我將代碼從Delphi改成了C,似乎長(zhǎng)度縮短了一些(原代碼中有一段在字符串和十六進(jìn)制數(shù)之間轉(zhuǎn)換來、轉(zhuǎn)換去,看起來比較怪異,被我省了),不過LHA解壓縮部分改起來實(shí)在太麻煩,我直接在網(wǎng)上找了一段現(xiàn)成的C代碼來用。
2.2.2.2 Caislabs eBook Pack Express 1.6
這個(gè)電子書制作工具也出過漢化版,所以在國(guó)內(nèi)也有一定影響,不過這種影響似乎還沒有大到足以使反編譯工具滿天飛的程度,嘿嘿……
在分析這種格式的電子書的時(shí)候,我沒有使用任何反匯編工具,用UltraEdit32和系統(tǒng)監(jiān)視工具就猜出來了:
文件標(biāo)識(shí):以十六進(jìn)制串 00 F8 03 00 結(jié)尾。這個(gè)似乎是一種慣例,差不多所有EXE格式的電子書都有自己特殊的文件結(jié)尾。
目錄塊起始地址指針:0003F81C
目錄塊中目錄項(xiàng)結(jié)構(gòu):以0字符結(jié)尾的文件名+4字節(jié)起始地址,文件名起始字節(jié)為FF則目錄塊結(jié)束。
如果文件存放在子目錄里,則文件名首字符:02=../,01:第一個(gè)00變成/,直到遇到02。
文件內(nèi)容實(shí)際起始地址:目錄項(xiàng)里的4字節(jié)起始地址+9
文件內(nèi)容長(zhǎng)度:目錄項(xiàng)里4字節(jié)起始地址所指內(nèi)容,DWORD。
在分析出目錄結(jié)構(gòu)后,我曾經(jīng)想通過調(diào)試工具,分析文件加密算法,再反編譯出具體的文件內(nèi)容,但是很快我就發(fā)現(xiàn)那樣干太累了,實(shí)在是得不償失。
不過在經(jīng)過幾次嘗試后,我還是找到了一個(gè)偷懶的辦法:
通過安裝hook的方法,往電子書的進(jìn)程空間注入一個(gè)DLL。
在這個(gè)DLL里,用Windows標(biāo)準(zhǔn)的API函數(shù)URLDownloadToFile,就可以下載到指定的文件。文件的URL可以按前面說的方法,從目錄項(xiàng)得到相對(duì)路徑,再加上一個(gè)固定前綴("file://Z:\\com_caislabs_ebk\\")構(gòu)成絕對(duì)路徑。
UnEbook在批量反編譯這種格式的電子書的時(shí)候,就是按照上面的分析結(jié)果實(shí)現(xiàn)的。
不過到了更高版本的Caislabs eBook Pack Express的時(shí)候,似乎Caislabs公司也開始意識(shí)到文件內(nèi)容保護(hù)的重要性,因此不僅對(duì)文件內(nèi)容采用更強(qiáng)的加密算法,杜絕了可以用URLDownloadToFile下載的漏洞,連目錄塊的加密強(qiáng)度都強(qiáng)到足夠使我不想去分析了。幸好這個(gè)時(shí)候我已經(jīng)有了更好的反編譯思路--與具體文件格式無關(guān)的,專門針對(duì)使用IE內(nèi)核的電子書的通用反編譯思想。
2.2.2.3 通用反編譯思路
在分析過幾種電子書格式后,我開始領(lǐng)悟到一個(gè)真理:電子書內(nèi)部文件結(jié)構(gòu)的變化是無窮的,而我的時(shí)間和精力是有限的;把有限的時(shí)間和精力投入到對(duì)抗無窮的變數(shù)中去,早晚會(huì)有累死的一天。
有此認(rèn)識(shí)后,我開始思考有沒有什么通用的方法,可以解決大部分電子書的反編譯問題(我還沒有幼稚到相信這世上會(huì)有萬能藥的程度)。按照慣例(不可救藥的職業(yè)病),第一步當(dāng)然是市場(chǎng)調(diào)查、產(chǎn)品定位,結(jié)論是目前大多數(shù)電子書都是基于IE內(nèi)核的,但是根據(jù)我在開發(fā)MyReader時(shí)對(duì)IE內(nèi)核的了解,這里面明顯存在一個(gè)誤區(qū):微軟以控件的形式提供IE內(nèi)核,其目的就是希望通過控件接口的開放性、方便性,吸引更多的人加入微軟的標(biāo)準(zhǔn)陣營(yíng),如果想在此基礎(chǔ)上添加加密、保護(hù)等等內(nèi)容,恐怕與微軟的初衷不合(我說的是當(dāng)時(shí),以后微軟改主意了也說不定)。因此我相信IE內(nèi)核一定有后門可走!經(jīng)過一番努力,果然沒有令我失望。
1、基本原理
針對(duì)IE內(nèi)核電子書的通用破解技術(shù)實(shí)現(xiàn)起來可能需要一些技術(shù)和技巧,但是原理卻很簡(jiǎn)單,幾句話就可以說清楚:不論電子書在存儲(chǔ)的時(shí)候如何對(duì)內(nèi)容進(jìn)行加密,在將內(nèi)容傳遞給IE內(nèi)核進(jìn)行顯示的時(shí)候,一定要將內(nèi)容轉(zhuǎn)換成IE內(nèi)核能夠識(shí)別的標(biāo)準(zhǔn)格式--HTML格式。而IE內(nèi)核為了便于顯示、刷新,在對(duì)HTML代碼進(jìn)行解析后,并不是立刻就把這些HTML代碼拋棄,而是在內(nèi)存里保存了一份備份。因此只要將這份備份從IE內(nèi)核里搞出來,就得到了解碼后的內(nèi)容,也就是反編譯想得到的內(nèi)容。
至于網(wǎng)頁中的其它內(nèi)容,包括圖片、css、js、Flash文件等,就更簡(jiǎn)單了:模擬IE內(nèi)核,直接找電子書要就好。如果電子書分辨不出請(qǐng)求是來自IE內(nèi)核還是來自其它地方,自然會(huì)乖乖把我們需要的東西雙手奉上!
雖然反編譯的原理幾句話就可以說清,但是要加以實(shí)現(xiàn),還需要經(jīng)過艱苦的探索和試驗(yàn),我自己就經(jīng)過了長(zhǎng)期的努力,IE內(nèi)核的源代碼都翻來覆去看了好幾遍(吹的,別當(dāng)真?。6宜枷氲陌l(fā)展也大概經(jīng)歷了兩個(gè)階段:第一個(gè)階段是在得到某份傳說中的源代碼(沒錯(cuò),就是那份展開后近700MB,被國(guó)內(nèi)主流媒體形容為噱頭、無足輕重、充滿無聊垃圾的東西)之前,完全立足于微軟公開的IE內(nèi)核接口。當(dāng)時(shí)我考慮將電子書內(nèi)容按照HTML、圖像等分類,分別解決獲取問題。第二個(gè)階段是在得到那份源代碼之后,我突然發(fā)現(xiàn)其實(shí)對(duì)于所有文件,我都可以直接找電子書要,只要假裝是IE內(nèi)核在要就行了。
由于某些東西比較敏感,因此下面敘述的主要是我第一個(gè)階段的想法,其中有些屬于基礎(chǔ)性的東西。第二個(gè)階段的實(shí)現(xiàn)恕我不便奉告。
2、獲取HTML源代碼的方法
從IE內(nèi)核獲取HTML源代碼的方法不僅我一個(gè)人在想,從國(guó)內(nèi)到國(guó)外,從CSDN(CSDN的VC/MFC區(qū)有一個(gè)欄目專門討論IE內(nèi)核編程)到MSDN,早就有很多人討論過了,歸納起來,一般認(rèn)為可以通過下列步驟實(shí)現(xiàn):
不管是通過鼠標(biāo)點(diǎn)擊也好,通過EnumChildWindow也好,總之先找到IE內(nèi)核的顯示窗口,也就是電子書顯示網(wǎng)頁內(nèi)容的那個(gè)窗口。
通過這個(gè)窗口的句柄(HWND),取得這個(gè)窗口對(duì)應(yīng)的IE內(nèi)核文檔接口IHTMLDocument2的接口指針。取得的方法目前認(rèn)為有兩種,我個(gè)人認(rèn)為這兩種需要結(jié)合使用,否則總有一些電子書會(huì)搞不定:一個(gè)是通過MSAA,一個(gè)是通過WM_HTML_GETOBJECT消息。至于具體的實(shí)現(xiàn)代碼,在CSDN上都快被討論爛了,因此此處從略,有需要的自己到CSDN上找。不過這兩種方法都對(duì)平臺(tái)有要求:XP下是完全沒有問題,2000下可能需要裝IE 6,98/Me/NT就不要想了。
在得到IHTMLDocument2接口指針后,按照這個(gè)接口提供的標(biāo)準(zhǔn)方法,即可獲得文檔的HTML代碼。具體實(shí)現(xiàn)代碼見CSDN中的例子。
除了上面這種方法外,我自己還嘗試過一種方法:使用MIME Filter。
對(duì)于搞過網(wǎng)頁在線翻譯、網(wǎng)頁內(nèi)容過濾的人來說,MIME Filter可是吃飯的本錢,它的作用和實(shí)現(xiàn)機(jī)理應(yīng)該早就爛熟于心,但是對(duì)于其它人來說,可能還不是很熟,所以這里簡(jiǎn)單介紹一下:為了便于對(duì)IE內(nèi)核的功能進(jìn)行擴(kuò)展,微軟規(guī)定在IE內(nèi)核顯示某種標(biāo)準(zhǔn)格式(HTML、TEXT等)的內(nèi)容之前,會(huì)先將要顯示的內(nèi)容傳遞給這種格式的過濾器,即MIME Filter,由它先對(duì)內(nèi)容進(jìn)行預(yù)處理(如將英文翻譯成中文,將下流文字替換成星號(hào)等),然后再顯示。
按照這個(gè)原理,如果實(shí)現(xiàn)一個(gè)針對(duì)HTML格式的MIME Filter,即可攔截到最原汁原味的HTML代碼。可惜,經(jīng)過我的嘗試,這招對(duì)IE本身是靈的,對(duì)某些電子書也有效,但是對(duì)另一些無效。再加上使用IHTMLDocument2接口指針的方法要比這種方法簡(jiǎn)單得多,也可靠得多,所以后來在我開發(fā)的反編譯工具KillEBook、IECracker和CtrlN里就沒有使用這種方法。不過這種方法也有一個(gè)好處:與平臺(tái)無關(guān),我在98/Me/2000/XP下都試過,當(dāng)然都是在虛擬機(jī)下試的啦。
MIME Filter的作用機(jī)理、實(shí)現(xiàn)方法在MSDN里有詳細(xì)說明,并提供了詳細(xì)的實(shí)例代碼,有需要的可以到MSDN上搜“MIME Filter”。
3、獲取圖像的方法
與HTML代碼相似,IE內(nèi)核對(duì)圖像的處理也有一個(gè)“下載->解碼->顯示”的過程??紤]到顯示代碼的抽象性,原來各種各樣的圖像格式,包括JPG、GIF、PNG、TIFF等,在解碼后都被統(tǒng)一表示成位圖格式,而原有格式數(shù)據(jù)在解碼后即被從內(nèi)存中釋放,只在IE的cache中留有文件備份。如果指定不允許保存本地cache,則連這個(gè)備份都沒有。在IE中通過右鍵菜單選“圖片另存為...”的時(shí)候,其實(shí)就是將cache中的文件備份拷貝一份出來,如果cache中已經(jīng)沒有備份,就只能保存內(nèi)存中的位圖(*.bmp)了?,F(xiàn)在明白為什么有些圖片明明是jpg格式,但是用IE卻只能保存為“無標(biāo)題.bmp”了吧?
因此,獲取圖像文件要比獲取HTML文件難得多。而且在MSDN里說得很清楚,用IHTMLDocument2接口只能得到圖像的鏈接,用MIME Filter也不能搞到網(wǎng)頁里的圖像數(shù)據(jù),因此需要另想辦法。我想過、試過的包括:
先將圖像復(fù)制到剪貼板,再從剪貼板里獲取圖像數(shù)據(jù),然后根據(jù)圖像文件擴(kuò)展名(可以從圖像元素的URL里解析),編碼成原始圖像格式,包括jpg、png、gif、tiff等。這個(gè)方法實(shí)現(xiàn)比較簡(jiǎn)單,到MSDN KB里搜索Q293125,拷貝圖像到剪貼板的現(xiàn)成源代碼就有了,圖像編碼的源代碼則可以參考cximage,這個(gè)也是google一下就有的。不過這個(gè)方法遠(yuǎn)非完美無缺:a). 對(duì)于png、gif等允許帶透明背景的格式,用這種方法處理后就不透明了。b). gif動(dòng)畫處理后就動(dòng)不起來了,只能顯示其中的某一幀。c). 對(duì)于jpg這樣的有損壓縮格式來說,每壓縮一次就損失一次,多壓縮幾次可能就沒法看了。d). 在電子書里,可以通過標(biāo)準(zhǔn)的Windows API函數(shù),使剪貼板失效。
將IE內(nèi)核導(dǎo)航到圖片,然后通過IViewObject接口獲取圖片的拷貝。這個(gè)方法與上面的方法基本相同,不過不通過剪貼板,可以防止因?yàn)榧糍N板被封鎖而搞不到圖像。
使用IE圖像解碼插件。IE內(nèi)核在下載到某種格式的圖像文件后,會(huì)調(diào)用對(duì)應(yīng)的解碼器,對(duì)圖像進(jìn)行解碼(類似于MIME Filter)。為了便于擴(kuò)充,解碼器是做成插件形式的。如果自己做一個(gè)圖像解碼器插件,對(duì)解碼請(qǐng)求進(jìn)行攔截,即可獲得解碼前的原始圖像格式數(shù)據(jù)。解碼器的接口、實(shí)現(xiàn)方法在微軟公開文檔中沒有任何蛛絲馬跡,但是在那份傳說中的源代碼里,不僅有詳細(xì)的接口規(guī)范,而且有好幾個(gè)內(nèi)嵌圖像解碼器的實(shí)現(xiàn)代碼,可供借鑒。奇怪的是,雖然在MSDN中找不到,但是我在google上搜的時(shí)候,卻發(fā)現(xiàn)有一個(gè)日本人在自己的個(gè)人網(wǎng)站上,早就給出了詳細(xì)的圖像解碼器插件實(shí)現(xiàn)方法,一步一步說得很清楚,而且落款時(shí)間是2002年12月!看來這份源代碼的泄漏時(shí)間可能比想象的要早。當(dāng)然這個(gè)日本人也可能本來就在微軟工作,或與微軟有合作關(guān)系,可以光明正大地查看解碼器源代碼也說不定。
4、通用反編譯器的實(shí)現(xiàn)
在解決了HTML、頁面元素等的獲取方法后,通用反編譯器KillEBook的實(shí)現(xiàn)就很簡(jiǎn)單了,其算法可以描述如下:
打開電子書。
定位電子書的顯示窗口。
獲取當(dāng)前顯示頁面的HTML代碼。
解析頁面HTML代碼,得到其中的所有鏈接。
獲取頁面上的所有元素內(nèi)容,包括圖片等。
引導(dǎo)IE內(nèi)核依次加載HTML鏈接頁面。
重復(fù)步驟3~6,直到所有頁面及其中的元素都已獲取到。
5、進(jìn)一步討論
在完成KillEBook后,我發(fā)現(xiàn)其實(shí)對(duì)它擴(kuò)展一下,就可以成為一種新的離線瀏覽器,解決傳統(tǒng)離線瀏覽器(Offline Explorer Pro、Webzip等)面臨的一個(gè)問題:傳統(tǒng)離線瀏覽器多半與IE內(nèi)核沒什么瓜葛,因此在抓靜態(tài)網(wǎng)頁的時(shí)候都沒有什么問題,但是在抓用session維持的動(dòng)態(tài)網(wǎng)頁時(shí),都有點(diǎn)問題,更不用說抓需要PKI證書驗(yàn)證的HTTPS網(wǎng)站。
因此我考慮可以實(shí)現(xiàn)這樣一個(gè)離線瀏覽器:
提供一個(gè)地址欄供用戶輸入起始URL。
內(nèi)嵌一個(gè)微軟web browser控件(IE內(nèi)核),供用戶交互,包括在網(wǎng)頁上輸入用戶名/密碼、從IE證書庫中選擇證書。
用戶登錄成功、進(jìn)入需要開始抓取的網(wǎng)頁后,設(shè)定遞歸深度、URL過濾條件,點(diǎn)“開始”按鈕開始抓取。
離線瀏覽器自動(dòng)引導(dǎo)web browser進(jìn)入每個(gè)頁面,每進(jìn)入一個(gè)頁面,都通過web browser控件獲取客戶端HTML源代碼及頁面元素,包括圖片、css、js、flash等。
采用這種方法實(shí)現(xiàn)的離線瀏覽器,由于使用web browser控件,因此可以維持客戶端session,抓取到動(dòng)態(tài)網(wǎng)頁。雖然網(wǎng)頁抓取下來就成了靜態(tài)的,但是對(duì)離線瀏覽來說應(yīng)該不成問題,對(duì)付收費(fèi)的網(wǎng)上教育等網(wǎng)站正好合適。
2.3 HLP格式
這種格式出現(xiàn)得比較早,在16位Windows(Windows 95以前的各Windows版本)下曾是標(biāo)準(zhǔn)的幫助文件格式,因此大概也算是Windows下出現(xiàn)得最早的電子書格式之一了。
由于這種格式比較流行,國(guó)外研究的也比較多,不過公開源代碼的我似乎只見過一個(gè)HELPDECO v2.1。這個(gè)軟件是一個(gè)控制臺(tái)程序,因此有人做了一個(gè)GUI外殼DuffOS對(duì)它進(jìn)行封裝。國(guó)內(nèi)有人對(duì)HELPDECO進(jìn)行過漢化,到漢化新世紀(jì)搜索一下就可以找到,包括全部源代碼。
在UnEBook中使用了HELPDECO的源代碼,實(shí)現(xiàn)對(duì)HLP文件的批量反編譯。不過從我使用的情況看,原版HELPDECO有一個(gè)小小的不足:反編譯出來的RTF文件沒有指定字符集。這對(duì)英文RTF來說沒有任何影響,但是對(duì)中文RTF來說,其影響足夠強(qiáng)到使您打開RTF后看到的是一堆亂碼。它的修正方法有兩個(gè):
用文本編輯器打開反編譯出來的RTF文件,手工指定中文字符集。這個(gè)是一種比較累的方法。
修改HELPDECO源代碼,加上字符集修正,這個(gè)是一勞永逸的辦法。但是不知道為什么,在漢化新世紀(jì)推出的漢化版上,我看到的還是原版的HELPDECO??磥頋h化者只是用它反編譯過英文HLP,沒有反編譯過中文HLP。
另外這份源代碼還有一個(gè)不知道算不算是嚴(yán)重的問題:變量沒有統(tǒng)一初始化、釋放,因此不僅在程序退出的時(shí)候,VC++會(huì)報(bào)告有內(nèi)存漏洞,而且就象當(dāng)年的DOS內(nèi)核一樣,幾乎沒有可重入性。我曾經(jīng)試圖修復(fù)這個(gè)bug,但是在經(jīng)過一個(gè)下午的奮斗后,有兩處泄漏死活找不到。最后我還是決定向DuffOS學(xué)習(xí):將HELPDECO代碼封裝成一個(gè)獨(dú)立的DLL,每反編譯一個(gè)HLP文件,都動(dòng)態(tài)加載、釋放一次DLL。這樣一方面可以利用Windows本身的DLL管理機(jī)制,彌補(bǔ)HELPDECO產(chǎn)生的內(nèi)存漏洞,一方面解決不可重入問題。收費(fèi)的“耶書制造”軟件提供的HLP反編譯功能也是用DLL文件實(shí)現(xiàn)的,因此我嚴(yán)重懷疑它的作者可能也曾遇到過相同的煩惱,嘿嘿嘿……
相關(guān)文章
可與Spreadsheets媲美的在線表格系統(tǒng):EditGrid
可與Spreadsheets媲美的在線表格系統(tǒng):EditGrid...2007-01-01
一個(gè)不錯(cuò)的shell 腳本教程 入門級(jí)
一個(gè)很不錯(cuò)的bash腳本編寫教程,至少?zèng)]接觸過BASH的也能看懂2011-10-10
RouterOS實(shí)現(xiàn)自動(dòng)禁止過期帳號(hào)的腳本
本篇文章主要介紹了RouterOS實(shí)現(xiàn)自動(dòng)禁止過期帳號(hào)的腳本,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2007-12-12
關(guān)于學(xué)習(xí) Flex 的一點(diǎn)建議(轉(zhuǎn)載)
關(guān)于學(xué)習(xí) Flex 的一點(diǎn)建議(轉(zhuǎn)載)...2007-01-01

