zoukankan      html  css  js  c++  java
  • JAVA 利用JNI加密class文件/自定义ClassLoader 类


    利用 JNI 对bytecode 加密.不影响java程序员的正常开发。
    09年的时候写的,现在拿出来晒晒
    ————————————————————————————
    混淆才是王道,如果混淆再加密就更酷了....
    ————————————————————————————
     一、环境
    a)  Windows_xp_Sp2_En
    b)  JavaSe_1.6
    c)  Eeclipse.buildId_M20090917-0800
    d)  Tomcat_6.02
    e)  VS2008_Sp1
    二、JAVA 程序加密关键点:
    1、ClassLoader的自定义
    代码:
    public class MyClassLoader extends ClassLoader {
    
      /**
     * @param args
       */
      private native void encrypt();
      public byte[] bytes;
      public String classDir;
      private String LocalName;
      private boolean Flag(FileInputStream fis, ByteArrayOutputStream bos) throws Exception{
      
        boolean Result = false;
        if(fis.read()==0xCA)Result=true;
        return Result;
        
      }
      @SuppressWarnings("deprecation")
      @Override
      protected Class<?> findClass(String arg0) throws ClassNotFoundException {
        
        String name;
        if(LocalName!=null)
          name=LocalName;
        else
          name=arg0;
        System.out.println("on my Findclass way");
        String ClassName = name.substring(name.lastIndexOf('.')+1) + ".class";
        String classFileName = System.getProperty("user.dir")+"\cn\drawingbox\"  + ClassName;
        try {
          FileInputStream fis = new FileInputStream(classFileName);
          ByteArrayOutputStream  bos = new ByteArrayOutputStream();
          fis.close();
          //这里调用JNI函数进行解码
          //System.getProperties().setProperties(String key,String value)
          //System.setProperties(arg0);
          System.load(classDir+"\encrypt_main.dll");
        //  System.loadLibrary("encrypt_main");
          MyClassLoader encypt_function= new MyClassLoader();
          encypt_function.classDir=classDir;
          encypt_function.bytes = bos.toByteArray();
          encypt_function.encrypt();
          
          ///////
          LocalName=null;
          return defineClass(encypt_function.bytes, 0, encypt_function.bytes.length);
        } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        return null;
      }
      @Override
      public Class<?> loadClass(String name) throws ClassNotFoundException {
        // TODO Auto-generated method stub
        
        
        boolean Result = false;
        String ClassName = name.substring(name.lastIndexOf('.')+1) + ".class";
        if(ClassName.equals("Foo.class")||ClassName.equals("bar.class")){
        String classFileName = classDir + "\"  + ClassName;
        try {
          FileInputStream fis = new FileInputStream(classFileName);
          ByteArrayOutputStream  bos = new ByteArrayOutputStream();
          Result = Flag(fis, bos);
          fis.close();
          bos.close();
        } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        // TODO Auto-generated method stub
        if(Result==true)
          {
          LocalName=name;
          return super.loadClass("ThisIsJoy");
          }
          else
          {
            LocalName=null;
            return super.loadClass(name);
          }
        }
        else
          return super.loadClass(name);
      }
    
    a)  Classloader 是个抽象类 其中通过覆盖findclass来改变文件搜索地址。已达到在任何父classloader加载不到的情况才会由他加载。
    b)  Classloader的加载机制是让自己的父classloader加载如果加载不到再有自己加载。如果有父classloader会一直向上询问。
    2、不影响程序的调用关系。
     文件格式不能改变class文件必须是合法文件否则编译时不能后通过。可以编译不代表可以正常运行、不对class文件进行加密。只对其方法中的字节码加密,正常编译在最后发布时进行classloader包开发进行加密解密
    通过Java Native Interface(JNI)的调用或的使用本地代码的方法可以实现java加密与本地信息的结合,演示中加密方法使用简单的XOR方法加密
    代码:
    //异或需要被加密的class的bytecode部分
    
    演示代码有两个部分:
    第一部分为程序主体,简单调用一个类中的一个方法在控制台上打印一串字符 HelloJava代码见源程序
    第二部分为自定义ClassLoader 负责加载主体程序文件。并解密其中的加密部分。详细过程见附录ClassLoader自定义和byteCode加密解密部分


    2.反射调用自己调用的加载类的的方法。此方法应该是你的程序的入口函数。这样可以保证你程序的顺利运行。
    代码:
    Class<?> clazz = null;
        clazz = new MyClassLoader(System.getProperty("user.dir")+"\cn\drawingbox").loadClass("cn.drawingbox.Foo");
        clazz.newInstance();
        //clazz.forName("cn.drawingbox.Foo");
        clazz.getMethod("FooFunction").invoke(null)
    
    a)  根据文件格式查找到文件中的方法实现的bytecode进行加密。加密bytecode不会影响class文件的格式。且所有的文件能在VM加载运行之前总认为他是合法的。可以顺利加载的。


    没有个源码。技术含量没有什么,所以就不给源码了,给个示例,key.lic 和java程序放一起就能够正确运行。key.lic不对。或没有程序都不能运行
  • 相关阅读:
    扩展:13-SpringBoot-尚硅谷-基础入门
    Java-JDK动态代理(AOP)使用及实现原理分析
    程序员常用算法合集
    数据结构-图
    多叉树的基本概念
    平衡二叉树(AVL树)
    TP5返回多维数组
    使用HttpSession实现验证码
    thinkphp6使用
    无法链接远程数据库
  • 原文地址:https://www.cnblogs.com/langtianya/p/3459726.html
Copyright © 2011-2022 走看看