2

I've been reverse engineering the Yikyak application, and I came across this function

One particular function is used in order to verify the integrity of the API call. The decompiler failed to figure out what was going on with the bytecode (provided below), so I wrote in what I thought was the byte code equivalent (this is my first time working with Java bytecode, my apologies for any errors).

One of the things I was stuck on is figuring out how to determine the value referred to in the constant pool.

/* Error */
/* public static String a(String paramString, byte[] paramArrayOfByte)
* Generates a hash to verify the integrity of the API call based on the time (param1 as String) and YikYak.uniqueMD5Hash.getBytes()
*/
public static String hashApiCall(String paramString, byte[] paramArrayOfByte)
{
    // Possible values for hash algo: HmacMD5, HmacSHA1, HmacSHA256, HmacSHA384, HmacSHA512
    SecretKeySpec localSecretKeySpec = new SecretKeySpec(paramArrayOfByte, (String hash algo)ldc 179);
    Mac localMac = Mac.getInstance((String hash aglo)ldc 179);
    localMac.init(localSecretKeySpec);
    localMac.doFinal(byte[] ?);
    String str2 = Base64.encodeToString(?);
    String str3 = str2.trim();
    return str3;

    // Byte code:
    //   0: new 177 javax/crypto/spec/SecretKeySpec
    //   3: dup
    //   4: aload_1
    //   5: ldc 179
    //   7: invokespecial 182   javax/crypto/spec/SecretKeySpec:<init>  ([BLjava/lang/String;)V
    //   10: astore_2
    //   11: ldc 179
    //   13: invokestatic 188   javax/crypto/Mac:getInstance    (Ljava/lang/String;)Ljavax/crypto/Mac;
    //   16: astore 8
    //   18: aload 8
    //   20: aload_2
    //   21: invokevirtual 192  javax/crypto/Mac:init   (Ljava/security/Key;)V
    //   24: aload 8
    //   26: aload_0
    //   27: invokevirtual 136  java/lang/String:getBytes   ()[B
    //   30: invokevirtual 196  javax/crypto/Mac:doFinal    ([B)[B
    //   33: iconst_0
    //   34: invokestatic 202   android/util/Base64:encodeToString  ([BI)Ljava/lang/String;
    //   37: astore 9
    //   39: aload 9
    //   41: invokevirtual 205  java/lang/String:trim   ()Ljava/lang/String;
    //   44: astore 12
    //   46: aload 12
    //   48: astore 4
    //   50: aload 4
    //   52: areturn
    //   53: astore 6
    //   55: aconst_null
    //   56: astore 4
    //   58: aload 6
    //   60: astore 7
    //   62: aload 7
    //   64: invokevirtual 208  java/security/NoSuchAlgorithmException:printStackTrace  ()V
    //   67: goto -17 -> 50
    //   70: astore_3
    //   71: aconst_null
    //   72: astore 4
    //   74: aload_3
    //   75: astore 5
    //   77: aload 5
    //   79: invokevirtual 209  java/security/InvalidKeyException:printStackTrace   ()V
    //   82: goto -32 -> 50
    //   85: astore 11
    //   87: aload 9
    //   89: astore 4
    //   91: aload 11
    //   93: astore 5
    //   95: goto -18 -> 77
    //   98: astore 10
    //   100: aload 9
    //   102: astore 4
    //   104: aload 10
    //   106: astore 7
    //   108: goto -46 -> 62
    // Local variable table:
    //   start  length  slot    name    signature
    //   0  111 0   paramString String
    //   0  111 1   paramArrayOfByte    byte[]
    //   10 11  2   localSecretKeySpec  javax.crypto.spec.SecretKeySpec
    //   70 5   3   localInvalidKeyException1   java.security.InvalidKeyException
    //   48 55  4   str1    String
    //   75 19  5   localObject1    Object
    //   53 6   6   localNoSuchAlgorithmException1  java.security.NoSuchAlgorithmException
    //   60 47  7   localObject2    Object
    //   16 9   8   localMac    javax.crypto.Mac
    //   37 64  9   str2    String
    //   98 7   10  localNoSuchAlgorithmException2  java.security.NoSuchAlgorithmException
    //   85 7   11  localInvalidKeyException2   java.security.InvalidKeyException
    //   44 3   12  str3    String
    // Exception table:
    //   from   to  target  type
    //   11 39  53  java/security/NoSuchAlgorithmException
    //   11 39  70  java/security/InvalidKeyException
    //   39 46  85  java/security/InvalidKeyException
    //   39 46  98  java/security/NoSuchAlgorithmException
}

Is there a way to determine what values are in the constant pool (specifically, 179) in order to determine the hashing algorithm that's being used?

Thanks in advance!

1

First off, have you tried using a better decompiler? I'd recommend Krakatau, since it's specifically designed for handling obfuscated applications (disclosure: I wrote it). Apart from Krakatau, the best decompiler I know of is Procyon.

Second, you can see the constant pool by passing the right option to the disassembler. If you're using the Krakatau disassembler, you'd just pass -cpool. You can also use javap in which case you'd pass -v. However, javap is not designed for reverse engineering and has numerous issues, so you're better off with Krakatau for serious disassembly.

  • I suppose I can chain this with dex2jar in order to get the source code – dreadiscool Apr 11 '15 at 20:25
  • Based on the Github description, I thought that Krakatau was able to decompile bytecode without needing all of the referenced libraries? I can't decompile things due to the classloader not finding things like java.lang.Object, and when I do run it with all errors disabled, all I get are the function names (with no content in them). Is there something I've done wrong? – dreadiscool Apr 12 '15 at 0:05
  • @user It needs to know the referenced classes for stuff like determining which classes are interfaces and what is a subclass of what. You need to pass a path to the library on the commandline with the -path option. The core classes are in rt.jar which comes with Java. For an Android application, you'll typically need android.jar too. You may need others depending on what the application uses. – Antimony Apr 12 '15 at 0:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.