Welcome back on exploitnetworking! After some months I’m returned! This week I’ve partecipate to Houseplant CTF.
This blogpost is related to a nice Android reverse engineering challenge: RTCP TRIVIA.

The challenge description was: “We now have our very own trivia app! Solve 1000 questions and win a flag!”. Ok, try to do it ūüėČ.

Decompile the apk

The first step, after download the client.apk, I was try to decompile it. I’ve used the utility apkx, that you can find in his official repository, that permit you to obtain the java code of the apk.

Copy to Clipboard

The code of the application it’s saved on client directory. Inspecting the code, it was possible to see some relevant classes inside client/wtf/riceteacatpanda/quiz directory:

  • MainActivity.java
  • LoggedIn.java
  • Game.java
  • Flag.java

In MainActivity.java class, there were some interesting lines that suggest such communication with a server using the websockets, like this line:

Copy to Clipboard

The next step, then, was run the application in an emulator or an Android device, setting up a proxy for check eventuals websocket communications.

Running and proxy

The main activity was a form login with an input text for the username and a login button:

I have tried to insert an username and press the login button and a websocket request was sent to a server, how I’ve seen in my BurpSuite proxy:

After the login there was the LoggedIn activity with only a play button:

Pressing the button, a websocket request happened with a reply by the server:

In the response, there was the first question that I had to answer correctly, but it was all encrypted, then I had to reverse the code of the apk for see how the answer was encrypted and decrypted.

Get the encryption keys

Looking at the code of the Game activity, I’ve seen that some lines are used to create a new cipher object:

Copy to Clipboard

The line with the following code: cipher = Cipher.getInstance((String)”AES/CBC/PKCS7Padding”); suggested an AES cipher, then the next step was search what key and iv was used for the encryption.
The iv was initialized with the following code: object2 = new IvParameterSpec((byte[])cipher);¬†where the cipher variable was created with cipher = nx.b(jSONObject.getString(“requestIdentifier”));, then I had to going into the nx class to see what b function does. This class was in the client/nx.java file, and the implementation of b function was:

Copy to Clipboard

Reverse this function was complex, then I’ve created a frida script for hooking at runtime the b function and see his input and outputūüėÜ:

Copy to Clipboard

Then I’ve started the frida server on my Android device:

Copy to Clipboard

and run my frida script with the following command:

Copy to Clipboard

The results was printed after that the play button was pressed. The value 435db0475dae503ff9f8f2e829bc1eff was the input of the b function and [67,93,-80,71,93,-82,80,63,-7,-8,-14,-24,41,-68,30,-1] was the output; this array was simple a byte array of the md5, and the hash was the value requestIdentifier of the websocket response how it was possible see on BurpSuite:

Copy to Clipboard

After obtaining the iv of the AES cipher, I’ve tried to get the key. Returning in the Game activity, I’ve looked to this line:

Copy to Clipboard

The second parameter was an object Key, that was the passkey of the cipher, and it was initialized in the following line in the same class:

Copy to Clipboard

Where object was created by the following snippet of code:

Copy to Clipboard

Essentially, it was the output of a function of the nx class and his input was a string construction. Below there is the code of a function:

Copy to Clipboard

It seemed to create a sha256 hash and return it’s bytes. For confirm this, I’ve added the following code to my frida script to print the input and the output:

Copy to Clipboard

Running the script I’ve obtained the following result:

Copy to Clipboard

where in the input of a function there was the following string:

Copy to Clipboard

that was a contatenation of two string: a sha256 hash and an id value. The id value was obtained from the response, in the websocket, exactly as requestIdentifier for the iv:

Copy to Clipboard

But the sha256 hash? It seemed to be computed by nx class from another implementation of a function, below reported:

Copy to Clipboard

After some investigation, I’ve found that the value returned by this method was computed from the hash that the app initially communicates to the server (inside the userToken¬†value provided in the first websocket request), in this way both, client and server, can compute the hash used for the encryption key.

Summarizing:

  • The key was a sha256 computed by a concatenation of two string: a sha256 value computed using userToken providing during the login, and the id provided by the server.
  • The iv was a value returned by the server in requestIdentifier.

After obtaining the keys used for decrypt the response, I was able to create a script to respond correctly at 1000 questionūüėÜ.

Final exploit

Copy to Clipboard

Finally, run it and:

Copy to Clipboard

If you’re interest to Android mobile pentest, I suggest you these nice books:

Recent Tweets

For privacy reasons Twitter needs your permission to be loaded.
I Accept