How to decode those JD-GUI error decompiled Bytecode
Asked Answered
Y

2

7

I want to decompile one apk file to see some part of its source code, but when I get to the part I am intrested in, JD-GUI gives following decompiled code

  /* Error */
  public void loginV2(Context paramContext, String paramString1, int paramInt, String paramString2, String paramString3, String paramString4, AsyncHttpResponseHandler paramAsyncHttpResponseHandler)
  {
    // Byte code:
    //   0: new 20  java/lang/StringBuilder
    //   3: dup
    //   4: getstatic 91    com/ipanel/join/homed/mobile/myt/Config:SERVER_ACCESS   Ljava/lang/String;
    //   7: invokestatic 32 java/lang/String:valueOf    (Ljava/lang/Object;)Ljava/lang/String;
    //   10: invokespecial 35   java/lang/StringBuilder:<init>  (Ljava/lang/String;)V
    //   13: ldc_w 491
    //   16: invokevirtual 41   java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   19: invokevirtual 45   java/lang/StringBuilder:toString    ()Ljava/lang/String;
    //   22: astore 10
    //   24: new 226    cn/ipanel/android/net/http/AsyncHttpClient
    //   27: dup
    //   28: invokespecial 227  cn/ipanel/android/net/http/AsyncHttpClient:<init>   ()V
    //   31: astore 11
    //   33: new 429    org/json/JSONObject
    //   36: dup
    //   37: invokespecial 430  org/json/JSONObject:<init>  ()V
    //   40: astore 12
    //   42: aconst_null
    //   43: astore 9
    //   45: aconst_null
    //   46: astore 8
    //   48: new 20 java/lang/StringBuilder
    //   51: dup
    //   52: invokespecial 169  java/lang/StringBuilder:<init>  ()V
    //   55: aload_1
    //   56: invokestatic 300   com/ipanel/join/homed/mobile/myt/utils/DeviceUtils:getDeviceId  (Landroid/content/Context;)Ljava/lang/String;
    //   59: invokevirtual 41   java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   62: invokevirtual 45   java/lang/StringBuilder:toString    ()Ljava/lang/String;
    //   65: astore 13
    //   67: new 20 java/lang/StringBuilder
    //   70: dup
    //   71: aload 13
    //   73: invokestatic 32    java/lang/String:valueOf    (Ljava/lang/Object;)Ljava/lang/String;
    //   76: invokespecial 35   java/lang/StringBuilder:<init>  (Ljava/lang/String;)V
    //   79: aload 13
    //   81: invokestatic 497   com/ipanel/join/homed/helper/OperationUtils:getMD5  (Ljava/lang/String;)Ljava/lang/String;
    //   84: bipush 7
    //   86: bipush 8
    //   88: invokevirtual 501  java/lang/String:substring  (II)Ljava/lang/String;
    //   91: invokevirtual 41   java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   94: invokevirtual 45   java/lang/StringBuilder:toString    ()Ljava/lang/String;
    //   97: astore 13
    //   99: invokestatic 506   java/util/Calendar:getInstance  ()Ljava/util/Calendar;
    //   102: invokevirtual 510 java/util/Calendar:getTimeInMillis  ()J
    //   105: lstore 14
    //   107: aload 12
    //   109: ldc_w 294
    //   112: aload 13
    //   114: invokevirtual 435 org/json/JSONObject:put (Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
    //   117: pop
    //   118: aload 12
    //   120: ldc_w 302
    //   123: aload_2
    //   124: invokevirtual 435 org/json/JSONObject:put (Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
    //   127: pop
    //   128: aload 12
    //   130: ldc_w 469
    //   133: iload_3
    //   134: invokevirtual 513 org/json/JSONObject:put (Ljava/lang/String;I)Lorg/json/JSONObject;
    //   137: pop
    //   138: aload 12
    //   140: ldc_w 467
    //   143: aload 4
    //   145: invokevirtual 435 org/json/JSONObject:put (Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
    //   148: pop
    //   149: aload 12
    //   151: ldc_w 515
    //   154: aload 5
    //   156: invokestatic 497  com/ipanel/join/homed/helper/OperationUtils:getMD5  (Ljava/lang/String;)Ljava/lang/String;
    //   159: invokevirtual 435 org/json/JSONObject:put (Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
    //   162: pop
    //   163: aload 6
    //   165: invokestatic 112  android/text/TextUtils:isEmpty  (Ljava/lang/CharSequence;)Z
    //   168: ifne +13 -> 181
    //   171: aload 12
    //   173: ldc 99
    //   175: aload 6
    //   177: invokevirtual 435 org/json/JSONObject:put (Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
    //   180: pop
    //   181: aload 12
    //   183: ldc_w 517
    //   186: new 20    java/lang/StringBuilder
    //   189: dup
    //   190: invokespecial 169 java/lang/StringBuilder:<init>  ()V
    //   193: lload 14
    //   195: invokevirtual 520 java/lang/StringBuilder:append  (J)Ljava/lang/StringBuilder;
    //   198: invokevirtual 45  java/lang/StringBuilder:toString    ()Ljava/lang/String;
    //   201: invokevirtual 435 org/json/JSONObject:put (Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
    //   204: pop
    //   205: aload 12
    //   207: ldc_w 522
    //   210: ldc 124
    //   212: invokevirtual 435 org/json/JSONObject:put (Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
    //   215: pop
    //   216: aload 12
    //   218: ldc_w 524
    //   221: new 20    java/lang/StringBuilder
    //   224: dup
    //   225: aload 13
    //   227: invokestatic 32   java/lang/String:valueOf    (Ljava/lang/Object;)Ljava/lang/String;
    //   230: invokespecial 35  java/lang/StringBuilder:<init>  (Ljava/lang/String;)V
    //   233: ldc_w 526
    //   236: invokevirtual 41  java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   239: aload_2
    //   240: invokevirtual 41  java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   243: ldc_w 526
    //   246: invokevirtual 41  java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   249: iload_3
    //   250: invokevirtual 176 java/lang/StringBuilder:append  (I)Ljava/lang/StringBuilder;
    //   253: ldc_w 526
    //   256: invokevirtual 41  java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   259: aload 4
    //   261: invokevirtual 41  java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   264: ldc_w 526
    //   267: invokevirtual 41  java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   270: lload 14
    //   272: invokevirtual 520 java/lang/StringBuilder:append  (J)Ljava/lang/StringBuilder;
    //   275: invokevirtual 45  java/lang/StringBuilder:toString    ()Ljava/lang/String;
    //   278: invokestatic 497  com/ipanel/join/homed/helper/OperationUtils:getMD5  (Ljava/lang/String;)Ljava/lang/String;
    //   281: invokevirtual 435 org/json/JSONObject:put (Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
    //   284: pop
    //   285: new 223   org/apache/http/entity/StringEntity
    //   288: dup
    //   289: aload 12
    //   291: invokevirtual 438 org/json/JSONObject:toString    ()Ljava/lang/String;
    //   294: ldc_w 440
    //   297: invokespecial 442 org/apache/http/entity/StringEntity:<init>  (Ljava/lang/String;Ljava/lang/String;)V
    //   300: astore_2
    //   301: getstatic 448 java/lang/System:out    Ljava/io/PrintStream;
    //   304: new 20    java/lang/StringBuilder
    //   307: dup
    //   308: ldc_w 450
    //   311: invokespecial 35  java/lang/StringBuilder:<init>  (Ljava/lang/String;)V
    //   314: aload 12
    //   316: invokevirtual 438 org/json/JSONObject:toString    ()Ljava/lang/String;
    //   319: invokevirtual 41  java/lang/StringBuilder:append  (Ljava/lang/String;)Ljava/lang/StringBuilder;
    //   322: invokevirtual 45  java/lang/StringBuilder:toString    ()Ljava/lang/String;
    //   325: invokevirtual 455 java/io/PrintStream:println (Ljava/lang/String;)V
    //   328: aload 11
    //   330: aload_1
    //   331: aload 10
    //   333: aload_2
    //   334: ldc -27
    //   336: aload 7
    //   338: invokevirtual 233 cn/ipanel/android/net/http/AsyncHttpClient:post (Landroid/content/Context;Ljava/lang/String;Lorg/apache/http/HttpEntity;Ljava/lang/String;Lcn/ipanel/android/net/http/AsyncHttpResponseHandler;)V
    //   341: return
    //   342: astore 4
    //   344: aload 8
    //   346: astore_2
    //   347: aload 4
    //   349: invokevirtual 456 org/json/JSONException:printStackTrace  ()V
    //   352: goto -24 -> 328
    //   355: astore 4
    //   357: aload 9
    //   359: astore_2
    //   360: aload 4
    //   362: invokevirtual 236 java/io/UnsupportedEncodingException:printStackTrace    ()V
    //   365: goto -37 -> 328
    //   368: astore 4
    //   370: goto -10 -> 360
    //   373: astore 4
    //   375: goto -28 -> 347
    // Local variable table:
    //   start  length  slot    name    signature
    //   0  378 0   this    APIManager
    //   0  378 1   paramContext    Context
    //   0  378 2   paramString1    String
    //   0  378 3   paramInt    int
    //   0  378 4   paramString2    String
    //   0  378 5   paramString3    String
    //   0  378 6   paramString4    String
    //   0  378 7   paramAsyncHttpResponseHandler   AsyncHttpResponseHandler
    //   46 299 8   localObject1    Object
    //   43 315 9   localObject2    Object
    //   22 310 10  str1    String
    //   31 298 11  localAsyncHttpClient    AsyncHttpClient
    //   40 275 12  localJSONObject JSONObject
    //   65 161 13  str2    String
    //   105    166 14  l   long
    // Exception table:
    //   from   to  target  type
    //   48 181 342 org/json/JSONException
    //   181    301 342 org/json/JSONException
    //   48 181 355 java/io/UnsupportedEncodingException
    //   181    301 355 java/io/UnsupportedEncodingException
    //   301    328 368 java/io/UnsupportedEncodingException
    //   301    328 373 org/json/JSONException
  }

I searched web and found that maybe the reason is the apk'a author deliberately made this error to protect the critical part of the code to be decompiled by JD-GUI.

What I want to ask is

  1. Could these so called "Byte code" be understood ? I read the code , authough I am not able to understand the code completely,I think it still keep the actual code info, I found getMD5 function in the code, so could someone explain to me which parameters the code uses and how to do MD5(actually this is the part I am interested in)

  2. Could someone give me some suggestions to help me to understand such codes by myself, for example , give me some reference web links to understand the so called "Byte Code" language's specification(just like c++ or C#), so next time maybe I can do the job myself

Thanks!

ps: I tried another hex viewer , and get following result code

public void loginV2(final Context p0, final String p1, final int p2, final String p3, final String p4, final String p5, final AsyncHttpResponseHandler p6) {
        // 
        // This method could not be decompiled.
        // 
        // Original Bytecode:
        // 
        //     0: new             Ljava/lang/StringBuilder;
        //     3: dup            
        //     4: getstatic       com/ipanel/join/homed/mobile/myt/Config.SERVER_ACCESS:Ljava/lang/String;
        //     7: invokestatic    java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
        //    10: invokespecial   java/lang/StringBuilder.<init>:(Ljava/lang/String;)V
        //    13: ldc_w           "account/user/v2/login"
        //    16: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //    19: invokevirtual   java/lang/StringBuilder.toString:()Ljava/lang/String;
        //    22: astore          8
        //    24: new             Lcn/ipanel/android/net/http/AsyncHttpClient;
        //    27: dup            
        //    28: invokespecial   cn/ipanel/android/net/http/AsyncHttpClient.<init>:()V
        //    31: astore          9
        //    33: new             Lorg/json/JSONObject;
        //    36: dup            
        //    37: invokespecial   org/json/JSONObject.<init>:()V
        //    40: astore          10
        //    42: aconst_null    
        //    43: astore          11
        //    45: new             Ljava/lang/StringBuilder;
        //    48: dup            
        //    49: invokespecial   java/lang/StringBuilder.<init>:()V
        //    52: aload_1        
        //    53: invokestatic    com/ipanel/join/homed/mobile/myt/utils/DeviceUtils.getDeviceId:(Landroid/content/Context;)Ljava/lang/String;
        //    56: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //    59: invokevirtual   java/lang/StringBuilder.toString:()Ljava/lang/String;
        //    62: astore          14
        //    64: new             Ljava/lang/StringBuilder;
        //    67: dup            
        //    68: aload           14
        //    70: invokestatic    java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
        //    73: invokespecial   java/lang/StringBuilder.<init>:(Ljava/lang/String;)V
        //    76: aload           14
        //    78: invokestatic    com/ipanel/join/homed/helper/OperationUtils.getMD5:(Ljava/lang/String;)Ljava/lang/String;
        //    81: bipush          7
        //    83: bipush          8
        //    85: invokevirtual   java/lang/String.substring:(II)Ljava/lang/String;
        //    88: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //    91: invokevirtual   java/lang/StringBuilder.toString:()Ljava/lang/String;
        //    94: astore          15
        //    96: invokestatic    java/util/Calendar.getInstance:()Ljava/util/Calendar;
        //    99: invokevirtual   java/util/Calendar.getTimeInMillis:()J
        //   102: lstore          16
        //   104: aload           10
        //   106: ldc_w           "deviceno"
        //   109: aload           15
        //   111: invokevirtual   org/json/JSONObject.put:(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
        //   114: pop            
        //   115: aload           10
        //   117: ldc_w           "devicetype"
        //   120: aload_2        
        //   121: invokevirtual   org/json/JSONObject.put:(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
        //   124: pop            
        //   125: aload           10
        //   127: ldc_w           "accounttype"
        //   130: iload_3        
        //   131: invokevirtual   org/json/JSONObject.put:(Ljava/lang/String;I)Lorg/json/JSONObject;
        //   134: pop            
        //   135: aload           10
        //   137: ldc_w           "account"
        //   140: aload           4
        //   142: invokevirtual   org/json/JSONObject.put:(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
        //   145: pop            
        //   146: aload           10
        //   148: ldc_w           "pwd"
        //   151: aload           5
        //   153: invokestatic    com/ipanel/join/homed/helper/OperationUtils.getMD5:(Ljava/lang/String;)Ljava/lang/String;
        //   156: invokevirtual   org/json/JSONObject.put:(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
        //   159: pop            
        //   160: aload           6
        //   162: invokestatic    android/text/TextUtils.isEmpty:(Ljava/lang/CharSequence;)Z
        //   165: ifne            178
        //   168: aload           10
        //   170: ldc             "code"
        //   172: aload           6
        //   174: invokevirtual   org/json/JSONObject.put:(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
        //   177: pop            
        //   178: aload           10
        //   180: ldc_w           "timestamp"
        //   183: new             Ljava/lang/StringBuilder;
        //   186: dup            
        //   187: invokespecial   java/lang/StringBuilder.<init>:()V
        //   190: lload           16
        //   192: invokevirtual   java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        //   195: invokevirtual   java/lang/StringBuilder.toString:()Ljava/lang/String;
        //   198: invokevirtual   org/json/JSONObject.put:(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
        //   201: pop            
        //   202: aload           10
        //   204: ldc_w           "isforce"
        //   207: ldc             "1"
        //   209: invokevirtual   org/json/JSONObject.put:(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
        //   212: pop            
        //   213: aload           10
        //   215: ldc_w           "signature"
        //   218: new             Ljava/lang/StringBuilder;
        //   221: dup            
        //   222: aload           15
        //   224: invokestatic    java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
        //   227: invokespecial   java/lang/StringBuilder.<init>:(Ljava/lang/String;)V
        //   230: ldc_w           "|"
        //   233: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //   236: aload_2        
        //   237: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //   240: ldc_w           "|"
        //   243: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //   246: iload_3        
        //   247: invokevirtual   java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        //   250: ldc_w           "|"
        //   253: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //   256: aload           4
        //   258: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //   261: ldc_w           "|"
        //   264: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //   267: lload           16
        //   269: invokevirtual   java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
        //   272: invokevirtual   java/lang/StringBuilder.toString:()Ljava/lang/String;
        //   275: invokestatic    com/ipanel/join/homed/helper/OperationUtils.getMD5:(Ljava/lang/String;)Ljava/lang/String;
        //   278: invokevirtual   org/json/JSONObject.put:(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;
        //   281: pop            
        //   282: new             Lorg/apache/http/entity/StringEntity;
        //   285: dup            
        //   286: aload           10
        //   288: invokevirtual   org/json/JSONObject.toString:()Ljava/lang/String;
        //   291: ldc_w           "UTF-8"
        //   294: invokespecial   org/apache/http/entity/StringEntity.<init>:(Ljava/lang/String;Ljava/lang/String;)V
        //   297: astore          26
        //   299: getstatic       java/lang/System.out:Ljava/io/PrintStream;
        //   302: new             Ljava/lang/StringBuilder;
        //   305: dup            
        //   306: ldc_w           "para: "
        //   309: invokespecial   java/lang/StringBuilder.<init>:(Ljava/lang/String;)V
        //   312: aload           10
        //   314: invokevirtual   org/json/JSONObject.toString:()Ljava/lang/String;
        //   317: invokevirtual   java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        //   320: invokevirtual   java/lang/StringBuilder.toString:()Ljava/lang/String;
        //   323: invokevirtual   java/io/PrintStream.println:(Ljava/lang/String;)V
        //   326: aload           26
        //   328: astore          11
        //   330: aload           9
        //   332: aload_1        
        //   333: aload           8
        //   335: aload           11
        //   337: ldc             "text/html"
        //   339: aload           7
        //   341: invokevirtual   cn/ipanel/android/net/http/AsyncHttpClient.post:(Landroid/content/Context;Ljava/lang/String;Lorg/apache/http/HttpEntity;Ljava/lang/String;Lcn/ipanel/android/net/http/AsyncHttpResponseHandler;)V
        //   344: return         
        //   345: astore          13
        //   347: aload           13
        //   349: invokevirtual   org/json/JSONException.printStackTrace:()V
        //   352: goto            330
        //   355: astore          12
        //   357: aload           12
        //   359: invokevirtual   java/io/UnsupportedEncodingException.printStackTrace:()V
        //   362: goto            330
        //   365: astore          12
        //   367: aload           26
        //   369: astore          11
        //   371: goto            357
        //   374: astore          13
        //   376: aload           26
        //   378: astore          11
        //   380: goto            347
        //    Exceptions:
        //  Try           Handler
        //  Start  End    Start  End    Type                                  
        //  -----  -----  -----  -----  --------------------------------------
        //  45     178    345    347    Lorg/json/JSONException;
        //  45     178    355    357    Ljava/io/UnsupportedEncodingException;
        //  178    299    345    347    Lorg/json/JSONException;
        //  178    299    355    357    Ljava/io/UnsupportedEncodingException;
        //  299    326    374    383    Lorg/json/JSONException;
        //  299    326    365    374    Ljava/io/UnsupportedEncodingException;
        // 
        // The error that occurred was:
        // 
        // java.lang.IllegalStateException: Expression is linked from several locations: Label_0330:
        //     at com.strobel.decompiler.ast.Error.expressionLinkedFromMultipleLocations(Error.java:27)
        //     at com.strobel.decompiler.ast.AstOptimizer.mergeDisparateObjectInitializations(AstOptimizer.java:2592)
        //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:235)
        //     at com.strobel.decompiler.ast.AstOptimizer.optimize(AstOptimizer.java:42)
        //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:214)
        //     at com.strobel.decompiler.languages.java.ast.AstMethodBodyBuilder.createMethodBody(AstMethodBodyBuilder.java:99)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethodBody(AstBuilder.java:757)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createMethod(AstBuilder.java:655)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addTypeMembers(AstBuilder.java:532)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeCore(AstBuilder.java:499)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createTypeNoCache(AstBuilder.java:141)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.createType(AstBuilder.java:130)
        //     at com.strobel.decompiler.languages.java.ast.AstBuilder.addType(AstBuilder.java:105)
        //     at com.strobel.decompiler.languages.java.JavaLanguage.buildAst(JavaLanguage.java:71)
        //     at com.strobel.decompiler.languages.java.JavaLanguage.decompileType(JavaLanguage.java:59)
        //     at the.bytecode.club.bytecodeviewer.decompilers.ProcyonDecompiler.decompileClassNode(ProcyonDecompiler.java:120)
        //     at the.bytecode.club.bytecodeviewer.gui.ClassViewer$13.doShit(ClassViewer.java:624)
        //     at the.bytecode.club.bytecodeviewer.gui.PaneUpdaterThread.run(PaneUpdaterThread.java:16)
        // 
        throw new IllegalStateException("An error occurred while decompiling this method.");
    }
Yell answered 25/6, 2017 at 2:10 Comment(0)
P
4

First off, JD-GUI is not a very good decompiler. You'll almost certainly get better results using other decompilers.

That being said, it is important to learn how to understand bytecode if you want to become serious about Java reverse engineering.

There are actually two different bytecode "languages". The first is the Java classfile format, which is executed by the JVM. This is what you get when you run a Java desktop application or applet. You can find the specification here: http://docs.oracle.com/javase/specs/jvms/se8/html/index.html

However, Android does not use Java bytecode at all. Instead, it uses its own system, known as Dex bytecode, which is similar, but subtly different. You can find the specification for Dex bytecode here: https://source.android.com/devices/tech/dalvik/dalvik-bytecode

APKs consist of Dex bytecode. However, the listing you showed is Java bytecode. Presumably, you either ran it through Dex2Jar first to translate the Dex file into Java bytecode or you used a tool that did this for you. (You can also use Enjarify to do this, but the bytecode you posted doesn't look like the output of Enjarify).

At any rate, if you're trying to understand an obfuscated binary, you might as well go straight to the source and look at the Dex bytecode, rather than the output of an imperfect conversion tool. I'd recommend checking out smali/baksmali and apktool, which are the best tools I know of for working with dex files.

Update: Now that you've provided the apk, I decompiled it myself, and it really doesn't look like anything nefarious is going on. The code just happens to have a try/catch with multiple catch blocks, which confuses the decompilers you used.

Since there were multiple classes with a loginV2 method in your apk, I decided to focus on com/ipanel/join/homed/utils/APIManager.

Using Enjarify + Krakatau, I get the following decompiled code.

public void loginV2(android.content.Context a, String s, int i, String s0, String s1, String s2, cn.ipanel.android.net.http.AsyncHttpResponseHandler a0)
{
    org.apache.http.entity.StringEntity a1 = null;
    String s3 = new StringBuilder(String.valueOf((Object)com.ipanel.join.homed.Config.SERVER_ACCESS)).append("account/user/v2/login").toString();
    cn.ipanel.android.net.http.AsyncHttpClient a2 = new cn.ipanel.android.net.http.AsyncHttpClient();
    org.json.JSONObject a3 = new org.json.JSONObject();
    label1: {
        java.io.UnsupportedEncodingException a4 = null;
        label0: {
            org.json.JSONException a5 = null;
            label2: {
                java.io.PrintStream a6 = null;
                label4: {
                    label3: {
                        try
                        {
                            try
                            {
                                String s4 = new StringBuilder().append(com.ipanel.join.homed.utils.DeviceUtils.getDeviceId(a)).toString();
                                String s5 = new StringBuilder(String.valueOf((Object)s4)).append(com.ipanel.join.homed.helper.OperationUtils.getMD5(s4).substring(7, 8)).toString();
                                long j = java.util.Calendar.getInstance().getTimeInMillis();
                                a3.put("deviceno", (Object)s5);
                                a3.put("devicetype", (Object)s);
                                a3.put("accounttype", i);
                                a3.put("account", (Object)s0);
                                a3.put("pwd", (Object)com.ipanel.join.homed.helper.OperationUtils.getMD5(s1));
                                if (!android.text.TextUtils.isEmpty((CharSequence)(Object)s2))
                                {
                                    a3.put("code", (Object)s2);
                                }
                                a3.put("timestamp", (Object)new StringBuilder().append(j).toString());
                                a3.put("isforce", (Object)"1");
                                a3.put("signature", (Object)com.ipanel.join.homed.helper.OperationUtils.getMD5(new StringBuilder(String.valueOf((Object)s5)).append("|").append(s).append("|").append(i).append("|").append(s0).append("|").append(j).toString()));
                                a1 = new org.apache.http.entity.StringEntity(a3.toString(), "UTF-8");
                                a6 = System.out;
                                break label4;
                            }
                            catch(org.json.JSONException a7)
                            {
                                a5 = a7;
                            }
                        }
                        catch(java.io.UnsupportedEncodingException a8)
                        {
                            a4 = a8;
                            break label3;
                        }
                        a1 = null;
                        break label2;
                    }
                    a1 = null;
                    break label0;
                }
                {
                    try
                    {
                        try
                        {
                            a6.println(new StringBuilder("para: ").append(a3.toString()).toString());
                            break label1;
                        }
                        catch(org.json.JSONException a9)
                        {
                            a5 = a9;
                        }
                    }
                    catch(java.io.UnsupportedEncodingException a10)
                    {
                        a4 = a10;
                        break label0;
                    }
                    break label2;
                }
            }
            a5.printStackTrace();
            break label1;
        }
        a4.printStackTrace();
    }
    a2.post(a, s3, (org.apache.http.HttpEntity)(Object)a1, "text/html", a0);
}

Krakatau is a bit hard to use, but it has the advantage of being able to handle nearly anything (apart from invokedynamic, which Android luckily doesn't have). However, while it will always give you something, there are cases where the code produced is unnecessarily complicated, and this is one of them - try/catch with multiple catch blocks is handled very poorly.

Fortunately, it is easy to see what the code is actually trying to do and clean it up manually. Here is my manually cleaned up version of the above, which is likely close to the original code, apart from the variable names and fully qualified class references. As you can see, there was no deliberate obfuscation. It just happens by chance to use try/catch which decompilers struggle with.

public void loginV2(android.content.Context a, String s, int i, String s0, String s1, String s2, cn.ipanel.android.net.http.AsyncHttpResponseHandler a0)
{
    org.apache.http.entity.StringEntity a1 = null;
    String s3 = com.ipanel.join.homed.Config.SERVER_ACCESS + "account/user/v2/login";
    cn.ipanel.android.net.http.AsyncHttpClient a2 = new cn.ipanel.android.net.http.AsyncHttpClient();
    org.json.JSONObject a3 = new org.json.JSONObject();

    try
    {
        String s4 = com.ipanel.join.homed.utils.DeviceUtils.getDeviceId(a);
        String s5 = s4 + com.ipanel.join.homed.helper.OperationUtils.getMD5(s4).substring(7, 8);
        long j = java.util.Calendar.getInstance().getTimeInMillis();
        a3.put("deviceno", s5);
        a3.put("devicetype", s);
        a3.put("accounttype", i);
        a3.put("account", s0);
        a3.put("pwd", com.ipanel.join.homed.helper.OperationUtils.getMD5(s1));
        if (!android.text.TextUtils.isEmpty(s2))
        {
            a3.put("code", s2);
        }
        a3.put("timestamp", "" + j);
        a3.put("isforce", "1");
        a3.put("signature", com.ipanel.join.homed.helper.OperationUtils.getMD5(s5 + "|" + s + "|" + i + "|" + s0 + "|" + j);
        a1 = new org.apache.http.entity.StringEntity(a3.toString(), "UTF-8");
        System.out.println("para: " + a3);
    }
    catch(org.json.JSONException a7)
    {
        a7.printStackTrace();
    }
    catch(java.io.UnsupportedEncodingException a8)
    {
        a8.printStackTrace();
    }

    a2.post(a, s3, a1, "text/html", a0);
}
Palladian answered 25/6, 2017 at 5:5 Comment(12)
You said right, I used dex2jar to convert dex file to jar file and then use jd-gui to view source code, but since this apk file maybe obfuscated(I guess so because most part of the code I decompiled using jd-gui is readable java source code),Is directly using apktool to compile rather than using dex2jar first effective? apktool can deal with those obfuscated apk file? PS: Thanks for your recommended byte code specification file, I will research on it later on, but if you are familiar with java byte code, could you please first help me to understand the code I pastedYell
I'd recommend first trying a different decompiler, since the code you posted doesn't look particularly obfuscated. This is likely just a failing of JD-GUI. Have you tried Helios or Konloch's bytecode viewer? They come with a bunch of different decompiler options.Palladian
I tried your recommend Konloch's byte viewer and got another kind of Byte Code of my intrested function(pasted on top of this thread), so I still think this function is deliberately obfuscated by the author of the apk,you said options,but what options I can use to deal with this ?Yell
@user I've worked with a lot of Java obfuscators, and the code you posted is not obfuscated at all. You just used a crappy decompiler. If you give me the APK, I can decompile it for you.Palladian
sorry for the late reply. I think I have caught what you said, you said this apk is not obfuscated, it is also right, what I mean obfuscated here is a generalized meaning, that is the author used decompiler(such as JD-GUI)'s bug to make a trick,so decompiler can not do correct job, the code's variable names , working suquence and other things are not changed as generalized obfuscate job does. following is the apk's download link, You can have a try ,Thanks wandoujia.com/apps/com.ipanel.join.homed.mobile.pingyao/…Yell
@user I posted the decompiled version of the method you mentioned, as well as a manually cleaned up decompilation. The author didn't try to obfuscate it or exploit bugs or anything, it just happens to use try/catch, which decompilers struggle with.Palladian
Great Thanks! I think for this apk,I can do following work by myself. But since you mentioned tools to decompile this apk and said it is a bit hard to use, could you please help me again to test following apk, this time I think it is really obfuscated, since I can not even find the function I am intrested in(of course maybe it's because my java and android programming skill is very poor),the apk's download link is : wandoujia.com/apps/com.cmcc.migutvtwo/…Yell
the apk will fire a http request like app1.tv.cmvideo.cn:9001/api/newrlive/rlive/…, I can get the parameter id , salt maybe is a random number, timestamp maybe is the time http request is fired, but sign should be produced with above parameters , but since my decompile result of the apk gives only Class A B AA BB,I can not even find the place where http request is fired,so if you mentioned tools can get such info,please tell meYell
I don't think the comments are a good place to discuss this. Maybe you should ask a new question on reverseengineering.stackexchange.comPalladian
ok, I opened a new thread reverseengineering.stackexchange.com/questions/15733/… , please give some help.Yell
Sorry to resurrect an old thread, but how did you actually decompile an Android jar with Krakatau? I tried but it fails because of course it doesn't find all the android classes. Is there a way to make it decompile anyway? -skip doesn't solve it.Baeyer
You need to find a jar containing the relevant classes and then pass it via -path. This is a major weakness of the current Krakatau decompiler that I'd like to fix sometime but haven't had the time to do yet.Palladian
D
13

Ran into a similar issue trying to decompile a Java 8 file that used try-with-resources and lambdas.

After trying the following unsuccessfully:

This guy did the trick:

Dolorisdolorita answered 10/7, 2017 at 17:19 Comment(1)
Yes. this worked for me after failing to work on JD-GUI. Thanks.Potluck
P
4

First off, JD-GUI is not a very good decompiler. You'll almost certainly get better results using other decompilers.

That being said, it is important to learn how to understand bytecode if you want to become serious about Java reverse engineering.

There are actually two different bytecode "languages". The first is the Java classfile format, which is executed by the JVM. This is what you get when you run a Java desktop application or applet. You can find the specification here: http://docs.oracle.com/javase/specs/jvms/se8/html/index.html

However, Android does not use Java bytecode at all. Instead, it uses its own system, known as Dex bytecode, which is similar, but subtly different. You can find the specification for Dex bytecode here: https://source.android.com/devices/tech/dalvik/dalvik-bytecode

APKs consist of Dex bytecode. However, the listing you showed is Java bytecode. Presumably, you either ran it through Dex2Jar first to translate the Dex file into Java bytecode or you used a tool that did this for you. (You can also use Enjarify to do this, but the bytecode you posted doesn't look like the output of Enjarify).

At any rate, if you're trying to understand an obfuscated binary, you might as well go straight to the source and look at the Dex bytecode, rather than the output of an imperfect conversion tool. I'd recommend checking out smali/baksmali and apktool, which are the best tools I know of for working with dex files.

Update: Now that you've provided the apk, I decompiled it myself, and it really doesn't look like anything nefarious is going on. The code just happens to have a try/catch with multiple catch blocks, which confuses the decompilers you used.

Since there were multiple classes with a loginV2 method in your apk, I decided to focus on com/ipanel/join/homed/utils/APIManager.

Using Enjarify + Krakatau, I get the following decompiled code.

public void loginV2(android.content.Context a, String s, int i, String s0, String s1, String s2, cn.ipanel.android.net.http.AsyncHttpResponseHandler a0)
{
    org.apache.http.entity.StringEntity a1 = null;
    String s3 = new StringBuilder(String.valueOf((Object)com.ipanel.join.homed.Config.SERVER_ACCESS)).append("account/user/v2/login").toString();
    cn.ipanel.android.net.http.AsyncHttpClient a2 = new cn.ipanel.android.net.http.AsyncHttpClient();
    org.json.JSONObject a3 = new org.json.JSONObject();
    label1: {
        java.io.UnsupportedEncodingException a4 = null;
        label0: {
            org.json.JSONException a5 = null;
            label2: {
                java.io.PrintStream a6 = null;
                label4: {
                    label3: {
                        try
                        {
                            try
                            {
                                String s4 = new StringBuilder().append(com.ipanel.join.homed.utils.DeviceUtils.getDeviceId(a)).toString();
                                String s5 = new StringBuilder(String.valueOf((Object)s4)).append(com.ipanel.join.homed.helper.OperationUtils.getMD5(s4).substring(7, 8)).toString();
                                long j = java.util.Calendar.getInstance().getTimeInMillis();
                                a3.put("deviceno", (Object)s5);
                                a3.put("devicetype", (Object)s);
                                a3.put("accounttype", i);
                                a3.put("account", (Object)s0);
                                a3.put("pwd", (Object)com.ipanel.join.homed.helper.OperationUtils.getMD5(s1));
                                if (!android.text.TextUtils.isEmpty((CharSequence)(Object)s2))
                                {
                                    a3.put("code", (Object)s2);
                                }
                                a3.put("timestamp", (Object)new StringBuilder().append(j).toString());
                                a3.put("isforce", (Object)"1");
                                a3.put("signature", (Object)com.ipanel.join.homed.helper.OperationUtils.getMD5(new StringBuilder(String.valueOf((Object)s5)).append("|").append(s).append("|").append(i).append("|").append(s0).append("|").append(j).toString()));
                                a1 = new org.apache.http.entity.StringEntity(a3.toString(), "UTF-8");
                                a6 = System.out;
                                break label4;
                            }
                            catch(org.json.JSONException a7)
                            {
                                a5 = a7;
                            }
                        }
                        catch(java.io.UnsupportedEncodingException a8)
                        {
                            a4 = a8;
                            break label3;
                        }
                        a1 = null;
                        break label2;
                    }
                    a1 = null;
                    break label0;
                }
                {
                    try
                    {
                        try
                        {
                            a6.println(new StringBuilder("para: ").append(a3.toString()).toString());
                            break label1;
                        }
                        catch(org.json.JSONException a9)
                        {
                            a5 = a9;
                        }
                    }
                    catch(java.io.UnsupportedEncodingException a10)
                    {
                        a4 = a10;
                        break label0;
                    }
                    break label2;
                }
            }
            a5.printStackTrace();
            break label1;
        }
        a4.printStackTrace();
    }
    a2.post(a, s3, (org.apache.http.HttpEntity)(Object)a1, "text/html", a0);
}

Krakatau is a bit hard to use, but it has the advantage of being able to handle nearly anything (apart from invokedynamic, which Android luckily doesn't have). However, while it will always give you something, there are cases where the code produced is unnecessarily complicated, and this is one of them - try/catch with multiple catch blocks is handled very poorly.

Fortunately, it is easy to see what the code is actually trying to do and clean it up manually. Here is my manually cleaned up version of the above, which is likely close to the original code, apart from the variable names and fully qualified class references. As you can see, there was no deliberate obfuscation. It just happens by chance to use try/catch which decompilers struggle with.

public void loginV2(android.content.Context a, String s, int i, String s0, String s1, String s2, cn.ipanel.android.net.http.AsyncHttpResponseHandler a0)
{
    org.apache.http.entity.StringEntity a1 = null;
    String s3 = com.ipanel.join.homed.Config.SERVER_ACCESS + "account/user/v2/login";
    cn.ipanel.android.net.http.AsyncHttpClient a2 = new cn.ipanel.android.net.http.AsyncHttpClient();
    org.json.JSONObject a3 = new org.json.JSONObject();

    try
    {
        String s4 = com.ipanel.join.homed.utils.DeviceUtils.getDeviceId(a);
        String s5 = s4 + com.ipanel.join.homed.helper.OperationUtils.getMD5(s4).substring(7, 8);
        long j = java.util.Calendar.getInstance().getTimeInMillis();
        a3.put("deviceno", s5);
        a3.put("devicetype", s);
        a3.put("accounttype", i);
        a3.put("account", s0);
        a3.put("pwd", com.ipanel.join.homed.helper.OperationUtils.getMD5(s1));
        if (!android.text.TextUtils.isEmpty(s2))
        {
            a3.put("code", s2);
        }
        a3.put("timestamp", "" + j);
        a3.put("isforce", "1");
        a3.put("signature", com.ipanel.join.homed.helper.OperationUtils.getMD5(s5 + "|" + s + "|" + i + "|" + s0 + "|" + j);
        a1 = new org.apache.http.entity.StringEntity(a3.toString(), "UTF-8");
        System.out.println("para: " + a3);
    }
    catch(org.json.JSONException a7)
    {
        a7.printStackTrace();
    }
    catch(java.io.UnsupportedEncodingException a8)
    {
        a8.printStackTrace();
    }

    a2.post(a, s3, a1, "text/html", a0);
}
Palladian answered 25/6, 2017 at 5:5 Comment(12)
You said right, I used dex2jar to convert dex file to jar file and then use jd-gui to view source code, but since this apk file maybe obfuscated(I guess so because most part of the code I decompiled using jd-gui is readable java source code),Is directly using apktool to compile rather than using dex2jar first effective? apktool can deal with those obfuscated apk file? PS: Thanks for your recommended byte code specification file, I will research on it later on, but if you are familiar with java byte code, could you please first help me to understand the code I pastedYell
I'd recommend first trying a different decompiler, since the code you posted doesn't look particularly obfuscated. This is likely just a failing of JD-GUI. Have you tried Helios or Konloch's bytecode viewer? They come with a bunch of different decompiler options.Palladian
I tried your recommend Konloch's byte viewer and got another kind of Byte Code of my intrested function(pasted on top of this thread), so I still think this function is deliberately obfuscated by the author of the apk,you said options,but what options I can use to deal with this ?Yell
@user I've worked with a lot of Java obfuscators, and the code you posted is not obfuscated at all. You just used a crappy decompiler. If you give me the APK, I can decompile it for you.Palladian
sorry for the late reply. I think I have caught what you said, you said this apk is not obfuscated, it is also right, what I mean obfuscated here is a generalized meaning, that is the author used decompiler(such as JD-GUI)'s bug to make a trick,so decompiler can not do correct job, the code's variable names , working suquence and other things are not changed as generalized obfuscate job does. following is the apk's download link, You can have a try ,Thanks wandoujia.com/apps/com.ipanel.join.homed.mobile.pingyao/…Yell
@user I posted the decompiled version of the method you mentioned, as well as a manually cleaned up decompilation. The author didn't try to obfuscate it or exploit bugs or anything, it just happens to use try/catch, which decompilers struggle with.Palladian
Great Thanks! I think for this apk,I can do following work by myself. But since you mentioned tools to decompile this apk and said it is a bit hard to use, could you please help me again to test following apk, this time I think it is really obfuscated, since I can not even find the function I am intrested in(of course maybe it's because my java and android programming skill is very poor),the apk's download link is : wandoujia.com/apps/com.cmcc.migutvtwo/…Yell
the apk will fire a http request like app1.tv.cmvideo.cn:9001/api/newrlive/rlive/…, I can get the parameter id , salt maybe is a random number, timestamp maybe is the time http request is fired, but sign should be produced with above parameters , but since my decompile result of the apk gives only Class A B AA BB,I can not even find the place where http request is fired,so if you mentioned tools can get such info,please tell meYell
I don't think the comments are a good place to discuss this. Maybe you should ask a new question on reverseengineering.stackexchange.comPalladian
ok, I opened a new thread reverseengineering.stackexchange.com/questions/15733/… , please give some help.Yell
Sorry to resurrect an old thread, but how did you actually decompile an Android jar with Krakatau? I tried but it fails because of course it doesn't find all the android classes. Is there a way to make it decompile anyway? -skip doesn't solve it.Baeyer
You need to find a jar containing the relevant classes and then pass it via -path. This is a major weakness of the current Krakatau decompiler that I'd like to fix sometime but haven't had the time to do yet.Palladian

© 2022 - 2024 — McMap. All rights reserved.