Bugdroid Fight [2/2]

404CTF{4v4D0_K1dAvR0!}

Catégorie: Reverse Difficulté: medium Flag: -

Challenge

Description


Vous venez de consulter le message du Bugdroid...

Dans son message, il explique que le combat ne peut être gagné à la seule force des poings... À moins que vous ne soyez aidé d'une force divine : une formule magique se cache ici, elle vous permettra de gagner le duel.

Format de flag : 404CTF{formule_magique}

Décompilation

On a un fichier .aab. Après quelques recherches, il est possible de générer un apk depuis celui-ci.

bundletool build-apks --bundle=Bugdroid_Fight_-_Part_2.aab --output=Bugdroid_Fight_-_Part_2.apks

Une fois l'archive créée, à l'intérieur se trouve universal.apk, il faut alors la décompiler avec apktool (ou autre).

apktool d universal.apk

Résolution

On commence par une recherche globale dans les fichiers avec le mot "Bugdroid" (c'est le nom du challenge). Bingo, on trouve app_name :

Searching 4652 files for "bugdroid" (whole word)

Bugdroid 2/resources.pb:
    <binary>

Bugdroid 2/apk/resources/res/values/strings.xml:
   32      <string name="alphabet">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890àé_{}</string>
   33      <string name="androidx_startup">androidx.startup</string>
   34:     <string name="app_name">Bugdroid : 2e Combat</string>
   35      <string name="appbar_scrolling_view_behavior">com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior</string>
   36      <string name="bottom_sheet_behavior">com.google.android.material.bottomsheet.BottomSheetBehavior</string>

2 matches across 2 files

En se rendant dans strings.xml, on observe une valeur un peu bizarre nommée action_header

<string name="action_header">!NFt8g7f_NOLtL</string>
<string name="action_settings">Settings</string>
<string name="alphabet">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890àé_{}</string>
<string name="androidx_startup">androidx.startup</string>
<string name="app_name">Bugdroid : 2e Combat</string>

Maintenant, on peut relancer une recherche avec action_header :

Searching 4652 files for "action_header" (whole word)

...

Bugdroid 2/apk/sources/r0/C0428a.java:
   43                  Context i4 = homeFragment.i();
   44                  String valueOf = String.valueOf(textInputEditText.getText());
   45:                 String string = homeFragment.G().getResources().getString(R.string.action_header);
   46                  c.n("getString(...)", string);
   47                  HashMap hashMap = new HashMap();

5 matches across 5 files

Le fichier r0/C0428a.java semble intéressant puisqu'à l'intérieur, on trouve une comparaison entre deux strings qui affiche Correct ou Incorrect. Surement la vérification du mot de passe.

Les valeurs utilisées dans alphabet, action_header et edit se trouvent dans strings.xml

Si l'on regarde les lignes au-dessus (j'ai supprimé les lignes inutiles et commenté) :

HomeFragment homeFragment = (HomeFragment) obj2;
TextInputEditText textInputEditText = (TextInputEditText) obj;
int i3 = HomeFragment.f2487W;
c.o("this$0", homeFragment);
c.o("$textInput", textInputEditText);
Context i4 = homeFragment.i();

// notre input de mot de passe
String password = String.valueOf(textInputEditText.getText());

// map de conversion de caractères
HashMap hashMap = new HashMap();

// !NFt8g7f_NOLtL
String action_header = homeFragment.G().getResources().getString(R.string.action_header);

// ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890àé_{}
String alphabet = homeFragment.G().getResources().getString(R.string.alphabet);

// 8qROIjDcr1fdXUSAkFH5hà9QToé3xg6eKnVlmu2zpCb4GJEtiwWy70vLPsYBaNZM_{}
String edit = homeFragment.G().getResources().getString(R.string.edit);

int i = 0;
while (i < alphabet.length() && i < edit.length()) {
    // Associe à chaque caractère de alphabet, le caractère à la même position dans edit
    hashMap.put(Character.valueOf(alphabet.charAt(i)), Character.valueOf(edit.charAt(i)));
    i++;
}

StringBuilder encrypted = new StringBuilder();
// En commençant par la fin du mot de passe, le transforme selon la map de conversion
for (int length = password.length() - 1; -1 < length; length--) {
    char charAt = password.charAt(length);
    // Ajoute le caractère converti à encrypted
    encrypted.append(((Character) hashMap.getOrDefault(Character.valueOf(charAt), Character.valueOf(charAt))).charValue());
}

if (c.f(encrypted.toString(), action_header)) message = "Correct!";
else message = "Incorrect!";
Toast.makeText(i4, message, 0).show();

Il suffit donc d'inverser le chiffrement depuis le résultat attendu.

alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890àé_{}'
edit = '8qROIjDcr1fdXUSAkFH5hà9QToé3xg6eKnVlmu2zpCb4GJEtiwWy70vLPsYBaNZM_{}'
action_header = '!NFt8g7f_NOLtL'

password = ''
for c in action_header[::-1]:
  if c in edit:
    password += alphabet[edit.index(c)]
  else:
    password += c

print('404CTF{' + password + '}')

Mis à jour

Ce contenu vous a-t-il été utile ?