It all starts from the beginning
Category: Reverse Engineering
200 points
Can you find the beginning!?
File: fina
, Main.java
fina
~T\7EWE1W;A5ZTdJ0Vag[ZREaHQEK~
Main.java
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
public class Main {
static String passer="a";
static int run=0;
public static void main(String[] args)throws IOException {
System.out.println("you shouldn't start from here :)");
}
public static void juzbYn(String[] args)throws IOException {
String Input;
if (args[0].contains("SBCTF{")){
Input=args[0];
}
else {
run++;
if (run==5){
System.exit(0);
}
Input=passer;
}
char array[]=passer.toCharArray();
int j=0;
for (int i=0;i<array.length;i++){
if (i%5==0){
if (j!=0) {
System.out.println(i + " : " + array[i]);
char a = array[j* 5];
System.out.println(a);
array[j* 5] = array[j-1];
array[j-1] = a;
}
j++;
}
}
StringBuilder stringBuilder=new StringBuilder();
for (char ch:array){
stringBuilder.append(ch);
}
passer = stringBuilder.toString();
Ft7BEg(new String[]{args[0]});
}
public static void b837Lz(String[] args) throws IOException {
String Input;
if (args[0].contains("SBCTF{")){
Input=args[0];
args[0]="aa";
}
else {
run++;
if (run==5){
System.exit(0);
}
Input=passer;
}
char array[]=passer.toCharArray();
for (int i=0;i<array.length;i++){
if (i%5==0){
array[i]=(char)((array[i]+255)-51*5);
}
if (i%2==0){
array[i]=(char)((array[i]+282)-141*2);
}
}
StringBuilder stringBuilder=new StringBuilder();
for (char ch:array){
stringBuilder.append(ch);
}
passer = stringBuilder.toString();
FileWriter myWriter = new FileWriter("fina",true);
myWriter.write(passer+"\n");
myWriter.close();
e66Cbf(new String[]{args[0]});
}
public static void e66Cbf(String[] args)throws IOException {
String Input;
Random rand = new Random();
if (args[0].contains("SBCTF{")){
Input=args[0];
args[0]="aa";
run++;
}
else {
run++;
if (run==5){
System.exit(0);
}
Input=passer;
}
char array[]= Input.toCharArray();
System.out.println(array);
int i=0;
for (char b:array){
array[i]= (char) (b+1);
i++;
}
int randoms[] = new int[6];
for (i=0;i<5;i++){
randoms[i]= rand.nextInt(9);
}
i=0;
for (char b:array) {
array[i] = (char) (b + randoms[i % 6]);
i++;
}
StringBuilder stringBuilder=new StringBuilder();
for (char ch:array){
stringBuilder.append(ch);
}
passer = stringBuilder.toString();
juzbYn(new String[]{args[0]});
}
public static void Ft7BEg(String[] args)throws IOException {
String Input;
if (args[0].contains("SBCTF{")){
Input=args[0];
}
else {
run++;
if (run==5){
System.exit(0);
}
Input=passer;
}
char array[]=passer.toCharArray();
for (int i=0;i<array.length;i++){
if (i%2==0){
array[i]= (char) (array[i]^2);
}
}
StringBuilder stringBuilder=new StringBuilder();
for (char ch:array){
stringBuilder.append(ch);
}
passer = stringBuilder.toString();
b837Lz(new String[]{args[0]});
}
}
Solution
I’m not a Java guy, so I’ve rewritten the whole program in Python (even with the parts of code that do nothing - lol). Then I’ve added decrypt method to it. Source is below.
Generally, there were 4 methods (I’ve named them d1
, d2
, d3
, d4
, they are in same order as original ones), which
do some work on flag and pass it to next one. The flow is in following order d3
=> d1
=> d4
=> d2
. Purpose of
each method is as below:
d3
add some random number (from range 0 to 8 inclusively) to integer representation of each byte,d1
swap places of some bytes (you can read the code to understand the logic),d4
xor each byte with2
,d2
do nothing ;-) or let’s say - in original program it writes the flag to file.
I’ve reversed above flow as a decrypt
method. Then iterated over the each possible random product until successful
flag decryption.
import random
from itertools import product
flag_encrypted = '~T\\7EWE1W;A5ZTdJ0Vag[ZREaHQEK~'
class Main:
def __init__(self, randoms=None):
self.randoms = [random.randint(0, 10) for i in range(6)] if randoms is None else randoms
self.run: int = 0
self.passer: str = 'a'
def d1(self, flag: str):
input_str: str
if 'SBCTF{' in flag:
input_str = flag
else:
self.run += 1
if self.run == 5:
exit(0)
input_str = self.passer
array = [c for c in self.passer]
j: int = 0
for i, k in enumerate(array):
if i % 5 == 0:
if j != 0:
# print(str(i) + " : " + k, end='')
a = array[j * 5]
# print(a, end='')
array[j * 5] = array[j - 1]
array[j - 1] = a
j += 1
self.passer = ''.join(array)
return self.d4(flag)
def d2(self, flag: str):
input_str: str
if 'SBCTF{' in flag:
input_str = flag
flag = 'aa'
else:
self.run += 1
if self.run == 5:
exit(0)
input_str = self.passer
array = [c for c in self.passer]
for i, j in enumerate(array):
if i % 5 == 0:
array[i] = chr((ord(array[i]) + 255) - 51 * 5)
if i % 2 == 0:
array[i] = chr((ord(array[i]) + 282) - 141 * 2)
self.passer = ''.join(array)
return self.passer # instead of saving it to file
def d3(self, flag: str):
input_str: str
input_str: str
if 'SBCTF{' in flag:
input_str = flag
flag = 'aa'
else:
self.run += 1
if self.run == 5:
exit(0)
input_str = self.passer
array = [c for c in input_str]
# print(array)
for i, b in enumerate(array):
array[i] = chr(ord(b) + 1)
for i, b in enumerate(array):
array[i] = chr(ord(b) + self.randoms[i % 6])
self.passer = ''.join(array)
return self.d1(flag)
def d4(self, flag: str):
input_str: str
if 'SBCTF{' in flag:
input_str = flag
else:
self.run += 1
if self.run == 5:
exit(0)
input_str = self.passer
array = [c for c in self.passer]
for i, j in enumerate(array):
if i % 2 == 0:
array[i] = chr(ord(array[i]) ^ 2)
self.passer = ''.join(array)
return self.d2(flag)
def decode(self, input_flag):
# d2 do nothing
flag = [c for c in input_flag]
# d4 xoring
for i, j in enumerate(flag):
if i % 2 == 0:
flag[i] = chr(ord(j) ^ 2)
# d1 switch bytes
for i in range(len(flag)):
if (i + 1) * 5 < len(flag):
flag[i], flag[(i+1)*5] = flag[(i+1)*5], flag[i]
# d3 some randomness
for i, b in enumerate(flag):
flag[i] = chr(ord(b) - self.randoms[i % 6])
for i, b in enumerate(flag):
flag[i] = chr(ord(b) - 1)
return ''.join(flag)
f = ''
d = Main()
options = [i for i in range(0, 7)]
for i in product(options, repeat=6):
d = Main(randoms=i)
f = d.decode(flag_encrypted)
if 'SBCTF{' in f:
print('Flag: {}'.format(f))
print('Randoms: {}'.format(i))
break
Output of execution:
Flag: SBCTF{C0N6R4TS_Y0U_f0UND_FL@G}
Randoms: (3, 0, 6, 4, 1, 0)
Flag
SBCTF{C0N6R4TS_Y0U_f0UND_FL@G}