如何解码那些JD-GUI错误的反编译字节码
How to decode those JD-GUI error decompiled Bytecode
我想反编译一个apk文件来查看它的部分源代码,但是当我到达我感兴趣的部分时,JD-GUI给出了以下反编译代码
/* 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
}
网上查了下,可能是apk'a作者为了保护关键部分代码不被JD-GUI反编译,故意犯了这个错误。
我想问的是
这些所谓的"Byte code"能看懂吗?我读了代码,虽然我不能完全理解代码,但我认为它仍然保留了实际的代码信息,我在代码中找到了 getMD5 函数,所以有人可以向我解释代码使用哪些参数以及如何做 MD5 (其实这是我感兴趣的部分)
谁能给我一些建议来帮助我自己理解这些代码,例如,给我一些参考网页链接来理解所谓的 "Byte Code" 语言的规范(就像c++ 或 C#), 所以下次也许我可以自己完成这项工作
谢谢!
ps:
我尝试了另一个十六进制查看器,并得到以下结果代码
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.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.");
}
首先,JD-GUI 不是一个很好的反编译器。使用其他反编译器几乎肯定会获得更好的结果。
也就是说,如果您想认真对待 Java 逆向工程,学习如何理解字节码很重要。
实际上有两种不同的字节码"languages"。第一种是Javaclass文件格式,由JVM执行。这就是当您 运行 一个 Java 桌面应用程序或小程序时得到的结果。您可以在此处找到规范:http://docs.oracle.com/javase/specs/jvms/se8/html/index.html
然而,Android根本不使用Java字节码。相反,它使用自己的系统,称为 Dex 字节码,该系统相似但略有不同。您可以在此处找到 Dex 字节码的规范:https://source.android.com/devices/tech/dalvik/dalvik-bytecode
APK 由 Dex 字节码组成。但是,您显示的清单是 Java 字节码。据推测,您可以先通过 Dex2Jar 运行 它 运行 将 Dex 文件转换为 Java 字节码,或者您使用了一个为您完成此操作的工具。 (您也可以使用 Enjarify 来执行此操作,但您发布的字节码看起来不像 Enjarify 的输出)。
无论如何,如果你想理解一个混淆的二进制文件,你最好直接去源代码并查看 Dex 字节码,而不是一个不完善的转换工具的输出。我建议查看 smali/baksmali 和 apktool,它们是我所知道的用于处理 dex 文件的最佳工具。
Update: 既然你提供了apk,我自己反编译了一下,确实没有什么不对的地方。该代码恰好有一个 try/catch 和多个 catch 块,这会混淆您使用的反编译器。
由于您的 apk 中有多个 classes 具有 loginV2 方法,我决定关注 com/ipanel/join/homed/utils/APIManager
。
使用Enjarify + Krakatau,我得到以下反编译代码。
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 有点难用,但它的优点是几乎可以处理任何事情(除了 invokedynamic,幸运的是 Android 没有)。然而,虽然它总会给你一些东西,但在某些情况下,生成的代码会不必要地复杂,这就是其中之一 - try/catch 多个 catch 块的处理非常糟糕。
幸运的是,很容易看到代码实际尝试做什么并手动清理它。这是我手动清理的上述版本,除了变量名和完全限定的 class 引用外,它可能接近原始代码。如您所见,没有故意混淆。它只是偶然使用 try/catch 反编译器遇到的问题。
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);
}
运行 尝试反编译使用 try-with-resources 和 lambda 的 Java 8 文件时出现类似问题。
尝试以下操作失败后:
- JD-GUI (http://jd.benow.ca/)
- cfr (http://www.benf.org/other/cfr/)
- jd-cmd (https://github.com/kwart/jd-cmd)
这家伙成功了:
我想反编译一个apk文件来查看它的部分源代码,但是当我到达我感兴趣的部分时,JD-GUI给出了以下反编译代码
/* 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
}
网上查了下,可能是apk'a作者为了保护关键部分代码不被JD-GUI反编译,故意犯了这个错误。
我想问的是
这些所谓的"Byte code"能看懂吗?我读了代码,虽然我不能完全理解代码,但我认为它仍然保留了实际的代码信息,我在代码中找到了 getMD5 函数,所以有人可以向我解释代码使用哪些参数以及如何做 MD5 (其实这是我感兴趣的部分)
谁能给我一些建议来帮助我自己理解这些代码,例如,给我一些参考网页链接来理解所谓的 "Byte Code" 语言的规范(就像c++ 或 C#), 所以下次也许我可以自己完成这项工作
谢谢!
ps: 我尝试了另一个十六进制查看器,并得到以下结果代码
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.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.");
}
首先,JD-GUI 不是一个很好的反编译器。使用其他反编译器几乎肯定会获得更好的结果。
也就是说,如果您想认真对待 Java 逆向工程,学习如何理解字节码很重要。
实际上有两种不同的字节码"languages"。第一种是Javaclass文件格式,由JVM执行。这就是当您 运行 一个 Java 桌面应用程序或小程序时得到的结果。您可以在此处找到规范:http://docs.oracle.com/javase/specs/jvms/se8/html/index.html
然而,Android根本不使用Java字节码。相反,它使用自己的系统,称为 Dex 字节码,该系统相似但略有不同。您可以在此处找到 Dex 字节码的规范:https://source.android.com/devices/tech/dalvik/dalvik-bytecode
APK 由 Dex 字节码组成。但是,您显示的清单是 Java 字节码。据推测,您可以先通过 Dex2Jar 运行 它 运行 将 Dex 文件转换为 Java 字节码,或者您使用了一个为您完成此操作的工具。 (您也可以使用 Enjarify 来执行此操作,但您发布的字节码看起来不像 Enjarify 的输出)。
无论如何,如果你想理解一个混淆的二进制文件,你最好直接去源代码并查看 Dex 字节码,而不是一个不完善的转换工具的输出。我建议查看 smali/baksmali 和 apktool,它们是我所知道的用于处理 dex 文件的最佳工具。
Update: 既然你提供了apk,我自己反编译了一下,确实没有什么不对的地方。该代码恰好有一个 try/catch 和多个 catch 块,这会混淆您使用的反编译器。
由于您的 apk 中有多个 classes 具有 loginV2 方法,我决定关注 com/ipanel/join/homed/utils/APIManager
。
使用Enjarify + Krakatau,我得到以下反编译代码。
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 有点难用,但它的优点是几乎可以处理任何事情(除了 invokedynamic,幸运的是 Android 没有)。然而,虽然它总会给你一些东西,但在某些情况下,生成的代码会不必要地复杂,这就是其中之一 - try/catch 多个 catch 块的处理非常糟糕。
幸运的是,很容易看到代码实际尝试做什么并手动清理它。这是我手动清理的上述版本,除了变量名和完全限定的 class 引用外,它可能接近原始代码。如您所见,没有故意混淆。它只是偶然使用 try/catch 反编译器遇到的问题。
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);
}
运行 尝试反编译使用 try-with-resources 和 lambda 的 Java 8 文件时出现类似问题。
尝试以下操作失败后:
- JD-GUI (http://jd.benow.ca/)
- cfr (http://www.benf.org/other/cfr/)
- jd-cmd (https://github.com/kwart/jd-cmd)
这家伙成功了: