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

时间:2025-03-22 14:34:30
1、自定义Classloader的代码如下:
package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
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)
  {
    (arg0);
  }
//系统方法
  protected Class<?> findClass(String name)
    throws ClassNotFoundException
  {
    try
    {
      check();
      return
        ((Class)(new PrivilegedExceptionAction(this, name) {
        public Object run() throws ClassNotFoundException {
          String path = $('.', '/').concat(".class");
Resource res = $0($0).getResource(path, false);
          if (res != null)
            try {
              return $1($0, $name, res);
            } catch (IOException e) {
              throw new ClassNotFoundException($name, e);
            }
          throw new ClassNotFoundException($name);
        }
      }
      , ));
    } catch (PrivilegedActionException pae) {
      throw ((ClassNotFoundException)());
    }
  }
//修改后的系统方法
  private Class defineClass(String name, Resource res)
    throws IOException
  {
    int i = (46);
    URL url = ();
    if (i != -1) {
      String pkgname = (0, i);
      Package pkg = getPackage(pkgname);
      Manifest man = ();
      if (pkg != null)
      {
        if (())
        {
          if ((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 = ();
    if (bb != null)
    {
      CodeSigner[] signers = ();
      CodeSource cs = new CodeSource(url, signers);
      byte[] b = getBytes(bb);
      return defineClassInternal(name, b, 0, , cs);
    }
    byte[] b = ();
    CodeSigner[] signers = ();
    CodeSource cs = new CodeSource(url, signers);
    return defineClassInternal(name, b, 0, , cs);
  }
//系统方法
  private boolean isSealed(String name, Manifest man)
  {
    String path = ('.', '/').concat("/");
    Attributes attr = (path);
    String sealed = null;
    if (attr != null)
      sealed = ();
    if (sealed == null)
      if ((attr = ()) != null)
        sealed = ();

    return "true".equalsIgnoreCase(sealed);
  }
//自定义方法 检测父类的属性初始化给子类调用,使用java反射技术实现。
  private void check()
  {
    try {
      if ( == null)
      {
        Field fieldOfucp = getClass().getSuperclass().getDeclaredField("ucp");//获取private类型的字段
        (true);//设置private类型修饰的字段可以访问
        = ((URLClassPath)(this));//访问private类型修饰的字段
      }
      if ( == null)
      {
        Field fieldOfacc = getClass().getSuperclass().getDeclaredField("acc");
        (true);
        = ((AccessControlContext)(this));
      }
      if ( != null) return;
      = getClass().getSuperclass().getSuperclass().getDeclaredMethod("getProtectionDomain", new Class[] { });
      (true);
    }
    catch (Exception ex)
    {
      ();
    }
  }
//自定义方法 字节缓冲中的字节获取
  private byte[] getBytes(ByteBuffer b)
  {
    int len = ();
    byte[] tb = new byte[len];
    if (!(()))
      if (()) {
        ((), () + (), tb, 0, len);
      }
      else
        (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 (name, b, off, len);
      return (name, b, off, len, getProtectionDomainInternal(cs));
    }
    if (clz == null)
    {
      if (cs == null)
        label75: return (name, b, off, len);
      return (name, b, off, len, getProtectionDomainInternal(cs));
    }
    return clz;
  }
//系统方法
  protected ProtectionDomain getProtectionDomainInternal(CodeSource cs)
  {
    try {
      return ((ProtectionDomain)(this, new Object[] { cs }));
    }
    catch (IllegalArgumentException e) {
      ();
    }
    catch (IllegalAccessException e) {
      ();
    }
    catch (InvocationTargetException e) {
      ();
    }
    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""
#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);//数组的复制相当于()方法
    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,自定义的数组赋值方法相当于()
   */
  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;
   }