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}