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不对。或没有程序都不能运行
  • 相关阅读:
    SqlServer 查看数据库中所有存储过程
    SqlServer 查看数据库中所有视图
    SqlServer 查询表的详细信息
    SqlServer 遍历修改字段长度
    net core 操作Redis
    Tuning SharePoint Workflow Engine
    Open With Explorer
    Download language packs for SharePoint 2013
    Change Maximum Size For SharePoint List Template when Saving
    Six ways to store settings in SharePoint
  • 原文地址:https://www.cnblogs.com/langtianya/p/3459726.html
Copyright © 2011-2022 走看看