Denton's Blog

A cybersecurity and tech focused blog from a college student

Vault 403 CTF 2025

On November 15th, SAIT hosted their fall 2025 CTF, themed around the Fallout franchise: Vault 403. I wasn’t competing this time around, instead I built a couple of the challenges.

I absolutely love competing in CTFs, but I will say, making challenges and watching people work through and solve them was almost just as fun. This post is going to walk through my intended solutions and share my thought process making each one.

Challenges

Terminal Hacking - Easy Reverse Engineering

You found a Vault maintenance terminal that was intended for communal use until someone locked it with a password. No one remembers it, but thankfully it still accepts guesses and provides a likeness hint on failure. Can you find a way to gain access?

For this challenge the user was provided with two files, the above description, and the option of two different hints if needed. One file was the C code and the other was the executable of that code.

Hint 1 - 0 points Try running the executable and entering anything for input, that should provide clues about the password
Hint 2 - 25 points Look at the variable names in the c file, look for any comments, and search unknown module functions

Challenge Walkthrough

A few areas of code that were very important for the user to investigate and pay attention to included the following:

These lines from the main function which showed the encoded hexadecimals of the required password, given away by the use of the variable name password.

	char encoded[] = {0x0D, 0x1F, 0x1B, 0x0A, 0x15, 0x14};
	char password[7];
	for (int i = 0; i < 6; i++) {
		password[i] = encoded[i] ^ 0x5A;
	}
	password[6] = '\0';

The function decryptFlag which included some hints for identifying the cipher used and included the flag variable.

void decryptFlag(char *plainText) {
	char flag[] = "ReuahPPJ{T3ga!a@h_L@cz3r}";
	int textLen = strlen(flag);
	char plainFlag[textLen];
	
    int keyLen = strlen(plainText);
    int i, j = 0;
	
	// v cipher
    for (i = 0; i < textLen; i++) {
        if (isalpha(flag[i])) {
            char base = isupper(flag[i]) ? 'A' : 'a';
            plainFlag[i] = (flag[i] - base - (toupper(plainText[j % keyLen]) - 'A') + 26) % 26 + base;
            j++;
        } else {
            plainFlag[i] = flag[i];
        }
    }
    plainFlag[textLen] = '\0';
    printf(GREEN ">%s\n", plainFlag);
}

Important information highlighted from the above included:

Info Value
The password encoded as hexadecimals char encoded[] = {0x0D, 0x1F, 0x1B, 0x0A, 0x15, 0x14};
XOR encoding and used key password[i] = encoded[i] ^ 0x5A;
The encrypted flag char flag[] = "ReuahPPJ{T3ga!a@h_L@cz3r}";
The encryption method used // v cipher or plainFlag[i] = (flag[i] - base - (toupper(plainText[j % keyLen]) - 'A') + 26) % 26 + base;

Plugging the string of hexadecimals, 0x0D, 0x1F, 0x1B, 0x0A, 0x15, 0x14, into CyberChef or another decrypting tool and applying From Hex with the delimiter set as Auto. Then applying XOR on top of that with 0x5A as the key reveals the plaintext password used for encrypting the flag, WEAPON.

From here there are two different ways to solve it:

  1. Running the executable and entering WEAPON when it asks for the password
  2. Decrypting the flag yourself through something like CyberChef - the encryption method was hinted at in the code by the comment v cipher, which meant Vigenere cipher and the key is WEAPON

The flag received for solving this challenge was VaultCTF{T3rm!n@l_H@ck3d}

My Thoughts and Experience

I’ve been slowly getting into more and more reverse engineering challenges so I wanted to create a simple one to hopefully also get others into them. I didn’t want it to be super easy but I did want it to be something that everyone could figure out no matter their experience or skill level.

For the challenge in general I had taken inspiration from the terminal hacking that you would see in the Fallout games but simplified it down since it didn’t need to match 100% for the purpose of the overall goal.

I had two different ideas for the intended solution, which were pretty similar. One of the testers had pointed out another solution though that I hadn’t really considered either, which was just brute-forcing the program, but it was cool to see how he went about doing it.

This same tester had also discovered a small flaw in my initial build that I had missed. Originally, if you ran strings on the executable, it would print out the password (WEAPON) in plaintext, completely bypassing the encryption. I didn’t change how I encrypted it, I just changed how I stored it so it wouldn’t be converted.

For how simple it turned out, I absolutely loved making this one. When I signed up to work on the technical team, this challenge was the first thing I thought of and I had a ton of fun planning, building, and modifying it as others had the chance to test it.

Corrupted Terminal Entries - Easy Crypto

While out searching the wasteland, a pre-war terminal was found in the ruins of a nearby neighborhood. A scavenger was able to read the logs, but something seemed off about the content. They copied the entries onto a spare holotape to take back to Vault 403 for further analysis. Can you figure out what they missed?

If you’re colourblind or would just prefer extra visual cues, run the program with the flag -u.

For this challenge the user was provided with one executable file, the above description, and the option of two different hints if needed.

Hint 1 - 0 points Pay attention to the miscoloured or underlined characters
Hint 2 - 25 points Use the brute force option for this decryption method

Challenge Walkthrough

To solve this challenge the user needed to pay attention to any white, red, or underlined characters in the the output of the executable.

When running the program, there are nine terminal entries to sift through and gather these unusual characters. Keeping track of them in the order they are found from 1-9 reveals some required info.

Colour Characters Importance
White toreadtheflagyouwillneedtosearchrot13b Reveals the encryption method used - rot13 brute force
Red/Underlined aleazovbskopkl The encrypted flag contents

Throwing the encrypted contents into something like CyberChef, applying either the ROT13 or ROT13 Brute Force option and looking for the human readable output will reveal the flag contents. The amount needed is 19 to get textshouldhide, brute force will print every amount or you can manually flip though each amount in the regular ROT13 option.

The flag received for solving this challenge was VaultCTF{textshouldhide}

My Thoughts and Experience

For this challenge I wanted to try something that I had never seen in any previous cryptography challenges. Instead of giving this user a text file and just letting them run loose off on their own, I wanted to create something that was (hopefully) close to Fallout lore for conveying the info.

Having already made a terminal hacking related challenge, I wanted to take advantage of the entry aspect of Fallout terminals, and utilizing ANSI codes I could colour the output.

Originally the user was provided with two executables for this challenge, one that ran on Windows and the other Linux. I had run into issues while building and testing where I couldn’t run the same executable on each OS, which then required me to create two.

The night before though, when testing to ensure that the CTFd platform had the right files, I had discovered that the issue I dealt with early on was no longer a problem so I scrapped the Windows executable as it began causing new issues when downloading where it was being flagged as malware.

Radio Transmission - Medium Crypto

An incoming transmission was detected and captured by the vault’s comms system. It looks to be heavily encrypted but no one has been able to crack through the other layers yet.

For this challenge the user was provided with one text file, the above description, and one hint if needed.

Hint 1 - 25 points Try online tools like CyberChef and dCode, both have options for detecting ciphers/decryption methods

Challenge Walkthrough

This challenge required decrypting a message that was encrypted multiple times. Each level after the first included a hint for identifying the used encryption method or a tool like dCode cipher identifier could also help.

In the given text file:

.. - # ... / -. --- - / -... .. -. .- .-. -.-- --..-- / -... ..- - / .. - # ... / -.-. .-.. --- ... . .-.-.- / - .... . / .-. --- -... --- - ... / .--. .-. . ..-. . .-. / .. - --..-- / ..... ----- -.... .---- --... ..--- --... ....- ..--- ----- -.... ..-. -.... -.... ..--- ----- --... ....- -.... ---.. -.... ----. --... ...-- ..--- ----- --... ....- --... ..--- -.... .---- -.... . --... ...-- -.... -.. -.... ----. --... ...-- --... ...-- -.... ----. -.... ..-. -.... . ..--- ----- -.... -.-. -.... ..-. -.... ..-. -.... -... --... ...-- ..--- ----- -.... -... -.... ----. -.... . -.... ....- ..--- ----- -.... ..-. -.... -.... ..--- ----- --... ...-- -.... ...-- --... ..--- -.... .---- -.... -.. -.... ..--- -.... -.-. -.... ..... -.... ....- ..--- -.-. ..--- ----- -.... .---- -.... -.-. -.... -.. -.... ..-. --... ...-- --... ....- ..--- ----- -.... -.-. -.... ----. -.... -... -.... ..... ..--- ----- -.... .---- ..--- ----- --... .- -.... ----. -.... --... ..--- ----- --... .- -.... .---- -.... --... ..--- -.-. ..--- ----- ..... ----- ..--- -.. ..--- -.. ..--- -.. -.... ..-. ..--- -.. ..--- -.. --... ....- -.... -.-. --... ..--- -.... ---.. -.... -.... --... ----. --... ..... --... ..--- -.... ---.. -.... . -.... ..-. ..--- -.. -.... ...-- --... ....- --... ....- -.... ..... -.... ---.. ..--- -.. --... --... ..--- -.. ..--- -.. -.... . -.... .---- ....- ...-- -.... ----. ..... ..-. --... ..--- -.... ----. -.... ---.. --... --... --... ----. --... ..... -.... --... --... ....- --... ....- --... ..--- --... ..... -.... ---.. -.... .---- -.... -.-. -.... ..-. ..--- -.. -.... ---.. ..--- -.. -.... .---- -.... ..... --... ...-- ..--- -.. -.... ..-. -.... ..... --... ..... -.... -.-. ..--- -.. -.... ..-. ..--- -.. -.... ..... -.... ..... --... ....- -.... ..... -.... ..-. -.... -.-. ..--- -.. -.... . ..--- . ..... --... ..--- -.. -.... .---- ..--- --... ..--- -.. -.... ..... ..--- -.. -.... ---.. ..--- -.. --... ....- -.... ..... --... ...-- -.... -... -.... ..-. ..--- -.. -.... -.... -.... ..-. --... ..--- --... ----- -.... .---- ..--- -.-. ..... -.... --... ..... --... ....- ..... ....- --... -... ..... ..-. ...-- ...-- -.... ..... -.... ...-- --... ----. --... ....- -.... ..-. --... -.. -.... ..... -.... ..-. -.... ..-. -.... ---.. -.... --... -.... -.-. -.... -.... -.... ..... --... ----. ..--- -.-. --... ----- -.... -.-. --... ----. --... --... ..--- -.. ..--- -.. --... ----. -.... ..... -.... ..... -.... . -.... -.-. --... ....- -.... ..-. --... ..--- -.... . -.... ..-. --... ..... -.... -.-. ..--- -.. -.... -.-. ....- -.... ...-- -.-. -.... . --... ----- -.... .

It is morse code, identifiable by the dots (.) and dashes (-)

Decrypted into the following, giving the hint IT'S NOT BINARY, BUT IT'S CLOSE. THE ROBOTS PREFER IT, at the beginning:

ITSNOTBINARY,BUTITSCLOSE.THEROBOTSPREFERIT,50617274206F662074686973207472616E736D697373696F6E206C6F6F6B73206B696E64206F6620736372616D626C65642C20616C6D6F7374206C696B652061207A6967207A61672C20502D2D2D6F2D2D746C726866797572686E6F2D63747465682D772D2D6E6143695F726968777975677474727568616C6F2D682D6165732D6F65756C2D6F2D656574656F6C2D6E2E572D61272D652D682D7465736B6F2D666F7270612C567574547B5F33656379746F7D656F6F68676C6665792C706C79772D2D7965656E6C746F726E6F756C2D6C463C6E706E

This one is a string of hexadecimals, which is identified by the 0-9 and A-F characters included.

It decrypted into this next message, with this hint at the beginning, Part of this transmission looks kind of scrambled, almost like a zig zag,:

Part of this transmission looks kind of scrambled, almost like a zig zag, P---o--tlrhfyurhno-ctteh-w--naCi_rihwyugttruhalo-h-aes-oeul-o-eeteol-n.W-a'-e-h-tesko-forpa,VutT{_3ecyto}eoohglfey,plyw--yeenltornoul-lF<npn

This last step used the rail fence or zig-zag cipher, the hint gave this away.

dCode has a Rail Fence (Zig-Zag) Cipher decoder, which is perfect for this challenge. Inputting the second half of the above message and setting the key as 3, the character for the spaces as dashes, and keeping punctuation and spaces enabled, decrypts the message successfully.

Lastly, it decrypted into the final message which included the flag:

Phew-you-got-through-all-of-the-layers,-hopefully-you-were-the-only-one.-We-can't-let-the-others-know-of-our-plan,-VaultCTF{i_<3_encryption}

The flag received for solving this challenge was VaultCTF{i_<3_encryption}

My Thoughts and Experience

For this challenge I had taken inspiration from two challenges I had experienced in previous competitions:

  1. Leaked and Loaded from CyberSci Regionals 2024 - I hadn’t solved it but I loved the multi-step encryption and it’s a challenge I still vividly remember.
  2. Cover All Your Bases from Huntress CTF 2025 - I really liked how John Hammond had added little messages to each one that explained a little bit about the encryption it used.

Cryptography challenges are one of my favourite categories when competing so I wanted to make a challenge inspired by two of my favourites and tweak it to better suit the theme of Fallout.

Taking the opportunity to introduce people to a cipher they may have never seen before either and use a couple common ones.

Conclusion

For my first time building challenges I was happy with how they turned out and I loved hearing how people had gone about working through and solving them.

Another cool thing about working on the technical team was also seeing the process of other challenges being created, and over time seeing how they changed and adapted.

Having been very busy with multiple things over the last few months, I’m glad this was something I had the chance to spend time on and see through. I look forward to the spring CTF coming up in March.