最近試用了幾個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 ()
運行java
jar joc
jar就可以啟動Java混淆編譯器
joc的命令行參數和javac完全相同
但增加了一個新的參數
Xobfuscate
它的用法如下
Xobfuscate:<level>
其中<level>指定混淆級別
可以是以下幾種級別
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 panel
= new JPanel();
JButton button
= new JButton();
JLabel jLabel
= new JLabel();
JTextArea jTextArea
= 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
);
panel
setLayout( null );
button
setText(
OK
);
button
setBounds(
);
panel
add( button
);
jLabel
setText(
File System Viewer for Swing
);
jLabel
setVerticalAlignment( SwingConstants
TOP );
jLabel
setBounds(
);
panel
add( jLabel
);
jTextArea
setFont( new java
awt
Font(
Dialog
));
jTextArea
setLineWrap( true );
jTextArea
setOpaque( false );
jTextArea
setText(
This computer program is protected by copyright law
);
jTextArea
setWrapstyleWord( true );
jTextArea
setBounds(
);
panel
add( jTextArea
);
this
getContentPane()
add( panel
Card
);
this
setSize(
);
button
addActionListener( new java
awt
event
ActionListener(){
public void actionPerformed( java
awt
event
ActionEvent ev ){
? button
_actionPerformed( ev );
}});
}
private void button
_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 panel
;
JButton button
;
JLabel jLabel
;
JTextArea jTextArea
;
public AboutBox()
{
panel
= new JPanel();
button
= new JButton();
jLabel
= new JLabel();
jTextArea
= new JTextArea();
initform();
}
private void initform()
{
setDefaultCloseOperation(
);
getContentPane()
setLayout(new CardLayout());
setModal(true);
setResizable(false);
setTitle(
About
);
panel
setLayout(null);
button
setText(
OK
);
button
setBounds(
);
panel
add(button
);
jLabel
setText(
File System Viewer for Swing
);
jLabel
setVerticalAlignment(
);
jLabel
setBounds(
);
panel
add(jLabel
);
jTextArea
setFont(new Font(
Dialog
));
jTextArea
setLineWrap(true);
jTextArea
setOpaque(false);
jTextArea
setText(
This computer program is protected by copyright law
);
jTextArea
setWrapstyleWord(true);
jTextArea
setBounds(
);
panel
add(jTextArea
);
getContentPane()
add(panel
Card
);
setSize(
);
button
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionevent)
{
button
_actionPerformed(actio
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19213.html