PicoCTF Writeup – vault-door-4
# Information:
CTF Name: PicoCTF
CTF Challenge: vault-door-4
Challenge Category: Reverse Engineering
Challenge Points: 250
PicoCTF 2019.
# Challenge Description:
This vault uses ASCII encoding for the password. The source code for this vault is here: VaultDoor4.java
Hints: Use a search engine to find an “ASCII table”. You will also need to know the difference between octal, decimal, and hexadecimal numbers.
# Writeup
In this challenge we are presented with a file VaultDoor4.java. This file consists in java code, as you can see below:
import java.util.*;
class VaultDoor4 {
public static void main(String args[]) {
VaultDoor4 vaultDoor = new VaultDoor4();
Scanner scanner = new Scanner(System.in);
System.out.print("Enter vault password: ");
String userInput = scanner.next();
String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
if (vaultDoor.checkPassword(input)) {
System.out.println("Access granted.");
} else {
System.out.println("Access denied!");
}
}
// I made myself dizzy converting all of these numbers into different bases,
// so I just *know* that this vault will be impenetrable. This will make Dr.
// Evil like me better than all of the other minions--especially Minion
// #5620--I just know it!
//
// .:::. .:::.
// :::::::.:::::::
// :::::::::::::::
// ':::::::::::::'
// ':::::::::'
// ':::::'
// ':'
// -Minion #7781
public boolean checkPassword(String password) {
byte[] passBytes = password.getBytes();
byte[] myBytes = {
106 , 85 , 53 , 116 , 95 , 52 , 95 , 98 ,
0x55, 0x6e, 0x43, 0x68, 0x5f, 0x30, 0x66, 0x5f,
0142, 0131, 0164, 063 , 0163, 0137, 0146, 064 ,
'a' , '8' , 'c' , 'd' , '8' , 'f' , '7' , 'e' ,
};
for (int i=0; i<32; i++) {
if (passBytes[i] != myBytes[i]) {
return false;
}
}
return true;
}
}
As you can see the code above makes a password check. The password seems to be the flag. However, by looking at the code we can not retrieve the password, we must reverse engineer it.
It seems that the byte array myBytes, in the checkPassword method,represents the bytes that are in the flag but in different bases. As you can see in that same method, in the for loop, the code does a comparison between the bytes of the password sent as input by the user, with is the passByes with the byte array myBytes. It seems that all we have to do is to convert from each base in the myBytes to ASCII and we get the flag. There are 3 bases and chars. The 3 bases are first decimal, second hexadecimal, and third octal.
Doing this conversion manually is cumbersome so I decided to create a python 3 script as you can see below:
def crackPassowrd():
myBytes = [106, 85, 53, 116, 95, 52, 95, 98,
0x55, 0x6e, 0x43, 0x68, 0x5f, 0x30, 0x66, 0x5f,
0o142, 0o131, 0o164, 0o63 , 0o163, 0o137, 0o146, 0o64 ,
'a' , '8' , 'c' , 'd' , '8' , 'f' , '7' , 'e' ,]
newMyBytes = []
for val in myBytes:
if(isinstance(val, int)):
newMyBytes.append(chr(val))
elif(str(val).startswith('0x')):
newMyBytes.append(bytes.fromhex(val).decode('utf-8'))
elif(str(val).startswith('0o')):
newMyBytes.append(val)
elif(isinstance(val, str)):
newMyBytes.append(val)
return newMyBytes
def getFlag(newMyBytes):
res = "picoCTF{"
for i in newMyBytes:
res += i
return res + "}"
print(getFlag(crackPassowrd()))
The first function, crackPassowrd performs the reverse engineering. It does so by verifying if each entry in the myBytes array is a decimal, hexadecimal, octal, or string. And, according to the type it converts to string in a particular way. After the conversion each entry is added to a newMyBytes array that, after the loop finishes is returned.
The second function, getFlag, receives as input the result of crackPassword and constructs the flag with it.
The flag is:
Your way of describing the whole thing in this article
is in fact nice, all can easily know it, Thanks a lot.