`

java反编译心得

阅读更多
现在的JDK都是1.4/1.5用比较老的JAD和ECLIPSE的JODE进行反编译,出来的代码的可读性比较差,而且比较多错误.

以下是同一CLASS文件反编译出来的代码:

可以看出:

1、JODE出来的代码的可读性最好,不过有CLASS文件代码用JODE是反编译不出来出现异常;

2、JAD出来的代码经常要进行大量整理;

3、JODE和JAD对混混淆过的代码,变量的顺序可能会不一样,自变量的命名,JODE会好一些。

4、对于PUSH和POP,左修整时候,可以自己加自变量,临时存储;

5、JAVA对于表达式或函数参数,是从右到左进行解释的。函数参数,最后PUSH的,是最右边的参数;对于

等号赋值也是先右后左进行出栈。

   /**
     * jode
     * @param i
     * @param i_1_
     * @param graphics
     */
    private void b(int i, int i_1_, Graphics graphics) {
     graphics.setColor(0);
     if (((h) this).e.f == null)
         graphics.setColor(6710886);
     else {
      int tmp=0;
         if (((h) this).e.f.size() == 1) {
     PUSH g.c;
      PUSH = 64;
         } else {
     PUSH g.c;
      PUSH = 80;
         }
         g.a(POP, POP, 0, 16, 16, i, i_1_, graphics);
     }
     StringBuffer stringbuffer = new StringBuffer();
     if (((h) this).e.e > 0) {
         graphics.setColor(16711680);
         stringbuffer.append('[');
         stringbuffer.append(((h) this).e.e);
         stringbuffer.append("\u65b0\u6d88\u606f");  //新消息
         stringbuffer.append(']');
     }
     if (((h) this).f)
         graphics.setColor(16777215);
     stringbuffer.append(((h) this).e.a());
     graphics.drawString(a(stringbuffer.toString(), 158), i + 16 + 1,
           i_1_ + 1, 20);
        }
   
    /**
     * jad
     * @param i
     * @param j
     * @param g1
     */
    private void b(int i, int j, Graphics g1)
    {
        g1.setColor(0);
        if(e.f != null) goto _L2; else goto _L1
_L1:
        g1.setColor(0x666666);
          goto _L3
_L2:
        if(e.f.size() != 1) goto _L5; else goto _L4
_L4:
        g.c;
        76;
          goto _L6
_L5:
        g.c;
        95;
_L6:
        0;
        19;
        19;
        i;
        j;
        g1;
        g.a();
_L3:
        StringBuffer stringbuffer = new StringBuffer();
        if(e.e > 0)
        {
            g1.setColor(0xff0000);
            stringbuffer.append('[');
            stringbuffer.append(e.e);
            stringbuffer.append("\u65B0\u6D88\u606F");
            stringbuffer.append(']');
        }
        if(f)
            g1.setColor(0xffffff);
        stringbuffer.append(e.a());
        g1.drawString(a(stringbuffer.toString(), 219), i + 19 + 1, j + 1, 20);
        return;
    }

//    public final void a(boolean bool) {
//     if (bool) {
//         PUSH this;
//         PUSH "BD";
//     } else {
//         PUSH this;
//         PUSH "AA";
//     }
//     ((n) POP).d = POP;
//        }
//   
    public final void a(boolean flag)
    {
        if(!flag){
         this.d="AA";
        }else{
         this.d="BD";
        }
        
//      if(!flag)   goto _L2; else goto _L1
//_L1:
//        this;
//        "BD";
//          goto _L3
//_L2:
//        this;
//        "AA";
//_L3:
//        d;
    }
再加几个用例:
一般情况下Java应用的开发者为了保护代码不被别人抄袭,在生成class文件的时候都java文件进行了混淆,这种class文件用反编译工具得到的结果很难看懂,并且不能进行编译。本文从研究的角度,浅析如何读懂这种反编译过来的文件。

例子一:赋值
反编译过来的代码如下:
        Node node;
        Node node1 = _$3.getChildNodes().item(0);
        node1;
        node1;
        JVM INSTR swap ;
        node;
        getChildNodes();
        0;
        item();
        getChildNodes();
        0;
        item();
        getNodeValue();
        String s;
        s;
原始语句:
        Node node;
        Node node1 = currDocument.getChildNodes().item(0);
node = node1;
        String s = node.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
注解:
        JVM INSTR swap ; //赋值语句
练习:
        String s1;
        String s8 = node.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
        s8;
        s8;
        JVM INSTR swap ;
        s1;
        10;
        Integer.parseInt();
        int i;
        i;

  
例子二:不带参数创建对象
反编译过来的代码如下:
        JVM INSTR new #244 <Class CrossTable>;
        JVM INSTR dup ;
        JVM INSTR swap ;
        CrossTable();
        CrossTable crosstable;
        crosstable;

原始语句:
        CrossTable crosstable = new CrossTable();
注解:
练习:
        JVM INSTR new #246 <Class Database>;
        JVM INSTR dup ;
        JVM INSTR swap ;
        Database();
        Object obj;
        obj;

例子三:带参数创建对象
反编译过来的代码如下:
        JVM INSTR new #262 <Class StringBuffer>;
        JVM INSTR dup ;
        JVM INSTR swap ;
        String.valueOf(s2);
        StringBuffer();
        s.substring(j, i);
        append();
        s6;
        append();
        toString();
        s2;

原始语句:
s2 = (new StringBuffer(String.valueOf(s2))).append(s.substring(j, i)).append(s6).toString();
注解:
此语句实际上是:s2 += s.substring(j, i) + s6;
练习:

例子四:for循环
反编译过来的代码如下:
        int k = 0;
          goto _L4
_L8:
...
k++;
_L4:
        if(k < as.length) goto _L8; else goto _L7

原始语句:
for(int k=0;k < as.length;k++)
{
     ...
}
注解:

例子五:while循环
反编译过来的代码如下:
        String s1 = "";
          goto _L1
_L3:
        JVM INSTR new #262 <Class StringBuffer>;
        JVM INSTR dup ;
        JVM INSTR swap ;
        String.valueOf(s1);
        StringBuffer();
        _$2(resultset, s, l);
        append();
        toString();
        s1;
_L1:
        if(resultset.next()) goto _L3; else goto _L2

原始语句:
String s1 = "";
while(resultset.next())
{
  s1 = s1 + resultSetToString(resultset, s, l);

}
注解:


欢迎有此兴趣的朋友和我交流。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics