Backdoor CTF 2023
Rev - Secret Door
This was a frustrating challenge, the binary asked for a 17 length password, I started debugging with ghidra but It was not friendly readable. It was hard.

After seeing every function, I noticed that the important one was func_2

If every comparisson was correct, a file that came with the binary encoded in the challenge will be decoded ('encoded.bin') and give us the flag.

Acording to that function the value should be something like:
N x x t d c xxrs!
The spaces were places of the password that were not checked to be equal to anything, trying to pass that as a password didnt go as expected.

This is because the previous functions were doing something with our input in order to alter it. As I didn't understand it enough with ghidra, I checked with pwndbg the input and and output of the functions: I added a breakpoint at the beggining of the functions and at the end and run it with r mmmmmmmmmmmmmmmm
(17 'm's)

func_5 was a troll, as the output was:

func_4 did something with my input of full 'mmmmmmmmmmmmmmmm' inputs:

Output:

A single '>' This was curious because checking with ghidra, that function was doing some kind of XOR Checking, as I imagined, the function was xoring my input with 'SeventeenChars!!!'

func_3 was the same as func4, so this time, it was xoring the output with 'ThatsHardcoded!!!'

Now I knew what was changing my input, now I just had to reverse XOR :)

This was something, but I knew that some values were odd, because of the spaces that weren't checked to decrypt the file, so I changed those bytes that should be spaces (or any printable character as it wasnt checked):
I o e p7n d oors! (this is characters were checked)
Ilove0p7n3ddoors! (for example this is valid, as long as we dont mess up with the chars that were not spaces we are fine)
And magically, running with this password will drop us a jpg image on our directory:


Rev - Open Sesame
This was easier than the last one, we are given an apk that checks for a user and a password Decompiling the apk, I saw the valid user and valid_password were:

User = Jack Ma
Pass = [52, 108, 49, 98, 97, 98, 97] which converted from ascii was = 4l1baba
However, giving the apk this values didnt spit out the flag, as the only thing shown was if it was incorrect or not. But now that we had the password value, we could recreate this function and get the flag:

functions to be recreated:
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();
}
With the given password, either you copied the java code, or you create a code with python, which was my case:
from pwn import *
part = 'U|]rURuoU^PoR_FDMo@X]uBUg'
valid_user = 'Jack Ma'
valid_pass = [52, 108, 49, 98, 97, 98, 97]
# Transformed in ascii chars:
password = '4l1baba'
def sh4dy(string):
sb = []
for x in string:
if x.isdigit():
sb.append(x)
return ''.join(i for i in sb)
# ['4', '1'] / 41
def sl4y3r(string):
return str(int(string) - 1)
# 40
def flag(string, part='U|]rURuoU^PoR_FDMo@X]uBUg'):
sb = []
check_list = []
for i in string:
check_list.append(i)
for n,x in enumerate(part):
check_val = check_list[n%len(string)]
sb.append(xor(x.encode(),check_val.encode()))
return ''.join(k.decode() for k in sb)
print("flag{" + flag(sl4y3r(sh4dy(password))) + "}")
Which gives us the flag:

Last updated