用Java或.NET來開發軟體,都必須注意到一件事實:Java或.NET的程式特別容易被反編譯(decompiling)。Java/.NET的程式容易被反編譯,是因為:

1. 採用兩階段式編譯,中間碼和源碼之間非常接近,所以容易反編譯。
2. Java Class File與.NET Managed PE檔保留相當多符號資訊以及metadata。
3. 使用的指令Opcode不多,且重複性太高。Java一直以來只有約202個Opcode,.NET 1.0/1.1只有213個Opcode。
4. Java和.NET的Opcode都相當高階。
5. 兩者都是使用Stack-Based的架構,指令之間的關係簡單,容易反向推導。
6. 許多程式沒有使用混淆器。
7. 現代程式架構良好,模組切割得當。

反編譯牽涉到法律、道德、和技術
如果你還是不相信我說的話,你可以去看看這本由Godfrey Nolan所寫的《Decompiling Java》,保證你看得心驚膽跳。這本書早在上個世紀末(1999年)就預計在McGraw Hill出版社出版,但是似乎由於內容敏感,所以面對許多壓力。幾經延宕,這本書在五年後終於出版,而出版社也換成了APress。反編譯不只是技術議題,還牽涉到法律和道德上的爭議,這正是本書的壓力來源。

上個世紀末的時候,作者曾經在網路上感嘆這本書可能會出版不成,於是作者把大部分的內容做成PDF放到網路上讓人下載,我正是當時PDF版的讀者之一。五年前我正在寫碩士論文,我的論文主題是Java Obfuscator,所以這本書的PDF檔讓我如獲至寶。

《Decompiling Java》討論的是反編譯Java的作法。本書共有七章:第一章介紹反編譯的概念,這一章有一些真實的故事,相當有趣;第二章介紹JVM(Java虛擬機器)的基本概念,以及Java Bytecode的檔案結構;第三章介紹現有的反組譯工具、反編譯工具、混淆器,是相當實用的一章;第四章介紹保護程式免於被他人反編譯的作法,這一章很重要;第五章介紹反編譯器的設計;第六章介紹反編譯器的實踐;第七章有一些案例說明,以及優缺點分析。這本書的精華在第四章到第六章,這部分的內容比較不容易在其他地方閱讀到。

反編譯器可以被視為是另類編譯器,所以實作方法和編譯器差不多,也是包括了分析(analysis)和合成(synthesis)兩個階段。對於反編譯來說,分析的程式(parser)很好寫,以我的經驗,只要兩三天就可以寫完Java Bytecode的parser(前提是使用對的程式語言),但是合成的部分就很不容易寫,寫出來的好壞也會差很多。幸好《Decompiling Java》的第六章對此頗有著墨,所以如果你真的要實作自己的Java反編譯器,那麼第六章應該會對你幫助很大。

想反編譯的人,以及不想被反編譯的人,都需要看本書需要閱讀《Decompiling Java》的讀者可以分成兩大類?一類是想要反編譯他人的程式者,另一類是想要保護自己的程式者。對於第一類的人來說,需要注意第二、三、五、六章;對於第二類的人來說,需要注意第四章。另外,想瞭解Java Bytecode檔案格式的讀者,也可以閱讀本書。本書第二章對於Java Bytecode的敘述還算完整,所以只要閱讀本書,可以不用閱讀《The Java Virtual Machine Specification》。

因為五年前XML剛起步,尚未席捲IT界,所以本書五年前PDF版所使用的Java Bytecode敘述格式是類似javap的反組譯結果,但是現在印刷版和以前PDF版的作法不同,改用XML的格式。

我注意到本書的缺點包括了:
● 沒有包含Java 5新增的格式。
● 圖少得離譜。
● 沒有提供反編譯器。作者有實作自己的Java反編譯器,卻沒有把它貢獻給讀者。
但是瑕不掩瑜,我還是覺得這是一本很棒的書。由於Java和.NET許多原理都是相通的,所以對於想要實作.NET反編譯器的人來說,依然具有參考價值。

《作者簡介》蔡學鏞
清華大學資訊工程碩士,曾任華碩集團軟體工程師、元智大學資訊系講師,現為寰震科技技術經理、美商歐萊禮出版社顧問、臺灣微軟特約的專欄作家。
蔡學鏞曾擔任數個研討會講師(包括 JavaTwo、TechEd、資策會)。參與設計清華大學 Java VOD 系統,該系統並獲得第一屆 Java Cup 比賽校園組冠軍。參與設計 Java To .NET Migration,成為美國微軟十大成功案例之一。

熱門新聞

Advertisement