標籤:
沒有比發現一個錯誤,卻沒有原始碼就不能修改更令人沮喪的了。正是這個原因導致了 Java 反編譯器的出現,它可以把編譯後的位元組碼完全轉回成原始碼。儘管代碼反編譯器不只是針對 Java 語言,但它從來沒有象在 Java 開發人員中那樣被公開地或廣泛地使用。
與反編譯針鋒相對的是模糊處理。假設反編譯人員能很容易從編譯後的代碼中設法得到原始碼,那麼要保護您的代碼和有價值的技術秘密就不是那麼簡單了。隨著 Java 反編譯器的普遍使用, Java 模糊處理器也同樣被普及,它的作用就好像放一塊煙幕在您的代碼前面。反編譯和模糊處理在商業開發領域中引起了一場爭論 -- 爭論中的大部分都集中在了 Java 語言上。
在本文中,我將讓您瞭解代碼反編譯和模糊處理的具體過程,討論在這兩種技術之後的理論問題,同時簡要地談到它們在商業編程領域中所引起的爭論。我還將介紹一些比較有名的反編譯器和模糊處理器(有商業的,也有開放原始碼的),並隨著文章的深入使用它們來建立一些執行個體。
什麼是反編譯? 反編譯是一個將目標代碼轉換成原始碼的過程。這應該很清楚了,因為編譯是一個將原始碼轉換成目標代碼的過程。但什麼是目標代碼呢?大體上的定義是:目標代碼是一種用語言表示的代碼,這種語言能通過實機或虛擬機器直接執行。對於象 C 這樣的語言,目標代碼通常運行在硬體 CPU 上,而 Java 目標代碼通常運行在虛擬機器上。
反編譯是困難的 正如以上所描述的,反編譯聽上去比較簡單,但它實際上是非常困難的 -- 從本質上說,它所包含的是根據小規模、低層次的行為來推斷大規模、高層次的行為。為了對此有個直觀的理解,我們把一個電腦程式看作是一個複雜的公司組織圖。高層管理員向他們的下屬下達類似“最大程度地提高技術生產能力”的命令,下屬們再把這些命令轉變成更具體的行動,例如安裝新的 XML 資料庫。
作為該公司的新僱員,您可能會問下屬他或她在做些什麼,並得到回答,“我在安裝新的 XML 資料庫。”從這句話中,您不可能推斷出其最終目的是最大程度地提高技術生產能力。畢竟,最終目標不盡相同,例如可能是分離供應鏈或累積消費者的資料。
然而,如果屬於好奇心特強的那類人,您可能會再多問幾個問題,並讓公司中不同層級的下屬回答您的問題。最後,當把所有的答案匯總後,您可能會猜到企業更大的目標是最大程度地提高技術生產能力。
如果您把電腦程式的工作方式看作類似一個公司的組織圖,那麼對於為什麼反編譯代碼不是無關緊要的,以上的這個比方就會給你一個直接的感受。從比較理論化的角度來看,這兒要引用在該領域的傑出研究員 Cristina Cifuentes 對反編譯過程的描述:
任何一個二進位改造工程都需要對儲存在二進位檔案中的代碼進行反組譯碼。從理論上說,分離 von Neumann 上的資料和代碼就好象停機問題,因此完全的靜態翻譯是不可能的。然而,實際上可以使用不同技術來提高可被靜態翻譯的代碼的所佔比例,或者採取可在運行中被使用的動態翻譯技術。 --"Binary Reengineering of Distributed Object Technology"(請參閱參考資料)
把目標代碼轉換成原始碼並不是反編譯時間碰到的唯一問題。一個 Java 類檔案潛在包含了一些不同類型的資訊。知道類檔案中可能包含了哪類資訊對於瞭解您如何利用該資訊以及對於資訊作何種處理都是很重要的。這其實就是 Java 反組譯碼器所要做的。
反組譯碼一個類檔案 Java 類檔案的真正二進位格式不是很重要。重要的是知道在那些位元組中包含了哪些不同種類的資訊。到了這一步,我們將利用多數 JDK 都帶有的一個工具 -- javap。 javap 是一個 Java 代碼反組譯碼器,它和反編譯器是不同的。反組譯碼器把機器可讀格式的目標代碼(如清單 1 所示)轉換成人們可讀的代碼(如清單 2 所示)。
清單 1. 一個類檔案的原始內容0000000 feca beba 0300 2d00 4200 0008 081f 34000000020 0008 073f 2c00 0007 0735 3600 0007 07370000040 3800 0007 0a39 0400 1500 000a 0007 0a150000060 0800 1600 000a 0008 0a17 0800 1800 0009...
清單 2. javap 的輸出結果Local variables for method void priv(int) Foo this pc=0, length=35, slot=0 int argument pc=0, length=35, slot=1Method void main(java.lang.String[]) 0 new #4 3 invokespecial #10 6 return
請注意,清單 2 所示的並不是原始碼。該清單的第一部分列出了方法的局部變數;第二部分是彙編代碼,它也是人們可讀的目標代碼。
一個類檔案中的元素 javap 被用來反組譯碼或解包一個類檔案。這裡簡要列出了可以通過使用 javap 進行反組譯碼的 Java 類檔案所包含的資訊:
- 成員變數。每個類檔案中包含了對應於該類每個資料成員的所有名稱資訊和類型資訊。
- 經過反組譯碼後的方法。類的每一個方法都是由一串虛擬機器指令來表示的,並附帶它的類型簽名。
- 行號。每個方法中的每個節被映射到原始碼行,在可能的情況下,原始碼行來產生節。這使得即時系統和調試器能夠為在運行狀態的程式提供堆疊追蹤。
- 局部變數名一旦方法被編譯了,這個方法的局部變數就不太需要名稱了,但是能通過對 javac 編譯器使用 -g 選項來包含它們。這也使得即時系統和調試器能協助您。
既然對 Java 類檔案的內部情況已有所瞭解,那麼下一篇如何讓我們看,如何能轉換這些資訊來達到我們的目的。那麼有想瞭解如何防止反編譯的小夥伴,小編在此推薦一個相關防護教程:
友情推薦愛加密:關於某社交app的安全分析 簡單介紹下app防止反編譯的方法
關於:Java 類檔案的內部情況課程詳析