知识大全 JAVA语言安全行研究--Java的反编译

Posted

篇首语:怀抱观古今,寝食展戏谑。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 JAVA语言安全行研究--Java的反编译相关的知识,希望对你有一定的参考价值。

JAVA语言安全行研究--Java的反编译  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  Java诞生于 年 是一门较年轻的语言 它以平台无关性 安全性 面向对象 分布式 键壮性等特点赢得了众多程序员的青睐 特别是它简洁的面向对象的语言风格 更让许多人对它爱不释手 但人们在使用Java的过程中 会发现它有几个致命的弱点 运行速度慢 用户使用不便 源代码保护机制不够安全 特别是在保护源代码方面 Java是基于解释一种叫Java字节码的中间代码来运行其程序的 而且Jvm比计算机的微处理器要简单的多 文档也很齐全 结果造成其目标程序很容易被反编译 而且所得代码和其原始代码十分相似 甚至可以一模一样 可读性相当好 这就给Java的代码保护带来了不利 但要实现Java程序的保护 也不是不可能的 经研究和总结 至少有三种实现方式 混淆器 网络加载重要类 加密重要类

   混淆器

  目前 开发人员使用的比较多的保护代码的方法是用混淆器 混淆器是采用一些方法将类 变量 方法 包的名字改为无意义的字符串 使用非法的字符代替符号 贴加一些代码使反编译软件崩溃 贴加一些无关的指令或永远执行不到的指令等使反编译无法成功或所得的代码可读性很差 这样就实现了反反编译的目的 我们来做个演示 原始代码如下

  

  import Java io *   import Java security *   public class sKey_kb   public static void main(String args[]) throws Exception   FileInputStream f=new FileInputStream( key dat )   ObJectInputStream b=new ObJectInputStream(f)   Key k=(Key)b readObJect()   byte[] kb=k getEncoded()   FileOutputStream f =new FileOutputStream( keykb dat )   f write(kb)   for(int i= i   System out print(kb[i]+ )   

  使用混淆器后 再用Jad反编译得代码如下

  

  import Java io *   import Java security Key   public class sKey_kb   public skey()   public static void main(String args[])   FileInputStream fileinputstream=new FileInputStream(ma)   ObJectInputStream obJectinputstream=new ObJectInputStream(filein putstream)   Key key=(Key)b readObJect()   byte abyte []=key getEncoded()   FileOutputStream fileoutputstream=new FileOutputStream(na)   fileoutputstream write(abyte )   for(int i= i   System out print(abyte [i]+oa)      private static String a(String s)   int i=s length()   char ac[]=new char[i]   for(int J= J   return new String(ac)      private static String ma= u AA u AAFu AF u AFBu AE u AAEu AABu ABE   private static String na= u AA u AAFu AB u AA u AA u AFBu AE u AAEu AABu ABE   private static String oa= u AE   public static   ma=a(ma)   na=a(ma)   oa=a(oa)   

  混淆后 再反编译所仍然能得到源代码 但显然 所得代码与原始代码比 变得难以读懂 代码中多了其他的方法 文件名等信息也被打乱了 并且 把以上代码写进sKey_kb Java中 无法通过编译

  但是 如果在编写软件时 在软件中写入某些注册信息 或一些简单的算法 通过反编译 还是有可能得到这些信息的 从而未能达到保护软件的目的 反编译器与混淆器之间的斗争是永无止尽的 所以从其他角度去保护Java的源代码是很有必要

   网络加载重要类

  在Java中提供了一个ClassLoader类 这个类可以让我们使用类加载器将所需要的Java字节码文件加载到Jvm中 我们通过重写这个类 可以实现从网络通过url加载Java字节码文件 这样 我们就可以把一些重要的 隐秘的class放在网络服务器上 通过口令去检验是否有权限下载该类 从而实现Java代码保护的目的 其次在Java中正好提供了URLClassLoader这个类 通过此类 正好可以实现我们的目的 URLClassLoader类的基本使用方法是通过一个URL类型的数组告诉URLClassLoader类的对象是从什么地方加载类 然后使用loadclass()方法 从给定的URL中加载字节码文件 获得它的方法 然后再执行

  具体步骤如下

   创建URL

  

  URL url[]=   new URL( file:///c /classloader/web )   new URL( /Javaclass/ )   

   创建URLClassLoader对象

  URLClassLoader cl=new URLClassLoader(url)

   使用URLClassLoader对象加载字节码文件

  Class class=cl loadClass( class )

   执行静态方法

  

  Class getarg[]=   (new String [ ]) getClass()   Method m=class getMethod( main getarg)   String[] myl= arg passed arg passed )   ObJect myarg[]=myl   m invole(null myarg)

   加密重要类

  使用网络加载重要类的方法固然有一定的用处 但是 在遇到无网络的情况时 还是无法解决我们的问题 对于这种情况 我们只能把所有文件放在本地计算机上 那么 对此我们该怎么做才能保护好Java代码呢?

  其实 要实现这一点 并不难 只需要对一些重要的类实行加密就可以了 当然 在装载时 加密的类是需要解密才能被ClassLoader识别的 所以 我们必须自己创建ClassLoader类 在标准Java api中ClassLoader有几个重要的方法 创建定制ClassLoader时 我们只需覆蓋其中的一个 即loadClass 添加获取原始类文件数据的代码 这个方法有两个参数 类的名字 以及一个表示JVM是否要求解析类名字的标记(即是否同时装入有依赖关系的类) 如果这个标记为true 我们只需在返回JVM之前调用resolveClass

  原代码如下

  

  public Class loadClass( String name boolean resolve )   throws ClassNotFoundException   try   Class clasz = null   //步骤 如果类已经在系统缓冲之中 我们就不需要再次装入它   clasz = findLoadedClass( name )   if (clasz != null)   return clasz   byte classData[] = /* 通过某种方法获取字节码数据 */   if (classData != null)   clasz = defineClass( name classData classData length )      //步骤 如果上面没有成功   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() )   

  代码中的大部分对所有ClassLoader对象来说都一样 但有一小部分是特有的 在处理过程中 ClassLoader对象要用到其他几个辅助方法 findLoadedClass 用来进行检查 以便确认被请求的类当前是否存在 loadClass方法应该首先调用它 defineClass 获得原始类文件字节码数据之后 调用defineClass把它转换成对象 任何loadClass实现都必须调用这个方法 findSystemClass 提供默认ClassLoader的支持 如果用来寻找类的定制方法不能找到指定的类 则可以调用该方法尝试默认的装入方式 resolveClass 当JVM想要装入的不仅包括指定的类 而且还包括该类引用的所有其他类时 它会把loadClass的resolve参数设置成true 这时 我们必须在返回刚刚装入的Class对象给调用者之前调用resolveClass

  接下来就是加密解密部分 Java加密扩展即Java Cryptography Extension 简称JCE 是Sun的加密服务软件 包含了加密和密匙生成功能 我们可以用DES算法加密和解密字节码 用JCE加密和解密数据是要遵循一些基本步骤的(可以参考<> 这里就不祥述了)

  加密完成后 就是通过解密来获取原始类的Java字节码 可以通过一个DecryptStart程序运行经过加密的应用

  具体方法如下

  

  public class DecryptStart extends ClassLoader      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的   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 )   DecryptStart dr = new DecryptStart( key )   System err println( [DecryptStart loading +appName+ ] )   Class clasz = dr loadClass( appName )   String proto[] = new String[ ]   Class mainArgs[] = (new String[ ]) getClass()   Method main = clasz getMethod( main mainArgs )   ObJect argsArray[] = realArgs   System err println( [DecryptStart running +appName+ main()] )   main invoke( null argsArray )   

  虽然应用本身经过了加密 但启动程序DecryptStart没有加密 攻击者可以反编译启动程序并修改它 把解密后的类文件保存到磁盘 降低这种风险的办法之一是对启动程序进行高质量的模糊处理 或者 启动程序也可以采用直接编译成机器语言的代码 使得启动程序具有传统执行文件格式的安全性 比如使用Java的Jini技术 来实现解密部分 就可以作到 当然 这是需要付出一定的代价的 就是丧失了Java的最大特点——平台无关性 不过 Jni技术可以用c语言在多种平台实现 我们可以在不同的平台编写不同的启动程序

   综合实例

cha138/Article/program/Java/hx/201311/25534

相关参考

知识大全 谈谈JAVA的反编译

谈谈JAVA的反编译  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  作者因最近分析一些JAVA程

知识大全 Java语言深入 多线程程序模型研究

Java语言深入多线程程序模型研究  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  多线程是较复杂

知识大全 Java 相关的编译技术

Java相关的编译技术  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  除了Java的编译器和虚拟

知识大全 如何用javac 和java 编译运行整个Java工程

如何用javac和java编译运行整个Java工程  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 

知识大全 Java混淆编译器

Java混淆编译器  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!    最近试用了几个Java混淆

知识大全 从思路开始 Java如何实现条件编译

从思路开始Java如何实现条件编译  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  条件编译绝对是

知识大全 Java SE6调用Java编译器的两种新方法

JavaSE6调用Java编译器的两种新方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nbs

知识大全 防止JAVA代码被反编译的方法

防止JAVA代码被反编译的方法  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  我们都知道JAVA

知识大全 使用Ant编译Java工程[4]

使用Ant编译Java工程[4]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!projectget

知识大全 使用Ant编译Java工程[5]

使用Ant编译Java工程[5]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Pathlike