熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

深入討論JAVA字節碼加密技術(2)

2013-11-23 19:48:56  來源: Java高級技術 

  這個累加載器(EncryptedClassLoader)有兩個基本的操作在給定的類路徑下加密一系列Class文件並且運行一個先前加密的程序加密後的文件很簡單有一些極討厭的各個字節的位組成(當然XOR運算符不可能被加密這只是一個范例請多多包涵
  
    通過EncryptedClassLoader來加載類需要注意一些問題我實現的是繼承自URLClassLoader並且重載了loadClass()和defineClass()兩個方法來實現自己的兩個功能一個是專心於JAVA 類加載器的委托規則並且在系統類加載器做之前先加載一個經加密過的類;二是在執行defineClass()之前立即調用crypt()方法否則會執行URLClassLoaderfindClass()
  
    執行下面的語句
  
  >javac d bin src/*java src/my/secret/code/*java
  
  
  
    我把Mainclass和MySecretClassclass進行了加密
  
  >java cp bin EncryptedClassLoader encrypt bin Main my
  deMySecretClass
  encrypted [Mainclass]
  encrypted [my\secret\code\MySecretClassclass]
  
  
  
    現在原先編譯的class文件已經被加密後的文件所替代了如果我想運行原始類文件需要使用EncryptedClassLoader來操作
  
  >java cp bin Main
  Exception in thread main javalangClassFormatError:
   Main (Illegal constant pool type)
   at javalangClassLoaderdefineClass(Native Method)
   at javalangClassLoaderdefineClass(ClassLoaderjava:)
   at javasecuritySecureClassLoaderdefineClass
   (SecureClassLoaderjava:)
   at URLClassLoaderdefineClass(URLClassLoaderjava:)
   at URLClassLoaderaccess$(URLClassLoaderjava:)
   at URLClassLoader$run(URLClassLoaderjava:)
   at javasecurityAccessControllerdoPrivileged(Native Method)
   at URLClassLoaderfindClass(URLClassLoaderjava:)
   at javalangClassLoaderloadClass(ClassLoaderjava:)
   at sunmiscLauncher$AppClassLoaderloadClass(Launcherjava:)
   at javalangClassLoaderloadClass(ClassLoaderjava:)
   at javalangClassLoaderloadClassInternal(ClassLoaderjava:)
  
  >java cp bin EncryptedClassLoader run bin Main
  decrypted [Main]
  decrypted [deMySecretClass]
  secret result =
  
  
  
    現在可以確信采用任何反編譯工具對加密後的Class文件都不會起作用的
  
    現在添加一個可靠的密碼保護機制把它打包成本地可執行文件並且使其對外收費這樣子可以嗎?當然不能這樣了
  
    ClassLoaderdefineClass():必然經過的接口
  
    所有的類加載器必須經過明確地API把類定義傳遞到JVM裡這就需要javalangClassLoaderdefineClass()方法了類加載器的API有多個這個方法的重載但是所有的方法都會調用defineClass(String byte[] int int ProtectionDomain)這是一個在經過一些簡單驗證後放入到JVM裡的最終的方法如果你想建立一個新的Class文件的話這對於理解每個類加載器都會不可避免的調用該方法是很重要的
  
    你只能在方法defineClass()裡把一些單調的字節數組生成Class對象並且我們猜測這些字節數組文件會包含一些文檔格式化(查看class文件格式規范welldocument.d format)的未加密的class定義通過攔截對該方法的所有調用可以很簡單的破壞這種加密模式並且很方便的反編譯你感興趣的Class文件
  
    做這種攔截並不困難實際上破壞自己建立的保護模式比用工具更加迅速的首先我取得基於JSDK的javalangClassLoader源文件並修改defineClass(String byte[] int int ProtectionDomain)方法在裡面加入其他的類正如下面
  
  
  c = defineClass(name b off len protectionDomain);
  //Intercept classes defined by the system loader and its children:
  if (isAncestor (getSystemClassLoader ()getParent ()))
   {
   // Choose your own dump location here [use an absolute pathname]:
   final File parentDir = new File (c:/TEMP/classes/);
   File dump = new File (parentDir
   namereplace ( FileseparatorChar) + [ +
   getClass ()getName () + @ +LongtoHexString
   (SystemidentityHashCode (this)) + ]class);
  
   dumpgetParentFile ()mkdirs ();
  
   FileOutputStream out = null;
   try
   {
   out = new FileOutputStream (dump);
   outwrite (b off len);
   }
   catch (IOException ioe)
   {
   ioeprintStackTrace (Systemout);
   }
   finally
   {
   if (out != null) try { outclose (); }
   catch (Exception ignore) {}
   }
   }
  
  
  
  
    注意if裡的語句可以過濾系統類加載器及其子類加載器同樣在defineClass()方法可以正常工作的情況下才能載入類很難以相信不只有一個類加載器實例加載一個類可通過在文件名堆裡面加入類加載器標志我還是最終把這一問題給解決了
  
    最後一步是用包含javalangClassLoader類的可執行文件臨時替換由JRE使用的文件rtjar你也可以使用Xbootclasspath/p選項
  
    我再一次運行加密的程序並恢復了所有的未加密的文件這麼說可以很容易的把class文件正確的反編譯我先聲明我並沒有用EncryptedClassLoader類的內部機制來完成此壯舉的
  
    在這裡注意一點假如我沒去使用一個系統類我可以使用別的方法比如自定義一個JVMPI代理來處理JVMPI_EVENT_CLASS_LOAD_HOOK事件
  
    學習小結
  
    我希望你能對本文有所興趣你必須認識到得很重要的一點是在購買市面上任何反編譯工具前要三思而行除非JVM體系結構進行改革以支持class字節碼在本地能進行譯碼轉換你才會更好的從傳統的困惑中走出來上演一場字節碼的改革浪潮!當然也有其他的更有效的方法對類加載進行調試盡可能地得到類加載的軌跡是很有價值的特別是在類加載時你去捕獲異常情況下使用因此JAVA的誕生可能純粹是為了開源項目當然其他一些體系結構(如NET)也正在傾向於反編譯目前我就說說這種思想了
  

From:http://tw.wingwit.com/Article/program/Java/gj/201311/27493.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.