Securebug.se CTF Odin 2021: It all starts from the beginning

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 with 2,
  • 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}

Privacy Policy
luc © 2021