Prelude
When you visit this challenge it tells you it is generating an APK file and to refresh in order to download it. Each instance of this challenge generates a different APK, and I guessed that either a secret is compiled in, or at least the configuration of what host to communicate with. So, using apktool
to decompile the resources and Java bytecode, I wasn't sure what I should look for.
Flag 0
I decided to inspect for network traffic using mitmproxy
and setting my Android device to go through my Kali Linux box as a proxy. This quickly revealed the first flag as a header on a normal HTTP REST API call. The instance of the challenge had even reset (shown by the fact that the response was a 404) but the flag is in the outbound request so it didn't matter.
Flag 1
After starting a new instance of the challenge I decided to look at the request some more on a successful connection. No surprises here, the body of the request contains some base64 encoded data indicating the temperature to set the "thermostat" to. There is a header, 'X-MAC' that must be some kind of Message Authentication Code, but how is it computed? I substituted some values via the proxy, but the server just happily returned 500 for bogus formatting, or 200 for well-formed but ridiculous temperatures.Request:
eyJjbWQiOiJzZXRUZW1wIiwidGVtcCI6Nzd9
{"cmd":"setTemp","temp":77}
Response:
eyJzdWNjZXNzIjogdHJ1ZX0=
{"success": true}
Modified Request:
{"cmd":"setTemp","temp":1000}
eyJjbWQiOiJzZXRUZW1wIiwidGVtcCI6MTAwMH0=
Back to the disassembled APK. Aha! Looking through the bytecode for making a request (PayloadRequest.smali
), we stumble upon some key phrases like "MD5" and "MessageDigest" but most importantly, "FLAG".
const-string p2, "MD5"
.line 43
invoke-static {p2}, Ljava/security/MessageDigest;->getInstance(Ljava/lang/String;)Ljava/security/MessageDigest;
move-result-object p2
const-string v0, "^FLAG^c8634e21d6a4b2b3763ed0250774e43c7054fe496062d5233ea4d0b37e95f19e$FLAG$"
.line 44
invoke-virtual {v0}, Ljava/lang/String;->getBytes()[B
move-result-object v0
invoke-virtual {p2, v0}, Ljava/security/MessageDigest;->update([B)V
.line 45
invoke-virtual {p1}, Ljava/lang/String;->getBytes()[B
move-result-object p1
invoke-virtual {p2, p1}, Ljava/security/MessageDigest;->update([B)V
.line 46
invoke-virtual {p2}, Ljava/security/MessageDigest;->digest()[B
move-result-object p1
const/4 p2, 0x0
invoke-static {p1, p2}, Landroid/util/Base64;->encodeToString([BI)Ljava/lang/String;
move-result-object p1
.line 47
iget-object p2, p0, Lcom/hacker101/level11/PayloadRequest;->mHeaders:Ljava/util/HashMap;
All Flags Captured!