1. 程式人生 > >Java程式碼加密與反編譯(一):利用混淆器工具proGuard對jar包加密

Java程式碼加密與反編譯(一):利用混淆器工具proGuard對jar包加密

Java 程式碼編譯後生成的 .class 中包含有原始碼中的所有資訊(不包括註釋),尤其是在其中儲存有除錯資訊的時候。所以一個按照正常方式編譯的 Java .class 檔案可以非常輕易地被反編譯。通常情況下,反編譯可以利用現有的工具jd-gui.exe或者jad.exe。

(這兩個反編譯工具在我的資源裡有下載:

       有些情況下,為了保護java原始碼不被別人看到,通常會使用加密手段對java原始碼進行加密,加密的方式可以利用加密工具(比如java程式碼混淆工具)、使用加密演算法(如DES演算法)修改classloader對編譯好的.class檔案進行加密。

一、用java混淆器工具proGuard實現加密

這裡使用proGuard對jar包進行加密。

1. 解壓下載的proguard,解壓後進入lib檔案把proguard.jar拷貝到自己新建的資料夾裡如圖:


2. 把需要混淆的jar和jar所依賴的包也放到新建的資料夾,都放在一起,如下圖。


3. 寫一個配置檔案,名稱自己定,例如”a”檔案,舉個簡單配置檔案例子(那個proguard.map是過後自己生成的),內容如下,其中-injars:是你需要混淆的jar,-outjars:是你混淆後輸出的jar,-libraryjars:是你混淆的jar需要所依賴的jar包,後面的不在一一說明,可以參考proguard文件,配置檔案可以參考文件來對自己混淆的需求來寫配置檔案。

-injars       TheFirstDesktopApplication1.jar

-outjars      TheFirstDesktopApplication1_out.jar

-libraryjars  <java.home>/lib/rt.jar

-libraryjars appframework-1.0.3.jar

-libraryjarsswing-worker-1.1.jar

-printmappingproguard.map

-overloadaggressively

-defaultpackage ''

-allowaccessmodification

-dontoptimize

-keep public class*

{

 public protected *;

}

-keep public classorg.**

-keep public classit.**

4.   把配置檔案儲存到你建的資料夾下,如下圖。


5.點選開始,執行,輸入cmd,進入你建的資料夾下,如下圖。


6.   然後輸入命令語句:java   -jarproguard.Jar  @a 然後回車,如下圖。


7.   混淆成功,在產生TheFirstDesktopApplication1_out.jar如下圖。


8.      混淆器後,利用反編譯器jad對沒TheFirstDesktopApplication1_out.jar反編譯,多了好多a,b,c之類的類檔案,對反編譯的java檔案是很難編譯的,即說明混淆成功。

        用上面方法試了一下,發現其實混淆效果並不好,使用jd-gui反編譯工具就可以輕易看到原始碼。總結一下,網上找了幾個程式碼混淆工具效果都不好,其實現成工具看來也並不是那麼好用。

        然後想想,就換了一種方式,直接使用加密演算法對java程式碼進行解密。在下篇文章裡再寫。

ProGuard是一個免費的java類檔案壓縮,優化,混淆器.它探測並刪除沒有使用的類,欄位,方法和屬性.它刪除沒有用的說明並使用位元組碼得到最大優化.它使用無意義的名字來重新命名類,欄位和方法.

ProGuard的作用: 

1.建立緊湊的程式碼文件是為了更快的網路傳輸,快速裝載和更小的記憶體佔用. 
2.建立的程式和程式庫很難使用反向工程. 
3.所以它能刪除來自原始檔中的沒有呼叫的程式碼 
4.充分利用java6的快速載入的優點來提前檢測和返回java6中存在的類檔案. 

引數: 

  1. -include {filename}    從給定的檔案中讀取配置引數   
  2. -basedirectory {directoryname}    指定基礎目錄為以後相對的檔案名稱   
  3. -injars {class_path}    指定要處理的應用程式jar,war,ear和目錄   
  4. -outjars {class_path}    指定處理完後要輸出的jar,war,ear和目錄的名稱   
  5. -libraryjars {classpath}    指定要處理的應用程式jar,war,ear和目錄所需要的程式庫檔案   
  6. -dontskipnonpubliclibraryclasses    指定不去忽略非公共的庫類。   
  7. -dontskipnonpubliclibraryclassmembers    指定不去忽略包可見的庫類的成員。   




保留選項 

  1. -keep {Modifier} {class_specification}    保護指定的類檔案和類的成員   
  2. -keepclassmembers {modifier} {class_specification}    保護指定類的成員,如果此類受到保護他們會保護的更好   
  3. -keepclasseswithmembers {class_specification}    保護指定的類和類的成員,但條件是所有指定的類和類成員是要存在。   
  4. -keepnames {class_specification}    保護指定的類和類的成員的名稱(如果他們不會壓縮步驟中刪除)   
  5. -keepclassmembernames {class_specification}    保護指定的類的成員的名稱(如果他們不會壓縮步驟中刪除)   
  6. -keepclasseswithmembernames {class_specification}    保護指定的類和類的成員的名稱,如果所有指定的類成員出席(在壓縮步驟之後)   
  7. -printseeds {filename}    列出類和類的成員-keep選項的清單,標準輸出到給定的檔案   



 
壓縮 

  1. -dontshrink    不壓縮輸入的類檔案   
  2. -printusage {filename}   
  3. -whyareyoukeeping {class_specification}       




優化 

  1. -dontoptimize    不優化輸入的類檔案   
  2. -assumenosideeffects {class_specification}    優化時假設指定的方法,沒有任何副作用   
  3. -allowaccessmodification    優化時允許訪問並修改有修飾符的類和類的成員   




混淆 

  1. -dontobfuscate    不混淆輸入的類檔案   
  2. -printmapping {filename}   
  3. -applymapping {filename}    重用對映增加混淆   
  4. -obfuscationdictionary {filename}    使用給定檔案中的關鍵字作為要混淆方法的名稱   
  5. -overloadaggressively    混淆時應用侵入式過載   
  6. -useuniqueclassmembernames    確定統一的混淆類的成員名稱來增加混淆   
  7. -flattenpackagehierarchy {package_name}    重新包裝所有重新命名的包並放在給定的單一包中   
  8. -repackageclass {package_name}    重新包裝所有重新命名的類檔案中放在給定的單一包中   
  9. -dontusemixedcaseclassnames    混淆時不會產生形形色色的類名   
  10. -keepattributes {attribute_name,...}    保護給定的可選屬性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.  
  11. -renamesourcefileattribute {string}    設定原始檔中給定的字串常量  





Ant Example:

  1. < !-- This Ant build file illustrates how to process applications,  
  2.       by including ProGuard-style configuration options.  
  3.       Usage: ant -f applications2.xml -->
  4. <projectname="Applications"default="obfuscate"basedir="../..">
  5. <targetname="obfuscate">
  6.    <taskdefresource="proguard/ant/task.properties"
  7.             classpath="lib/proguard.jar"/>
  8.   <proguard>
  9.     <!-- Specify the input jars, output jars, and library jars. -->
  10.     -injars  in.jar  
  11.      -outjars out.jar  
  12.     -libraryjars ${java.home}/lib/rt.jar  
  13.      <!-- -libraryjars junit.jar    -->
  14.      <!-- -libraryjars servlet.jar  -->
  15.      <!-- -libraryjars jai_core.jar -->
  16.      <!-- ...                       -->
  17.     <!-- Save the obfuscation mapping to a file, and preserve line numbers. -->
  18.     -printmapping out.map  
  19.      -renamesourcefileattribute SourceFile  
  20.      -keepattributes SourceFile,LineNumberTable  
  21.     <!-- Preserve all annotations. -->
  22.     -keepattributes *Annotation*  
  23.     <!-- Preserve all public applications. -->
  24.     -keepclasseswithmembers public class * {  
  25.          public static void main(java.lang.String[]);  
  26.      }  
  27.     <!-- Preserve all native method names and the names of their classes. -->
  28.     -keepclasseswithmembernames class * {  
  29.          native <methods>;  
  30.      }  
  31.     <!-- Preserve the methods that are required in all enumeration classes. -->
  32.     -keepclassmembers class * extends java.lang.Enum {  
  33.          public static **[] values();  
  34.          public static ** valueOf(java.lang.String);  
  35.      }  
  36.     <!-- Explicitly preserve all serialization members. The Serializable  
  37.           interface is only a marker interface, so it wouldn't save them.  
  38.           You can comment this out if your library doesn't use serialization.  
  39.           If your code contains serializable classes that have to be backward  
  40.           compatible, please refer to the manual. -->
  41.     -keepclassmembers class * implements java.io.Serializable {  
  42.          static final long serialVersionUID;  
  43.          static final java.io.ObjectStreamField[] serialPersistentFields;  
  44.          private void writeObject(java.io.ObjectOutputStream);  
  45.          private void readObject(java.io.ObjectInputStream);  
  46.          java.lang.Object writeReplace();  
  47.          java.lang.Object readResolve();  
  48.      }  
  49.     <!-- Your application may contain more items that need to be preserved;  
  50.           typically classes that are dynamically created using Class.forName -->
  51.   </proguard>
  52.  < /target>
  53. < /project>