首页
社区
课程
招聘
[原创]JAVA 利用JNI加密
发表于: 2011-3-6 17:25 17450

[原创]JAVA 利用JNI加密

2011-3-6 17:25
17450
利用 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不对。或没有程序都不能运行

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 31
活跃值: (48)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
顶了!!!。
2011-3-6 20:02
0
雪    币: 257
活跃值: (105)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
有个最大的问题是MyClassLoader容易被反编译分析,
由于代码不多,就算高质量混淆,分析后写一个解密程序,
直接调用dll生成没加密的class应该容易实现。
2011-3-8 09:22
0
雪    币: 2368
活跃值: (81)
能力值: (RANK:300 )
在线值:
发帖
回帖
粉丝
4
是的,如果有正确的key文件。是可以写出解码程序的。如果所有的文件都混淆了。
这样既需要正确的一组key和对应的机器识别码。还要求有强大的耐心分析代码。不过此时bytecode 的加密看上去就有点多余了。

所以混淆还是王道...
2011-3-9 00:22
0
游客
登录 | 注册 方可回帖
返回
//