Rating: 5.0

Opened the APK with JEB, and then we see one activity (`LoginActivity`) mentioned in the manifest.
In the resources we have 2 raw files called `qa.p12` and `prod.p12`.

The login activity contains two inputs and a button that has an onClick- sends those input values along with some other data to a function. It then toasts the result of that function.


The function opens a connection to `https://certifiedapp.ctf.bsidestlv.com:8003/authenticate` and sends a POST request.
The connection is encrypted using one of the keys provided in the resources (`prod.p12`) which was sent as argument to the function (the resource ID, `0x7F0C0000`).


The username and password are sent as HTTP's basic authorization header by combining them to `username:password` string and encoding with Base64.


The function then returns the response it receives (By trying to login inside the app we see that the failure response is `Login Failed`).

At first we thought that this was a timing attack scenario. We tried this using Frida, but it didn't get us anything.
Then we saw the `TestActivity` which isn't included in the manifest but provided everything we needed.

The `TestActivity` activity calls the same function that `LoginActivity` calls, but with different arguments.

The key provided is the resource Id of `qa.p12` (`0x7F0C0001`) instead of `prod.p12`.

The username sent is `token`.

The password is base64, of the sha256 of the app's signature (which is also an opaque object that you can't really guess or calculate):


We used Frida to obtain the app's signature:


We calculated it's sha256 and encoded it with Base64, and then we could use Frida to hook the function and execute it with different arguments when submitting:

Java.perform(function() {

const loginclass = Java.use("a.b.k.o");

loginclass.a.overload('android.content.Context', 'int', 'java.lang.String', 'java.lang.String', 'boolean').implementation = function(ctxt, integ, username, password, someBool) {
const rawFunctionCall = this.a(ctxt, 0x7F0C0001, "token", "p9/BXgbp6d1vRtHIcCbi6Vm6faNALQIhYzQ6jXCpUvk=", false);
const output = rawFunctionCall;
return output;