关于jdk中类装载器ClassLoader扩展和JNI技术(JavaNativeInterface)以及类文件的加密解密算法

来源:互联网 发布:mac os山狮系统 编辑:程序博客网 时间:2024/06/04 18:19
1、自定义Classloader的代码如下:
package com.test.start;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.ByteBuffer;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.Manifest;
import sun.misc.Resource;
import sun.misc.URLClassPath;
public class CommonClassLoader extends URLClassLoader
{
  private URLClassPath ucp;
  private AccessControlContext acc;
  private Method getProtectionDomainMethod;
  public CommonClassLoader(URL[] urls)
  {
    super(urls);
  }
  public CommonClassLoader(URL[] urls, ClassLoader parent) {
    super(urls);
  }
  protected void addURL(URL arg0)
  {
    super.addURL(arg0);
  }
//系统方法
  protected Class<?> findClass(String name)
    throws ClassNotFoundException
  {
    try
    {
      check();
      return
        ((Class)AccessController.doPrivileged(new PrivilegedExceptionAction(this, name) {
        public Object run() throws ClassNotFoundException {
          String path = this.val$name.replace('.', '/').concat(".class");
Resource res = CommonClassLoader.access$0(this.this$0).getResource(path, false);
          if (res != null)
            try {
              return CommonClassLoader.access$1(this.this$0, this.val$name, res);
            } catch (IOException e) {
              throw new ClassNotFoundException(this.val$name, e);
            }
          throw new ClassNotFoundException(this.val$name);
        }
      }
      , this.acc));
    } catch (PrivilegedActionException pae) {
      throw ((ClassNotFoundException)pae.getException());
    }
  }
//修改后的系统方法
  private Class defineClass(String name, Resource res)
    throws IOException
  {
    int i = name.lastIndexOf(46);
    URL url = res.getCodeSourceURL();
    if (i != -1) {
      String pkgname = name.substring(0, i);
      Package pkg = getPackage(pkgname);
      Manifest man = res.getManifest();
      if (pkg != null)
      {
        if (pkg.isSealed())
        {
          if (pkg.isSealed(url)) break label172;
          throw new SecurityException(
            "sealing violation: package " + pkgname + " is sealed");
        }
        if ((man == null) || (!(isSealed(pkgname, man)))) break label172;
        throw new SecurityException(
          "sealing violation: can't seal package " + pkgname +
          ": already loaded");
      }
      if (man != null)
        definePackage(pkgname, man, url);
      else {
        definePackage(pkgname, null, null, null, null, null, null, null);
      }
    }
    label172: ByteBuffer bb = res.getByteBuffer();
    if (bb != null)
    {
      CodeSigner[] signers = res.getCodeSigners();
      CodeSource cs = new CodeSource(url, signers);
      byte[] b = getBytes(bb);
      return defineClassInternal(name, b, 0, b.length, cs);
    }
    byte[] b = res.getBytes();
    CodeSigner[] signers = res.getCodeSigners();
    CodeSource cs = new CodeSource(url, signers);
    return defineClassInternal(name, b, 0, b.length, cs);
  }
//系统方法
  private boolean isSealed(String name, Manifest man)
  {
    String path = name.replace('.', '/').concat("/");
    Attributes attr = man.getAttributes(path);
    String sealed = null;
    if (attr != null)
      sealed = attr.getValue(Attributes.Name.SEALED);
    if (sealed == null)
      if ((attr = man.getMainAttributes()) != null)
        sealed = attr.getValue(Attributes.Name.SEALED);

    return "true".equalsIgnoreCase(sealed);
  }
//自定义方法 检测父类的属性初始化给子类调用,使用java反射技术实现。
  private void check()
  {
    try {
      if (this.ucp == null)
      {
        Field fieldOfucp = getClass().getSuperclass().getDeclaredField("ucp");//获取private类型的字段
        fieldOfucp.setAccessible(true);//设置private类型修饰的字段可以访问
        this.ucp = ((URLClassPath)fieldOfucp.get(this));//访问private类型修饰的字段
      }
      if (this.acc == null)
      {
        Field fieldOfacc = getClass().getSuperclass().getDeclaredField("acc");
        fieldOfacc.setAccessible(true);
        this.acc = ((AccessControlContext)fieldOfacc.get(this));
      }
      if (this.getProtectionDomainMethod != null) return;
      this.getProtectionDomainMethod = getClass().getSuperclass().getSuperclass().getDeclaredMethod("getProtectionDomain", new Class[] { CodeSource.class });
      this.getProtectionDomainMethod.setAccessible(true);
    }
    catch (Exception ex)
    {
      ex.printStackTrace();
    }
  }
//自定义方法 字节缓冲中的字节获取
  private byte[] getBytes(ByteBuffer b)
  {
    int len = b.remaining();
    byte[] tb = new byte[len];
    if (!(b.isDirect()))
      if (b.hasArray()) {
        System.arraycopy(b.array(), b.position() + b.arrayOffset(), tb, 0, len);
      }
      else
        b.get(tb);

    return tb;
  }
//自定义方法 让加密的的class文件交给解密方法来执行装载否则由系统来装载
  protected final Class<?> defineClassInternal(String name, byte[] b, int off, int len, CodeSource cs)
  {
    Class clz = null;
    try
    {
      if (cs == null) {
        clz = defineClass0(name, b, off, len); break label75:
      }
      clz = defineClass1(name, b, off, len, getProtectionDomainInternal(cs));
    }
    catch (ClassFormatError ex)
    {
      if (cs == null)
        return super.defineClass(name, b, off, len);
      return super.defineClass(name, b, off, len, getProtectionDomainInternal(cs));
    }
    if (clz == null)
    {
      if (cs == null)
        label75: return super.defineClass(name, b, off, len);
      return super.defineClass(name, b, off, len, getProtectionDomainInternal(cs));
    }
    return clz;
  }
//系统方法
  protected ProtectionDomain getProtectionDomainInternal(CodeSource cs)
  {
    try {
      return ((ProtectionDomain)this.getProtectionDomainMethod.invoke(this, new Object[] { cs }));
    }
    catch (IllegalArgumentException e) {
      e.printStackTrace();
    }
    catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    catch (InvocationTargetException e) {
      e.printStackTrace();
    }
    return null;
  }
//自定义方法 调用dll文件中的解密算法来解密class文件并装载到jvm中
  private native Class<?> defineClass0(String paramString, byte[] paramArrayOfByte, int paramInt1, int paramInt2);
  private native Class<?> defineClass1(String paramString, byte[] paramArrayOfByte, int paramInt1, int paramInt2, ProtectionDomain paramProtectionDomain);
}
2、c++实现加密和解密算法以及JNI技术的应用实例:
#include"jni.h"
#include"com_test_start_CommonClassLoader.h"
static void arraycopy(JNIEnv *env,jbyteArray sb,int spo,jbyteArray db,int start,int len);
static jbyteArray encrypt(JNIEnv *env,jbyteArray b,jint len);
static jbyteArray getValidateCode(JNIEnv *env);
static jbyteArray getCode(JNIEnv *env);
/*
* Clasbs:     com_test_start_CommonClassLoader
* Method:    defineClass0
* Signature: (Ljava/lang/String;[BII)Ljava/lang/Class;
*/
JNIEXPORT jclass JNICALL Java_com_test_start_CommonClassLoader_defineClass0
  (JNIEnv *env, jobject loader, jstring  name, jbyteArray buffer, jint start, jint len)
{
jbyteArray temp=env->NewByteArray(len);//new一个数组,并申请一块内存
arraycopy(env,buffer,start,temp,start,len);//数组的复制相当于System.copy()方法
    jbyteArray byte0=encrypt(env,temp,len);//进行class文件的解密操作
if(byte0==NULL)
{
       env->DeleteLocalRef(temp);//释放内存
       return NULL;
}
jsize size=env->GetArrayLength(byte0);//技术数组的长度相当于Array的length属性
jclass classLoader=env->GetSuperclass(env->GetSuperclass(env->GetSuperclass(env->GetObjectClass(loader))));//获取父类装载器
jmethodID mid=env->GetMethodID(classLoader,"defineClass","(Ljava/lang/String;[BII)Ljava/lang/Class;");//获取defineClass方法
defineClass jclass cls=(jclass)env->CallObjectMethod(loader,mid,name,byte0,start,size);//调用Classloader的defineClass定义一个类到jvm中
env->DeleteLocalRef(byte0);//释放内存
return cls;
}
/*
* Class:     com_test_start_CommonClassLoader
* Method:    defineClass1
* Signature: (Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
*/
JNIEXPORT jclass JNICALL Java_com_test_start_CommonClassLoader_defineClass1
  (JNIEnv *env, jobject loader, jstring name, jbyteArray buffer, jint start, jint len, jobject pro)
{
    jbyteArray temp=env->NewByteArray(len);
arraycopy(env,buffer,start,temp,start,len);
    jbyteArray byte0=encrypt(env,temp,len);
if(byte0==NULL)
{
       env->DeleteLocalRef(temp);
       return NULL;
}
jsize size=env->GetArrayLength(byte0);
jclass classLoader=env->GetSuperclass(env->GetSuperclass(env->GetSuperclass(env->GetObjectClass(loader))));
jmethodID mid=env->GetMethodID(classLoader,"defineClass","(Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;");
jclass cls=(jclass)env->CallObjectMethod(loader,mid,name,byte0,start,size,pro);
env->DeleteLocalRef(byte0);
return cls;
}
  /*
   getCode,密钥,用于加密
  */
static jbyteArray getCode(JNIEnv *env)
  {
  char char0[]={'0','1','2','3','4','5','6','7','8','9'};
  char char1[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','s','y','z'};
  char char2[36];
  int i=0;
     int j=0; 
     int k=0;
     while(i<36)
  {
   
     if(i>=12&&j<10)
  {
      char2[i]=char0[j];
   j++;
  }
     else if(i>=23&&k<26)
  {
   char2[i]=char1[k];
   k++;
  }
     else
  {
      char2[i]=char1[k];
      k++;
  }
     i++;
  }
  jbyteArray code=env->NewByteArray(36);
  env->SetByteArrayRegion(code,0,36,(jbyte*)char2);
     return code;
  }
  /*
   getValidateCode,验证码用于区分是否是加密文件
  */
   static jbyteArray getValidateCode(JNIEnv *env)
   {
      char char0[]={'0','1','2','3','4','5','6','7'};
      jbyteArray char1=env->NewByteArray(8);
   env->SetByteArrayRegion(char1,0,8,(jbyte *)char0);
   return char1;
   }
   /*
   encrypt,解密操作
   */
   static jbyteArray encrypt(JNIEnv *env,jbyteArray b,jint len)
{
         int i = 0;
   jint j = 0;
   int k =len;
   jbyte* bb = (env->GetByteArrayElements(b,JNI_FALSE));
   while (i < k) {
    j = bb[i];
    if ((j >= 48) && (j <= 57)) {
     j = (((j - 48) + 5) % 10) + 48;
    } else if ((j >= 65) && (j <= 90)) {
     j = (((j - 65) + 13) % 26) + 65;
    } else if ((j >= 97) && (j <= 122)) {
     j = (((j - 97) + 13) % 26) + 97;
    }
    bb[i]=(jbyte)j;
    i++;
   }
   env->SetByteArrayRegion(b,0,k,bb);
   int length=500;//长度
   int start=0;//起始次数
   jbyteArray temp=getCode(env);//密钥
   int mode=(k-8)%(length+36);//剩余部分
   int count=(k-8)/(length+36);//总次数
         int spo=0;//源位置
         int dpo=0;//目标位置
   int size=count*length+mode;//大小
   jbyteArray byte0=env->NewByteArray(size);//密文大小
   if(count>0)
   {//进行解密
    while(start<count)
    {
     arraycopy(env,b, spo, byte0, dpo, length);
     spo=spo+length+36;
     dpo=dpo+length;
     start++;
    }
   }
   if(mode>0)
   {//复制剩余部分
    arraycopy(env,b, spo, byte0, dpo, mode);
    spo=spo+mode;
   }
   //校验码
   jbyteArray validateCode0=getValidateCode(env);
   jbyte* validateCode=env->GetByteArrayElements(validateCode0,JNI_FALSE);
   jbyteArray validate0=env->NewByteArray(8);
   arraycopy(env,b, spo, validate0, 0,8);
            jbyte* validate=env->GetByteArrayElements(validate0,JNI_FALSE);
   for(int index=0;index<8;index++)
   {//校验解码是否成功
    if(validate[index]!=validateCode[index])
    {
     return NULL;
    }
   }
   env->DeleteLocalRef(validate0);
   env->DeleteLocalRef(validateCode0);
   env->DeleteLocalRef(temp);
   return byte0;
}

    /*
    decrypt,加密操作
    */
   static jbyteArray decrypt(JNIEnv *env,jbyteArray b,jboolean end)
{
            int length=500;//长度
   int start=0;//起始次数
   int count=env->GetArrayLength(b)/length;//总次数
   jbyteArray temp=getCode(env);//密钥
         int spo=0;//源位置
         int dpo=0;//目标位置
         int mode=env->GetArrayLength(b)%length;//剩余部分
   int size=count*(length+36)+mode;//大小
   if(end==JNI_TRUE)
   {//是否结束
    size=size+8;
   }
   jbyteArray byte0=env->NewByteArray(size);//密文大小
   if(count>0)
   {//进行加密
    while(start<count)
    {
     arraycopy(env,b, spo, byte0, dpo, length);
     arraycopy(env,temp, 0, byte0, dpo+length, 36);
     spo=spo+length;
     dpo=dpo+length+36;
     start++;
    }
   }
   if(mode>0)
   {//复制剩余部分
    arraycopy(env,b, spo, byte0, dpo, mode);
    dpo=dpo+mode;
   }
   if(end==JNI_TRUE)
   {//结束位置加校验码
       jbyteArray validateCode=getValidateCode(env);
    arraycopy(env,validateCode, 0, byte0, dpo, 8);
    env->DeleteLocalRef(validateCode);
   }
   jbyte * byte1=env->GetByteArrayElements(byte0,0);
   //转换字节位置
   int i = 0;
   int j = 0;
   int k = size;
   while (i < k) {
    j = byte1[i];
   
    if ((j >= 48) && (j <= 57)) {
     j = (((j - 48) + 5) % 10) + 48;
    } else if ((j >= 65) && (j <= 90)) {
     j = (((j - 65) + 13) % 26) + 65;
    } else if ((j >= 97) && (j <= 122)) {
     j = (((j - 97) + 13) % 26) + 97;
    }
    byte1[i]=(jbyte)j;
    i++;
   }
            env->SetByteArrayRegion(byte0,0,size,byte1);
   env->DeleteLocalRef(temp);
   return byte0;
}
    /*
   arraycopy,自定义的数组赋值方法相当于System.copy()
   */
  static void arraycopy(JNIEnv *env,jbyteArray sb,int spo,jbyteArray db,int start,int len)
   {
    jbyte * t=new jbyte[len];
    env->GetByteArrayRegion(sb,spo,len,t);
    env->SetByteArrayRegion(db,start,len,t);
    delete t;
   }