zoukankan      html  css  js  c++  java
  • 【转】5个常用Java 代码混淆器 助你保护你的代码

    摘要:从事Java编程的人都知道,可以通过逆向工程反编译得到Java程序的源代码,这种反编译工具之一就是JAD。

    【CSDN 7月23日消息】从事Java编程的人都知道,可以通过逆向工程反编译得到Java程序的源代码,这种反编译工具之一就是JAD。因此,为保护我们的劳动成果,尽可能给反编译人员制造障碍,我们可以使用Java Obfuscator(Java混淆器)保护Java的类文件。

    Java Obfuscator的原理就是将字节码转换为一个逻辑上的对等物,这种转换后的版本极难拆散。即使有人试图去反编译,过程将极其艰难复杂,并很难绕过转换后模糊晦涩的编码。主要的过程如下:

    用一个常规编译器(比如JDK)编译Java源代码运行混淆器,在受保护的环境下生成编译类文件。最后生成的会是一个不同的输出文档,也许扩展名也会不同。

    这个被重命名为.class file的文件在功能上与原字节码是对等的,由于虚拟机仍然可以对其进行解译,因此对性能不会产生影响。

    以下是一些可用来混淆(obfuscate)Java字节码的工具:

    ProGuard 
    ProGuard 是一个免费的 Java类文件的压缩,优化,混肴器。它删除没有用的类,字段,方法与属性。使字节码最大程度地优化,使用简短且无意义的名字来重命名类、字段和方法 。eclipse已经把Proguard集成在一起了。官方网站:http://proguard.sourceforge.net/

    JavaGuard 
    JavaGuard是一个通用的字节码模糊器,旨在容易地适合你的规则建造和测试进程,保证你的有价值的代码更安全,使其不易被反编译以及其它形式的反向处理。

    Zelix KlassMaster

    Zelix KlassMaster是一款用Java写的实用工具,能读取和修改Java类文件,可以运行在任何支持1.1.6版Java虚拟机的平台上。
    下载:http://www.zdnetindia.com/downloads/info/898255.html

    Cinnabar Canner

    Canner通过创建一个原生Windows可执行文件(EXE文件)保护你的代码不被逆向工程反编译,这个可执行文件包含了你的应用程序类和资源的全部加密版本,只有在被JVM调用到内存中时才处于非加密状态。
    网站:http://www.cinnabarsystems.com/canner.html
    下载:http://www.cinnabarsystems.com/download.html

    Jmangle Java类粉碎机

    Jmangle是用来阻止反编译Java程序,降低盗版的软件,开发者可用其粉碎类文件中的符号。
    网站:http://www.elegant-software.com/software/jmangle/
    下载:http://www.elegant-software.com/software/jmangle/download.html

    RetroGuard

    JavaGuard是一款通用的字节码混淆器,用来无缝融入你的日常构建和测试过程中,使得你辛苦编写宝贵的Java代码更加安全。
    网站:http://java-source.net/open-source/obfuscators/javaguard

    yGuard 
    yGuard 是RetroGuard的一个升级版本自带一个ANT任务

    JODE

    JODE是一款含Java解码器和优化器的java包。
    网站:http://java-source.net/open-source/obfuscators/jode

    最后要说的是,你也可使用其他几款类似的实用工具,这些工具运用许多不同的方法达到了相同的目标。他们也有共同之处,就是允许通过不同的过程转换生成.exe文件,将.class和.jar文件模糊化。Google Directory上有一张它们的综合列表:
    http://directory.google.com/Top/Computers/Programming/Languages/Java/Development_Tools/Obfus

    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:<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 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  <Class Font>;
           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;
               }
       }
    }
  • 相关阅读:
    896. Monotonic Array单调数组
    865. Smallest Subtree with all the Deepest Nodes 有最深节点的最小子树
    489. Robot Room Cleaner扫地机器人
    JavaFX
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
    《Python CookBook2》 第一章 文本
  • 原文地址:https://www.cnblogs.com/duanxz/p/2831077.html
Copyright © 2011-2022 走看看