Flagdroid
- 147 solves
- 153 points
- Easy
- Category: Reverse
- Author: m0ney
- Text: “This app won’t let me in without a secret message. Can you do me a favor and find out what it is?”
- Download file: an APK
Analysis of the app
We decompile the application. The validation of the flag is done when you press the button check:
1
2
3
4
5
6
7
8
9
10
11
12
13
| public void onClick(View arg10) {
TextView tvWrong = (TextView)MainActivity.this.findViewById(0x7F0700EC); // id:textViewWrong
TextView tvCorrect = (TextView)MainActivity.this.findViewById(0x7F0700EB); // id:textViewCorrect
String secretInput = ((EditText)MainActivity.this.findViewById(0x7F0700C4)).getText().toString(); // id:secretInput
Matcher match = Pattern.compile("flag\\{(.*)\\}").matcher(secretInput);
if(match.find()) {
String[] flagcore = match.group().replace("flag{", "").replace("}", "").split("_");
if(flagcore.length == 4 && ((MainActivity.this.checkSplit1(flagcore[0])) && (MainActivity.this.checkSplit2(flagcore[1])) && (MainActivity.this.checkSplit3(flagcore[2])) && (MainActivity.this.checkSplit4(flagcore[3])))) {
tvWrong.setVisibility(4);
tvCorrect.setVisibility(0);
return;
}
}
|
The flag is surrounded by flag{...} and each part is separated by a _. There are 4 different parts. Each part is validated by a method checkSplitX() where X is the number of the split.
First part
It is a base64 string dEg0VA==: tH4T
Second part
The second part is created from an algorithm that:
- checks the length is 9
- performs a translation on the character
- XORs the result with a fixed key
hack.lu20
To do the decode, we must do it the other way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| public static String createSplit2() {
try {
String s = new String("\u001fTT:\u001f5\u00f1HG");
char[] v8 = s.toCharArray();
byte[] key = "hack.lu20".getBytes("UTF-8");
int v3;
for(v3 = 0; v3 < 9; ++v3) {
v8[v3] = (char)(v8[v3] ^ key[v3]);
v8[v3] = (char)(v8[v3] - v3);
}
System.out.println("Result: "+ String.valueOf(v8));
return new String(v8);
}
catch(UnsupportedEncodingException unused_ex) {
System.out.println("Exception");
}
return null;
}
|
The main difficulty is to copy paste the Unicode string correctly…
Result: w45N-T~so
Third part
We know the part consists of 8 characters. The first four are h4rd, possibly with a different case.
The last 4 characters are not given, but we know the MD5 of the string must be 6d90ca30c5de200fe9f671abb2dd704e.
We search for the string on MD5 reverse but it is not known
So, we brute force it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| import hashlib
prefix = 'h4rd'
for a in ['h', 'H']:
for b in ['r', 'R']:
for c in ['d', 'D']:
for i in range(ord('-'), ord('~')+1):
for j in range(ord('-'), ord('~')+1):
for k in range(ord('-'), ord('~')+1):
for l in range(ord('-'), ord('~')+1):
s = a + '4' + b + c + chr(i) + chr(j) + chr(k) + chr(l)
print("Testing: {0}".format(s))
value = hashlib.md5(bytes(s,'utf-8')).hexdigest()
if value == "6d90ca30c5de200fe9f671abb2dd704e":
print("FOUND: {0}".format(s))
quit()
|
Result:
1
2
3
4
5
| Testing: h4rd~hue
Testing: h4rd~huf
Testing: h4rd~hug
Testing: h4rd~huh
FOUND: h4rd~huh
|
Fourth part
The last part of the flag is given by a native function stringFromJNI.
We write a Frida hook for that:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| 'use strict';
console.log("[*] INSIDE native-lib.js");
global.run = function () {
console.log("[debug] global.run: Java.available="+Java.available);
Java.perform(function () {
var mainClass = Java.use("lu.hack.Flagdroid.MainActivity");
mainClass.stringFromJNI.implementation = function() {
console.log("[*] Hooking");
var ret = this.stringFromJNI();
console.log("ret="+ret);
return ret;
}
mainClass.checkSplit1.implementation = function(b) {
var ret = this.stringFromJNI();
console.log("ret="+ret);
return this.checkSplit1(b);
}
console.log("[*] loaded hooks - v4");
});
};
|
Then, we launch the Frida server on the smartphone, launch the app, and on the laptop, launch Frida client: frida -U -l native-lib.js -n lu.hack.Flagdroid
1
2
| [*] Hooking
ret=0r~w4S-1t?8)
|
Final solution
flag{tH4T_w45N-T~so_h4rd~huh_0r~w4S-1t?8)}