JEB is much more than just a Dalvik decompiler and disassembler. The interactivity and flexibility it provides are equally important for reverse engineers. However, you will be interested to see how JEB's decompiler output compares to that of the current standard tools.
This page shows how our decompiler performs versus the two most common combination of tools: dex2jar+JD-GUI and dex2jar+JAD.
Note: JD and JAD being Java class files decompilers, a prerequisite step to show you their output is to convert the Java bytecode to Dalvik bytecode. This step can be destructive, both for bytecode data and metadata. It is also extremely easy to write Dalvik bytecode that will crash dex2jar. One such example of obfuscated code is presented later in this page.
This document is divided into three parts:
In all four cases below, JEB gives almost perfect source code. JD-GUI and JAD, particularly the latter, produce incorrect, overly complex and difficult to read decompiled code.
RC4 encryption
A ubiquitous, standard stream cipher. Algorithmically, nothing fancy: three loops and a couple of bit-wise arithmetic operations.
Quicksort
The most famous divide-and-conquer sorting algorithm. The presence of nested loops and recursion calls makes it algorithmically more complex than RC4.
Eratosthenes sieve
One of the most basic way to generate prime numbers. A standard implementation is based on loops, nested loops, conditionals, arrays and so on.
LZSS decompression
Improved upon LZ77, this Lempel-Ziv compression scheme is the basis of many more compression algorithms. Algorithmically, it is at par with the prime number generator presented above.
Here, we show the decompiled output for android.support.v4.app.BackStackRecord
, one of the big classes of the
Android Support framework.
As you can see, the code produced by JD and JAD does not appear as unreadable as for the examples above. Still, many routines are incorrectly or poorly rendered by those tools, especially when they contain nested complex loops.
As previously shown, JEB is doing very well. For an example of that, see the method popFromBackStack().
(For enhanced clarity, here are the individual output files : JEB / JD-GUI / JAD)
Obfuscated code and/or modified+repackaged apps are likely to break DEX-to-JAR converters. It is the case here:
$ 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
For this reason, we can only present JEB's output.
This example is a very simple piece of code that was run through a flow obfuscator and junk insertion program.
JEB reconstructs the flow and removes junk code, giving simplified Java source.
.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
This Dalvik listing appears unnaturally complex. 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; }
Try JEB for yourself, download a demo version.