强大的dex反编译器

来源:互联网 发布:淘宝退款不退货违法 编辑:程序博客网 时间:2024/04/28 04:47

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 poolimport osfrom jeb.api import IScriptfrom jeb.api import EngineOptionclass 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 alphapublic 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.5public 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.dexdex2jar obfuscated.dex -> obfuscated-dex2jar.jarcom.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 moreCaused 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 alphapublic int f(int arg2) {    int v0 = arg2 + 1;    return v0;}