PoliCTF 2015 Android Reversing Writeup

Et7r46P

Decoding and Decompiling the APK

  1. apktool d crack-me-if-you-can.apk
  2. d2j-dex2jar -o crack-me-if-you-can.jar crack-me-if-you-can.apk
  3. 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.

vJtbheZ

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.

M7YBig5

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.

yIvx9DS

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}

qubnOWo