CTF Backdoor CTF - [Write-Ups]

Kevgen

Green Team
04.08.2020
41
85
BIT
398
Всем привет!

Подошёл к концу Backdoor CTF и я хочу поделиться решениями некоторых тасков.
Сейчас разберу пока 2 таска: на реверс и форензику.


1. Reverse: Open Sesame

Нам дается apk файл.
Запускаем, смотрим что есть. Есть поле для ввода имени и ключа(далее пароль).
интерфейс


Запускаем APKlab в VScode и смотрим MainActivity.java.

Java:
package com.example.open_sesame;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
/* loaded from: classes.dex */
public class MainActivity extends AppCompatActivity {
    private static final int[] valid_password = {52, AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR, 49, 98, 97, 98, 97};
    private static final String valid_user = "Jack Ma";
    private Button buttonLogin;
    private EditText editTextPassword;
    private EditText editTextUsername;

    /* JADX INFO: Access modifiers changed from: protected */
    @Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(C0567R.layout.activity_main);
        this.editTextUsername = (EditText) findViewById(C0567R.C0570id.editTextUsername);
        this.editTextPassword = (EditText) findViewById(C0567R.C0570id.editTextPassword);
        Button button = (Button) findViewById(C0567R.C0570id.buttonLogin);
        this.buttonLogin = button;
        button.setOnClickListener(new View.OnClickListener() { // from class: com.example.open_sesame.MainActivity.1
            @Override // android.view.View.OnClickListener
            public void onClick(View view) {
                MainActivity.this.validateCredentials();
            }
        });
    }

    /* JADX INFO: Access modifiers changed from: private */
    public void validateCredentials() {
        String trim = this.editTextUsername.getText().toString().trim();
        String trim2 = this.editTextPassword.getText().toString().trim();
        if (trim.equals(valid_user) && n4ut1lus(trim2)) {
            String str = "flag{" + flag(Integer.toString(sl4y3r(sh4dy(trim2))), "U|]rURuoU^PoR_FDMo@X]uBUg") + "}";
            return;
        }
        showToast("Invalid credentials. Please try again.");
    }

    private boolean n4ut1lus(String str) {
        int[] it4chi = it4chi(str);
        if (it4chi.length != valid_password.length) {
            return false;
        }
        for (int i = 0; i < it4chi.length; i++) {
            if (it4chi[i] != valid_password[i]) {
                return false;
            }
        }
        return true;
    }

    private int[] it4chi(String str) {
        int[] iArr = new int[str.length()];
        for (int i = 0; i < str.length(); i++) {
            iArr[i] = str.charAt(i);
        }
        return iArr;
    }

    private String sh4dy(String str) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char charAt = str.charAt(i);
            if (Character.isDigit(charAt)) {
                sb.append(charAt);
            }
        }
        return sb.toString();
    }

    private int sl4y3r(String str) {
        return Integer.parseInt(str) - 1;
    }

    private String flag(String str, String str2) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str2.length(); i++) {
            sb.append((char) (str2.charAt(i) ^ str.charAt(i % str.length())));
        }
        return sb.toString();
    }

    private void showToast(String str) {
        Toast.makeText(this, str, 0).show();
    }
}

Сразу были найдены переменные valid_user, а также valid_password, который равен {52, AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR, 49, 98, 97, 98, 97};.
Отбрасываем valid_user, работаем только с паролем.

Далее у нас идет XOR строки "U|]rURuoU^PoR_FDMo@X]uBUg" с тем самым паролем и проверки на валидность введенного пароля(нам ни к чему).
Обращаем внимание на то, что в valid_password не все значения числовые. Строка "AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR" тоже является числом, так как "108".

Пишем солвер:
Python:
import re

valid_password = [52, 108, 49, 98, 97, 98, 97]
TextPassword = ''.join(chr(num) for num in valid_password)

def sh4dy(str_value):
    digits_only = re.sub(r"\D", "", str_value)
    return digits_only

def sl4y3r(str_value):
    return int(str_value) - 1

def flag(str1, str2):
    sb = []
    for i in range(len(str2)):
        sb.append(chr(ord(str2[i]) ^ ord(str1[i % len(str1)])))
    return "".join(sb)

print(flag(str(sl4y3r(sh4dy(TextPassword))), "U|]rURuoU^PoR_FDMo@X]uBUg"))

Получаем флаг: flag{aLiBabA_and_forty_thiEveS}



2. Forensics: Forenscript

Нам даётся какой-то файл a.bin. Смотрим в hex редакторе:

hex.png


Очень похоже на "магические" байты png картинки, да только в странном порядке.
Чтобы восстановить картинку нам надо сделать реверс каждых 4 байт, например "47 4e 50 89" должны превратиться в "89 50 4e 47"

Пишем программу для декодирования:
Python:
with open('C:/users/hidden/Desktop/a.bin', 'rb') as file:
    data = file.read()
output = b''

for i in range(0, len(data), 4):
    segment = data[i:i+4]
    reversed_segment = segment[::-1]
    output += reversed_segment

with open('C:/users/hidden/Desktop/out.png', 'wb') as file:
    file.write(output)

Открываем и видим сие:

fake.png


Раз флаг не на экране - значит он в картинке.
Открываем , видим что там есть ещё одна картинка:

binwalk.png


Скачиваем, распаковываем, переименовываем нужный файл в "flag.png" и получаем флаг: flag{scr1pt1ng_r34lly_t0ugh_a4n't_1t??}

EA90.png



Спасибо за прочтение!
 
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!