n00bzCTF 2023 - EZrev
Table of Contents
Challenge Overview
In this challenge, we were given a downloadable Java class here .
To reverse engineer a Java class, we will need a Java decompiler. I decided to use jadx-gui.
Code Analysis
Initial Code Analysis
By analyzing the source code, we have the main() function which contains the following code:
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");
}
}
}
Program Flow
This Java program accepts a single character string as a command-line argument and performs a series of manipulations and checks on this string. Here are the steps of its operation:
-
Checks if a single argument is passed to the program. If the number of arguments is different from 1, it prints
"L"and terminates execution. -
Checks if the length of the provided string is exactly 31 characters. If not, it prints
"L"and terminates execution. -
Converts the character string into an array of integers, each integer representing the ASCII code of a character. For each character, if the character’s index is even, it performs an XOR (exclusive OR) operation with
19, otherwise, it performs an XOR operation with55. -
Then, it modifies the array again. For each element of the array up to its half, if the index is even, it swaps the values between the current index and the symmetric index relative to the middle of the array, while adjusting the values with an addition or subtraction. If the index is odd, it simply adds
30to the value at the current index. -
Finally, it compares the resulting array to a predefined array. If the two arrays are identical, it prints
"W", otherwise, it prints"L".
Goal
The goal here is to find the character string that allows validating the condition and thus displaying "W".
Exploitation
Reverse Engineering Script
We need to perform all the reverse actions to recover the string, and here is the code that allows doing this:
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));
}
}
Result
By executing the program, we get the following result:
$ javac Test.java; java Test
n00bz{r3v_1s_s0_e4zy_r1ght??!!}
Flag
The flag is therefore n00bz{r3v_1s_s0_e4zy_r1ght??!!}