<option draggable='i4y2cplw'></option>
<dt lang='r8fx5p4f'><dt dropzone='u1sma41'></dt></dt>
      <lu dir='atoin60'></lu>

          文章熱詞:

          日期:2020-07-16 19:49 by Mr. Yang 516 0 收藏
          我要分享

          摘要:Java代碼混淆技術

          Java是一種跨平台的編程語言,其源碼(.java文件)被編譯成與平台無關的字節碼(.class文件),然後在運行期動态鏈接。這樣,編譯後的類文件中将包含有符号表,從而使得Java程序很容易被反編譯。相信絕大部分Java開發人員,都曾經用過諸如Jad之類的反編譯器,對Java的class 文件進行反編譯,從而觀察程序的結構與實現細節。如此一來,對于那些需要嚴格進行知識産權保護的Java應用,如何有效的保護客戶的商業投資,是開發人員經常需要面對的問題。有鑒于此,對于商業軟件來說,必須選擇一種代碼混淆工具保護我們的産品。


          使用一種或多種處理方式将class文件、java源代碼進行混淆處理後生成新的class,使混淆後的代碼不易被反編譯,被反編譯後其代碼也是難以閱讀和理解。

          這類混淆器工具很多,而且也很有成效。最常用的Java混淆工具ProGuard就是基于此原理。

          缺點:雖然混淆的代碼反編譯後不易讀懂,但對于有經驗的人,還是能找到或計算出你代碼中隐藏的敏感内容,而且在很多應用中不是全部代碼都能混淆的,往往一些關鍵的庫、類名、方法名、變量名等因使用要求的限制反而還不能混淆。


          自定義ClassLoader,将class文件和相關文件加密,運行時由此ClassLoader解密相關文件并裝載類,要起到保護作用必須自定義本地代碼執行器将自定義ClassLoader和加密解密的相關類和配套文件也保護起來。此種方式能很有效地保護java代碼。

          缺點:

          (1)可以通過替換JRE包中與類裝載相關的java類或虛拟機動态庫截獲java字節碼;

          (2)相關工具基本都是收費的,若自己開發需要開發自己代碼執行器,有一定的開發難度和工作量;

          (3)由于自定義了代碼執行器,安裝包中需要攜帶自己的JRE環境,Class在加載時必須先解密,對産品性能有影響;

          (4)對于由web容器啓動的web服務來說,其class文件是由對應web容器的classload加載的,使用成本較高。


          将java代碼靜态編譯成本地機器碼,脫離通用JRE。此種方式能夠非常有效地保護java代碼,且程序啓動比通用JVM快一些。具有代表性的是GNU的GCJ(GNU Compiler for the Java Programing Language),可以做到對java代碼完全提前編譯,但GCJ存在諸多局限性,如:對JRE 5不能完整支持、不支持JRE 6及以後的版本。

          由于java平台的複雜性,做到能及時支持最新java版本和JRE的完全提前編譯是非常困難的,所以這類工具往往采取靈活方式,該用即時編譯的地方還是要用,成爲提前編譯和即時編譯的混合體。

          缺點:使用成本高,不适用跑在容器中的web服務,java版本不支持。


          将敏感的方法和數據通過JNI(Java Native Interface,JAVA調用C/C++函數的接口)方式處理。此種方式可以看作把需要保護的代碼和數據“隔離”到動态庫中。

          缺點:

          1)隻可能将少數關鍵函數和數據做成動态鏈接庫;

          2)沒有自動化工具,隻能自己開發,使用成本高;

          3)JNI在使用過程處理不當容易造成内存洩漏。


          使用與硬件相關的專用程序将java虛拟機啓動程序加殼,将虛拟機配套文件和java程序加密,啓動的是加殼程序,由加殼程序建立一個與硬件相關的受保護的運行環境,爲了加強安全性可以和加密鎖内植入的程序互動。

          此種方式使用了專用硬件設備,安全度最高,主流的Java安全保護的商業軟件都是采用該策略。

          缺點:隻有收費軟件,自己開發基本不可能。


          對于普通Java項目,推薦采用Java混淆器方法。Java混淆器中最常用的開源工具是ProGuard,有以下幾個以優點:

          1)開源免費;

          2)安卓項目官方推薦的混淆工具,被集成進了Android SDK,技術比較成熟,網上資料也比較豐富;

          3)有對應的maven插件proguard-maven-plugin,可以方便的集成到現有的自動化構建流程中。

          缺點:

          1)如之前所說提供的保護是有限的

          2)由于ProGuard會改變包、類、方法、變量的命名,所以在某些使用了反射、與外部系統通信的Bean(controller中的bean)、某些框架中的回調函數(如springboot)、native方法等,如果被混淆運行時将會報錯,需要在配置混淆規則時排除這個class文件。


          ProGuard使用說明

          Proguard簡介

          ProGuard是一個混淆代碼的開源項目,它的主要作用是混淆代碼,ProGuard包括以下4個功能:

          1)壓縮(Shrink):檢測并移除代碼中無用的類、字段、方法和特性(Attribute)。

          2)優化(Optimize):對字節碼進行優化,移除無用的指令。

          3)混淆(Obfuscate):使用a,b,c,d這樣簡短而無意義的名稱,對類、字段和方法進行重命名。

          4)預檢(Preveirfy):在Java平台上對處理後的代碼進行預檢,确保加載的class文件是可執行的。

          Proguard是一個Java類文件壓縮器、優化器、混淆器、預校驗器。壓縮環節會檢測以及移除沒有用到的類、字段、方法以及屬性。優化環節會分析以及優化方法的字節碼。混淆環節會用無意義的短變量去重命名類、變量、方法。這些步驟讓代碼更精簡,更高效,也更難被逆向了。

          便于集成到自動化構建中,推薦以maven插件的形式使用,這裏以web工程爲例。


          <dependency>
          	<groupId>net.sf.proguard</groupId>
          	<artifactId>proguard-base</artifactId>
          	<version>6.0.1</version>
          	<scope>runtime</scope></dependency><!-- ProGuard混淆插件--><plugin>
          	<groupId>com.github.wvengen</groupId>
          	<!--<version>2.1.1</version>-->
          	<artifactId>proguard-maven-plugin</artifactId>
          	<executions>
          		<execution>
          			<!-- 混淆時刻,這裏是打包的時候混淆-->
                      <phase>package</phase>
          			<goals>
          				<!-- 使用插件的什麽功能 -->
          				<goal>proguard</goal>
          			</goals>
          		</execution>
          	</executions>
          	<configuration>
          		<proguardVersion>6.0.1</proguardVersion>
          		<!-- 加載文件的過濾器 -->
          		<inFilter>com/**</inFilter>
          		 <!-- 對什麽東西進行加載-->
          		<injar>classes</injar>
          		<!-- 輸出-->
          		<outjar>${project.build.finalName}-pg.jar</outjar>
          		<outputDirectory>${project.build.directory}</outputDirectory>
          		<obfuscate>true</obfuscate>
          		<proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
          		<libs>
          			<lib>${java.home}/lib/rt.jar</lib>
          			<lib>${project.basedir}/src/main/webapp/WEB-INF/lib</lib>
          		</libs>
          	</configuration></plugin>
          # JDK目标版本1.8-target 8# 不做收縮(删除注釋、未被引用代碼)-dontshrink# 不做優化(變更代碼實現邏輯)-dontoptimize# 确定統一的混淆類的成員名稱來增加混淆-useuniqueclassmembernames
          -adaptclassstrings
          -dontusemixedcaseclassnames
          -keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod# 不混淆main函數-keepclasseswithmembers public class * { public static void main(java.lang.String[]);}# 不混淆action包下的所有類名和方法,混淆後struts2框架江找不到對應的方法-keep class com.action.** {*;}# 不混淆所有的set/get方法,很多第三方框架(例如Shiro)會用到大量的set/get映射-keepclassmembers public class * {void set*(***);*** get*();}
          -keep class com.zxc.action.job.** { <methods>; }# 忽略告警-ignorewarnings

          執行mvn clean package 命令,執行完即可在項目根路徑下找到混淆過的jar:${project.build.finalName}-pg.jar


          上一篇:網絡遊戲服務器開發框架淺談

          下一篇:好的用戶界面設計


          評論