Published on

Android CTF Juicy Bar::Obfuscated Secrets

Authors
  • avatar
    Name
    Ajin Deepak
    Twitter

Hey all,

Let's continue with our Juicy Bar series. If you're new here, feel free to check out our other write-ups. However, I suggest that you try to solve it on your own before proceeding.

https://juicy.barsk.xyz

Challenge

We will continue with solving the challenges in the dynamic analysis section. Today we will solve the obfuscated secrets challenge. We only have to find one flag in this challenge. Let's see the hints.

Let's use jadx and see the decompiled code.

If we take a look at the code it's highly obfuscated.

        byte[] decode = Base64.decode(da.n.u0(3, "eyJbG9vayBhdCB0aGUgaXYgYW5kIHRoZSBrZXkgaW5zdGVhZA=="), 0);
        SecretKeySpec secretKeySpec = new SecretKeySpec(bArr, "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(bArr2);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(1, secretKeySpec, ivParameterSpec);
        Base64.encodeToString(cipher.doFinal(decode), 10);

The code is encrypting some data as we see the option in the app.

It's the standard code for AES encryption but the only thing is the Key and the IV is obfuscated.

byte[] decode = Base64.decode(da.n.u0(3, "eyJbG9vayBhdCB0aGUgaXYgYW5kIHRoZSBrZXkgaW5zdGVhZA=="), 0);

The function da.n.u0(3, "...") appears to be a custom or application-specific function that manipulates data before decoding it. It looks like a base64 string, but it's not, and this is not the plain text . The decoded result is stored in the byte array decode, which contains the string for encryption. Let's use frida and get this.

Java.perform(function () {
  var Base64 = Java.use('android.util.Base64');
  Base64.decode.overload('java.lang.String', 'int').implementation = function (base64String, flags) {
    console.log('Base64 String:', base64String);
    var decodedBytes = this.decode(base64String, flags);
    var decodedString = Java.use("java.lang.String").$new(decodedBytes);
    console.log('Decoded String:', decodedString);
    return decodedBytes;
  };
});

We got the decoded string. It says look at the iv and the key instead. Hmm interesting.

Okay let's get the the IV and Key.

To get the Key and IV, we can write a frida script to hook the corresponding methods and obtain them.

SecretKeySpec secretKeySpec = new SecretKeySpec(bArr, "AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(bArr2);

Let's do it. For this, we can just ask chatgpt to hook these.

Java.perform(function () {
  var SecretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec');
  var IvParameterSpec = Java.use('javax.crypto.spec.IvParameterSpec');

  // Hook the SecretKeySpec constructor
  SecretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function (keyBytes, algorithm) {
    console.log('AES Key:', bytesToHex(keyBytes));
    return this.$init(keyBytes, algorithm);
  };

  // Hook the IvParameterSpec constructor
  IvParameterSpec.$init.overload('[B').implementation = function (ivBytes) {
    console.log('AES IV:', bytesToHex(ivBytes));
    return this.$init(ivBytes);
  };

  // Helper function to convert byte arrays to hex strings
  function bytesToHex(bytes) {
    var result = [];
    for (var i = 0; i < bytes.length; i++) {
      result.push(('0' + (bytes[i] & 0xFF).toString(16)).slice(-2));
    }
    return result.join('');
  }
})

You may need some tweaking but it will work. Let's try it.

Okay now we have both the Key and the IV.

  • AES Key: 4a554943597b61323333373461336433
  • AES IV: 6634366564337d203c2d2d7e7e3d3d23d.

Based on our hint, we should examine the IV and the key more closely since this is hex. Let's see if we can get anything from it. I'm going to use cyberhhef for this.

Woah we got the first half of our flag from the key. Let's decode the IV too.

Nice we got the full flag :) I hope you enjoyed this one.