`
tiantian911
  • 浏览: 216272 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

自定义classloader加密java程序

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

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


import java.io.File;
import java.io.FileOutputStream;
import java.security.SecureRandom;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

class Key {

	private String keyName;

	public Key() {

	}

	public Key(String keyName) {
		this.keyName = keyName;
	}

	public void createKey(String keyName) throws Exception {

		SecureRandom sr = new SecureRandom();
		KeyGenerator kg = KeyGenerator.getInstance("DES");
		kg.init(sr);
		SecretKey key = kg.generateKey();
		System.out.println(key.toString());
		byte rawKeyData[] = key.getEncoded();
		FileOutputStream fo = new FileOutputStream(new File(keyName));
		fo.write(rawKeyData);
		fo.close();
	}

	public static void main(String args[]) {
		try {
			new Key("").createKey("d:/key.txt");

		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}



有了key之后就可以对class进行加密了:
package com.hitachi.crypt;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

public class Crypt {

    public static void main(String[] args) throws Exception {

        SecureRandom sr = new SecureRandom();
        FileInputStream fi = new FileInputStream(new File("d:/key.txt"));
        byte rawKeyData[] = new byte[fi.available()];
        fi.read(rawKeyData);
        fi.close();
        DESKeySpec dks = new DESKeySpec(rawKeyData);
        SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);
        Cipher cipher = Cipher.getInstance("DES");
        cipher.init(Cipher.ENCRYPT_MODE, key, sr);
        FileInputStream fi2 = new FileInputStream(new File("d:/HelloWorld.class"));
        byte data[] = new byte[fi2.available()];
        fi2.read(data);
        fi2.close();
        byte encryptedData[] = cipher.doFinal(data);
        FileOutputStream fo = new FileOutputStream(new File("d:/HelloWorld.class"));
        fo.write(encryptedData);
        fo.close();
    }
}


然后还是关键的classloader类:
package com.hitachi.classloader;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

public class MyClassLoader extends ClassLoader {

	private static String myClasspath = new String("");
	private static Hashtable<String, Class<?>> loadClassHashTable = new Hashtable<String, Class<?>>();
	private static Hashtable<String, Long> loadClassTime = new Hashtable<String, Long>();

	public MyClassLoader() {

	}

	/** */
	/**
	 * create a classloader and specify a classpath.
	 * 
	 * @param myClasspath
	 *            the specified classpath name.
	 */
	public MyClassLoader(String myClasspath) {
		if (!myClasspath.endsWith("\\")) {
			myClasspath = myClasspath + "\\";
		}
		MyClassLoader.myClasspath = myClasspath;
	}

	/** */
	/**
	 * set the classpath
	 * 
	 * @param myClasspath
	 *            the specified classpath name
	 */
	public void SetmyClasspath(String myClasspath) {
		if (!myClasspath.endsWith("\\")) {
			myClasspath = myClasspath + "\\";
		}
		MyClassLoader.myClasspath = myClasspath;
	}

	/** */
	/**
	 * Loads the class with the specified binary name. This method searches for
	 * classes in the same manner as the loadClass(String, boolean) method.
	 * Invoking this method is equivalent to invoking {loadClass(name,false)}.
	 * 
	 * @param className
	 *            The binary name of the class.
	 * 
	 * @return The resulting <tt>Class</tt> object.
	 * 
	 * @throws ClassNotFoundException
	 *             If the class was not found.
	 */
	@SuppressWarnings("unchecked")
	public Class loadClass(String className) throws ClassNotFoundException {
		return loadClass(className, false);
	}

	/** */
	/**
	 * Loads the class with the specified binary name. The default
	 * implementation of this method searches for classes in the following
	 * order:
	 * 
	 * Invoke {findLoadedClass(String)} to check if the class has already been
	 * loaded.
	 * 
	 * Invoke {findSystemClass(String)} to load the system class.
	 * 
	 * Invoke the {findClass(String)} method to find the class.
	 * 
	 * If the class was found using the above steps, and the resolve flag is
	 * true, this method will then invoke the {resolveClass(Class)} method on
	 * the resulting Class object.
	 * 
	 * @param name
	 *            The binary name of the class.
	 * 
	 * @param resolve
	 *            If true then resolve the class.
	 * 
	 * @return The resulting Class object.
	 * 
	 * @throws ClassNotFoundException
	 *             If the class could not be found.
	 */
	@SuppressWarnings("unchecked")
	protected Class loadClass(String name, boolean resolve)
			throws ClassNotFoundException {

		try {
			Class foundClass = findLoadedClass(name);

			// check if the class has already been loaded.
			if (foundClass != null) {
				System.out.println("Complete to load the class: " + name);
				return foundClass;
			}

			// if the class is systemClass, load the system class by system
			if (name.startsWith("java.")) {
				foundClass = findSystemClass(name);
				loadClassHashTable.put(name, foundClass);
				System.out.println("System is loading the class: " + name);
				return foundClass;
			}

			// invoke the findClass() method to load the class
			try {
				foundClass = findClass(name);
			} catch (Exception fnfe) {
			}

			if (resolve && (foundClass != null)) {
				resolveClass(foundClass);
			}
			return foundClass;
		} catch (Exception e) {
			throw new ClassNotFoundException(e.toString());
		}
	}

	/** */
	/**
	 * Finds the class with the specified binary name.The default implementation
	 * throws a ClassNotFoundException.
	 * 
	 * @param className
	 *            The binary name of the class.
	 * 
	 * @return The resulting Class object.
	 * 
	 * @throws ClassNotFoundException
	 *             If the class could not be found.
	 */
	@SuppressWarnings("unchecked")
	public Class findClass(String className) {

		byte[] classData = null;
		try {
			classData = loadClassData(className);
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (classData == null) {
			return null;
		}

		System.out.println("MyClassLoader is loading : " + className + "");
		Class c = defineClass(className, classData, 0, classData.length);
		MyClassLoader.loadClassHashTable.put(className, c);
		System.out.println("Complete to load the class :" + className);
		return c;
	}

	/** */
	/**
	 * Loads the classData with the specified binary name. This method searches
	 * for classes in the specified classpath as
	 * searchFile(myClasspath,className) method.
	 * 
	 * @param name
	 *            The binary name of the class
	 * 
	 * @return The resulting the classData of the class object by byte[]
	 * 
	 * @throws IOException
	 *             if have some failed or interrupted I/O operations.
	 */
	private byte[] loadClassData(String className) throws IOException {

		String filePath = searchFile(myClasspath, className + ".class");

		if (!(filePath == null || filePath == "")) {

			System.out.println("It have found the file : " + className
					+ ".  Begin to read the data and load the class。");
			FileInputStream inFile = new FileInputStream(filePath);
			byte[] classData = new byte[inFile.available()];
			inFile.read(classData);
			inFile.close();
			loadClassTime.put(className, new File(filePath).lastModified());
			return classData;
		} else {

			filePath = searchFile(myClasspath, className + ".java");
			if (!(filePath == null || filePath == "")) {
				System.out.println("It have found the file : " + filePath
						+ ".  Begin to translate");
				Runtime.getRuntime().exec("javac " + filePath);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("Translate it over : " + filePath);
				return loadClassData(className);
			} else {
				System.out
						.println("Haven't found the file, and fail to read the classData!");
				return null;
			}
		}
	}

	/** */
	/**
	 * Loads the class with the specified binary name.The default implementation
	 * throws a ClassNotFoundException.
	 * 
	 * @param classData
	 *            The data of the class.
	 * @param className
	 *            The binary name of the class.
	 * 
	 * @return The resulting Class object.
	 * 
	 * @throws ClassNotFoundException
	 *             If the class could not be found.
	 */
	public Class loadClass(byte[] classData, String className)
			throws ClassNotFoundException {

		System.out.println("MyClassLoader is loading : " + className + "");
		Class c = defineClass(className, classData, 0, classData.length);
		loadClassHashTable.put(className, c);
		System.out.println("Complete to load the class :" + className);

		return c;
	}

	/** */
	/**
	 * Loads the class with the specified binary name.The default implementation
	 * throws a ClassNotFoundException.
	 * 
	 * @param className
	 *            The binary name of the class.
	 * @param jarName
	 *            The binary name of the jar that search the class from it.
	 * 
	 * @return The resulting Class object.
	 * 
	 * @throws ClassNotFoundException
	 *             If the class could not be found.
	 */
	protected Class loadClass(String className, String jarName)
			throws ClassNotFoundException {

		String jarPath = searchFile(myClasspath, jarName + ".jar");
		JarInputStream in = null;

		if (!(jarPath == null || jarPath == "")) {

			try {
				in = new JarInputStream(new FileInputStream(jarPath));
				JarEntry entry;
				while ((entry = in.getNextJarEntry()) != null) {
					String outFileName = entry.getName().substring(
							entry.getName().lastIndexOf("/") + 1,
							entry.getName().length());
					if (outFileName.equals(className + ".class")) {
						if (entry.getSize() == -1) {
							System.err.println("error : can't read the file!");
							return null;
						}
						byte[] classData = new byte[(int) entry.getSize()];
						System.out
								.println("It have found the file : "
										+ className
										+ ".  Begin to read the data and load the class。");
						in.read(classData);
						return loadClass(classData, className);
					}
				}
				System.out.println("Haven't found the file " + className
						+ " in " + jarName + ".jar.");
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} else {
			System.out.println("Haven't found the jarFile: " + jarName
					+ ".jar.");
			return null;
		}
		return null;
	}

	/** */
	/**
	 * Reloads the class with the specified binary name. Needn't have to restart
	 * JVM then reload the class.
	 * 
	 * @param className
	 *            The binary name of the class need to reload .
	 * 
	 * @return The resulting Class object.
	 * 
	 * @throws ClassNotFoundException
	 *             If the class was not found.
	 */
	public Class reload(String fileName) {

		String filePath = searchFile(myClasspath, fileName + ".class");
		Long a = new File(filePath).lastModified();

		if (!a.equals(loadClassTime.get(fileName))) {
			loadClassHashTable.remove(fileName);
			loadClassTime.remove(fileName);
			try {
				MyClassLoader mc2 = new MyClassLoader(myClasspath);
				mc2.loadClass(fileName);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		} else {
			System.out
					.println("The class is the newest version , needn't reloading.");
		}
		return null;
	}

	/** */
	/**
	 * search the file with the specified binary name. Needn't have to restart
	 * JVM then reload the class.
	 * 
	 * @param classpath
	 *            the specified path where we search.
	 * @param fileName
	 *            The binary name of the file that want to search.
	 * 
	 * @return The resulting file path.
	 */
	public String searchFile(String classpath, String fileName) {

		String cut = fileName.substring(fileName.lastIndexOf('.'), fileName
				.length());
		String path = fileName.substring(0, fileName.lastIndexOf('.')).replace(
				'.', '/')
				+ cut;

		File f = new File(classpath + path);
		if (f.isFile()) {
			return f.getPath();
		} else {
			String objects[] = new File(classpath).list();
			for (int i = 0; i < objects.length; i++) {
				if (new File(classpath + File.separator + objects[i])
						.isDirectory()) {
					String s = searchFile(classpath + objects[i]
							+ File.separator, fileName);
					if (s == null || s == "") {
						continue;
					} else {
						return s;
					}
				}
			}
		}
		return null;
	};

}




最后解密,并且通过反射机制执行:
package com.hitachi.crypt;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import com.hitachi.classloader.MyClassLoader;
public class Decrypt {

	public static void main(String[] args) throws Exception {

		SecureRandom sr = new SecureRandom();
		FileInputStream fi = new FileInputStream(new File("d:/key.txt"));
		byte rawKeyData[] = new byte[fi.available()];
		fi.read(rawKeyData);
		fi.close();
		DESKeySpec dks = new DESKeySpec(rawKeyData);
		SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(dks);
		Cipher cipher = Cipher.getInstance("DES");
		cipher.init(Cipher.DECRYPT_MODE, key, sr);
		FileInputStream fi2 = new FileInputStream(new File(
				"D:/HelloWorld.class"));
		byte encryptedData[] = new byte[fi2.available()];
		fi2.read(encryptedData);
		fi2.close();
		byte decryptedData[] = cipher.doFinal(encryptedData);
		MyClassLoader mcl = new MyClassLoader("D:/");
		Class cl = mcl.loadClass(decryptedData, "HelloWorld");
		Method mainMethod = cl.getMethod("sayHello");
		mainMethod.invoke(null, null);
	}
}


其中源文件是这样的:

public class HelloWorld {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("Hello world");
	}

	public static void sayHello() {
		System.out.println("Hello");
	}

}


就可以了。
2
0
分享到:
评论
4 楼 lzj0470 2011-12-24  
这种方式,带来的问题很大。如:返回一个对象,然后再调用一些办法
3 楼 qskm 2010-07-22  
这个怎么用呢?楼主没说清楚啊,
1、 加密的话该怎么加密?直接执行Crypt类,一个一个加密class文件还是怎么整?
2、 加载class的classloader类是放在哪里?需要配置还是如何调用的?
3、 基于ssh的系统能用不?
4、 ???
2 楼 thxg 2009-11-08  
博主好,请教一个classloader相关的问题,我用classloader加载了一个jar文件,用完之后希望可以跟据用户意愿删掉这个jar文件,但据说VM不退出,就不会释放,就无法删除,有什么好办法解决这个问题吗?参考问答模块的链接:
http://www.iteye.com/problems/28854
1 楼 雁行 2009-06-12  
好复杂啊
参考一下

相关推荐

    加密Java源代码

    加密Java源代码 ,使用自定义classloader加载器和加密解密技术实现

    Java类加密程序

    例如,本加密工具安装在c:\hideasoft\java_protect,执行加密后的CLASS文件的命令行如下: java -agentlib:c:\hideasoft\java_protect\hidea &lt;您的CLASS类及参数&gt; 应用场合 独立的应用程序(Application,...

    Java类加密2.0版本,无限制

    独立的应用程序(Application,自定义main方法),运行java时,带上参数-agentlib:&lt;所在路径&gt;\lanswon Tomcat等JAVA Web Server,修改启动脚本,把执行java的命令行加上参数-agentlib:&lt;所在路径&gt;\lanswon JBOSS等...

    service_classloader

    工程名为service_classloader,功能全部使用corejava实现,使用maven管理依赖,没有使用任何框架(junit除外)。 使用的技术主要包括:classlaoder,加密解密,线程,ThreadLocal使用,反射,IO操作,jdbc, 序列化,...

    java 面试题 总结

     GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...

    超级有影响力霸气的Java面试题大全文档

     GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...

    汪文君高并发编程实战视频资源全集

     高并发编程第三阶段13讲 一个JNI程序的编写,通过Java去调用C,C++程序.mp4  高并发编程第三阶段14讲 Unsafe中的方法使用,一半是天使,一半是魔鬼的Unsafe.mp4  高并发编程第三阶段15讲 Unsafe背后的汇编指令,...

    汪文君高并发编程实战视频资源下载.txt

     高并发编程第三阶段13讲 一个JNI程序的编写,通过Java去调用C,C++程序.mp4  高并发编程第三阶段14讲 Unsafe中的方法使用,一半是天使,一半是魔鬼的Unsafe.mp4  高并发编程第三阶段15讲 Unsafe背后的汇编指令,...

    Spring.3.x企业应用开发实战(完整版).part2

    3.2.2 类装载器ClassLoader 3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 ...

    Spring3.x企业应用开发实战(完整版) part1

    3.2.2 类装载器ClassLoader 3.2.3 Java反射机制 3.3 资源访问利器 3.3.1 资源抽象接口 3.3.2 资源加载 3.4 BeanFactory和ApplicationContext 3.4.1 BeanFactory介绍 3.4.2 ApplicationContext介绍 3.4.3 父子容器 ...

Global site tag (gtag.js) - Google Analytics