⚡ Stray Voltage

Pinned (HTB)

Write-ups exist for this lab in abundance but I had some specific problems with this one and wanted to document the work-arounds.

The lab is called Pinned and is available in HTB's mobile exploitation track.

Lab Setup

I initially set up an android 10, API 29 emulator like the readme recommended. When I did this I encountered this issue, and since no resolution exists there I set my lab up using API 30 instead.

I then followed these steps to install the burp certificate on the emulator.

APK Installation

The move from API 29 -> 30 meant the APK was no longer compatible.

image

I found this repo, I needed to fix the zipaling and apksigner paths as the android sdk tools aren't in my PATH but having run the script and fixed the errors I was able to install the application.

Vulnerability

When running the app, credentials are saved in the username and password field. Clicking login shows that the log in was successful however nothing happens and no traffic is logged in Burp Suite.

image

As the lab is called "Pinned", we can safely assume our goal is to bypass certificate pinning and retrieve the credentials.

Exploitation

This should be trivial to achieve with Objection:

objection --name Pinned start

android sslpinning disable

This time, when we press login, there is traffic in Burp Suite.

POST /pinned.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Accept: application/x-www-form-urlencoded
charset: utf-8
User-Agent: Dalvik/2.1.0 (Linux; U; Android 11; Android SDK built for arm64 Build/RSR1.210722.013.A4)
Host: pinned.com
Connection: keep-alive
Accept-Encoding: gzip, deflate, br
Content-Length: 52

uname=bnavarro&pass=HTB{trust_n0_1_n0t_3v3n_@_c3rt!}

Exploitation using Frida

Reviewing the APK in jadx-gui, we find a function x() in the MainActivity:

public void x() {
        HttpsURLConnection httpsURLConnection;
        TextView textView;
        String str;
        MainActivity mainActivity = this;
        HttpsURLConnection httpsURLConnection2 = (HttpsURLConnection) new URL("https://pinned.com:443/pinned.php").openConnection();
        httpsURLConnection2.setRequestMethod("POST");
        httpsURLConnection2.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        httpsURLConnection2.setRequestProperty("Accept", "application/x-www-form-urlencoded");
        httpsURLConnection2.setRequestProperty("charset", "utf-8");
        httpsURLConnection2.setDoOutput(true);
        httpsURLConnection2.setSSLSocketFactory(mainActivity.q.getSocketFactory());
        if (mainActivity.s.getText().toString().equals("bnavarro") && mainActivity.t.getText().toString().equals("1234567890987654")) {
            StringBuilder g = c.a.a.a.a.g("uname=bnavarro&pass=");
            StringBuilder sb = new StringBuilder();
            sb.append(d.a());
            sb.append(c.b.a.b.a());
            sb.append(h.a());
            sb.append(c.a());
            sb.append(i.a());
            ArrayList arrayList = new ArrayList();
            arrayList.add("9GDFt6");
            arrayList.add("83h736");
            arrayList.add("kdiJ78");
            arrayList.add("vcbGT6");
            arrayList.add("LPGt63");
            arrayList.add("kFgde4");
            arrayList.add("5drDr4");
            arrayList.add("Y6ttr5");
            arrayList.add("444w45");
            arrayList.add("hjKd56");
            sb.append((String) arrayList.get(4));
            sb.append(e.a());
            sb.append(f.a());
            ArrayList arrayList2 = new ArrayList();
            arrayList2.add("TG7ygj");
            arrayList2.add("U8uu8i");
            arrayList2.add("gGtT56");
            arrayList2.add("84hYDG");
            arrayList2.add("yRCYDm");
            arrayList2.add("7ytr4E");
            arrayList2.add("j5jU87");
            arrayList2.add("yRCYDm");
            arrayList2.add("jd9Idu");
            arrayList2.add("kd546G");
            sb.append((String) arrayList2.get(7));
            sb.append(c.b.a.a.a());
            String sb2 = sb.toString();
            char charAt = b.q.h.b().charAt(3);
            char charAt2 = b.q.h.b().charAt(0);
            char charAt3 = c.a().charAt(0);
            char charAt4 = c.b.a.a.a().charAt(8);
            char charAt5 = h.a().charAt(1);
            char charAt6 = b.q.h.b().charAt(0);
            char charAt7 = i.a().charAt(5);
            char charAt8 = c.b.a.a.a().charAt(7);
            char charAt9 = c.b.a.b.a().charAt(4);
            httpsURLConnection = httpsURLConnection2;
            char charAt10 = e.a().charAt(4);
            char charAt11 = e.a().charAt(4);
            char charAt12 = i.a().charAt(5);
            char charAt13 = d.a().charAt(3);
            char charAt14 = d.a().charAt(5);
            char charAt15 = h.a().charAt(1);
            char charAt16 = h.a().charAt(1);
            SecretKeySpec secretKeySpec = new SecretKeySpec((String.valueOf(charAt) + String.valueOf(charAt2) + String.valueOf(charAt3) + String.valueOf(charAt4).toUpperCase() + String.valueOf(charAt5) + String.valueOf(charAt6) + String.valueOf(charAt7).toUpperCase() + String.valueOf(charAt8) + String.valueOf(charAt9) + String.valueOf(charAt10) + String.valueOf(charAt11) + String.valueOf(charAt12).toUpperCase() + String.valueOf(charAt13) + String.valueOf(charAt14) + String.valueOf(charAt15) + String.valueOf(charAt16)).getBytes(), g.a());
            Cipher cipher = Cipher.getInstance(g.a());
            cipher.init(2, secretKeySpec);
            g.append(new String(cipher.doFinal(Base64.decode(sb2, 0)), "utf-8"));
            mainActivity = this;
            mainActivity.o = g.toString();
            textView = mainActivity.r;
            str = "You are logged in.";
        } else {
            httpsURLConnection = httpsURLConnection2;
            StringBuilder g2 = c.a.a.a.a.g("uname=");
            g2.append(mainActivity.s.getText().toString());
            g2.append("&pass=");
            g2.append(mainActivity.t.getText().toString());
            mainActivity.o = g2.toString();
            textView = mainActivity.r;
            str = "Wrong credentials!";
        }
        textView.setText(str);
        DataOutputStream dataOutputStream = new DataOutputStream(httpsURLConnection.getOutputStream());
        try {
            dataOutputStream.writeBytes(mainActivity.o);
            dataOutputStream.flush();
            dataOutputStream.close();
            new Thread(new b(httpsURLConnection)).start();
        } finally {
    }
}

We can use frida to hook the methods of the Cipher class.

Java.perform(function () {
    var cipher = Java.use("javax.crypto.Cipher");

    cipher.doFinal.implementation = function (data) {
        var result = this.doFinal(data);
        console.log("Decrypted: " + Java.use("java.lang.String").$new(result));
        return result;
    };
});

This produces the following error:

Error: doFinal(): has more than one overload, use .overload(<signature>) to choose from:
	.overload()
	.overload('[B')
	.overload('java.nio.ByteBuffer', 'java.nio.ByteBuffer')
	.overload('[B', 'int')
	.overload('[B', 'int', 'int')
        .overload('[B', 'int', 'int', '[B')
	.overload('[B', 'int', 'int', '[B', 'int')

Looking at the Java code above, we can see doFinal is taking one argument, so the overload must be .overload('[B', 'int').

Let's amend the frida script:

Java.perform(function () {
    var cipher = Java.use("javax.crypto.Cipher");

    cipher.doFinal.overload('[B').implementation = function (data) {
        var result = this.doFinal(data);
        console.log("Decrypted: " + Java.use("java.lang.String").$new(result));
        return result;
    };
});
% frida -U -f com.example.pinned -l pinned-2.js 
     ____
    / _  |   Frida 17.8.0 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to Android Emulator 5554 (id=emulator-5554)
Spawned `com.example.pinned`. Resuming main thread!                     
[Android Emulator 5554::com.example.pinned ]-> Decrypted: HTB{trust_n0_1_n0t_3v3n_@_c3rt!}