我是Arren :)
我们知道现在很多的Java反编译器,使得所有的java class文件很容易就被编译成源代码,即使使用了混淆器,但是治标不治本,因为对java虚拟机呈现的总是相同的指令,而java的指令系统就注定了反编译的可行性,以及容易性。
编译为本机指令的二进制代码的C语言程序,以及汇编程序,在反汇编的时候相对来说很难,而能够分析反汇编结果的人需要更高的技能,如果要反编译,更难,因为C语言程序编译的结果已经导致所有的原始代码信息丢失(非debug编译方式),要反编译为可读的代码很困难。 当然能够直接分析 机器指令的人可以在不反编译的情况下直接读懂程序,这样的人很少,计算机领域也没有几个。
所以我的保护程序是建立在此基础上。
(1)
正常开发我们的java程序,完成测试任务后, 摘除核心部分,或者要保护的部分,或者由于某种原因而不想公开的部分, 打包成jar文件,这个对于java开发来说是很简单的部分。 得到 kernal.jar,文件内容为:
/kernal/core/util.class
/kernal/core/main.class
/kernal/startup.class
其中manifest文件包含了:
Main-Class:kernal.startup
,只是了此包的可执行类为 kernal.startup.class。 这个类将在此包被加载的时候引导核心程序的执行。
(2)
加密kernal.jar。我们使用RSA算法加密保护一个AES随机密钥,而整个jar文件使用此密钥加密。
加密工具类如下:
加密的结果是一个文件,因为使用了RSA算法保护密钥,因此即使拿到此文件也无法获取其中的内容。 将此文件命名为 resource, 并和java程序的其他部分一起打包, 形成testproject.jar, 内容如下:
/test/pj/aaa.class
/test/pj/bbb.class
/resource
现在kernal.jar成了整体程序的一个资源文件,且是加密的。
其中比如 test.aaa.class调用了: org.az.io.LibLoader.load();
启动核心部分。
(3)
加密包加载程序。
是一个Java程序,一个类, 如下:
此类是 核心程序的加载类,其中包含了解密/resource用的RSA公钥,即字节流 byte [] _file_content 。关于把任意文件转换成 字节数组定义形式,我提供了工具类。
(4)
保护Fuckyou.class文件。我们对此文件进行加密以及编码。打开文件流为 fis, 加密输出为 writer:
输出为加密并编码的 byte数组定义文件。 注意到,我们使用了简单的字节异或操作来加密。这样子比较简单。方法类似可替换。
(5)
至此,核心程序kernal.jar已经加密,而加密包引导程序也已经准备好。注意:(2),(3),(4)步骤中的类都是我们加密工具的一部分,因此普通用户只需要完成步骤(1)的任务即可,所以程序是通用的。
(6)
引导加密程序,我们需要使用C语言代码,调用JNI。
注意其中的 private native void spawn(Object loader) 方法。
创建C语言动态库项目,使用如下程序:libloader.c,
编译结果为libloader.dll. 我们把此文件和
LibLoader .class一起打包成libloader.jar。这个文件就是提供给最终程序的。
至此,保护程序的唯一入口就是 libloader.dll文件,也是保护程序的弱点,但是所有的安全程序都有一个弱点,即使全部使用 RSA加密,也存在一个问题,你如何存放RSA私钥,如果你加密此私钥,那么你加密此私钥的密钥又放在何处? 所以最后总是有一个弱点。
当然可以用硬件之类的保护此弱点,但我在此介绍方法而已。当然攻破C程序难度不小,相对安全。
LibLoader.class 和libloader.dll一起打包后得到, libloader.jar.
(7)最后发布程序
至此我们得到的文件包括:
testproject.jar, 其中包含了加密过的kernal.jar。
libloader.jar,加密程序,可以通用。
这就是所有了,保护程序其实是和程序主体部分分离的,只需要在发布之前进行保护。当然如果你已经公布了核心部分的代码,那保护就没有必要了:)
我们知道现在很多的Java反编译器,使得所有的java class文件很容易就被编译成源代码,即使使用了混淆器,但是治标不治本,因为对java虚拟机呈现的总是相同的指令,而java的指令系统就注定了反编译的可行性,以及容易性。
编译为本机指令的二进制代码的C语言程序,以及汇编程序,在反汇编的时候相对来说很难,而能够分析反汇编结果的人需要更高的技能,如果要反编译,更难,因为C语言程序编译的结果已经导致所有的原始代码信息丢失(非debug编译方式),要反编译为可读的代码很困难。 当然能够直接分析 机器指令的人可以在不反编译的情况下直接读懂程序,这样的人很少,计算机领域也没有几个。
所以我的保护程序是建立在此基础上。
(1)
正常开发我们的java程序,完成测试任务后, 摘除核心部分,或者要保护的部分,或者由于某种原因而不想公开的部分, 打包成jar文件,这个对于java开发来说是很简单的部分。 得到 kernal.jar,文件内容为:
/kernal/core/util.class
/kernal/core/main.class
/kernal/startup.class
其中manifest文件包含了:
Main-Class:kernal.startup
,只是了此包的可执行类为 kernal.startup.class。 这个类将在此包被加载的时候引导核心程序的执行。
(2)
加密kernal.jar。我们使用RSA算法加密保护一个AES随机密钥,而整个jar文件使用此密钥加密。
加密工具类如下:
/*
* EncryptFile.java
*
* Created on May 24, 2007, 10:41 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package az.pkg.util;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyStore;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
/**
* Encrypt file as secret.
*
* The private key is in file "{AZ_HOME}/_KERNAL/keys/checker_rsa.jsk".
*
* @author Arren
*/
public class EncryptFile {
/**
* Creates a new instance of EncryptFile
*/
public EncryptFile() {
}
private void combine(Key key) throws FileNotFoundException, IOException, Exception{
// @todo set this array with the file you want to combine.
String file_to_enc="G:/PJ/TT/dist/TT.jar";
//@todo end.
File src_file = new File(file_to_enc);
if(!src_file.exists() || !src_file.isFile()) return;
FileOutputStream fos=null;
try{
System.out.println("Encrypt file:"+src_file.getCanonicalPath());
/// cipher for encrypt content of the file.
KeyGenerator kg = KeyGenerator.getInstance("AES");
SecretKey seckey=kg.generateKey();
Cipher content_cipher=Cipher.getInstance("AES/ECB/PKCS5Padding");
content_cipher.init(Cipher.ENCRYPT_MODE, seckey);
/// Get the Cipher for wrap the secret-key.
System.out.println("Key we use:" + key.getAlgorithm());
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.WRAP_MODE, key);
System.out.println("Key Cipher got:"+cipher.getAlgorithm());
byte[] b_sec_key = cipher.wrap(seckey);
/// Open the destination file.
/// Where do we store the output file.
File ofile=null;
fos=new FileOutputStream(ofile=new File(src_file.getParent(), src_file.getName()+"_enc"));
System.out.println("Output file="+ofile.getCanonicalPath());
/// Store the secret-key in file first.
DataOutputStream dos=new DataOutputStream(fos);
dos.writeInt(b_sec_key.length);
dos.write(b_sec_key);
dos.flush();
/// Create ciphered stream object.
javax.crypto.CipherOutputStream cos = new CipherOutputStream(fos, content_cipher);
System.out.println("Ciphered content stream got");
byte[] buffer = new byte[2048];
int n=0;
n+=combine_child_file(cos, src_file, buffer);
cos.close();
System.out.println(n+" bytes written.");
}
finally{
if(fos!=null){fos.close();}
}
}
private int combine_child_file(OutputStream os, File file, byte[] buffer) throws Exception {
FileInputStream fis = null;
int buf_sz =buffer.length;
int n=0, r=0;
try{
fis=new FileInputStream(file);
while(-1!=(r = fis.read(buffer))){
os.write(buffer, 0, r);
os.flush();
n+=r;
}
}finally{
if(fis!=null) fis.close();
}
return n;
}
public static void main(String [] args){
String home=System.getenv("AZ_HOME");
System.out.println("AZ_HOME:"+home);
File _kernal = new File(home, "_KERNAL");
File jks = new File(_kernal, "keys/checker_rsa.jks");
FileInputStream fis = null;
try{
KeyStore store = KeyStore.getInstance("JKS");
fis =new FileInputStream(jks);
store.load(fis, "howtofuckyou".toCharArray());
Key key=store.getKey("checker", "howtofuckyou".toCharArray());
new EncryptFile().combine(key);
}catch(Exception e){
if(fis!=null){
try {fis.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
System.out.println("failed to combine files:"+e.getMessage());
}
}
}
* EncryptFile.java
*
* Created on May 24, 2007, 10:41 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package az.pkg.util;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.Key;
import java.security.KeyStore;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
/**
* Encrypt file as secret.
*
* The private key is in file "{AZ_HOME}/_KERNAL/keys/checker_rsa.jsk".
*
* @author Arren
*/
public class EncryptFile {
/**
* Creates a new instance of EncryptFile
*/
public EncryptFile() {
}
private void combine(Key key) throws FileNotFoundException, IOException, Exception{
// @todo set this array with the file you want to combine.
String file_to_enc="G:/PJ/TT/dist/TT.jar";
//@todo end.
File src_file = new File(file_to_enc);
if(!src_file.exists() || !src_file.isFile()) return;
FileOutputStream fos=null;
try{
System.out.println("Encrypt file:"+src_file.getCanonicalPath());
/// cipher for encrypt content of the file.
KeyGenerator kg = KeyGenerator.getInstance("AES");
SecretKey seckey=kg.generateKey();
Cipher content_cipher=Cipher.getInstance("AES/ECB/PKCS5Padding");
content_cipher.init(Cipher.ENCRYPT_MODE, seckey);
/// Get the Cipher for wrap the secret-key.
System.out.println("Key we use:" + key.getAlgorithm());
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.WRAP_MODE, key);
System.out.println("Key Cipher got:"+cipher.getAlgorithm());
byte[] b_sec_key = cipher.wrap(seckey);
/// Open the destination file.
/// Where do we store the output file.
File ofile=null;
fos=new FileOutputStream(ofile=new File(src_file.getParent(), src_file.getName()+"_enc"));
System.out.println("Output file="+ofile.getCanonicalPath());
/// Store the secret-key in file first.
DataOutputStream dos=new DataOutputStream(fos);
dos.writeInt(b_sec_key.length);
dos.write(b_sec_key);
dos.flush();
/// Create ciphered stream object.
javax.crypto.CipherOutputStream cos = new CipherOutputStream(fos, content_cipher);
System.out.println("Ciphered content stream got");
byte[] buffer = new byte[2048];
int n=0;
n+=combine_child_file(cos, src_file, buffer);
cos.close();
System.out.println(n+" bytes written.");
}
finally{
if(fos!=null){fos.close();}
}
}
private int combine_child_file(OutputStream os, File file, byte[] buffer) throws Exception {
FileInputStream fis = null;
int buf_sz =buffer.length;
int n=0, r=0;
try{
fis=new FileInputStream(file);
while(-1!=(r = fis.read(buffer))){
os.write(buffer, 0, r);
os.flush();
n+=r;
}
}finally{
if(fis!=null) fis.close();
}
return n;
}
public static void main(String [] args){
String home=System.getenv("AZ_HOME");
System.out.println("AZ_HOME:"+home);
File _kernal = new File(home, "_KERNAL");
File jks = new File(_kernal, "keys/checker_rsa.jks");
FileInputStream fis = null;
try{
KeyStore store = KeyStore.getInstance("JKS");
fis =new FileInputStream(jks);
store.load(fis, "howtofuckyou".toCharArray());
Key key=store.getKey("checker", "howtofuckyou".toCharArray());
new EncryptFile().combine(key);
}catch(Exception e){
if(fis!=null){
try {fis.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
System.out.println("failed to combine files:"+e.getMessage());
}
}
}
加密的结果是一个文件,因为使用了RSA算法保护密钥,因此即使拿到此文件也无法获取其中的内容。 将此文件命名为 resource, 并和java程序的其他部分一起打包, 形成testproject.jar, 内容如下:
/test/pj/aaa.class
/test/pj/bbb.class
/resource
现在kernal.jar成了整体程序的一个资源文件,且是加密的。
其中比如 test.aaa.class调用了: org.az.io.LibLoader.load();
启动核心部分。
(3)
加密包加载程序。
是一个Java程序,一个类, 如下:
/*
* FuckYou.java
*
* Created on May 23, 2007, 9:59 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package az.jni;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.NoSuchPaddingException;
/**
* This class is wrapped in "commons-util".
* for more detailed information please @see "org.az.io.LibLoader".
*
* This file is extract files been encrypted by "az.pkg.util.EncryptFile".
*
* @author Arren
*/
public class FuckYou extends ClassLoader {
/**
* Creates a new instance of FuckYou
*/
public FuckYou() {
super (FuckYou. class .getClassLoader());
System.out.println( " [FuckYou] when you read this, i'm begin to fuck you :) " );
try {
init();
} catch (Exception e){
System.out.println( " [FuckYou] i failed to fuck you : " + e.getMessage());
} finally {
Runtime.getRuntime().gc();
}
}
private void init() throws IOException, InvalidKeyException, CertificateException, NoSuchAlgorithmException, NoSuchPaddingException, Exception{
// / Get the encrypted stream.
InputStream in = getClass().getResourceAsStream( " /resource " );
if (in != null ){
System.out.println( " [FuckYou] resource got : " + in);
} else {
System.out.println( " [FuckYou] no resource. finished. " );
return ;
}
// / Load certificate to encrypt the resource.
// / this byte array is the stream of the certificate.
byte [] _file_content = {
( byte ) 0x30 ,( byte ) 0x82 ,( byte ) 0x1 ,( byte ) 0xe5 ,( byte ) 0x30 ,( byte ) 0x82 ,( byte ) 0x1 ,( byte ) 0x4e ,( byte ) 0xa0 ,( byte ) 0x3 ,( byte ) 0x2 ,( byte ) 0x1 ,( byte ) 0x2 ,( byte ) 0x2 ,( byte ) 0x4 ,( byte ) 0x46 ,( byte ) 0x55 ,( byte ) 0xa ,( byte ) 0x27 ,( byte ) 0x30 ,( byte ) 0xd ,( byte ) 0x6 ,( byte ) 0x9 ,( byte ) 0x2a ,( byte ) 0x86 ,( byte ) 0x48 ,( byte ) 0x86 ,( byte ) 0xf7 ,( byte ) 0xd ,( byte ) 0x1 ,( byte ) 0x1 ,( byte ) 0x5 ,( byte ) 0x5 ,( byte ) 0x0 ,( byte ) 0x30 ,( byte ) 0x36 ,( byte ) 0x31 ,( byte ) 0xb ,( byte ) 0x30 ,( byte ) 0x9 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0x6 ,( byte ) 0x13 ,( byte ) 0x2 ,( byte ) 0x43 ,( byte ) 0x4e ,( byte ) 0x31 ,( byte ) 0xb ,( byte ) 0x30 ,( byte ) 0x9 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0xa ,( byte ) 0x13 ,( byte ) 0x2 ,( byte ) 0x61 ,( byte ) 0x7a ,( byte ) 0x31 ,( byte ) 0x1a ,( byte ) 0x30 ,( byte ) 0x18 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0x3 ,( byte ) 0x13 ,( byte ) 0x11 ,( byte ) 0x61 ,( byte ) 0x7a ,( byte ) 0x2e ,( byte ) 0x64 ,( byte ) 0x6f ,( byte ) 0x63 ,( byte ) 0x6d ,( byte ) 0x61 ,( byte ) 0x6e ,( byte ) 0x2e ,( byte ) 0x63 ,( byte ) 0x68 ,( byte ) 0x65 ,( byte ) 0x63 ,( byte ) 0x6b ,( byte ) 0x65 ,( byte ) 0x72 ,( byte ) 0x30 ,( byte ) 0x20 ,( byte ) 0x17 ,( byte ) 0xd ,( byte ) 0x30 ,( byte ) 0x37 ,( byte ) 0x30 ,( byte ) 0x35 ,( byte ) 0x32 ,( byte ) 0x34 ,( byte ) 0x30 ,( byte ) 0x33 ,( byte ) 0x34 ,( byte ) 0x34 ,( byte ) 0x33 ,( byte ) 0x39 ,( byte ) 0x5a ,( byte ) 0x18 ,( byte ) 0xf ,( byte ) 0x32 ,( byte ) 0x31 ,( byte ) 0x30 ,( byte ) 0x37 ,( byte ) 0x30 ,( byte ) 0x34 ,( byte ) 0x33 ,( byte ) 0x30 ,( byte ) 0x30 ,( byte ) 0x33 ,( byte ) 0x34 ,( byte ) 0x34 ,( byte ) 0x33 ,( byte ) 0x39 ,( byte ) 0x5a ,( byte ) 0x30 ,( byte ) 0x36 ,( byte ) 0x31 ,( byte ) 0xb ,( byte ) 0x30 ,( byte ) 0x9 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0x6 ,( byte ) 0x13 ,( byte ) 0x2 ,( byte ) 0x43 ,( byte ) 0x4e ,( byte ) 0x31 ,( byte ) 0xb ,( byte ) 0x30 ,( byte ) 0x9 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0xa ,( byte ) 0x13 ,( byte ) 0x2 ,( byte ) 0x61 ,( byte ) 0x7a ,( byte ) 0x31 ,( byte ) 0x1a ,( byte ) 0x30 ,( byte ) 0x18 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0x3 ,( byte ) 0x13 ,( byte ) 0x11 ,( byte ) 0x61 ,( byte ) 0x7a ,( byte ) 0x2e ,( byte ) 0x64 ,( byte ) 0x6f ,( byte ) 0x63 ,( byte ) 0x6d ,( byte ) 0x61 ,( byte ) 0x6e ,( byte ) 0x2e ,( byte ) 0x63 ,( byte ) 0x68 ,( byte ) 0x65 ,( byte ) 0x63 ,( byte ) 0x6b ,( byte ) 0x65 ,( byte ) 0x72 ,( byte ) 0x30 ,( byte ) 0x81 ,( byte ) 0x9f ,( byte ) 0x30 ,( byte ) 0xd ,( byte ) 0x6 ,( byte ) 0x9 ,( byte ) 0x2a ,( byte ) 0x86 ,( byte ) 0x48 ,( byte ) 0x86 ,( byte ) 0xf7 ,( byte ) 0xd ,( byte ) 0x1 ,( byte ) 0x1 ,( byte ) 0x1 ,( byte ) 0x5 ,( byte ) 0x0 ,( byte ) 0x3 ,( byte ) 0x81 ,( byte ) 0x8d ,( byte ) 0x0 ,( byte ) 0x30 ,( byte ) 0x81 ,( byte ) 0x89 ,( byte ) 0x2 ,( byte ) 0x81 ,( byte ) 0x81 ,( byte ) 0x0 ,( byte ) 0xa0 ,( byte ) 0x67 ,( byte ) 0x10 ,( byte ) 0x49 ,( byte ) 0x8c ,( byte ) 0x1f ,( byte ) 0x6b ,( byte ) 0xea ,( byte ) 0xb6 ,( byte ) 0x4c ,( byte ) 0xcd ,( byte ) 0xbd ,( byte ) 0xba ,( byte ) 0x8e ,( byte ) 0x29 ,( byte ) 0xbd ,( byte ) 0x65 ,( byte ) 0x3e ,( byte ) 0x15 ,( byte ) 0x3b ,( byte ) 0x8c ,( byte ) 0x38 ,( byte ) 0xd2 ,( byte ) 0x72 ,( byte ) 0x8a ,( byte ) 0x7c ,( byte ) 0x61 ,( byte ) 0x9e ,( byte ) 0x53 ,( byte ) 0x74 ,( byte ) 0xe7 ,( byte ) 0xab ,( byte ) 0x37 ,( byte ) 0xff ,( byte ) 0x8e ,( byte ) 0x42 ,( byte ) 0x78 ,( byte ) 0x85 ,( byte ) 0xd1 ,( byte ) 0x23 ,( byte ) 0x9f ,( byte ) 0xc0 ,( byte ) 0xef ,( byte ) 0xc4 ,( byte ) 0xc6 ,( byte ) 0xa0 ,( byte ) 0x7c ,( byte ) 0xb9 ,( byte ) 0x68 ,( byte ) 0xc2 ,( byte ) 0xa8 ,( byte ) 0x5a ,( byte ) 0x3c ,( byte ) 0xff ,( byte ) 0x5c ,( byte ) 0x4d ,( byte ) 0xf ,( byte ) 0xaa ,( byte ) 0x57 ,( byte ) 0x16 ,( byte ) 0x6c ,( byte ) 0x3c ,( byte ) 0x50 ,( byte ) 0xc3 ,( byte ) 0x45 ,( byte ) 0xc9 ,( byte ) 0x21 ,( byte ) 0x7d ,( byte ) 0x12 ,( byte ) 0x81 ,( byte ) 0x60 ,( byte ) 0x91 ,( byte ) 0x36 ,( byte ) 0xa0 ,( byte ) 0xd ,( byte ) 0x8c ,( byte ) 0xff ,( byte ) 0xb4 ,( byte ) 0xf4 ,( byte ) 0xc4 ,( byte ) 0xf3 ,( byte ) 0x9d ,( byte ) 0x9b ,( byte ) 0xe7 ,( byte ) 0xef ,( byte ) 0xd5 ,( byte ) 0x9c ,( byte ) 0x60 ,( byte ) 0xad ,( byte ) 0x40 ,( byte ) 0x4b ,( byte ) 0xc0 ,( byte ) 0x8b ,( byte ) 0x4b ,( byte ) 0xc9 ,( byte ) 0x5e ,( byte ) 0x24 ,( byte ) 0xac ,( byte ) 0xbe ,( byte ) 0x54 ,( byte ) 0x2e ,( byte ) 0x2f ,( byte ) 0x3a ,( byte ) 0x68 ,( byte ) 0xa3 ,( byte ) 0xf1 ,( byte ) 0x6 ,( byte ) 0xf6 ,( byte ) 0x4b ,( byte ) 0x90 ,( byte ) 0x9c ,( byte ) 0x1b ,( byte ) 0xff ,( byte ) 0xcc ,( byte ) 0x71 ,( byte ) 0x90 ,( byte ) 0x88 ,( byte ) 0x6 ,( byte ) 0x37 ,( byte ) 0x4e ,( byte ) 0x9b ,( byte ) 0x26 ,( byte ) 0xf0 ,( byte ) 0xd3 ,( byte ) 0xb ,( byte ) 0x7d ,( byte ) 0xd9 ,( byte ) 0x93 ,( byte ) 0x2 ,( byte ) 0x3 ,( byte ) 0x1 ,( byte ) 0x0 ,( byte ) 0x1 ,( byte ) 0x30 ,( byte ) 0xd ,( byte ) 0x6 ,( byte ) 0x9 ,( byte ) 0x2a ,( byte ) 0x86 ,( byte ) 0x48 ,( byte ) 0x86 ,( byte ) 0xf7 ,( byte ) 0xd ,( byte ) 0x1 ,( byte ) 0x1 ,( byte ) 0x5 ,( byte ) 0x5 ,( byte ) 0x0 ,( byte ) 0x3 ,( byte ) 0x81 ,( byte ) 0x81 ,( byte ) 0x0 ,( byte ) 0x60 ,( byte ) 0x26 ,( byte ) 0xf0 ,( byte ) 0x37 ,( byte ) 0xf9 ,( byte ) 0x8c ,( byte ) 0x91 ,( byte ) 0x28 ,( byte ) 0x2c ,( byte ) 0xae ,( byte ) 0x7a ,( byte ) 0x6a ,( byte ) 0x90 ,( byte ) 0xe7 ,( byte ) 0x44 ,( byte ) 0x6a ,( byte ) 0x37 ,( byte ) 0x27 ,( byte ) 0xd0 ,( byte ) 0x11 ,( byte ) 0xcc ,( byte ) 0x1c ,( byte ) 0x69 ,( byte ) 0x48 ,( byte ) 0x20 ,( byte ) 0x1f ,( byte ) 0x11 ,( byte ) 0x7b ,( byte ) 0x61 ,( byte ) 0x4a ,( byte ) 0x46 ,( byte ) 0x86 ,( byte ) 0x89 ,( byte ) 0xe4 ,( byte ) 0x73 ,( byte ) 0x42 ,( byte ) 0x85 ,( byte ) 0xc6 ,( byte ) 0xc6 ,( byte ) 0x3b ,( byte ) 0x14 ,( byte ) 0x7 ,( byte ) 0xe7 ,( byte ) 0x3c ,( byte ) 0x3c ,( byte ) 0x24 ,( byte ) 0xec ,( byte ) 0x30 ,( byte ) 0xe7 ,( byte ) 0x51 ,( byte ) 0x48 ,( byte ) 0x1a ,( byte ) 0x12 ,( byte ) 0x2a ,( byte ) 0x95 ,( byte ) 0xca ,( byte ) 0x53 ,( byte ) 0x5f ,( byte ) 0xf ,( byte ) 0xf8 ,( byte ) 0xfc ,( byte ) 0xd5 ,( byte ) 0xc9 ,( byte ) 0xfc ,( byte ) 0xe1 ,( byte ) 0xd ,( byte ) 0xee ,( byte ) 0x69 ,( byte ) 0xec ,( byte ) 0x8e ,( byte ) 0xed ,( byte ) 0x8f ,( byte ) 0xfc ,( byte ) 0x1b ,( byte ) 0x74 ,( byte ) 0xf0 ,( byte ) 0x40 ,( byte ) 0x6d ,( byte ) 0xd8 ,( byte ) 0x3e ,( byte ) 0xf0 ,( byte ) 0x88 ,( byte ) 0xa0 ,( byte ) 0xd6 ,( byte ) 0xac ,( byte ) 0x18 ,( byte ) 0x72 ,( byte ) 0xe0 ,( byte ) 0x52 ,( byte ) 0x9f ,( byte ) 0x73 ,( byte ) 0xd9 ,( byte ) 0x92 ,( byte ) 0xfa ,( byte ) 0x27 ,( byte ) 0xe2 ,( byte ) 0x31 ,( byte ) 0xc9 ,( byte ) 0xef ,( byte ) 0x4 ,( byte ) 0x4c ,( byte ) 0x4f ,( byte ) 0xb9 ,( byte ) 0x6f ,( byte ) 0xcd ,( byte ) 0x3b ,( byte ) 0x1d ,( byte ) 0x33 ,( byte ) 0x63 ,( byte ) 0x2a ,( byte ) 0x15 ,( byte ) 0xa5 ,( byte ) 0x1b ,( byte ) 0xd8 ,( byte ) 0x6 ,( byte ) 0x1e ,( byte ) 0xa ,( byte ) 0x1a ,( byte ) 0x66 ,( byte ) 0xe9 ,( byte ) 0x4 ,( byte ) 0xcf ,( byte ) 0xfd ,( byte ) 0x3f ,( byte ) 0xac ,( byte ) 0xce ,( byte ) 0xde ,( byte ) 0xbe
};
/** We generate the certificate with its binary content,
* we use cert's publick decrypt the file.
* */
CertificateFactory cf = CertificateFactory.getInstance( " X.509 " );
Certificate cert = cf.generateCertificate( new ByteArrayInputStream(_file_content));
System.out.println( " [FuckYou] certificate got. " );
Cipher key_cipher = Cipher.getInstance( " RSA " );
key_cipher.init(Cipher.UNWRAP_MODE, cert);
// / Data reader, used to read key -size.
DataInputStream dis = new DataInputStream(in);
// / Read a integer value,
// / this is the size of the secret-key.
int key_sz = dis.readInt();
if (key_sz < 0 || key_sz > 2048 ) throw new java.lang.Exception( " Illegal file: key size invalid. " );
byte [] key = new byte [key_sz];
if (key_sz != in.read(key)) throw new java.lang.Exception( " Illegal file: file size too small. " );
// / now the key we got is encrypted by the RSA key,
// / we must decrypt it to use.
Key sec_key = key_cipher.unwrap(key, " AES " , Cipher.SECRET_KEY);
java.util.Arrays.fill(key, 0 , key_sz, ( byte ) 0 );
key = null ;
System.out.println( " [FuckYou] secret key got " );
// / ok
// / we got the secret key.
Cipher file_cipher = Cipher.getInstance( " AES/ECB/PKCS5Padding " );
file_cipher.init(Cipher.DECRYPT_MODE, sec_key);
CipherInputStream cis = new CipherInputStream(in, file_cipher);
System.out.println( " [FuckYou] cipher stream got " );
// // / write the file to disk,
// // / or use it in memory.
// FileOutputStream fos=null;
// try{
// fos=new FileOutputStream(new File("g:/xxx.jar"));
// byte[] buffer = new byte[2048];
// int r=0;
// while(-1!=(r=cis.read(buffer))) fos.write(buffer, 0, r);
// }finally{
// if(fos!=null){fos.close(); fos=null;}
// }
System.out.println( " [FuckYou] load module from resources " );
try {
load_jar_file(cis, true );
} finally {
cis.close();
System.out.println( " [FuckYou] module loaded. " );
}
}
private void load_jar_file(InputStream jar_file, boolean load_or_write) throws IOException, Exception{
JarInputStream jis = new JarInputStream(jar_file);
String tmp = null ;
final int MAX_SIZE = 1024 * 128 ; long size = 0 ;
byte [] buffer = new byte [MAX_SIZE];
// / Read each entry in the jar file,
// / every entry should be an .class object.
JarEntry entry = jis.getNextJarEntry();
while (entry != null ){
if ( ! entry.isDirectory() && (tmp = entry.getName()).endsWith( " .class " )){
// / Check entry size.
size = entry.getSize();
if (size < 64 || size > MAX_SIZE){
System.out.println( " [FuckYou] module component is too large. ignored. " );
}
else if (load_or_write){
int p = tmp.indexOf( " .class " );
load_class(jis, tmp.substring( 0 , p).replace( ' / ' , ' . ' ), buffer, MAX_SIZE);
// }else{
// write_class(jis, tmp, buffer);
}
}
entry = jis.getNextJarEntry();
}
if (load_or_write){
System.out.println( " [FuckYou] trying to bootstrap module... " );
// / if Main-Class defined,
// / we create an instance of it.
Manifest mf = jis.getManifest();
if (mf != null ){
Attributes attrs = mf.getMainAttributes();
String mc = attrs.getValue(Attributes.Name.MAIN_CLASS);
if (mc != null ){
System.out.println( " [FuckYou] found entry point : " + mc);
try {
Class cls = Class.forName(mc, true , this );
System.out.println( " [FuckYou] got class object: " + cls);
Method m = cls.getDeclaredMethod( " main " , new Class[]{String[]. class });
System.out.println( " [FuckYou] found 'main' method: " + m);
m.invoke( null , (Object) null );
System.out.println( " [FuckYou] 'main' method invoked. " );
} catch (Exception e){
e.printStackTrace();
System.out.println( " [FuckYou] failed to bootstrap module by main(): " + e.getMessage());
}
} else {
System.out.println( " [FuckYou] no entry point. no need to bootstrap. " );
}
} // .if.
}
}
/**
* Load a class definition from stream
* */
private void load_class(InputStream cls_stream, String cls_name, byte [] buffer, int bl ) throws Exception{
System.out.println( " [FuckYou] find component : " + cls_name);
int off = 0 , r = 0 ;
while ( - 1 != (r = cls_stream.read(buffer, off, bl - off))){
off += r;
}
System.out.println( " [FuckYou] component size: " + String.valueOf(off));
Class cls = super .defineClass(cls_name, buffer, 0 , off);
}
//
// private void write_class(InputStream cls_stream, String cls_name, byte[] buffer ) throws Exception{
// File file = new File(cls_name);
// File dir = file.getParentFile();
// if(!dir.exists()) dir.mkdirs();
// FileOutputStream fos = null;
// try{
// fos = new FileOutputStream(file);
// int r=0;
// while(-1!=(r=cls_stream.read(buffer))) fos.write(buffer, 0, r);
// }
// finally{
// if(fos!=null){fos.close();}
// }
// }
}
* FuckYou.java
*
* Created on May 23, 2007, 9:59 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package az.jni;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.NoSuchPaddingException;
/**
* This class is wrapped in "commons-util".
* for more detailed information please @see "org.az.io.LibLoader".
*
* This file is extract files been encrypted by "az.pkg.util.EncryptFile".
*
* @author Arren
*/
public class FuckYou extends ClassLoader {
/**
* Creates a new instance of FuckYou
*/
public FuckYou() {
super (FuckYou. class .getClassLoader());
System.out.println( " [FuckYou] when you read this, i'm begin to fuck you :) " );
try {
init();
} catch (Exception e){
System.out.println( " [FuckYou] i failed to fuck you : " + e.getMessage());
} finally {
Runtime.getRuntime().gc();
}
}
private void init() throws IOException, InvalidKeyException, CertificateException, NoSuchAlgorithmException, NoSuchPaddingException, Exception{
// / Get the encrypted stream.
InputStream in = getClass().getResourceAsStream( " /resource " );
if (in != null ){
System.out.println( " [FuckYou] resource got : " + in);
} else {
System.out.println( " [FuckYou] no resource. finished. " );
return ;
}
// / Load certificate to encrypt the resource.
// / this byte array is the stream of the certificate.
byte [] _file_content = {
( byte ) 0x30 ,( byte ) 0x82 ,( byte ) 0x1 ,( byte ) 0xe5 ,( byte ) 0x30 ,( byte ) 0x82 ,( byte ) 0x1 ,( byte ) 0x4e ,( byte ) 0xa0 ,( byte ) 0x3 ,( byte ) 0x2 ,( byte ) 0x1 ,( byte ) 0x2 ,( byte ) 0x2 ,( byte ) 0x4 ,( byte ) 0x46 ,( byte ) 0x55 ,( byte ) 0xa ,( byte ) 0x27 ,( byte ) 0x30 ,( byte ) 0xd ,( byte ) 0x6 ,( byte ) 0x9 ,( byte ) 0x2a ,( byte ) 0x86 ,( byte ) 0x48 ,( byte ) 0x86 ,( byte ) 0xf7 ,( byte ) 0xd ,( byte ) 0x1 ,( byte ) 0x1 ,( byte ) 0x5 ,( byte ) 0x5 ,( byte ) 0x0 ,( byte ) 0x30 ,( byte ) 0x36 ,( byte ) 0x31 ,( byte ) 0xb ,( byte ) 0x30 ,( byte ) 0x9 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0x6 ,( byte ) 0x13 ,( byte ) 0x2 ,( byte ) 0x43 ,( byte ) 0x4e ,( byte ) 0x31 ,( byte ) 0xb ,( byte ) 0x30 ,( byte ) 0x9 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0xa ,( byte ) 0x13 ,( byte ) 0x2 ,( byte ) 0x61 ,( byte ) 0x7a ,( byte ) 0x31 ,( byte ) 0x1a ,( byte ) 0x30 ,( byte ) 0x18 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0x3 ,( byte ) 0x13 ,( byte ) 0x11 ,( byte ) 0x61 ,( byte ) 0x7a ,( byte ) 0x2e ,( byte ) 0x64 ,( byte ) 0x6f ,( byte ) 0x63 ,( byte ) 0x6d ,( byte ) 0x61 ,( byte ) 0x6e ,( byte ) 0x2e ,( byte ) 0x63 ,( byte ) 0x68 ,( byte ) 0x65 ,( byte ) 0x63 ,( byte ) 0x6b ,( byte ) 0x65 ,( byte ) 0x72 ,( byte ) 0x30 ,( byte ) 0x20 ,( byte ) 0x17 ,( byte ) 0xd ,( byte ) 0x30 ,( byte ) 0x37 ,( byte ) 0x30 ,( byte ) 0x35 ,( byte ) 0x32 ,( byte ) 0x34 ,( byte ) 0x30 ,( byte ) 0x33 ,( byte ) 0x34 ,( byte ) 0x34 ,( byte ) 0x33 ,( byte ) 0x39 ,( byte ) 0x5a ,( byte ) 0x18 ,( byte ) 0xf ,( byte ) 0x32 ,( byte ) 0x31 ,( byte ) 0x30 ,( byte ) 0x37 ,( byte ) 0x30 ,( byte ) 0x34 ,( byte ) 0x33 ,( byte ) 0x30 ,( byte ) 0x30 ,( byte ) 0x33 ,( byte ) 0x34 ,( byte ) 0x34 ,( byte ) 0x33 ,( byte ) 0x39 ,( byte ) 0x5a ,( byte ) 0x30 ,( byte ) 0x36 ,( byte ) 0x31 ,( byte ) 0xb ,( byte ) 0x30 ,( byte ) 0x9 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0x6 ,( byte ) 0x13 ,( byte ) 0x2 ,( byte ) 0x43 ,( byte ) 0x4e ,( byte ) 0x31 ,( byte ) 0xb ,( byte ) 0x30 ,( byte ) 0x9 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0xa ,( byte ) 0x13 ,( byte ) 0x2 ,( byte ) 0x61 ,( byte ) 0x7a ,( byte ) 0x31 ,( byte ) 0x1a ,( byte ) 0x30 ,( byte ) 0x18 ,( byte ) 0x6 ,( byte ) 0x3 ,( byte ) 0x55 ,( byte ) 0x4 ,( byte ) 0x3 ,( byte ) 0x13 ,( byte ) 0x11 ,( byte ) 0x61 ,( byte ) 0x7a ,( byte ) 0x2e ,( byte ) 0x64 ,( byte ) 0x6f ,( byte ) 0x63 ,( byte ) 0x6d ,( byte ) 0x61 ,( byte ) 0x6e ,( byte ) 0x2e ,( byte ) 0x63 ,( byte ) 0x68 ,( byte ) 0x65 ,( byte ) 0x63 ,( byte ) 0x6b ,( byte ) 0x65 ,( byte ) 0x72 ,( byte ) 0x30 ,( byte ) 0x81 ,( byte ) 0x9f ,( byte ) 0x30 ,( byte ) 0xd ,( byte ) 0x6 ,( byte ) 0x9 ,( byte ) 0x2a ,( byte ) 0x86 ,( byte ) 0x48 ,( byte ) 0x86 ,( byte ) 0xf7 ,( byte ) 0xd ,( byte ) 0x1 ,( byte ) 0x1 ,( byte ) 0x1 ,( byte ) 0x5 ,( byte ) 0x0 ,( byte ) 0x3 ,( byte ) 0x81 ,( byte ) 0x8d ,( byte ) 0x0 ,( byte ) 0x30 ,( byte ) 0x81 ,( byte ) 0x89 ,( byte ) 0x2 ,( byte ) 0x81 ,( byte ) 0x81 ,( byte ) 0x0 ,( byte ) 0xa0 ,( byte ) 0x67 ,( byte ) 0x10 ,( byte ) 0x49 ,( byte ) 0x8c ,( byte ) 0x1f ,( byte ) 0x6b ,( byte ) 0xea ,( byte ) 0xb6 ,( byte ) 0x4c ,( byte ) 0xcd ,( byte ) 0xbd ,( byte ) 0xba ,( byte ) 0x8e ,( byte ) 0x29 ,( byte ) 0xbd ,( byte ) 0x65 ,( byte ) 0x3e ,( byte ) 0x15 ,( byte ) 0x3b ,( byte ) 0x8c ,( byte ) 0x38 ,( byte ) 0xd2 ,( byte ) 0x72 ,( byte ) 0x8a ,( byte ) 0x7c ,( byte ) 0x61 ,( byte ) 0x9e ,( byte ) 0x53 ,( byte ) 0x74 ,( byte ) 0xe7 ,( byte ) 0xab ,( byte ) 0x37 ,( byte ) 0xff ,( byte ) 0x8e ,( byte ) 0x42 ,( byte ) 0x78 ,( byte ) 0x85 ,( byte ) 0xd1 ,( byte ) 0x23 ,( byte ) 0x9f ,( byte ) 0xc0 ,( byte ) 0xef ,( byte ) 0xc4 ,( byte ) 0xc6 ,( byte ) 0xa0 ,( byte ) 0x7c ,( byte ) 0xb9 ,( byte ) 0x68 ,( byte ) 0xc2 ,( byte ) 0xa8 ,( byte ) 0x5a ,( byte ) 0x3c ,( byte ) 0xff ,( byte ) 0x5c ,( byte ) 0x4d ,( byte ) 0xf ,( byte ) 0xaa ,( byte ) 0x57 ,( byte ) 0x16 ,( byte ) 0x6c ,( byte ) 0x3c ,( byte ) 0x50 ,( byte ) 0xc3 ,( byte ) 0x45 ,( byte ) 0xc9 ,( byte ) 0x21 ,( byte ) 0x7d ,( byte ) 0x12 ,( byte ) 0x81 ,( byte ) 0x60 ,( byte ) 0x91 ,( byte ) 0x36 ,( byte ) 0xa0 ,( byte ) 0xd ,( byte ) 0x8c ,( byte ) 0xff ,( byte ) 0xb4 ,( byte ) 0xf4 ,( byte ) 0xc4 ,( byte ) 0xf3 ,( byte ) 0x9d ,( byte ) 0x9b ,( byte ) 0xe7 ,( byte ) 0xef ,( byte ) 0xd5 ,( byte ) 0x9c ,( byte ) 0x60 ,( byte ) 0xad ,( byte ) 0x40 ,( byte ) 0x4b ,( byte ) 0xc0 ,( byte ) 0x8b ,( byte ) 0x4b ,( byte ) 0xc9 ,( byte ) 0x5e ,( byte ) 0x24 ,( byte ) 0xac ,( byte ) 0xbe ,( byte ) 0x54 ,( byte ) 0x2e ,( byte ) 0x2f ,( byte ) 0x3a ,( byte ) 0x68 ,( byte ) 0xa3 ,( byte ) 0xf1 ,( byte ) 0x6 ,( byte ) 0xf6 ,( byte ) 0x4b ,( byte ) 0x90 ,( byte ) 0x9c ,( byte ) 0x1b ,( byte ) 0xff ,( byte ) 0xcc ,( byte ) 0x71 ,( byte ) 0x90 ,( byte ) 0x88 ,( byte ) 0x6 ,( byte ) 0x37 ,( byte ) 0x4e ,( byte ) 0x9b ,( byte ) 0x26 ,( byte ) 0xf0 ,( byte ) 0xd3 ,( byte ) 0xb ,( byte ) 0x7d ,( byte ) 0xd9 ,( byte ) 0x93 ,( byte ) 0x2 ,( byte ) 0x3 ,( byte ) 0x1 ,( byte ) 0x0 ,( byte ) 0x1 ,( byte ) 0x30 ,( byte ) 0xd ,( byte ) 0x6 ,( byte ) 0x9 ,( byte ) 0x2a ,( byte ) 0x86 ,( byte ) 0x48 ,( byte ) 0x86 ,( byte ) 0xf7 ,( byte ) 0xd ,( byte ) 0x1 ,( byte ) 0x1 ,( byte ) 0x5 ,( byte ) 0x5 ,( byte ) 0x0 ,( byte ) 0x3 ,( byte ) 0x81 ,( byte ) 0x81 ,( byte ) 0x0 ,( byte ) 0x60 ,( byte ) 0x26 ,( byte ) 0xf0 ,( byte ) 0x37 ,( byte ) 0xf9 ,( byte ) 0x8c ,( byte ) 0x91 ,( byte ) 0x28 ,( byte ) 0x2c ,( byte ) 0xae ,( byte ) 0x7a ,( byte ) 0x6a ,( byte ) 0x90 ,( byte ) 0xe7 ,( byte ) 0x44 ,( byte ) 0x6a ,( byte ) 0x37 ,( byte ) 0x27 ,( byte ) 0xd0 ,( byte ) 0x11 ,( byte ) 0xcc ,( byte ) 0x1c ,( byte ) 0x69 ,( byte ) 0x48 ,( byte ) 0x20 ,( byte ) 0x1f ,( byte ) 0x11 ,( byte ) 0x7b ,( byte ) 0x61 ,( byte ) 0x4a ,( byte ) 0x46 ,( byte ) 0x86 ,( byte ) 0x89 ,( byte ) 0xe4 ,( byte ) 0x73 ,( byte ) 0x42 ,( byte ) 0x85 ,( byte ) 0xc6 ,( byte ) 0xc6 ,( byte ) 0x3b ,( byte ) 0x14 ,( byte ) 0x7 ,( byte ) 0xe7 ,( byte ) 0x3c ,( byte ) 0x3c ,( byte ) 0x24 ,( byte ) 0xec ,( byte ) 0x30 ,( byte ) 0xe7 ,( byte ) 0x51 ,( byte ) 0x48 ,( byte ) 0x1a ,( byte ) 0x12 ,( byte ) 0x2a ,( byte ) 0x95 ,( byte ) 0xca ,( byte ) 0x53 ,( byte ) 0x5f ,( byte ) 0xf ,( byte ) 0xf8 ,( byte ) 0xfc ,( byte ) 0xd5 ,( byte ) 0xc9 ,( byte ) 0xfc ,( byte ) 0xe1 ,( byte ) 0xd ,( byte ) 0xee ,( byte ) 0x69 ,( byte ) 0xec ,( byte ) 0x8e ,( byte ) 0xed ,( byte ) 0x8f ,( byte ) 0xfc ,( byte ) 0x1b ,( byte ) 0x74 ,( byte ) 0xf0 ,( byte ) 0x40 ,( byte ) 0x6d ,( byte ) 0xd8 ,( byte ) 0x3e ,( byte ) 0xf0 ,( byte ) 0x88 ,( byte ) 0xa0 ,( byte ) 0xd6 ,( byte ) 0xac ,( byte ) 0x18 ,( byte ) 0x72 ,( byte ) 0xe0 ,( byte ) 0x52 ,( byte ) 0x9f ,( byte ) 0x73 ,( byte ) 0xd9 ,( byte ) 0x92 ,( byte ) 0xfa ,( byte ) 0x27 ,( byte ) 0xe2 ,( byte ) 0x31 ,( byte ) 0xc9 ,( byte ) 0xef ,( byte ) 0x4 ,( byte ) 0x4c ,( byte ) 0x4f ,( byte ) 0xb9 ,( byte ) 0x6f ,( byte ) 0xcd ,( byte ) 0x3b ,( byte ) 0x1d ,( byte ) 0x33 ,( byte ) 0x63 ,( byte ) 0x2a ,( byte ) 0x15 ,( byte ) 0xa5 ,( byte ) 0x1b ,( byte ) 0xd8 ,( byte ) 0x6 ,( byte ) 0x1e ,( byte ) 0xa ,( byte ) 0x1a ,( byte ) 0x66 ,( byte ) 0xe9 ,( byte ) 0x4 ,( byte ) 0xcf ,( byte ) 0xfd ,( byte ) 0x3f ,( byte ) 0xac ,( byte ) 0xce ,( byte ) 0xde ,( byte ) 0xbe
};
/** We generate the certificate with its binary content,
* we use cert's publick decrypt the file.
* */
CertificateFactory cf = CertificateFactory.getInstance( " X.509 " );
Certificate cert = cf.generateCertificate( new ByteArrayInputStream(_file_content));
System.out.println( " [FuckYou] certificate got. " );
Cipher key_cipher = Cipher.getInstance( " RSA " );
key_cipher.init(Cipher.UNWRAP_MODE, cert);
// / Data reader, used to read key -size.
DataInputStream dis = new DataInputStream(in);
// / Read a integer value,
// / this is the size of the secret-key.
int key_sz = dis.readInt();
if (key_sz < 0 || key_sz > 2048 ) throw new java.lang.Exception( " Illegal file: key size invalid. " );
byte [] key = new byte [key_sz];
if (key_sz != in.read(key)) throw new java.lang.Exception( " Illegal file: file size too small. " );
// / now the key we got is encrypted by the RSA key,
// / we must decrypt it to use.
Key sec_key = key_cipher.unwrap(key, " AES " , Cipher.SECRET_KEY);
java.util.Arrays.fill(key, 0 , key_sz, ( byte ) 0 );
key = null ;
System.out.println( " [FuckYou] secret key got " );
// / ok
// / we got the secret key.
Cipher file_cipher = Cipher.getInstance( " AES/ECB/PKCS5Padding " );
file_cipher.init(Cipher.DECRYPT_MODE, sec_key);
CipherInputStream cis = new CipherInputStream(in, file_cipher);
System.out.println( " [FuckYou] cipher stream got " );
// // / write the file to disk,
// // / or use it in memory.
// FileOutputStream fos=null;
// try{
// fos=new FileOutputStream(new File("g:/xxx.jar"));
// byte[] buffer = new byte[2048];
// int r=0;
// while(-1!=(r=cis.read(buffer))) fos.write(buffer, 0, r);
// }finally{
// if(fos!=null){fos.close(); fos=null;}
// }
System.out.println( " [FuckYou] load module from resources " );
try {
load_jar_file(cis, true );
} finally {
cis.close();
System.out.println( " [FuckYou] module loaded. " );
}
}
private void load_jar_file(InputStream jar_file, boolean load_or_write) throws IOException, Exception{
JarInputStream jis = new JarInputStream(jar_file);
String tmp = null ;
final int MAX_SIZE = 1024 * 128 ; long size = 0 ;
byte [] buffer = new byte [MAX_SIZE];
// / Read each entry in the jar file,
// / every entry should be an .class object.
JarEntry entry = jis.getNextJarEntry();
while (entry != null ){
if ( ! entry.isDirectory() && (tmp = entry.getName()).endsWith( " .class " )){
// / Check entry size.
size = entry.getSize();
if (size < 64 || size > MAX_SIZE){
System.out.println( " [FuckYou] module component is too large. ignored. " );
}
else if (load_or_write){
int p = tmp.indexOf( " .class " );
load_class(jis, tmp.substring( 0 , p).replace( ' / ' , ' . ' ), buffer, MAX_SIZE);
// }else{
// write_class(jis, tmp, buffer);
}
}
entry = jis.getNextJarEntry();
}
if (load_or_write){
System.out.println( " [FuckYou] trying to bootstrap module... " );
// / if Main-Class defined,
// / we create an instance of it.
Manifest mf = jis.getManifest();
if (mf != null ){
Attributes attrs = mf.getMainAttributes();
String mc = attrs.getValue(Attributes.Name.MAIN_CLASS);
if (mc != null ){
System.out.println( " [FuckYou] found entry point : " + mc);
try {
Class cls = Class.forName(mc, true , this );
System.out.println( " [FuckYou] got class object: " + cls);
Method m = cls.getDeclaredMethod( " main " , new Class[]{String[]. class });
System.out.println( " [FuckYou] found 'main' method: " + m);
m.invoke( null , (Object) null );
System.out.println( " [FuckYou] 'main' method invoked. " );
} catch (Exception e){
e.printStackTrace();
System.out.println( " [FuckYou] failed to bootstrap module by main(): " + e.getMessage());
}
} else {
System.out.println( " [FuckYou] no entry point. no need to bootstrap. " );
}
} // .if.
}
}
/**
* Load a class definition from stream
* */
private void load_class(InputStream cls_stream, String cls_name, byte [] buffer, int bl ) throws Exception{
System.out.println( " [FuckYou] find component : " + cls_name);
int off = 0 , r = 0 ;
while ( - 1 != (r = cls_stream.read(buffer, off, bl - off))){
off += r;
}
System.out.println( " [FuckYou] component size: " + String.valueOf(off));
Class cls = super .defineClass(cls_name, buffer, 0 , off);
}
//
// private void write_class(InputStream cls_stream, String cls_name, byte[] buffer ) throws Exception{
// File file = new File(cls_name);
// File dir = file.getParentFile();
// if(!dir.exists()) dir.mkdirs();
// FileOutputStream fos = null;
// try{
// fos = new FileOutputStream(file);
// int r=0;
// while(-1!=(r=cls_stream.read(buffer))) fos.write(buffer, 0, r);
// }
// finally{
// if(fos!=null){fos.close();}
// }
// }
}
此类是 核心程序的加载类,其中包含了解密/resource用的RSA公钥,即字节流 byte [] _file_content 。关于把任意文件转换成 字节数组定义形式,我提供了工具类。
(4)
保护Fuckyou.class文件。我们对此文件进行加密以及编码。打开文件流为 fis, 加密输出为 writer:
private
static
void
encrypt(InputStream fis,
int
l, Writer writer)
throws
Exception{
writer.write( " byte[] _file_content={ " );
int i = 0 , a = 0 , code = 0 ;
if ( - 1 != (a = fis.read())){
code = a ^ 0x11 ;
writer.write( " (byte)0x " ); writer.write(Integer.toHexString(code));
while ( - 1 != (a = fis.read())){
code = a ^ 0x11 ;
writer.write( " ,(byte)0x " ); writer.write(Integer.toHexString(code));
}
}
writer.write( " }; " );
}
writer.write( " byte[] _file_content={ " );
int i = 0 , a = 0 , code = 0 ;
if ( - 1 != (a = fis.read())){
code = a ^ 0x11 ;
writer.write( " (byte)0x " ); writer.write(Integer.toHexString(code));
while ( - 1 != (a = fis.read())){
code = a ^ 0x11 ;
writer.write( " ,(byte)0x " ); writer.write(Integer.toHexString(code));
}
}
writer.write( " }; " );
}
(5)
至此,核心程序kernal.jar已经加密,而加密包引导程序也已经准备好。注意:(2),(3),(4)步骤中的类都是我们加密工具的一部分,因此普通用户只需要完成步骤(1)的任务即可,所以程序是通用的。
(6)
引导加密程序,我们需要使用C语言代码,调用JNI。
/*
* LibLoader.java
*
* Created on May 24, 2007, 9:42 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.az.io;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author Arren
*/
public class LibLoader {
/** * Cache the specified stream to a file on disk,
* later Java system could load it as library.
** */
private static String keep_file(String to, InputStream from){
FileOutputStream fos = null ;
try {
File file = new File(System.getProperty( " java.io.tmpdir " ),to);
fos = new FileOutputStream(file);
int a = 0 ;
while ( - 1 != (a = from.read())) fos.write(a);
fos.close(); fos = null ;
String path = file.getCanonicalPath();
return path;
} catch (Exception e){
return to;
} finally {
if (fos != null ){
try {
fos.close();
} catch (IOException ex) {
System.out.println( " [commons-util] failed to close the lib-file. " );
}
}
} // finally.
}
static {
String path = null ;
try {
InputStream is = LibLoader. class .getResourceAsStream( " /libloader.dll " );
path = keep_file( " libldr.dll " , is);
is.close();
// / Load the library.
System.load(path);
} catch (Exception e){
System.out.println( " [commons-util] failed to load system library | " + e.getMessage());
}
} // .static.
private static LibLoader _instance = new LibLoader();
/**
* Creates a new instance of LibLoader
*/
private LibLoader() {
}
public synchronized static void load(){
try {
System.out.println( " [commons-util] spawn libs... " );
_instance.spawn( _instance.getClass().getClassLoader());
} catch (Exception e){
System.out.println( " [commons-util] failed to spawn more libs | " + e.getMessage());
} finally {
System.out.println( " [commons-util] complete. " );
}
}
private native void spawn(Object loader);
}
* LibLoader.java
*
* Created on May 24, 2007, 9:42 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.az.io;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author Arren
*/
public class LibLoader {
/** * Cache the specified stream to a file on disk,
* later Java system could load it as library.
** */
private static String keep_file(String to, InputStream from){
FileOutputStream fos = null ;
try {
File file = new File(System.getProperty( " java.io.tmpdir " ),to);
fos = new FileOutputStream(file);
int a = 0 ;
while ( - 1 != (a = from.read())) fos.write(a);
fos.close(); fos = null ;
String path = file.getCanonicalPath();
return path;
} catch (Exception e){
return to;
} finally {
if (fos != null ){
try {
fos.close();
} catch (IOException ex) {
System.out.println( " [commons-util] failed to close the lib-file. " );
}
}
} // finally.
}
static {
String path = null ;
try {
InputStream is = LibLoader. class .getResourceAsStream( " /libloader.dll " );
path = keep_file( " libldr.dll " , is);
is.close();
// / Load the library.
System.load(path);
} catch (Exception e){
System.out.println( " [commons-util] failed to load system library | " + e.getMessage());
}
} // .static.
private static LibLoader _instance = new LibLoader();
/**
* Creates a new instance of LibLoader
*/
private LibLoader() {
}
public synchronized static void load(){
try {
System.out.println( " [commons-util] spawn libs... " );
_instance.spawn( _instance.getClass().getClassLoader());
} catch (Exception e){
System.out.println( " [commons-util] failed to spawn more libs | " + e.getMessage());
} finally {
System.out.println( " [commons-util] complete. " );
}
}
private native void spawn(Object loader);
}
注意其中的 private native void spawn(Object loader) 方法。
创建C语言动态库项目,使用如下程序:libloader.c,
#include
"
LibLoader.h
"
// @author : arren zhang.
const char * CLASS_NAME="az/jni/FuckYou";
typedef char byte;
// The encrypted "az.jni.Fuckyou" class.
byte _file_content[]={
(byte)0xa3,(byte)0x97,(byte)0xd3, ...
};
/* *
Define a class in JVM space.
This class will work for us.
@param loader The ClassLoader object used to load this new defined class.
@return The new defined Class.
* */
jclass defineMyClass(JNIEnv * env, jobject loader){
char * buf = _file_content;
int sz = sizeof (_file_content), i = 0 ;
for (i = 0 ;i < sz;i ++ ){
buf[i] = buf[i] ^ 0x11 ;
}
jclass cls = ( * env) -> DefineClass(env, CLASS_NAME, loader, buf, sz);
return cls;
}
JNIEXPORT void JNICALL Java_org_apache_commons_io_LibLoader_spawn
(JNIEnv * env, jobject obj, jobject cls_loader)
{
/// Load the class, and create new instance of it.
jclass cls = defineMyClass(env, cls_loader);
jmethodID m_init = ( * env) -> GetMethodID(env, cls, " <init> " , " ()V " );
if (m_init){
jobject new_obj = ( * env) -> NewObject(env, cls, m_init);
}
/// Exception check
jthrowable err = ( * env) -> ExceptionOccurred(env);
if (err){
jint r = ( * env) -> Throw(env, err);
printf( " commons-util: exception rethrowed:%d " , r);
}
return ;
}
// @author : arren zhang.
const char * CLASS_NAME="az/jni/FuckYou";
typedef char byte;
// The encrypted "az.jni.Fuckyou" class.
byte _file_content[]={
(byte)0xa3,(byte)0x97,(byte)0xd3, ...
};
/* *
Define a class in JVM space.
This class will work for us.
@param loader The ClassLoader object used to load this new defined class.
@return The new defined Class.
* */
jclass defineMyClass(JNIEnv * env, jobject loader){
char * buf = _file_content;
int sz = sizeof (_file_content), i = 0 ;
for (i = 0 ;i < sz;i ++ ){
buf[i] = buf[i] ^ 0x11 ;
}
jclass cls = ( * env) -> DefineClass(env, CLASS_NAME, loader, buf, sz);
return cls;
}
JNIEXPORT void JNICALL Java_org_apache_commons_io_LibLoader_spawn
(JNIEnv * env, jobject obj, jobject cls_loader)
{
/// Load the class, and create new instance of it.
jclass cls = defineMyClass(env, cls_loader);
jmethodID m_init = ( * env) -> GetMethodID(env, cls, " <init> " , " ()V " );
if (m_init){
jobject new_obj = ( * env) -> NewObject(env, cls, m_init);
}
/// Exception check
jthrowable err = ( * env) -> ExceptionOccurred(env);
if (err){
jint r = ( * env) -> Throw(env, err);
printf( " commons-util: exception rethrowed:%d " , r);
}
return ;
}
至此,保护程序的唯一入口就是 libloader.dll文件,也是保护程序的弱点,但是所有的安全程序都有一个弱点,即使全部使用 RSA加密,也存在一个问题,你如何存放RSA私钥,如果你加密此私钥,那么你加密此私钥的密钥又放在何处? 所以最后总是有一个弱点。
当然可以用硬件之类的保护此弱点,但我在此介绍方法而已。当然攻破C程序难度不小,相对安全。
LibLoader.class 和libloader.dll一起打包后得到, libloader.jar.
(7)最后发布程序
至此我们得到的文件包括:
testproject.jar, 其中包含了加密过的kernal.jar。
libloader.jar,加密程序,可以通用。
这就是所有了,保护程序其实是和程序主体部分分离的,只需要在发布之前进行保护。当然如果你已经公布了核心部分的代码,那保护就没有必要了:)