自定义classloader加密java程序

转载 2013年12月05日 12:45:21

 

大概想法是这样的: 
1. 生成密钥用于在des算法中加密。 
2. classloader类中动态的解密class,并且通过反射机制执行main方法。 
3. 对classloader类进行高质量的混淆。 

首先需要生成des算法中的key: 

Java代码  收藏代码
  1. import java.io.File;  
  2. import java.io.FileOutputStream;  
  3. import java.security.SecureRandom;  
  4. import javax.crypto.KeyGenerator;  
  5. import javax.crypto.SecretKey;  
  6.   
  7. class Key {  
  8.   
  9.     private String keyName;  
  10.   
  11.     public Key() {  
  12.   
  13.     }  
  14.   
  15.     public Key(String keyName) {  
  16.         this.keyName = keyName;  
  17.     }  
  18.   
  19.     public void createKey(String keyName) throws Exception {  
  20.   
  21.         SecureRandom sr = new SecureRandom();  
  22.         KeyGenerator kg = KeyGenerator.getInstance("DES");  
  23.         kg.init(sr);  
  24.         SecretKey key = kg.generateKey();  
  25.         System.out.println(key.toString());  
  26.         byte rawKeyData[] = key.getEncoded();  
  27.         FileOutputStream fo = new FileOutputStream(new File(keyName));  
  28.         fo.write(rawKeyData);  
  29.         fo.close();  
  30.     }  
  31.   
  32.     public static void main(String args[]) {  
  33.         try {  
  34.             new Key("").createKey("d:/key.txt");  
  35.   
  36.         } catch (Exception e) {  
  37.             e.printStackTrace();  
  38.         }  
  39.   
  40.     }  
  41. }  


有了key之后就可以对class进行加密了: 
Java代码  收藏代码
  1. package com.hitachi.crypt;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.security.SecureRandom;  
  7.   
  8. import javax.crypto.Cipher;  
  9. import javax.crypto.SecretKey;  
  10. import javax.crypto.SecretKeyFactory;  
  11. import javax.crypto.spec.DESKeySpec;  
  12.   
  13. public class Crypt {  
  14.   
  15.     public static void main(String[] args) throws Exception {  
  16.   
  17.         SecureRandom sr = new SecureRandom();  
  18.         FileInputStream fi = new FileInputStream(new File("d:/key.txt"));  
  19.         byte rawKeyData[] = new byte[fi.available()];  
  20.         fi.read(rawKeyData);  
  21.         fi.close();  
  22.         DESKeySpec dks = new DESKeySpec(rawKeyData);  
  23.         SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);  
  24.         Cipher cipher = Cipher.getInstance("DES");  
  25.         cipher.init(Cipher.ENCRYPT_MODE, key, sr);  
  26.         FileInputStream fi2 = new FileInputStream(new File("d:/HelloWorld.class"));  
  27.         byte data[] = new byte[fi2.available()];  
  28.         fi2.read(data);  
  29.         fi2.close();  
  30.         byte encryptedData[] = cipher.doFinal(data);  
  31.         FileOutputStream fo = new FileOutputStream(new File("d:/HelloWorld.class"));  
  32.         fo.write(encryptedData);  
  33.         fo.close();  
  34.     }  
  35. }  

然后还是关键的classloader类: 
Java代码  收藏代码
  1. package com.hitachi.classloader;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.IOException;  
  6. import java.util.Hashtable;  
  7. import java.util.jar.JarEntry;  
  8. import java.util.jar.JarInputStream;  
  9.   
  10. public class MyClassLoader extends ClassLoader {  
  11.   
  12.     private static String myClasspath = new String("");  
  13.     private static Hashtable<String, Class<?>> loadClassHashTable = new Hashtable<String, Class<?>>();  
  14.     private static Hashtable<String, Long> loadClassTime = new Hashtable<String, Long>();  
  15.   
  16.     public MyClassLoader() {  
  17.   
  18.     }  
  19.   
  20.     /** */  
  21.     /** 
  22.      * create a classloader and specify a classpath. 
  23.      *  
  24.      * @param myClasspath 
  25.      *            the specified classpath name. 
  26.      */  
  27.     public MyClassLoader(String myClasspath) {  
  28.         if (!myClasspath.endsWith("\")) {  
  29.             myClasspath = myClasspath + "\";  
  30.         }  
  31.         MyClassLoader.myClasspath = myClasspath;  
  32.     }  
  33.   
  34.     /** */  
  35.     /** 
  36.      * set the classpath 
  37.      *  
  38.      * @param myClasspath 
  39.      *            the specified classpath name 
  40.      */  
  41.     public void SetmyClasspath(String myClasspath) {  
  42.         if (!myClasspath.endsWith("\")) {  
  43.             myClasspath = myClasspath + "\";  
  44.         }  
  45.         MyClassLoader.myClasspath = myClasspath;  
  46.     }  
  47.   
  48.     /** */  
  49.     /** 
  50.      * Loads the class with the specified binary name. This method searches for 
  51.      * classes in the same manner as the loadClass(String, boolean) method. 
  52.      * Invoking this method is equivalent to invoking {loadClass(name,false)}. 
  53.      *  
  54.      * @param className 
  55.      *            The binary name of the class. 
  56.      *  
  57.      * @return The resulting <tt>Class</tt> object. 
  58.      *  
  59.      * @throws ClassNotFoundException 
  60.      *             If the class was not found. 
  61.      */  
  62.     @SuppressWarnings("unchecked")  
  63.     public Class loadClass(String className) throws ClassNotFoundException {  
  64.         return loadClass(className, false);  
  65.     }  
  66.   
  67.     /** */  
  68.     /** 
  69.      * Loads the class with the specified binary name. The default 
  70.      * implementation of this method searches for classes in the following 
  71.      * order: 
  72.      *  
  73.      * Invoke {findLoadedClass(String)} to check if the class has already been 
  74.      * loaded. 
  75.      *  
  76.      * Invoke {findSystemClass(String)} to load the system class. 
  77.      *  
  78.      * Invoke the {findClass(String)} method to find the class. 
  79.      *  
  80.      * If the class was found using the above steps, and the resolve flag is 
  81.      * true, this method will then invoke the {resolveClass(Class)} method on 
  82.      * the resulting Class object. 
  83.      *  
  84.      * @param name 
  85.      *            The binary name of the class. 
  86.      *  
  87.      * @param resolve 
  88.      *            If true then resolve the class. 
  89.      *  
  90.      * @return The resulting Class object. 
  91.      *  
  92.      * @throws ClassNotFoundException 
  93.      *             If the class could not be found. 
  94.      */  
  95.     @SuppressWarnings("unchecked")  
  96.     protected Class loadClass(String name, boolean resolve)  
  97.             throws ClassNotFoundException {  
  98.   
  99.         try {  
  100.             Class foundClass = findLoadedClass(name);  
  101.   
  102.             // check if the class has already been loaded.  
  103.             if (foundClass != null) {  
  104.                 System.out.println("Complete to load the class: " + name);  
  105.                 return foundClass;  
  106.             }  
  107.   
  108.             // if the class is systemClass, load the system class by system  
  109.             if (name.startsWith("java.")) {  
  110.                 foundClass = findSystemClass(name);  
  111.                 loadClassHashTable.put(name, foundClass);  
  112.                 System.out.println("System is loading the class: " + name);  
  113.                 return foundClass;  
  114.             }  
  115.   
  116.             // invoke the findClass() method to load the class  
  117.             try {  
  118.                 foundClass = findClass(name);  
  119.             } catch (Exception fnfe) {  
  120.             }  
  121.   
  122.             if (resolve && (foundClass != null)) {  
  123.                 resolveClass(foundClass);  
  124.             }  
  125.             return foundClass;  
  126.         } catch (Exception e) {  
  127.             throw new ClassNotFoundException(e.toString());  
  128.         }  
  129.     }  
  130.   
  131.     /** */  
  132.     /** 
  133.      * Finds the class with the specified binary name.The default implementation 
  134.      * throws a ClassNotFoundException. 
  135.      *  
  136.      * @param className 
  137.      *            The binary name of the class. 
  138.      *  
  139.      * @return The resulting Class object. 
  140.      *  
  141.      * @throws ClassNotFoundException 
  142.      *             If the class could not be found. 
  143.      */  
  144.     @SuppressWarnings("unchecked")  
  145.     public Class findClass(String className) {  
  146.   
  147.         byte[] classData = null;  
  148.         try {  
  149.             classData = loadClassData(className);  
  150.         } catch (IOException e) {  
  151.             e.printStackTrace();  
  152.         }  
  153.         if (classData == null) {  
  154.             return null;  
  155.         }  
  156.   
  157.         System.out.println("MyClassLoader is loading : " + className + "");  
  158.         Class c = defineClass(className, classData, 0, classData.length);  
  159.         MyClassLoader.loadClassHashTable.put(className, c);  
  160.         System.out.println("Complete to load the class :" + className);  
  161.         return c;  
  162.     }  
  163.   
  164.     /** */  
  165.     /** 
  166.      * Loads the classData with the specified binary name. This method searches 
  167.      * for classes in the specified classpath as 
  168.      * searchFile(myClasspath,className) method. 
  169.      *  
  170.      * @param name 
  171.      *            The binary name of the class 
  172.      *  
  173.      * @return The resulting the classData of the class object by byte[] 
  174.      *  
  175.      * @throws IOException 
  176.      *             if have some failed or interrupted I/O operations. 
  177.      */  
  178.     private byte[] loadClassData(String className) throws IOException {  
  179.   
  180.         String filePath = searchFile(myClasspath, className + ".class");  
  181.   
  182.         if (!(filePath == null || filePath == "")) {  
  183.   
  184.             System.out.println("It have found the file : " + className  
  185.                     + ".  Begin to read the data and load the class。");  
  186.             FileInputStream inFile = new FileInputStream(filePath);  
  187.             byte[] classData = new byte[inFile.available()];  
  188.             inFile.read(classData);  
  189.             inFile.close();  
  190.             loadClassTime.put(className, new File(filePath).lastModified());  
  191.             return classData;  
  192.         } else {  
  193.   
  194.             filePath = searchFile(myClasspath, className + ".java");  
  195.             if (!(filePath == null || filePath == "")) {  
  196.                 System.out.println("It have found the file : " + filePath  
  197.                         + ".  Begin to translate");  
  198.                 Runtime.getRuntime().exec("javac " + filePath);  
  199.                 try {  
  200.                     Thread.sleep(1000);  
  201.                 } catch (InterruptedException e) {  
  202.                     e.printStackTrace();  
  203.                 }  
  204.                 System.out.println("Translate it over : " + filePath);  
  205.                 return loadClassData(className);  
  206.             } else {  
  207.                 System.out  
  208.                         .println("Haven't found the file, and fail to read the classData!");  
  209.                 return null;  
  210.             }  
  211.         }  
  212.     }  
  213.   
  214.     /** */  
  215.     /** 
  216.      * Loads the class with the specified binary name.The default implementation 
  217.      * throws a ClassNotFoundException. 
  218.      *  
  219.      * @param classData 
  220.      *            The data of the class. 
  221.      * @param className 
  222.      *            The binary name of the class. 
  223.      *  
  224.      * @return The resulting Class object. 
  225.      *  
  226.      * @throws ClassNotFoundException 
  227.      *             If the class could not be found. 
  228.      */  
  229.     public Class loadClass(byte[] classData, String className)  
  230.             throws ClassNotFoundException {  
  231.   
  232.         System.out.println("MyClassLoader is loading : " + className + "");  
  233.         Class c = defineClass(className, classData, 0, classData.length);  
  234.         loadClassHashTable.put(className, c);  
  235.         System.out.println("Complete to load the class :" + className);  
  236.   
  237.         return c;  
  238.     }  
  239.   
  240.     /** */  
  241.     /** 
  242.      * Loads the class with the specified binary name.The default implementation 
  243.      * throws a ClassNotFoundException. 
  244.      *  
  245.      * @param className 
  246.      *            The binary name of the class. 
  247.      * @param jarName 
  248.      *            The binary name of the jar that search the class from it. 
  249.      *  
  250.      * @return The resulting Class object. 
  251.      *  
  252.      * @throws ClassNotFoundException 
  253.      *             If the class could not be found. 
  254.      */  
  255.     protected Class loadClass(String className, String jarName)  
  256.             throws ClassNotFoundException {  
  257.   
  258.         String jarPath = searchFile(myClasspath, jarName + ".jar");  
  259.         JarInputStream in = null;  
  260.   
  261.         if (!(jarPath == null || jarPath == "")) {  
  262.   
  263.             try {  
  264.                 in = new JarInputStream(new FileInputStream(jarPath));  
  265.                 JarEntry entry;  
  266.                 while ((entry = in.getNextJarEntry()) != null) {  
  267.                     String outFileName = entry.getName().substring(  
  268.                             entry.getName().lastIndexOf("/") + 1,  
  269.                             entry.getName().length());  
  270.                     if (outFileName.equals(className + ".class")) {  
  271.                         if (entry.getSize() == -1) {  
  272.                             System.err.println("error : can't read the file!");  
  273.                             return null;  
  274.                         }  
  275.                         byte[] classData = new byte[(int) entry.getSize()];  
  276.                         System.out  
  277.                                 .println("It have found the file : "  
  278.                                         + className  
  279.                                         + ".  Begin to read the data and load the class。");  
  280.                         in.read(classData);  
  281.                         return loadClass(classData, className);  
  282.                     }  
  283.                 }  
  284.                 System.out.println("Haven't found the file " + className  
  285.                         + " in " + jarName + ".jar.");  
  286.             } catch (IOException e) {  
  287.                 e.printStackTrace();  
  288.             } finally {  
  289.                 try {  
  290.                     in.close();  
  291.                 } catch (IOException e) {  
  292.                     e.printStackTrace();  
  293.                 }  
  294.             }  
  295.         } else {  
  296.             System.out.println("Haven't found the jarFile: " + jarName  
  297.                     + ".jar.");  
  298.             return null;  
  299.         }  
  300.         return null;  
  301.     }  
  302.   
  303.     /** */  
  304.     /** 
  305.      * Reloads the class with the specified binary name. Needn't have to restart 
  306.      * JVM then reload the class. 
  307.      *  
  308.      * @param className 
  309.      *            The binary name of the class need to reload . 
  310.      *  
  311.      * @return The resulting Class object. 
  312.      *  
  313.      * @throws ClassNotFoundException 
  314.      *             If the class was not found. 
  315.      */  
  316.     public Class reload(String fileName) {  
  317.   
  318.         String filePath = searchFile(myClasspath, fileName + ".class");  
  319.         Long a = new File(filePath).lastModified();  
  320.   
  321.         if (!a.equals(loadClassTime.get(fileName))) {  
  322.             loadClassHashTable.remove(fileName);  
  323.             loadClassTime.remove(fileName);  
  324.             try {  
  325.                 MyClassLoader mc2 = new MyClassLoader(myClasspath);  
  326.                 mc2.loadClass(fileName);  
  327.             } catch (ClassNotFoundException e) {  
  328.                 e.printStackTrace();  
  329.             }  
  330.         } else {  
  331.             System.out  
  332.                     .println("The class is the newest version , needn't reloading.");  
  333.         }  
  334.         return null;  
  335.     }  
  336.   
  337.     /** */  
  338.     /** 
  339.      * search the file with the specified binary name. Needn't have to restart 
  340.      * JVM then reload the class. 
  341.      *  
  342.      * @param classpath 
  343.      *            the specified path where we search. 
  344.      * @param fileName 
  345.      *            The binary name of the file that want to search. 
  346.      *  
  347.      * @return The resulting file path. 
  348.      */  
  349.     public String searchFile(String classpath, String fileName) {  
  350.   
  351.         String cut = fileName.substring(fileName.lastIndexOf('.'), fileName  
  352.                 .length());  
  353.         String path = fileName.substring(0, fileName.lastIndexOf('.')).replace(  
  354.                 '.''/')  
  355.                 + cut;  
  356.   
  357.         File f = new File(classpath + path);  
  358.         if (f.isFile()) {  
  359.             return f.getPath();  
  360.         } else {  
  361.             String objects[] = new File(classpath).list();  
  362.             for (int i = 0; i < objects.length; i++) {  
  363.                 if (new File(classpath + File.separator + objects[i])  
  364.                         .isDirectory()) {  
  365.                     String s = searchFile(classpath + objects[i]  
  366.                             + File.separator, fileName);  
  367.                     if (s == null || s == "") {  
  368.                         continue;  
  369.                     } else {  
  370.                         return s;  
  371.                     }  
  372.                 }  
  373.             }  
  374.         }  
  375.         return null;  
  376.     };  
  377.   
  378. }  



最后解密,并且通过反射机制执行: 
Java代码  收藏代码
  1. package com.hitachi.crypt;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.lang.reflect.Method;  
  6. import java.security.SecureRandom;  
  7.   
  8. import javax.crypto.Cipher;  
  9. import javax.crypto.SecretKey;  
  10. import javax.crypto.SecretKeyFactory;  
  11. import javax.crypto.spec.DESKeySpec;  
  12.   
  13. import com.hitachi.classloader.MyClassLoader;  
  14. public class Decrypt {  
  15.   
  16.     public static void main(String[] args) throws Exception {  
  17.   
  18.         SecureRandom sr = new SecureRandom();  
  19.         FileInputStream fi = new FileInputStream(new File("d:/key.txt"));  
  20.         byte rawKeyData[] = new byte[fi.available()];  
  21.         fi.read(rawKeyData);  
  22.         fi.close();  
  23.         DESKeySpec dks = new DESKeySpec(rawKeyData);  
  24.         SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);  
  25.         Cipher cipher = Cipher.getInstance("DES");  
  26.         cipher.init(Cipher.DECRYPT_MODE, key, sr);  
  27.         FileInputStream fi2 = new FileInputStream(new File(  
  28.                 "D:/HelloWorld.class"));  
  29.         byte encryptedData[] = new byte[fi2.available()];  
  30.         fi2.read(encryptedData);  
  31.         fi2.close();  
  32.         byte decryptedData[] = cipher.doFinal(encryptedData);  
  33.         MyClassLoader mcl = new MyClassLoader("D:/");  
  34.         Class cl = mcl.loadClass(decryptedData, "HelloWorld");  
  35.         Method mainMethod = cl.getMethod("sayHello");  
  36.         mainMethod.invoke(nullnull);  
  37.     }  
  38. }  


其中源文件是这样的: 

Java代码  收藏代码
  1. public class HelloWorld {  
  2.   
  3.     /** 
  4.      * @param args 
  5.      */  
  6.     public static void main(String[] args) {  
  7.         // TODO Auto-generated method stub  
  8.         System.out.println("Hello world");  
  9.     }  
  10.   
  11.     public static void sayHello() {  
  12.         System.out.println("Hello");  
  13.     }  
  14.   
  15. }  

本文来自:夜猫技术网(www.360cat.cn)

本文地址:http://www.360cat.cn/detail/119.html

相关文章推荐

自定义classloader加密java程序

大概想法是这样的:  1. 生成密钥用于在des算法中加密。  2. classloader类中动态的解密class,并且通过反射机制执行main方法。  3. 对classloader类进行高...

利用自定义的 ClassLoader 加密 Java Class 文件

本文演示利用自定义的 ClassLoader 加密 Java Class 文件 首先,我们定义一个需要被加密的Java Class: classload.MyClassBase。 为了让客户端使用...

java源代码加密+使用proguard混淆java web项目代码+自定义Classloader

如何保护我们的源代码,实际上,应该有几种方法可以使用:1、使用代码混淆器 2、重载应用服务器的classloader    使用代码混淆器proguard进行代码混淆    1.首先下载proGuar...

自定义ClassLoader的简单例子 - bitan????s java - CSDNBlog

导读: Test1.java: package test; import java.io.*; import java.lang.reflect.*; class ACla...

【java】自定义ClassLoader 加载外部类和jar文件

我们写的程序,默认会编译src下的。java文件,但是如果一个类不在这个项目的src下,怎么在本项目内new出它的一个实例?这就需要自定义一个ClassLoader,让它去加载指定位置的class,因...

ClassLoader的双亲代理机制和能否自定义一个java.lang.String类

文章参考:                    1.    Java Classloader机制解析--http://my.oschina.net/aminqiao/blog/262601   ...

Java Class的热替换 自定义ClassLoader加载.class

本文是java热替换的实验,参考了 Java 类的热替换 —— 概念、设计与实现http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls...
  • ozwarld
  • ozwarld
  • 2012年04月09日 14:38
  • 9435

自定义 Java ClassLoader

首先看一下 java.lang.ClassLoader 方法 loadClass(String name) 方法的源码public Class loadClass(String name) throw...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:自定义classloader加密java程序
举报原因:
原因补充:

(最多只允许输入30个字)