Artifacts of Dangerous Sightings

hard | forensics | 300 points

Pandora has been using her computer to uncover the secrets of the elusive relic. She has been relentlessly scouring through all the reports of its sightings. However, upon returning from a quick coffee break, her heart races as she notices the Windows Event Viewer tab open on the Security log. This is so strange! Immediately taking control of the situation she pulls out the network cable, takes a snapshot of her machine and shuts it down. She is determined to uncover who could be trying to sabotage her research, and the only way to do that is by diving deep down and following all traces...

First Impressions

The challenge comes with a folder containing a disk image.

$ file 2023-03-09T132449_PANDORA.vhdx
2023-03-09T132449_PANDORA.vhdx: Microsoft Disk Image eXtended, by .NET DiscUtils, sequence 0x8, NO Log Signature; region, 2 entries, id Metadata, at 0x200000, Required 1, id BAT, at 0x300000, Required 1

The virtual hard disk can be accessed directly in Windows by double clicking on it. So far, the file structure resembles a regular filesystem in Windows.

Event Log Analysis

According to the description, the Security log was open before the machine’s snapshot was taken. So looking into the Event logs seemed like a good starting point, located in C\Windows\System32\winevt\logs. The Powershell related logs generally provide further information, however in this case they were empty.

They were not always empty though. After going through the System log, I found that the Powershell log files were most likely cleared by the attacker.

Windows Event Viewer window displaying events of the category "Log clear". The highlighted event contains the message "The Windows PowerShell log file was cleared"

I then thought of ways to retrieve this log file using forensic tools, hoping it may be somewhere on the disk even after being cleared. In hindsight, that wasn’t possible, but the steps got me to the solution anyway.

Virtual Hard Disk Analysis

Convert VHDX File

To look for deleted and other interesting files on the disk, I analyzed the disk using Autopsy. I first tried adding the disk as is, but it had trouble recognizing the file due to its format.

Luckily, there is a Powershell command, Convert-VHD, that converts VHDX files to VHD, a file format that Autopsy supports. Before I could use it, it required enabling all features related to Hyper-V and rebooting the system.

PS> Convert-VHD -Path .\2023-03-09T132449_PANDORA.vhdx -DestinationPath .\2023-03-09T132449_PANDORA.vhd

Get Powershell History

I added the VHD file as a Disk Image to Autopsy, and waited for the analysis to run.

*Cue elevator music*

I went through the different files, and look what we have here - Console_history.txt, which stores a list of previously executed shell commands.

An Autopsy window showing the contents of ConsoleHost_history.txt. The most significant command in this list is "type finpayload > C:\Windows\Tasks\ActiveSyncProvider.dll:hidden.ps1", which is discussed further in the post.

Some payload has been injected into ActiveSyncProvider.dll, so that the code executes whenever the DLL runs. The syntax after the file name and how to get the payload is something I’ll come to in the next section. And as was assumed earlier, the attacker did in fact clear the Powershell logs after executing the payload.

Getting the Payload

The colon after the DLL name was a little confusing at first. Some good 'ol searching introduced me to the idea of Alternate Data Streams or ADS, a way to store different streams of data in the same file.1

Since only the primary data stream is visible in the file system, this has become a way to hide malicious data, which is exactly what the attacker has done here.

This is where analyzing the disk image in Autopsy proved to be useful, as it showed the alternate data stream, hidden.ps1, as a separate file!

An Autopsy window displaying the contents of hidden.ps1, an alternate data stream of ActiveSyncProvider.dll. The script runs powerShell.exe with a long string of base64 encoded data as input.

I extracted the file, and at this point felt very close to finishing the challenge because I thought I was one base64-decode away from the flag. I was so wrong.

De-obfuscating the Payload

The payload decoded to another payload *sigh*

${[~@} = $(); ${!!@!!]} = ++${[~@}; ${[[!} = --${[~@} + ${!!@!!]} + ${!!@!!]}; ${~~~]} = ${[[!} + ${!!@!!]}; ${[!![!} = ${[[!} + ${[[!}; ${(~(!} = ${~~~]} + ${[[!}; ${!~!))} = ${[!![!} + ${[[!}; ${((!} = ${!!@!!]} + ${[!![!} + ${[[!}; ${=!!@!!} = ${~~~]} - ${!!@!!]} + ${!~!))}; ${!=} = ${((!} - ${~~~]} + ${!~!))} - ${!!@!!]}; ${=@!~!} = "".("$(@{})"[14]+"$(@{})"[16]+"$(@{})"[21]+"$(@{})"[27]+"$?"[1]+"$(@{})"[3]); ${=@!~!} = "$(@{})"[14]+"$?"[3]+"${=@!~!}"[27]; ${@!=} = "["+"$(@{})"[7]+"$(@{})"[22]+"$(@{})"[20]+"$?"[1]+"]";

"${@!=}${~~~]}${(~(!} + ${@!=}${~~~]}${(~(!} + ${@!=}${~~~]}${(~(!} + ${@!=}${~~~]}${[[!} + ${@!=}${[!![!}${!~!))} + ${@!=}${~~~]}${[[!} + ${@!=}${~~~]}${[[!} + ${@!=}${~~~]}
...

It reminded me of this weird code written in Javascript only using symbols, but I had never seen something like this in Powershell.

My first thought was to find an automated tool but the good 'ol searching didn’t help. I was getting a bit annoyed and decided to de-obfuscate it myself.

De-obfuscation Boss Fight

When I had a closer look at the payload, I saw it as two parts - the first part had a bunch of variable assignments, and the second part was an extremely long line of more gibberish.

I separated the first part into different line with semicolons as the separator, and here it started to make some sense. Then I proceeded to enter each line in Powershell and replaced each instance of the variable with the output. As I continued to replace the variables, the second part of the payload also started to make sense!

${[~@} = 0;
${!!@!!]} = 1;
${[[!} = 2;
${~~~]} = 3;
${[!![!} = 4;
${(~(!} = 5;
${!~!))} = 6;
${((!} = 7;
${=!!@!!} = 8;
${!=} =  9;
${=@!~!} = "iex";
${@!=} = "[Char]";

"[Char]35 + [Char]35 + [Char]35 + [Char]32 + [Char]46 + [Char]32 ... [Char]34 + [Char]10 | iex" |& iex

This alternate name for this challenge could be Obfuscation Confusion, it doesn’t stop! Fortunately, this was the last stage, as all that was left to do was copy the second part (leaving the iex portion) to Powershell and let it decode each character. The output returned a script, which contained the challenge flag, FINALLY!

...
$Pass = makePass;
$fileList = @(makeFileList);
$fileResult = makeFileListTable $fileList;
compress $Pass;
$TopSecretCodeToDisableScript = "HTB{Y0U_C4nt_St0p_Th3_Alli4nc3}"

Flag: HTB{Y0U_C4nt_St0p_Th3_Alli4nc3}

Footnotes

  1. Days after making this write-up, I realized that the challenge name initials are also ADS, a reference to Alternate Data Streams, nice! 

More writeups from HTB Cyber Apocalypse 2023