n00bzCTF 2023 - EZrev
Énoncé
Dans ce challenge, on nous a donné une classe Java téléchargeable ici,
Pour reverse engineer une classe Java, nous aurons besoin d’un decompilateur Java, j’ai décidé d’utiliser jadx-gui
.
Analyse du code initial
En analysant le code source, nous avons la fonction main()
qui contient le code suivant:
package defpackage;
import java.util.Arrays;
/* renamed from: EZrev reason: default package */
/* loaded from: EZrev.class */
public class EZrev {
public static void main(String[] strArr) {
if (strArr.length != 1) {
System.out.println("L");
return;
}
String str = strArr[0];
if (str.length() != 31) {
System.out.println("L");
return;
}
int[] array = str.chars().toArray();
for (int i = 0; i < array.length; i++) {
if (i % 2 == 0) {
array[i] = (char) (array[i] ^ 19);
} else {
array[i] = (char) (array[i] ^ 55);
}
}
for (int i2 = 0; i2 < array.length / 2; i2++) {
if (i2 % 2 == 0) {
array[i2] = (char) (array[(array.length - 1) - i2] + 20);
array[(array.length - 1) - i2] = (char) (array[i2] - 10);
} else {
array[i2] = (char) (array[i2] + 30);
}
}
if (Arrays.equals(array, new int[]{130, 37, 70, 115, 64, 106, 143, 34, 54, 134, 96, 98, 125, 98, 138, 104, 25, 3, 66, 78, 24, 69, 91, 80, 87, 67, 95, 8, 25, 22, 115})) {
System.out.println("W");
} else {
System.out.println("L");
}
}
}
Ce programme Java accepte une seule chaîne de caractères comme argument en ligne de commande et effectue une série de manipulations et de contrôles sur cette chaîne. Voici les étapes de son fonctionnement :
-
Vérifie si un seul argument est passé au programme. Si le nombre d’arguments est différent de 1, il imprime
"L"
et termine l’exécution. -
Vérifie si la longueur de la chaîne fournie est exactement 31 caractères. Si ce n’est pas le cas, il imprime
"L"
et termine l’exécution. -
Convertit la chaîne de caractères en un tableau d’entiers, chaque entier représentant le code ASCII d’un caractère. Pour chaque caractère, si l’index du caractère est pair, il effectue une opération XOR (exclusive OR) avec
19
, sinon, il effectue une opération XOR avec55
. -
Puis, il modifie encore le tableau. Pour chaque élément du tableau jusqu’à sa moitié, si l’index est pair, il échange les valeurs entre l’index courant et l’index symétrique par rapport au milieu du tableau, tout en ajustant les valeurs avec une addition ou une soustraction. Si l’index est impair, il ajoute simplement
30
à la valeur à l’index courant. -
Enfin, il compare le tableau résultant à un tableau prédéfini. Si les deux tableaux sont identiques, il imprime
"W"
, sinon, il imprime"L"
.
Le but ici est de trouver la chaine de caractère qui permet de valider la condition et ainsi afficher "W"
.
Exploitation
Nous devons faire toutes les actions inverses pour retrouver la chaîne, et voici le code qui permet de le faire:
public class Test {
public static void main(String[] args) {
int[] targetArray = {130, 37, 70, 115, 64, 106, 143, 34, 54, 134, 96, 98, 125, 98, 138, 104, 25, 3, 66, 78, 24, 69, 91, 80, 87, 67, 95, 8, 25, 22, 115};
char[] result = new char[31];
// Reverse the second part of the transformations
for (int i = 0; i < 31 / 2; i++) {
if (i % 2 == 0) {
int tmp = targetArray[i];
targetArray[i] = (char) (targetArray[30 - i] + 10);
targetArray[30 - i] = (char) (tmp - 20);
} else {
targetArray[i] -= 30;
}
}
// Reverse the first part of the transformations
for (int i = 0; i < 31; i++) {
if (i % 2 == 0) {
result[i] = (char) (targetArray[i] ^ 19);
} else {
result[i] = (char) (targetArray[i] ^ 55);
}
}
// Print the reversed string
System.out.println(new String(result));
}
}
En executant le programme nous avons le résultat suivant:
$ javac Test.java; java Test
n00bz{r3v_1s_s0_e4zy_r1ght??!!}
Le flag est donc n00bz{r3v_1s_s0_e4zy_r1ght??!!}