首页 > Linux操作系统 > Linux操作系统 > [转载]Java反编译的研究
一、 混淆器
目前,开发人员使用的比较多的保护代码的方法是用混淆器。混淆器是采用一些方
法将类,变量,方法,包的名字改为无意义的字符串;使用非法的字符代替符号;贴加一些代码使反编译软件崩溃;贴加一些无关的指令或永远执行不到的指令等使
反编译无法成功或所得的代码可读性很差。这样就实现了反反编译的目的。我们来做个演示。原始代码如下:
import java.io.*;
import java.security.*;
public class sKey_kb{
public static void main(String args[]) throws Exception{
FileInputStream f=new FileInputStream("key1.dat");
ObjectInputStream b=new ObjectInputStream(f);
Key k=(Key)b.readObject();
byte[] kb=k.getEncoded();
FileOutputStream f2=new FileOutputStream("keykb1.dat");
f2.write(kb);
for(int i=0;i
System.out.print(kb[i]+",");
} } }
import java.io.*;
import java.security.Key;
public class sKey_kb{
public skey() {}
public static void main(String args[]) {
FileInputStream fileinputstream=new FileInputStream(ma);
ObjectInputStream objectinputstream=new ObjectInputStream(fileinputstream);
Key key=(Key)b.readObject();
byte abyte0[]=key.getEncoded();
FileOutputStream fileoutputstream=new FileOutputStream(na);
fileoutputstream.write(abyte0);
for(int i=0;i
System.out.print(abyte0[i]+oa);
}
private static String a(String s){
int i=s.length();
char ac[]=new char[i];
for(int j=0;j
return new String(ac);
}
private static String ma="u5AA1u5AAFu5AF3u5AFBu5AE4u5AAEu5AABu5ABE";
private static String na="u5AA1u5AAFu5AB3u5AA1u5AA8u5AFBu5AE4u5AAEu5AABu5ABE";
private static String oa="u5AE6";
public static{
ma=a(ma);
na=a(ma)
oa=a(oa);
} }
URL url[]={
new URL("file:///c:/classloader/web"),
new URL("http://www.asp.zjc.zjut.edu.cn/javaclass/")
};
URLClassLoader cl=new URLClassLoader(url);
Class class=cl.loadClass("class1");
Class getarg[]={
(new String [1]).getClass() };
Method m=class.getMethod("main",getarg);
String[] myl={"arg1 passed","arg2 passed");
Object myarg[]={myl};
m.invole(null,myarg);
三、 加密重要类
使用网络加载重要类的方法固然有一定的用处,但是,在遇到无网络的情况时,还是无法解决我们的问题。对于这种情况,我们只能把所有文件放在本地计算机上。那么,对此我们该怎么做才能保护好java代码呢?
其实,要实现这一点,并不难,只需要对一些重要的类实行加密就可以了。当然,在装载时,加密的类是需要解密才能被ClassLoader识别的。所以,
我们必须自己创建ClassLoader类。在标准java
api中ClassLoader有几个重要的方法。创建定制ClassLoader时,我们只需覆盖其中的一个,即loadClass,添加获取原始类文
件数据的代码。这个方法有两个参数:类的名字,以及一个表示JVM是否要求解析类名字的标记(即是否同时装入有依赖关系的类)。如果这个标记为true,
我们只需在返回JVM之前调用resolveClass。
原代码如下:
public Class loadClass( String name, boolean resolve )
throws ClassNotFoundException {
try {
Class clasz = null;
//步骤1:如果类已经在系统缓冲之中,我们就不需要再次装入它
clasz = findLoadedClass( name );
if (clasz != null)
return clasz;
byte classData[] = /* 通过某种方法获取字节码数据 */;
if (classData != null) {
clasz = defineClass( name, classData, 0, classData.length );
}
//步骤2:如果上面没有成功,
if (clasz == null)
clasz = findSystemClass( name );
//步骤3:如有必要,则装入相关的类
if (resolve && clasz != null)
resolveClass( clasz );
return clasz;
} catch( IOException ie ) {
throw new ClassNotFoundException( ie.toString() );
} catch( GeneralSecurityException gse ) {
throw new ClassNotFoundException( gse.toString() );
} }
代码中的大部分对所有ClassLoader对象来说都一样,但有一小部分是特有的。在处理过程中,ClassLoader对
象要用到其他几个辅助方法:findLoadedClass:用来进行检查,以便确认被请求的类当前是否存在,loadClass方法应该首先调用它。
defineClass:获得原始类文件字节码数据之后,调用defineClass把它转换成对象,任何loadClass实现都必须调用这个方法。
findSystemClass:提供默认ClassLoader的支持。如果用来寻找类的定制方法不能找到指定的类,则可以调用该方法尝试默认的装入方
式。resolveClass:当JVM想要装入的不仅包括指定的类,而且还包括该类引用的所有其他类时,它会把loadClass的resolve参数
设置成true。这时,我们必须在返回刚刚装入的Class对象给调用者之前调用resolveClass。
接下来就是加密解密
部分。Java加密扩展即Java Cryptography
Extension,简称JCE,是Sun的加密服务软件,包含了加密和密匙生成功能。我们可以用DES算法加密和解密字节码。用JCE加密和解密数据是
要遵循一些基本步骤的(可以参考<>,这里就不祥述了)。
加密完成后,就是通过解密来获取原始类的java字节码。可以通过一个DecryptStart程序运行经过加密的应用。
具体方法如下:
public class DecryptStart extends ClassLoader
{
private SecretKey key;
private Cipher cipher;
public DecryptStart( SecretKey key ) throws GeneralSecurityException,IOException {
this.key = key;
String algorithm = "DES";
SecureRandom sr = new SecureRandom();
System.err.println( "[DecryptStart: creating cipher]" );
cipher = Cipher.getInstance( algorithm );
cipher.init( Cipher.DECRYPT_MODE, key, sr );
}
// main过程:我们要在这里读入密匙,创建DecryptStart的
static public void main( String args[] ) throws Exception {
String keyFilename = args[0];
String appName = args[1];
String realArgs[] = new String[args.length-2];
System.arraycopy( args, 2, realArgs, 0, args.length-2 );
System.err.println( "[DecryptStart: reading key]" );
byte rawKey[] = Util.readFile( keyFilename );
DESKeySpec dks = new DESKeySpec( rawKey );
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );
SecretKey key = keyFactory.generateSecret( dks );
DecryptStart dr = new DecryptStart( key );
System.err.println( "[DecryptStart: loading "+appName+"]" );
Class clasz = dr.loadClass( appName );
String proto[] = new String[1];
Class mainArgs[] = { (new String[1]).getClass() };
Method main = clasz.getMethod( "main", mainArgs );
Object argsArray[] = { realArgs };
System.err.println( "[DecryptStart: running "+appName+".main()]" );
main.invoke( null, argsArray );
}
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/374079/viewspace-130969/ ,如需转载,请注明出处,否则将追究法律责任。