您的位置:首页 > 编程语言 > Java开发

给大家提供一个工具:Java混淆编译器

2008-05-21 02:52 295 查看
google_ad_client = "pub-8800625213955058";

/* 336x280, 创建于 07-11-21 */

google_ad_slot = "0989131976";

google_ad_width = 336;

google_ad_height = 280;

//

最近试用了几个Java混淆器(Java Obfuscator),感觉没有一个完全另人满意的,于是想干脆自己写一个得了。翻了几页Java虚拟机规范之后突发奇想,别的混淆器都是在编译好的byte code上做文章,能不能从源码直接编译成经过混淆的class文件呢?就这样花了一个多星期的时间写了一个Java混淆编译器(Java Obfuscator Compiler)。

Q: 什么是混淆器?

A: 由于Java程序运行时是动态连接的,因此编译成的目标文件中包含有符号表,使得Java程序很容易被反编译,混淆器可以打乱class文件中的符号信息,使反向工程变得非常困难。

Q: 现有的混淆器有什么问题?

A: 现有的混淆器都是对编译好的class文件进行混淆,这样就需要编译和混淆两个步骤。并不是所有的符号都需要混淆,如果你开发的是一个类库,或者某些类需要动态装载,那些公共API就必须保留符号不变,这样别人才能使用你的类库。现有的混淆器提供了GUI或脚本的方式来对那些需要保留的符号名称进行配置,如果程序较大时配置工作变得很复杂,而程序一旦修改配置工作又要重新进行。某些混淆器能够调整字节码的顺序,使反编译更加困难,但我经历过混淆之后的程序运行出错的情况。

Q: Java混淆编译器是如何工作的?

A: Java混淆编译器是在Sun JDK中提供的Java编译器(javac)的基础上完成的,修改了代码生成过程,对编译器生成的中间代码进行混淆,最后再生成class文件,这样编译和混淆只需要一个步骤就可以完成。另外可以在源程序中插入符号保留指令来控制哪些符号需要保留,不需要单独的配置。

Q: 如何安装和运行JOC?

A: 下载joc.jar (http://www.apusic.com/product/cpsy.htm),运行java -jar joc.jar就可以启动Java混淆编译器,joc的命令行参数和javac完全相同,但增加了一个新的参数-Xobfuscate,它的用法如下:

-Xobfuscate:

其中指定混淆级别,可以是以下几种级别:

-Xobfuscate:none 不进行混淆

-Xobfuscate:private 对所有private访问级别的元素进行混淆

-Xobfuscate:package 对所有private或package private元素进行混淆

-Xobfuscate:protected 对所有private, package private, protected元素进行混淆

-Xobfuscate:public 对所有的元素都进行混淆

-Xobfuscate:all 相当于-Xobfuscate:public

如果使用-Xobfuscate不带级别参数,则相当于-Xobfuscate:package

Q: 如何使用符号保留指令?

A: 除了在命令行用-Xobfuscate参数控制符号混淆级别外,还可以在源代码中使用符号保留指令来控制那些符号需要保留,符号保留指令是一个Java文档注释指令,可以插入在类和类成员的文档注释中,例如:

/**

* This class should preserve.

* @preserve

*/

public class Foo {

/**

* You can specify which field should be preserved.

* @preserve

*/

private int x;

/**

* This field is not preserved.

*/

private int y;

/**

* You can also preserve methods.

* @preserve

*/

public void hello() {}

/**

* This method is not preserved.

*/

private void collect() {}

}

如果没有@preserve指令,则根据混淆级别及成员的访问级别来确定符号是否保留。

对于类的符号保留指令可以附带一个保留级别参数,来控制类成员的符号保留,包括:

@preserve 仅对类名进行保留,类成员的保留根据-Xobfuscate命令行参数决定

@preserve public 保留所有public成员

@preserve protected 保留所有public和protected成员

@preserve package 保留所有public, protected, package private成员

@preserve private 保留所有成员

@preserve all 相当于@preserve private

Q: JOC有哪些限制?

A: 不支持分别编译,必须对所有的源文件进行混淆编译。

最后给出一个JOC混淆的效果:

源文件:

import java.awt.event.*;

import javax.swing.*;

public class AboutBox extends JDialog

{

public AboutBox()

{

initForm();

}

JPanel panel1 = new JPanel();

JButton button1 = new JButton();

JLabel jLabel2 = new JLabel();

JTextArea jTextArea1 = new JTextArea();

/**

* NOTE: The following code is required by the form designer.

* It can be modified using the form editor. Do not

* modify it using the code editor.

*/

private void initForm()

{

this.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );

this.getContentPane().setLayout( new java.awt.CardLayout());

this.setModal( true );

this.setResizable( false );

this.setTitle( "About..." );

panel1.setLayout( null );

button1.setText( "OK" );

button1.setBounds( 272, 168, 88, 24 );

panel1.add( button1 );

jLabel2.setText( "File System Viewer for Swing 1.1.1" );

jLabel2.setVerticalAlignment( SwingConstants.TOP );

jLabel2.setBounds( 64, 32, 240, 56 );

panel1.add( jLabel2 );

jTextArea1.setFont( new java.awt.Font( "Dialog", 0, 10 ));

jTextArea1.setLineWrap( true );

jTextArea1.setOpaque( false );

jTextArea1.setText( "This computer program is protected by copyright law." );

jTextArea1.setWrapStyleWord( true );

jTextArea1.setBounds( 8, 112, 256, 80 );

panel1.add( jTextArea1 );

this.getContentPane().add( panel1, "Card1" );

this.setSize( 376, 228 );

button1.addActionListener( new java.awt.event.ActionListener(){

public void actionPerformed( java.awt.event.ActionEvent ev ){

button1_actionPerformed( ev );

}});

}

private void button1_actionPerformed(ActionEvent ev)

{

this.dispose();

}

}

经Javac编译后用JAD反编译的结果:

import java.awt.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.*;

import javax.swing.text.JTextComponent;

public class AboutBox extends JDialog

{

JPanel panel1;

JButton button1;

JLabel jLabel2;

JTextArea jTextArea1;

public AboutBox()

{

panel1 = new JPanel();

button1 = new JButton();

jLabel2 = new JLabel();

jTextArea1 = new JTextArea();

initForm();

}

private void initForm()

{

setDefaultCloseOperation(2);

getContentPane().setLayout(new CardLayout());

setModal(true);

setResizable(false);

setTitle("About...");

panel1.setLayout(null);

button1.setText("OK");

button1.setBounds(272, 168, 88, 24);

panel1.add(button1);

jLabel2.setText("File System Viewer for Swing 1.1.1");

jLabel2.setVerticalAlignment(1);

jLabel2.setBounds(64, 32, 240, 56);

panel1.add(jLabel2);

jTextArea1.setFont(new Font("Dialog", 0, 10));

jTextArea1.setLineWrap(true);

jTextArea1.setOpaque(false);

jTextArea1.setText("This computer program is protected by copyright law.");

jTextArea1.setWrapStyleWord(true);

jTextArea1.setBounds(8, 112, 256, 80);

panel1.add(jTextArea1);

getContentPane().add(panel1, "Card1");

setSize(376, 228);

button1.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent actionevent)

{

button1_actionPerformed(actionevent);

}

});

}

private void button1_actionPerformed(ActionEvent actionevent)

{

dispose();

}

}

经JOC混淆编译后用JAD反编译的结果:

import java.awt.*;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.*;

import javax.swing.text.JTextComponent;

public class AboutBox extends JDialog

{

JPanel _$1;

JButton _$2;

JLabel _$3;

JTextArea _$4;

public AboutBox()

{

_$1 = new JPanel();

_$2 = new JButton();

_$3 = new JLabel();

_$4 = new JTextArea();

_$1();

}

private void _$1()

{

2;

this;

JVM INSTR swap ;

setDefaultCloseOperation();

getContentPane().setLayout(new CardLayout());

true;

this;

JVM INSTR swap ;

setModal();

false;

this;

JVM INSTR swap ;

setResizable();

"About...";

this;

JVM INSTR swap ;

setTitle();

_$1.setLayout(null);

_$2.setText("OK");

_$2;

168;

272;

JVM INSTR swap ;

24;

88;

JVM INSTR swap ;

setBounds();

_$1.add(_$2);

_$3.setText("File System Viewer for Swing 1.1.1");

_$3.setVerticalAlignment(1);

_$3;

32;

64;

JVM INSTR swap ;

56;

240;

JVM INSTR swap ;

setBounds();

_$1.add(_$3);

_$4;

JVM INSTR new #13 ;

JVM INSTR dup ;

0;

"Dialog";

JVM INSTR swap ;

10;

Font();

setFont();

_$4.setLineWrap(true);

_$4.setOpaque(false);

_$4.setText("This computer program is protected by copyright law.");

_$4.setWrapStyleWord(true);

_$4;

112;

8;

JVM INSTR swap ;

80;

256;

JVM INSTR swap ;

setBounds();

_$1.add(_$4);

getContentPane().add(_$1, "Card1");

376;

this;

JVM INSTR swap ;

228;

setSize();

_$2.addActionListener(new IIlIlIIIIlllIIII(this));

return;

}

private void _$1(ActionEvent actionevent)

{

dispose();

}

/*

static void access$0(AboutBox aboutbox, ActionEvent actionevent)

{

actionevent;

aboutbox;

JVM INSTR swap ;

_$1();

return;

}

*/

// Unreferenced inner classes:

/* anonymous class */

final class IIlIlIIIIlllIIII

implements ActionListener

{

public void actionPerformed(ActionEvent actionevent)

{

AboutBox.access$0(AboutBox.this, actionevent);

}

{

AboutBox.this;

this;

JVM INSTR swap ;

this$0;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐