文章出處
利用 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的自定義
a) Classloader 是個抽象類 其中通過覆蓋findclass來改變文件搜索地址。已達到在任何父classloader加載不到的情況才會由他加載。
b) Classloader的加載機制是讓自己的父classloader加載如果加載不到再有自己加載。如果有父classloader會一直向上詢問。
2、不影響程序的調用關系。
文件格式不能改變class文件必須是合法文件否則編譯時不能后通過。可以編譯不代表可以正常運行、不對class文件進行加密。只對其方法中的字節碼加密,正常編譯在最后發布時進行classloader包開發進行加密解密
通過Java Native Interface(JNI)的調用或的使用本地代碼的方法可以實現java加密與本地信息的結合,演示中加密方法使用簡單的XOR方法加密
演示代碼有兩個部分:
第一部分為程序主體,簡單調用一個類中的一個方法在控制臺上打印一串字符 HelloJava代碼見源程序
第二部分為自定義ClassLoader 負責加載主體程序文件。并解密其中的加密部分。詳細過程見附錄ClassLoader自定義和byteCode加密解密部分
2.反射調用自己調用的加載類的的方法。此方法應該是你的程序的入口函數。這樣可以保證你程序的順利運行。
a) 根據文件格式查找到文件中的方法實現的bytecode進行加密。加密bytecode不會影響class文件的格式。且所有的文件能在VM加載運行之前總認為他是合法的。可以順利加載的。
沒有個源碼。技術含量沒有什么,所以就不給源碼了,給個示例,key.lic 和java程序放一起就能夠正確運行。key.lic不對。或沒有程序都不能運行
文章列表
利用 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); }
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)
沒有個源碼。技術含量沒有什么,所以就不給源碼了,給個示例,key.lic 和java程序放一起就能夠正確運行。key.lic不對。或沒有程序都不能運行
文章列表
全站熱搜