PoliCTF 2015 Android Reversing Writeup

Decoding and Decompiling the APK
- apktool d crack-me-if-you-can.apk
- d2j-dex2jar -o crack-me-if-you-can.jar crack-me-if-you-can.apk
- java -jar procyon-decompiler.jar -jar crack-me-if-you-can.jar -o src
Finding the Flag
Two common starting points are the AndroidManifest.xml and strings.xml files decoded from Apktool.
The AndroidManifest.xml file tells us that the main activity class for this application is LoginActivity from the it.polictf2015 package.

As shown below, strings.xml shows some interesting strings, particularly àè and àò which might be obfuscated flags. The next step would be to find their usages, starting from it.polictf2015.LoginActivity.

The excerpt below is from LoginActivity.java. Activities refer to strings using the getString() method and a resource ID parameter.
private boolean a(String paramString)
{
if (paramString.equals(c.a(b.a(b.b(b.c(b.d(b.g(b.h(b.e(b.f(b.i(c.c(c.b(c.d(getString(2131492920))))))))))))))))
{
Toast.makeText(getApplicationContext(), getString(2131492924), 1).show();
return true;
}
return false;
}
The public.xml file below maps the resource IDs of strings to their names. The respective decimal resource IDs for the àè and àò strings are 2131492920 and 2131492921. One usage was found for àè in the code excerpt above. No usages were found for àò which indicates that it might have been a decoy.

Below are the methods for it.polictf2015.b and it.polictf2015.c which are applied in the code excerpt above to the value of the àè string.
package it.polictf2015;
public class b
{
public static String a(String paramString)
{
return paramString.replace("c", "a");
}
public static String b(String paramString)
{
return paramString.replace("%", "");
}
public static String c(String paramString)
{
return paramString.replace("[", "");
}
public static String d(String paramString)
{
return paramString.replace("]", "");
}
public static String e(String paramString)
{
return paramString.replaceFirst("\\{", "");
}
public static String f(String paramString)
{
return paramString.replaceFirst("\\}", "");
}
public static String g(String paramString)
{
return paramString.replaceFirst("c", "f");
}
public static String h(String paramString)
{
return paramString.replaceFirst("R", "f");
}
public static String i(String paramString)
{
return paramString.replace("=", "_");
}
}
package it.polictf2015;
public class c
{
public static String a(String paramString)
{
return paramString.replace("aa", "ca");
}
public static String b(String paramString)
{
return paramString.replace("aat", "his");
}
public static String c(String paramString)
{
return paramString.replace("buga", "Goo");
}
public static String d(String paramString)
{
return paramString.replace("spdgj", "yb%e");
}
}
A Python script was made to combine the methods from those classes in the manner they are applied to the value of the àè string.
str_2131492920 = r"[[c%l][c{g}[%{%Mc%spdgj=]T%aat%=O%bRu%sc]c%ti[o%n=Wcs%=No[t=T][hct%=buga[d=As%=W]e=T%ho[u%[%g]h%t[%}%"
flag = str_2131492920.replace('spdgj', r'yb%e') \
.replace('aat', 'his') \
.replace('buga', 'Goo') \
.replace('=', '_') \
.replace('}', '', 1) \
.replace('{', '', 1) \
.replace('R', 'f', 1) \
.replace('c', 'f', 1) \
.replace(']', '') \
.replace('[', '') \
.replace('%', '') \
.replace('c', 'a') \
.replace('aa', 'ca')
print flag
Executing it outputs the decoded flag:
flag{Maybe_This_Obfuscation_Was_Not_That_Good_As_We_Thought}
