Décompiler en Java
Vous pouvez utiliser JADX pour obtenir le code java de l’application. Voici un exemple de commande :
$ /home/al/Téléchargements/jadx-1.5.2/bin/jadx -r -d /home/al/Téléchargements/jakarta.apk-decompiled2 /home/al/Téléchargements/jakarta.apk
Trouver la méthode de vérification pour en déduire le flag
Sur une application Android basique, il suffit généralement de chercher dans l’arborescence des fichiers correspondant au packageName
, pour facilement trouver les classes importantes.
La classe suivante semble être un bon candidat pour contenir la méthode de vérification : com/fcsc2021/jakarta/Check.java
.
Check.java
Il est possible de voir que le constructeur de la classe Check
prend la valeur saisie par l’utilisateur et que la méthode valid()
effectue des opérations avant de la comparer avec le tableau enc
.
Java
public class Check {
int[] enc = {11, 152, 177, 51, 145, 152, 153, 185, 26, 156, 177, 19, 177, 50, 156, 26, 156, 35, 176, 159, 185, 185, 185, 26, 19, 152, 177, 50, 144, 144, 176, 177, 26, 184, 190, 50, 11, 26, 51, 26, 26, 156, 19, 58, 148, 19, 176, 51, 26, 177, 58, 58, 144, 139, 152, 50, 185, 153, 177, 153, 144, 26, 176, 144, 50, 156, 145, 153, 156, 156};
String flag;
public Check(String _flag) {
this.flag = _flag;
}
public boolean valid() {
int len = this.flag.length();
if (len != this.enc.length) {
return false;
}
int[] A = new int[len];
for (int i = 0; i < len; i++) {
int idx = ((i * 37) + 1) % len;
int ch = this.flag.charAt(idx);
for (int j = 7; j >= 0; j--) {
int idxx = ((j * 5) + 3) % 8;
int b = ((ch >> j) & 1) << idxx;
A[i] = A[i] ^ b;
}
}
int res = 0;
for (int i2 = 0; i2 < len; i2++) {
res |= A[i2] ^ this.enc[i2];
}
return res == 0;
}
}
Inverser l’opération
Une fois la liste des opérations obtenue, on peut créer une méthode inversant l’opération puis l’appliquer sur les éléments du tableau enc
.
public class Main {
// enc est issu de la décompilation avec apkTool à partir de Check.smali
// La méthode valid() est plus facile à lire après conversion en Java avec jadx.
static int[] enc = {11, 152, 177, 51, 145, 152, 153, 185, 26, 156, 177, 19, 177, 50, 156, 26, 156, 35, 176, 159, 185, 185, 185, 26, 19, 152, 177, 50, 144, 144, 176, 177, 26, 184, 190, 50, 11, 26, 51, 26, 26, 156, 19, 58, 148, 19, 176, 51, 26, 177, 58, 58, 144, 139, 152, 50, 185, 153, 177, 153, 144, 26, 176, 144, 50, 156, 145, 153, 156, 156};
public static void main(String[] args) {
String flag = decode();
System.out.println(flag);
}
public static String decode() {
int len = enc.length;
char[] flag_chars = new char[len];
int[] idxx_to_j = new int[8];
for (int j = 0; j < 8; j++) {
int idxx = ((j * 5) + 3) % 8;
idxx_to_j[idxx] = j;
}
char[] intermediate_chars = new char[len];
for (int i = 0; i < len; i++) {
int decoded_ch_val = getDecodedChVal(idxx_to_j, enc[i]);
intermediate_chars[i] = (char) decoded_ch_val;
}
for (int i = 0; i < len; i++) {
int idx = ((i * 37) + 1) % len;
flag_chars[idx] = intermediate_chars[i];
}
return new String(flag_chars);
}
private static int getDecodedChVal(int[] idxx_to_j, int enc_val) {
int decoded_ch_val = 0;
for (int bit_pos_in_enc = 0; bit_pos_in_enc < 8; bit_pos_in_enc++) {
int bit = (enc_val >> bit_pos_in_enc) & 1;
int original_j_pos = idxx_to_j[bit_pos_in_enc];
decoded_ch_val |= (bit << original_j_pos);
}
return decoded_ch_val;
}
}
Résultat
En exécutant le programme on obtient :
FCSC{6df723aa33b1aa8.......694b0bdf4d26aa9e}