Home P3rf3ctr00t CTF 2024 Write up
Post
Cancel

P3rf3ctr00t CTF 2024 Write up

image.png

As part of our engagement in the P3rf3ctr00t CTF, Fr334aks-mini showcased remarkable teamwork and determination, achieving 5th place overall, while our second team secured 26th position. This competition presented diverse challenges that tested our problem-solving skills across multiple domains, sharpening our technical expertise and teamwork.

pfrootresults.png

Team B

pfrootresultsb.png

In this write-up, I will delve into some of the challenges I tackled in OSINT, Reverse Engineering, Forensics, and Steganography. These categories not only highlight the breadth of the competition but also underline the strategic approaches and methodologies I employed to solve them. Each challenge provided unique insights and opportunities for growth, contributing to our overall success.

Let’s explore the challenges and my journey through these fascinating categories.

OSINT

Adversary Within - Part 1

oaw1.png

From the description, this was definitely referring to Active Directory.

“…roasts” This hinted on kerberoasting. Kerberoasting is a technique that exploits Kerberos authentication protocol where a threat actor steals Kerberos service tickets to uncover the plaintext passwords of network service accounts.

At first I thought of ACLs but then looking around with a team mate(jnmunene) I got hold of “schema” that defines all the objects and attributes that the directory service uses to store data as per Microsoft.

r00t{schema}

Steg

Mayday Mayday

stegmay.png

We are given a .wav file. What came into my mind was morse code for some reason(may be it’s the description).

Using this site I got the flag quite easily.

(had to use this in Chromium browser - Firefox probably doesn’t like morse)

mayday1.png

r00t{J@M35_007_B0ND_2OO9}

Forensics

Code Mirage

fcode.png

Just a heads up, I blooded this challenge!

I found it quite easy since I had done something similar at Huntress CTF 2023.

Check it out here HuntressCTF 2023 writeup

I will not go much into this but here is a breakdown of what is happening.

We are given a file with PHP code and some strings. (snippet looked a bit frivolous)

1
2
3
4
5
6
7
8
9
10
11
12
<?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: Decoding Key Elements

  • The explode() function separates the content of the PHP file based on the delimiter ?>, derived from decoding Pz4= using Base64. This effectively splits the script into two parts: the code before and after ?>.
  • Several strings were decoded using base64_decode(), revealing:
    • L3gvaQ== translates to /x/i, a regular expression pattern.
    • eA== translates to x, a string used in pattern matching.
  • The second part of the split content (after ?>) undergoes multiple transformations:
    1. Decoded from Base64.
    2. Passed through a ROT47 cipher.
    3. Reversed using strrev().

Step 2: Leveraging CyberChef

To decode the extracted and transformed string, I used CyberChef with the following recipe:

  1. Reverse the string.
  2. Apply ROT47.
  3. Decode the result from Base64.
1
r00t{8f93d0a6b7c8d90e4f7a1b9e6c3d4f8e9a2d0f3c5e7b8c6d1f3a5b9c4d2}

The author explained it well here - P3rf3ctr00tCTF

Rev

Pores

rpores.png

Just started learning reverse engineering so, I may not know what I am doing but I am good at it.

Looking at the file type revealed that it was an unstripped(has debug information) elf

poreshot3.png

I then checked out for any readable strings within the file with the strings command

poreshot4.png

Making the file executable with chmod +x poresssss then running it ./poresssss gave no output.

What just happened! Ever downloaded a random game online and installed it locally. While playing you get to see random pop ups that disappear in a sec? that’s what it feels running a binary and there’s no nothing.

surprise.webp

Ghidra’s take:

The main functions is empty and does not seem to call any other function, especially the printFlag function which is why we are here in the first place!

poreshot6.png

The function printFlag takes two parameters:

  1. param_1 (of type long):
    • Represents the memory address of an array(our flag) of size 8 bytes The function uses this address to access and manipulate the encoded data for decoding and printing.
  2. param_2 (of type int):
    • Specifies the number of elements in the array to process.

Together, these parameters allow the function to decode and print data stored in a memory block, treating each element as an encoded value to be broken down into individual characters.

poreshot7.png

Let’s check with GDB

investigate.webp

GDB’s take:

I opened the file in gdb and set a breakpoint at the main function.

Running the program and disassembling the main function:

poreshot5.png

Seems there is a flag stored at address 0x555555558040.

I noticed the program has a condition that stops the printflag function from being executed. Specifically, there is a comparison operation between the values 0 and 1. If these values are found to be unequal, the program jumps to the memory address main+41, bypassing the call to printFlag.

The comparison instruction (cmp DWORD PTR [rbp-0x4], 0x1) checks whether the value stored at [rbp-0x4] is equal to 1. However, [rbp-0x4] is set to 0, so the condition always evaluates as false.

Thus, the program never proceeds to execute printFlag.

Using the layout asm I jumped around addresses looking at the contents of the addresses.

poresshot.png

We will use gdb’s call command to directly execute the printFlag function from its starting point.

When invoking printFlag in gdb, it’s necessary to cast the function to a void return type. This ensures gdb handles the call correctly since it doesn’t know how to deal with functions that return void, and the cast avoids potential errors.

Additionally, remember to provide the required two arguments(as we saw with ghidra) to the function:

the address of the flag (0x555555558040) and 8, which specifies the number of 8-byte blocks the data contains.

poreshot2.png

r00t{p4tch_th3_bin_and_h4ve_fun}

Big thanks to my team mate here for a little help.

Till next time, cheers!

And remember, there are many ways of killing a rat!

jerry.webp

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

BlueHens CTF 2024 Write up

-