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