首页编程java编程java代码加密防止反编译(Java编译器)

java代码加密防止反编译(Java编译器)

编程之家2026-05-271072次浏览

各位老铁们好,相信很多人对java代码加密防止反编译都不是特别的了解,因此呢,今天就来为大家分享下关于java代码加密防止反编译以及Java编译器的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!

java代码加密防止反编译(Java编译器)

一些防止 Java 代码被反编译的方法

防止Java代码被反编译的方法主要包括以下几种:

隔离Java程序:通过将关键的Java Class放在服务器端,客户端通过访问服务器的相关接口来获得服务,而不是直接访问Class文件。这种方法可以防止用户直接访问到Java Class程序,从而增加反编译的难度。

对Class文件进行加密:对关键的Class文件进行加密,例如对注册码、序列号管理相关的类等。在使用这些被加密的类之前,程序首先需要对这些类进行解密,然后再将这些类装载到JVM当中。自定义的ClassLoader可以用来完成加密类的装载。

转换成本地代码:将程序转换成本地代码,因为本地代码往往难以被反编译。开发人员可以选择将整个应用程序转换成本地代码,也可以选择关键模块转换。如果仅仅转换关键部分模块,Java程序在使用这些模块时,需要使用JNI技术进行调用。

代码混淆:对Class文件进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能(语义),但是混淆后的代码很难被反编译。混淆技术包括符号混淆、数据混淆、控制混淆和预防性混淆。符号混淆:将方法名称、变量名称等符号信息打乱,变成无任何意义的表示,增加反编译的难度。

数据混淆:对程序使用的数据进行混淆,包括改变数据存储及编码、改变数据访问等方式。

java代码加密防止反编译(Java编译器)

控制混淆:对程序的控制流进行混淆,增加额外的计算和控制流,使得程序的控制流更加难以反编译。

预防性混淆:针对一些专用的反编译器而设计的混淆方法,利用反编译器的弱点或者Bug来设计混淆方案。

在实际应用中,通常需要综合使用这些方法,而不是单一使用某一种方法,以提高Java程序的保护效果。

如何防止代码被反编译

由于apk是Android虚拟机加载的,它有一定的规范,加密apk后Dalvik无法识别apk了。完全避免是不可能的,总有人能够破解你的代码。但是有几种方式来提高被反编译取代码的难度。

1关键代码使用jni调用本地代码,用c或者c++编写,因此相对比较难于反编译

2混淆java代码。混淆是不改变代码逻辑的情况下,增加无用代码,或者重命名,使反编译后的源代码难于看懂。网上开源的java代码混淆工具较多,一般是用ant的方式来编译的。

java代码加密防止反编译(Java编译器)

1.在工程文件project.properties中加入下proguard.config=proguard.cfg,如下所示:

target=android-8

proguard.config=proguard.cfg

Eclipse会通过此配置在工程目录生成proguard.cfg文件

2.生成keystore(如已有可直接利用)

按照下面的命令行在D:\Program Files\Java\jdk1.6.0_07\bin>目录下,输入keytool-genkey-alias android.keystore-keyalg RSA-validity 100000-keystore android.keystore

参数意义:-validity主要是证书的有效期,写100000天;空格,退格键都算密码。

命令执行后会在D:\Program Files\Java\jdk1.6.0_07\bin>目录下生成 android.keystore文件。

3.在Eclipce的操作

File-> Export-> Export Android Application-> Select project-> Using the existing keystore, and input password-> select the destination APK file

经过混淆后的源代码,原先的类名和方法名会被类似a,b,c。。。的字符所替换,混淆的原理其实也就是类名和方法名的映射。

但4大组件并没有混淆(所有在清单文件定义的组件不能被混淆),因为系统需要通过清单文件来查找和运行应用程序。

proguard.cfg文件代码解读

-optimizationpasses 5->设置混淆的压缩比率 0~ 7

-dontusemixedcaseclassnames-> Aa aA

-dontskipnonpubliclibraryclasses->如果应用程序引入的有jar包,并且想混淆jar包里面的class

-dontpreverify

-verbose->混淆后生产映射文件 map类名->转化后类名的映射

-optimizations!code/simplification/arithmetic,!field/*,!class/merging/*->混淆采用的算法.

-keep public class* extends android.app.Activity->所有activity的子类不要去混淆

-keep public class* extends android.app.Application

-keep public class* extends android.app.Service

-keep public class* extends android.content.BroadcastReceiver

-keep public class* extends android.content.ContentProvider

-keep public class* extends android.app.backup.BackupAgentHelper

-keep public class* extends android.preference.Preference

-keep public class com.android.vending.licensing.ILicensingService

-keepclasseswithmembernames class*{

native<methods>;->所有native的方法不能去混淆.

}

-keepclasseswithmembers class*{

public<init>(android.content.Context, android.util.AttributeSet);

-->某些构造方法不能去混淆

}

-keepclasseswithmembers class*{

public<init>(android.content.Context, android.util.AttributeSet, int);

}

-keepclassmembers class* extends android.app.Activity{

public void*(android.view.View);

}

-keepclassmembers enum*{->枚举类不能去混淆.

public static**[] values();

public static** valueOf(java.lang.String);

}

-keep class* implements android.os.Parcelable{-> aidl文件不能去混淆.

public static final android.os.Parcelable$Creator*;

}

如何有效防止Java程序源码被人偷窥

Java程序的源代码很容易被别人偷看只要有一个反编译器任何人都可以分析别人的代码本文讨论如何在不修改原有程序的情况下通过加密技术保护源代码一为什么要加密?

对于传统的C或C++之类的语言来说要在Web上保护源代码是很容易的只要不发布它就可以遗憾的是 Java程序的源代码很容易被别人偷看只要有一个反编译器任何人都可以分析别人的代码 Java的灵活性使得源代码很容易被窃取但与此同时它也使通过加密保护代码变得相对容易我们唯一需要了解的就是Java的ClassLoader对象当然在加密过程中有关Java Cryptography Extension(JCE)的知识也是必不可少的

有几种技术可以模糊 Java类文件使得反编译器处理类文件的效果大打折扣然而修改反编译器使之能够处理这些经过模糊处理的类文件并不是什么难事所以不能简单地依赖模糊技术来保证源代码的安全

我们可以用流行的加密工具加密应用比如PGP(Pretty Good Privacy)或GPG(GNU Privacy Guard)这时最终用户在运行应用之前必须先进行解密但解密之后最终用户就有了一份不加密的类文件这和事先不进行加密没有什么差别

Java运行时装入字节码的机制隐含地意味着可以对字节码进行修改 JVM每次装入类文件时都需要一个称为ClassLoader的对象这个对象负责把新的类装入正在运行的JVM JVM给ClassLoader一个包含了待装入类(比如java lang Object)名字的字符串然后由ClassLoader负责找到类文件装入原始数据并把它转换成一个Class对象

我们可以通过定制ClassLoader在类文件执行之前修改它这种技术的应用非常广泛??在这里它的用途是在类文件装入之时进行解密因此可以看成是一种即时解密器由于解密后的字节码文件永远不会保存到文件系统所以窃密者很难得到解密后的代码

由于把原始字节码转换成Class对象的过程完全由系统负责所以创建定制ClassLoader对象其实并不困难只需先获得原始数据接着就可以进行包含解密在内的任何转换

Java在一定程度上简化了定制ClassLoader的构建在Java中 loadClass的缺省实现仍旧负责处理所有必需的步骤但为了顾及各种定制的类装入过程它还调用一个新的findClass方法

这为我们编写定制的ClassLoader提供了一条捷径减少了麻烦只需覆盖findClass而不是覆盖loadClass这种方法避免了重复所有装入器必需执行的公共步骤因为这一切由loadClass负责

不过本文的定制ClassLoader并不使用这种方法原因很简单如果由默认的ClassLoader先寻找经过加密的类文件它可以找到;但由于类文件已经加密所以它不会认可这个类文件装入过程将失败因此我们必须自己实现loadClass稍微增加了一些工作量

二定制类装入器

每一个运行着的JVM已经拥有一个ClassLoader这个默认的ClassLoader根据CLASSPATH环境变量的值在本地文件系统中寻找合适的字节码文件

应用定制ClassLoader要求对这个过程有较为深入的认识我们首先必须创建一个定制ClassLoader类的实例然后显式地要求它装入另外一个类这就强制JVM把该类以及所有它所需要的类关联到定制的ClassLoader Listing显示了如何用定制ClassLoader装入类文件

【Listing利用定制的ClassLoader装入类文件】

以下是引用片段

//首先创建一个ClassLoader对象 ClassLoader myClassLoader= new myClassLoader();//利用定制ClassLoader对象装入类文件//并把它转换成Class对象 Class myClass= myClassLoader loadClass( mypackage MyClass);//最后创建该类的一个实例 Object newInstance= myClass newInstance();//注意 MyClass所需要的所有其他类都将通过//定制的ClassLoader自动装入

如前所述定制ClassLoader只需先获取类文件的数据然后把字节码传递给运行时系统由后者完成余下的任务

ClassLoader有几个重要的方法创建定制的ClassLoader时我们只需覆盖其中的一个即loadClass提供获取原始类文件数据的代码这个方法有两个参数类的名字以及一个表示JVM是否要求解析类名字的标记(即是否同时装入有依赖关系的类)如果这个标记是true我们只需在返回JVM之前调用resolveClass

【Listing ClassLoader loadClass()的一个简单实现】

以下是引用片段

public Class loadClass( String name boolean resolve) throws ClassNotFoundException{ try{//我们要创建的Class对象 Class clasz= null;//必需的步骤如果类已经在系统缓冲之中//我们不必再次装入它 clasz= findLoadedClass( name); if(clasz!= null) return clasz;//下面是定制部分 byte classData[]=/*通过某种方法获取字节码数据*/; if(classData!= null){//成功读取字节码数据现在把它转换成一个Class对象 clasz= defineClass( name classData classData length);}//必需的步骤如果上面没有成功//我们尝试用默认的ClassLoader装入它 if(clasz== null) clasz= findSystemClass( name);//必需的步骤如有必要则装入相关的类 if(resolve&& clasz!= null) resolveClass( clasz);//把类返回给调用者 return clasz;} catch( IOException ie){ throw new ClassNotFoundException( ie toString());} catch( GeneralSecurityException gse){ throw new ClassNotFoundException( gse toString());}}

Listing显示了一个简单的loadClass实现代码中的大部分对所有ClassLoader对象来说都一样但有一小部分(已通过注释标记)是特有的在处理过程中 ClassLoader对象要用到其他几个辅助方法

findLoadedClass用来进行检查以便确认被请求的类当前还不存在 loadClass方法应该首先调用它

defineClass获得原始类文件字节码数据之后调用defineClass把它转换成一个Class对象任何loadClass实现都必须调用这个方法

findSystemClass提供默认ClassLoader的支持如果用来寻找类的定制方法不能找到指定的类(或者有意地不用定制方法)则可以调用该方法尝试默认的装入方式这是很有用的特别是从普通的JAR文件装入标准Java类时

resolveClass当JVM想要装入的不仅包括指定的类而且还包括该类引用的所有其他类时它会把loadClass的resolve参数设置成true这时我们必须在返回刚刚装入的Class对象给调用者之前调用resolveClass

三加密解密

Java加密扩展即Java Cryptography Extension简称JCE它是Sun的加密服务软件包含了加密和密匙生成功能 JCE是JCA(Java Cryptography Architecture)的一种扩展

JCE没有规定具体的加密算法但提供了一个框架加密算法的具体实现可以作为服务提供者加入除了JCE框架之外 JCE软件包还包含了SunJCE服务提供者其中包括许多有用的加密算法比如DES(Data Encryption Standard)和Blowfish

为简单计在本文中我们将用DES算法加密和解密字节码下面是用JCE加密和解密数据必须遵循的基本步骤

步骤生成一个安全密匙在加密或解密任何数据之前需要有一个密匙密匙是随同被加密的应用一起发布的一小段数据 Listing显示了如何生成一个密匙【Listing生成一个密匙】

以下是引用片段

// DES算法要求有一个可信任的随机数源 SecureRandom sr= new SecureRandom();//为我们选择的DES算法生成一个KeyGenerator对象 KeyGenerator kg= KeyGenerator getInstance( DES); kg init( sr);//生成密匙 SecretKey key= kg generateKey();//获取密匙数据 byte rawKeyData[]= key getEncoded();/*接下来就可以用密匙进行加密或解密或者把它保存为文件供以后使用*/ doSomething( rawKeyData);步骤加密数据得到密匙之后接下来就可以用它加密数据除了解密的ClassLoader之外一般还要有一个加密待发布应用的独立程序(见Listing)【Listing用密匙加密原始数据】

以下是引用片段

// DES算法要求有一个可信任的随机数源 SecureRandom sr= new SecureRandom(); byte rawKeyData[]=/*用某种方法获得密匙数据*/;//从原始密匙数据创建DESKeySpec对象 DESKeySpec dks= new DESKeySpec( rawKeyData);//创建一个密匙工厂然后用它把DESKeySpec转换成//一个SecretKey对象 SecretKeyFactory keyFactory= SecretKeyFactory getInstance( DES); SecretKey key= keyFactory generateSecret( dks);// Cipher对象实际完成加密操作 Cipher cipher= Cipher getInstance( DES);//用密匙初始化Cipher对象 cipher init( Cipher ENCRYPT_MODE key sr);//现在获取数据并加密 byte data[]=/*用某种方法获取数据*///正式执行加密操作 byte encryptedData[]= cipher doFinal( data);//进一步处理加密后的数据 doSomething( encryptedData);步骤解密数据运行经过加密的应用时 ClassLoader分析并解密类文件操作步骤如Listing所示【Listing用密匙解密数据】

// DES算法要求有一个可信任的随机数源 SecureRandom sr= new SecureRandom(); byte rawKeyData[]=/*用某种方法获取原始密匙数据*/;//从原始密匙数据创建一个DESKeySpec对象 DESKeySpec dks= new DESKeySpec( rawKeyData);//创建一个密匙工厂然后用它把DESKeySpec对象转换成//一个SecretKey对象 SecretKeyFactory keyFactory= SecretKeyFactory getInstance( DES); SecretKey key= keyFactory generateSecret( dks);// Cipher对象实际完成解密操作 Cipher cipher= Cipher getInstance( DES);//用密匙初始化Cipher对象 cipher init( Cipher DECRYPT_MODE key sr);//现在获取数据并解密 byte encryptedData[]=/*获得经过加密的数据*///正式执行解密操作 byte decryptedData[]= cipher doFinal( encryptedData);//进一步处理解密后的数据 doSomething( decryptedData);

四应用实例

前面介绍了如何加密和解密数据要部署一个经过加密的应用步骤如下

步骤创建应用我们的例子包含一个App主类两个辅助类(分别称为Foo和Bar)这个应用没有什么实际功用但只要我们能够加密这个应用加密其他应用也就不在话下

步骤生成一个安全密匙在命令行利用GenerateKey工具(参见GenerateKey java)把密匙写入一个文件% java GenerateKey key data

步骤加密应用在命令行利用EncryptClasses工具(参见EncryptClasses java)加密应用的类% java EncryptClasses key data App class Foo class Bar class

该命令把每一个 class文件替换成它们各自的加密版本

步骤运行经过加密的应用用户通过一个DecryptStart程序运行经过加密的应用 DecryptStart程序如Listing所示【Listing DecryptStart java启动被加密应用的程序】

以下是引用片段

import java io*; import java security*; import java lang reflect*; import javax crypto*; import javax crypto spec*; public class DecryptStart extends ClassLoader{//这些对象在构造函数中设置//以后loadClass()方法将利用它们解密类 private SecretKey key; private Cipher cipher;//构造函数设置解密所需要的对象 public DecryptStart( SecretKey key) throws GeneralSecurityException IOException{ this key= key; String algorithm= DES; SecureRandom sr= new SecureRandom(); System err println( [DecryptStart: creating cipher]); cipher= Cipher getInstance( algorithm); cipher init( Cipher DECRYPT_MODE key sr);}// main过程我们要在这里读入密匙创建DecryptStart的//实例它就是我们的定制ClassLoader//设置好ClassLoader以后我们用它装入应用实例//最后我们通过Java Reflection API调用应用实例的main方法 static public void main( String args[]) throws Exception{ String keyFilename= args[ ]; String appName= args[ ];//这些是传递给应用本身的参数 String realArgs[]= new String[args length ]; System arraycopy( args realArgs args length);//读取密匙 System err println( [DecryptStart: reading key]); byte rawKey[]= Util readFile( keyFilename); DESKeySpec dks= new DESKeySpec( rawKey); SecretKeyFactory keyFactory= SecretKeyFactory getInstance( DES); SecretKey key= keyFactory generateSecret( dks);//创建解密的ClassLoader DecryptStart dr= new DecryptStart( key);//创建应用主类的一个实例//通过ClassLoader装入它 System err println( [DecryptStart: loading+appName+ ]); Class clasz= dr loadClass( appName);//最后通过Reflection API调用应用实例//的main()方法//获取一个对main()的引用 String proto[]= new String[ ]; Class mainArgs[]={(new String[ ]) getClass()}; Method main= clasz getMethod( main mainArgs);//创建一个包含main()方法参数的数组 Object argsArray[]={ realArgs}; System err println( [DecryptStart: running+appName+ main()]);//调用main() main invoke( null argsArray);} public Class loadClass( String name boolean resolve) throws ClassNotFoundException{ try{//我们要创建的Class对象 Class clasz= null;//必需的步骤如果类已经在系统缓冲之中//我们不必再次装入它 clasz= findLoadedClass( name); if(clasz!= null) return clasz;//下面是定制部分 try{//读取经过加密的类文件 byte classData[]= Util readFile( name+ class); if(classData!= null){//解密 byte decryptedClassData[]= cipher doFinal( classData);//再把它转换成一个类 clasz= defineClass( name decryptedClassData decryptedClassData length); System err println( [DecryptStart: decrypting class+name+ ]);}} catch( FileNotFoundException fnfe)//必需的步骤如果上面没有成功//我们尝试用默认的ClassLoader装入它 if(clasz== null) clasz= findSystemClass( name);//必需的步骤如有必要则装入相关的类 if(resolve&& clasz!= null) resolveClass( clasz);//把类返回给调用者 return clasz;} catch( IOException ie){ throw new ClassNotFoundException( ie toString());} catch( GeneralSecurityException gse){ throw new ClassNotFoundException( gse toString());}}}对于未经加密的应用正常执行方式如下% java App arg arg arg

对于经过加密的应用则相应的运行方式为% java DecryptStart key data App arg arg arg

DecryptStart有两个目的一个DecryptStart的实例就是一个实施即时解密操作的定制ClassLoader;同时 DecryptStart还包含一个main过程它创建解密器实例并用它装入和运行应用示例应用App的代码包含在App java Foo java和Bar java内 Util java是一个文件I/O工具本文示例多处用到了它完整的代码请从本文最后下载

五注意事项

我们看到要在不修改源代码的情况下加密一个Java应用是很容易的不过世上没有完全安全的系统本文的加密方式提供了一定程度的源代码保护但对某些攻击来说它是脆弱的

虽然应用本身经过了加密但启动程序DecryptStart没有加密攻击者可以反编译启动程序并修改它把解密后的类文件保存到磁盘降低这种风险的办法之一是对启动程序进行高质量的模糊处理或者启动程序也可以采用直接编译成机器语言的代码使得启动程序具有传统执行文件格式的安全性

另外还要记住的是大多数JVM本身并不安全狡猾的黑客可能会修改JVM从ClassLoader之外获取解密后的代码并保存到磁盘从而绕过本文的加密技术 Java没有为此提供真正有效的补救措施

lishixinzhi/Article/program/Java/hx/201311/25751

好了,文章到此结束,希望可以帮助到大家。

动态网页制作(网页设计制作网站模板)php源码泄露漏洞,php漏洞怎么修复