强大的dex反编译器

APK反编译、重打包。这都是老话题了,现在也有不少工具来实现apk反编译,比如apktool-gui。Virtuous Ten Studio等。尤其后者还是很强大的。

大家可以自己去体验。今天给大家介绍的这是一个商业产品,也即不是免费的,不过自然有其特点。

那就是来自于http://www.android-decompiler.com/的JEB

JEB是一个功能强大的为安全专业人士设计的Android应用程序的反编译。反向工程或审计APK文件,并减少许多工程师的分析时间。

1、dextojar

目前的工具在转化到jar都存在不少问题。

EB的独特功能是,其Dalvik字节码反编译为Java源代码的能力

比如这是常规工具的结果:

下图是JEB的结果:

如果说转化jar效果有明显提升的话,对于工程师读懂代码的效率还是有很大提升的。

2、可编辑性:

特别是当他们处理混淆的或受保护的代码块。 JEB的强大的用户界面,可以检查交叉引用,重命名的方法,字段,类,代码和数据之间导航,做笔记,添加注释,以及更多。

3、APK全浏览

Full APK view. Take advantage of the full APK view, including decompressed manifest, resources, certificates, strings, constants, etc. Again, flexibility is key.

也可以直接看到证书内容:

各类资源信息:

4、API for Automation. Use JEB's Application Programming Interface (API) to write Python scripts and plugins, and automate your analysis needs.

可以根据需要程序猿自己定制。比如下面的示例:

JEBReplaceStrings.py

# Sample JEB script (UI:yes, Automation:yes)
# Replace code strings by the string 'foobar'
# This script shows how to navigate the DEX file
# and how to modify strings in the string pool


import os

from jeb.api import IScript
from jeb.api import EngineOption


class JEBReplaceStrings(IScript):

  def run(self, jeb):
    self.jeb = jeb
    self.dex = jeb.getDex()
    if not self.dex:
      print 'Error! Please provide an input file.'
      sef.jeb.exit()

    for msig in self.dex.getMethodSignatures(True):
      #print msig

      md = self.dex.getMethodData(msig)
      if not md:
        continue

      code = md.getCodeItem()
      if not code:
        continue

      for insn in code.getInstructions():
        if not insn.getMnemonic() in ('const-string', 'const-string/jumbo'):
          continue

        stringindex = insn.getParameters()[1].getValue()
        s = self.dex.getString(stringindex)
        if s:
          s2 = self.modifyString(s)
          if s2 and s2 != s:
            self.dex.setString(stringindex, s2)

  def modifyString(self, s):
    # totally useless: alphanumeric string are replaced by 'foobar'
    # could be the base script for something more useful, like
    # string language identification and translation into English
    if not s.isalnum():
      return None
    return 'foobar'

 5、火拼:

JEB和dex2jar+JD-GUI and dex2jar+JAD.开始PK

这是一个标准的RC4加密算法代码。RC4不懂的请百度。

 

/**
 * RC4 encryption/decryption routine.
 * @param key
 * @param data input/output buffer
 */
public static void rc4_crypt(byte[] key, byte[] data) {
    int keylen = key.length;
    int datalen = data.length;
    int i;
    int j;
    
    // key scheduling
    byte[] sbox = new byte[256];
    for(i = 0; i < 256; i++) {
        sbox[i] = (byte)i;
    }
    j = 0;
    for(i = 0; i < 256; i++) {
        j = ((j + sbox[i] + key[i % keylen]) % 256) & 0xFF;
        byte tmp = sbox[i];
        sbox[i] = sbox[j];
        sbox[j] = tmp;
    }
    
    // generate output
    i = 0;
    j = 0;
    int index = 0;
    while(index < datalen) {
        i = ((i + 1) % 256) & 0xFF;
        j = ((j + sbox[i]) % 256) & 0xFF;
        
        byte tmp = sbox[i];
        sbox[i] = sbox[j];
        sbox[j] = tmp;
        
        byte k = (byte)(sbox[((sbox[i] + sbox[j]) % 256) & 0xFF]);
        data[index] ^= k;
        index++;
    }
}

 

这是JEB的输出:

// Decompiled by JEB v0.9.0 alpha

public static void rc4_crypt(byte[] arg11, byte[] arg12) {
    int v10 = 0x100;
    int v5 = arg11.length;
    int v0 = arg12.length;
    byte[] v6 = new byte[v10];
    int v1 = 0;
    while(v1 < v10) {
        v6[v1] = ((byte)v1);
        ++v1;
    }

    int v3 = 0;
    v1 = 0;
    while(v1 < v10) {
        v3 = (v6[v1] + v3 + arg11[v1 % v5]) % 0x100 & 0xFF;
        byte v7 = v6[v1];
        v6[v1] = v6[v3];
        v6[v3] = v7;
        ++v1;
    }

    v1 = 0;
    v3 = 0;
    int v2 = 0;
    while(v2 < v0) {
        v1 = (v1 + 1) % 0x100 & 0xFF;
        v3 = (v6[v1] + v3) % 0x100 & 0xFF;
        v7 = v6[v1];
        v6[v1] = v6[v3];
        v6[v3] = v7;
        arg12[v2] = ((byte)(arg12[v2] ^ v6[(v6[v1] + v6[v3]) % 0x100 & 0xFF]));
        ++v2;
    }
}

这是的JD-GUI输出:

// Decompiled by JD-GUI v0.3.5

public static void rc4_crypt(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2)
{
  int i = paramArrayOfByte1.length;
  int j = paramArrayOfByte2.length;
  byte[] arrayOfByte = new byte[256];
  int k = 0;
  int m;
  int n;
  label30: int i2;
  int i3;
  if (k >= 256)
  {
    m = 0;
    n = 0;
    if (n < 256)
      break label68;
    i2 = 0;
    i3 = 0;
  }
  for (int i4 = 0; ; i4++)
  {
    if (i4 >= j)
    {
      return;
      arrayOfByte[k] = ((byte)k);
      k++;
      break;
      label68: m = 0xFF & (m + arrayOfByte[n] + paramArrayOfByte1[(n % i)]) % 256;
      int i1 = arrayOfByte[n];
      arrayOfByte[n] = arrayOfByte[m];
      arrayOfByte[m] = i1;
      n++;
      break label30;
    }
    i2 = 0xFF & (i2 + 1) % 256;
    i3 = 0xFF & (i3 + arrayOfByte[i2]) % 256;
    int i5 = arrayOfByte[i2];
    arrayOfByte[i2] = arrayOfByte[i3];
    arrayOfByte[i3] = i5;
    paramArrayOfByte2[i4] = ((byte)(arrayOfByte[(0xFF & (arrayOfByte[i2] + arrayOfByte[i3]) % 256)] ^ paramArrayOfByte2[i4]));
  }
}

http://www.android-decompiler.com/comp.php

另外现在很多给dex加点料,让工具崩了的手法。

$ dex2jar obfuscated.dex
dex2jar obfuscated.dex -> obfuscated-dex2jar.jar
com.googlecode.dex2jar.DexException: while accept method:[LA;.f(I)I]
        at com.googlecode.dex2jar.reader.DexFileReader.acceptMethod(DexFileReader.java:699)
        at com.googlecode.dex2jar.reader.DexFileReader.acceptClass(DexFileReader.java:446)
        at com.googlecode.dex2jar.reader.DexFileReader.accept(DexFileReader.java:328)
        at com.googlecode.dex2jar.v3.Dex2jar.doTranslate(Dex2jar.java:84)
        at com.googlecode.dex2jar.v3.Dex2jar.to(Dex2jar.java:239)
        at com.googlecode.dex2jar.v3.Dex2jar.to(Dex2jar.java:230)
        at com.googlecode.dex2jar.tools.Dex2jarCmd.doCommandLine(Dex2jarCmd.java:107)
        at com.googlecode.dex2jar.tools.BaseCmd.doMain(BaseCmd.java:168)
        at com.googlecode.dex2jar.tools.Dex2jarCmd.main(Dex2jarCmd.java:34)
Caused by: com.googlecode.dex2jar.DexException: while accept code in method:[LA;.f(I)I]
        at com.googlecode.dex2jar.reader.DexFileReader.acceptMethod(DexFileReader.java:689)
        ... 8 more
Caused by: java.lang.ArrayIndexOutOfBoundsException: 15
        at com.googlecode.dex2jar.v3.V3CodeAdapter.visitConstStmt(V3CodeAdapter.java:326)
        at com.googlecode.dex2jar.reader.DexOpcodeAdapter.x1n(DexOpcodeAdapter.java:262)
        at com.googlecode.dex2jar.reader.DexCodeReader.acceptInsn(DexCodeReader.java:411)
        at com.googlecode.dex2jar.reader.DexCodeReader.accept(DexCodeReader.java:330)
        at com.googlecode.dex2jar.reader.DexFileReader.acceptMethod(DexFileReader.java:686)
        ... 8 more
        

一个简单的例子混淆一下,里面再加点料。 如何加料从而和各类工具作斗争也是个大学问!!

This example is a very simple piece of code that was run through a flow obfuscator and junk insertion program.

.method public f(I)I
          const/4             v15, 0x7
          move/from16         v6, v15
          move                v7, v15
          and-int/lit8        v6, v15, 0x4
          move/from16         v9, v7
          const               v14, 0x5
          add-int             v9, v9, v15
          mul-int/2addr       v7, v9
          const               v7, 0x5
          sub-int/2addr       v9, v6
          move                v11, v7
          move/16             v13, v6
          goto/16             :180
:30
          return              v0
:36
          goto                :38
:38
          const               v7, 0x6
          move                v15, v7
          const/4             v8, 0x3
          move                v0, v2
          const               v15, 0x2
          const               v3, 0x1
          div-int/lit8        v3, v8, 0x3
          mul-int/lit8        v8, v3, 0x2
          div-int/lit8        v8, v3, 0x2
          div-int/2addr       v7, v8
          const/4             v5, 0x2
          and-int             v8, v8, v5
          const               v5, 0x6
          goto                :6C
:6C
          const               v9, 0x1
          const/16            v6, 0x2
          add-int/lit8        v9, v6, 0x2
          move/from16         v10, v9
          move/from16         v14, v10
          move/16             v5, v6
          const/16            v3, 0x0
          move/from16         v6, v9
          add-int             v6, v6, v14
          add-int/lit8        v0, v0, 0x1
          const               v14, 0x6
          rem-int             v5, v5, v6
          const/4             v10, 0x6
          shr-int/lit8        v10, v14, 0x5
          goto/16             :1EC
:AC
          const               v13, 0x2
          const/4             v9, 0x7
          const/4             v15, 0x1
          const/4             v10, 0x2
          rem-int/lit16       v9, v13, 0x7
          move/from16         v4, v15
          ushr-int/2addr      v15, v10
          const               v5, 0x6
          shl-int             v5, v5, v13
          div-int/lit8        v4, v5, 0x1
          const               v14, 0x6
          xor-int             v15, v15, v14
          const               v7, 0x6
          move                v15, v5
          if-ltz              v15, :12E
:E6
          const/16            v7, 0x4
          const/16            v4, 0x7
          move/16             v14, v5
          xor-int/lit16       v7, v14, 0x2
          move/from16         v9, v15
          div-int             v4, v4, v10
          move                v8, v15
          and-int             v9, v9, v4
          const/16            v4, 0x0
          move/from16         v14, v9
          const               v12, 0x1
          move/16             v4, v12
          mul-int/lit16       v14, v10, 0x0
          move                v7, v10
          div-int             v10, v10, v7
          or-int/lit16        v4, v8, 0x6
          mul-int             v5, v5, v15
          goto                :12E
:12E
          const               v3, 0x7
          move/16             v10, v3
          ushr-int/lit8       v10, v3, 0x0
          and-int/lit8        v10, v3, 0x0
          const/4             v4, 0x4
          xor-int/lit16       v3, v4, 0x3
          move/from16         v6, v4
          xor-int/lit8        v3, v6, 0x3
          sub-int             v10, v10, v4
          goto                :156
:156
          const               v4, 0x2
          const               v6, 0x4
          add-int/lit16       v6, v4, 0x6
          move                v11, v4
          const               v6, 0x5
          move/from16         v10, v11
          move/from16         v3, v4
          and-int             v10, v10, v4
          shr-int             v4, v4, v6
          goto                :1E2
:180
          const               v13, 0x0
          move/from16         v7, v13
          add-int/lit8        v13, v7, 0x1
          const/16            v11, 0x3
          div-int             v7, v7, v11
          xor-int             v13, v13, v11
          if-ge               v7, v13, :36
:19E
          xor-int/2addr       v7, v13
          move                v10, v13
          and-int/lit16       v11, v13, 0x6
          const               v7, 0x5
          const/16            v8, 0x6
          rsub-int            v10, v11, 0x6
          const               v13, 0x5
          const               v5, 0x0
          const               v5, 0x1
          and-int             v10, v10, v5
          rem-int/lit16       v11, v8, 0x7
          move/16             v4, v10
          move                v10, v13
          or-int/2addr        v7, v13
          rem-int/lit16       v5, v13, 0x0
          div-int/2addr       v10, v11
          goto/16             :36
:1E2
          const               v11, 0x1
          goto/16             :30
:1EC
          const               v8, 0x0
          move                v9, v8
          move/from16         v8, v9
          goto/16             :AC
.end method

上面的程序看起来好好负责吆!JEB's deobfuscator chimes in and decompiles it to a simple:

你妹,原来就是这么简单的程序呀:

 

// Decompiled by JEB v0.9.0 alpha

public int f(int arg2) {
    int v0 = arg2 + 1;
    return v0;
}

没有更多推荐了,返回首页