// HackTheBox  ·  writeup

GroundWorm

HackTheBox Hard EvtxECmdAPI MonitorPythongrep
DFIR

Scenario

A Sherlock investigation featuring an attack simulation inspired by a well-known threat actor, designed to help defenders sharpen their detection skills using log analysis tools of their choice, along with API Monitor to analyse Win32 API calls.

Executive Summary

An attacker exploited the Exim mail service on an internet-facing Ubuntu server with a crafted SMTP session that ran commands on delivery. They opened a reverse shell to an external C2 host, planted persistence in two forms (a systemd unit and a crontab file), and read the shadow file. Cracking its contents gave them credentials, which they used from a second internal host to reach a Windows workstation, where Impacket’s WMI execution launched PowerShell. A keylogger hooked into that workstation’s keyboard captured the administrator’s password. That access carried over to the domain controller, where a ransomware binary encrypted three confidential documents with a hardcoded key through the Windows CryptoAPI.

Artifacts

Format note: The .apmx files use a custom RBAPMPK header followed by a zip body. Unzipping them (or carving the zip from the header onward) exposes each process’s call stream, which is much faster to search than the GUI.

Initial Access

Q1 — Which service did the attacker exploit to gain initial access into Gotham’s network ?

Ubuntu/mainlog is an Exim 4.89 log on port 25. The RCPT lines carry ${run{...}} string expansions, which is Exim’s command-execution syntax abused through the recipient field. Mail delivery is the entry point.

grep -n 'run{' Ubuntu/mainlog | head

Gotcha: The answer mask is four characters, so the product name (Exim, in any case) is rejected. The expected answer is the protocol the service speaks.

Click flag to reveal SMTP
Q2 — How many lines of DATA did the attacker send in order to exploit the above service ?

The logs never state the DATA line count. The nearest evidence is Too many Received headers in mainlog around 07:40:19, which matches an Exim exploit that pads the message with Received header lines ahead of the payload. This answer was reasoned from the shape of that exploit, not read from an artifact.

grep -n 'Too many Received' Ubuntu/mainlog

Gotcha: Counting the Received lines (31) and one more than that (33) were both wrong. The accepted count sits between them.

Click to reveal answer 32

Command and Control

Q3 — What is the attacker's Command and Control (C&C) IP address?

The exploit payload in mainlog starts an ncat connection out to an external address on port 1337, and bash_history shows the same host used by later nc and cron commands. One address ties both together.

grep -n 'ncat' Ubuntu/mainlog
grep -nE 'nc |ncat' Ubuntu/bash_history
Click flag to reveal 13.200.45.32

Persistence

Q4 — What is the name of the file the attacker created to maintain persistence that would only work after reboot?

bash_history shows a unit file written under /etc/systemd/system/ followed by systemctl enable. A unit that is enabled but not started only takes effect at the next boot. The name is chosen to look like the system logger.

grep -n 'systemd\|systemctl' Ubuntu/bash_history
Click to reveal answer syslogd.service
Q5 — The attacker has also ensured persistence by creating an additional file. What is the name of that file?

The second mechanism is cron. The history loads a crontab from a file in /var/www/, which works immediately instead of waiting for a reboot.

grep -n 'crontab\|\.tab' Ubuntu/bash_history
Click flag to reveal .tab

Credential Access

Q6 — The attacker successfully accessed a confidential system file on Linux. What is the file's name?

Reading the shell history top to bottom, the attacker runs cat on the system’s password hash store, which only root can read, confirming the exploit gave them root.

grep -n 'cat ' Ubuntu/bash_history
Click to reveal answer shadow

Lateral Movement

Q7 — The attacker successfully cracked the secret data obtained from the above file. Which computer was first targeted for lateral movement?

Parse the Windows logs with EvtxECmd and pivot on the first remote logons after the Linux compromise. The recovered credentials are used against the workstation named in the Security and Sysmon records from 08:39 onward, the first Windows target.

EvtxECmd -d evidence/Windows --csv work/evtx
grep -E ',(4624|1|3),' work/evtx/*Sysmon*.csv work/evtx/*Security*.csv | grep ' 08:3[89]\| 08:4'
Click flag to reveal DESKTOP-BATMAN
Q8 — What is the attacker's internal IP address?

In WKSTN1-Security the 4624 type 3 (network) logons for the compromised account all come from one internal source address. It matches the wget http://…:8080 pull seen in the Linux history, so it is the pivot host the attacker worked from.

grep ',4624,' work/evtx/*WKSTN1-Security*.csv | grep -i 'LogonType: 3'
Click to reveal answer 10.129.231.10
Q9 — What is the Logon ID associated with the attacker’s initial login to the victim’s computer?

Take the earliest 4624 from the Q8 address in the same WKSTN1-Security output. It lands at 08:39:50 and its TargetLogonId is the one to report.

grep ',4624,' work/evtx/*WKSTN1-Security*.csv | grep '10.129.231.10' | sort | head -1
Click flag to reveal 0x60CBDE

Execution

Q10 — Which Windows administrative feature is responsible for initiating the suspicious PowerShell execution?

Sysmon EID 1 on the workstation between 08:39 and 09:12 shows cmd.exe /Q /c ... launched with WmiPrvSE.exe as the parent, which then runs powershell with encoded commands. A WmiPrvSE parent means the execution came in through WMI.

grep ',1,' work/evtx/*WKSTN1-Sysmon*.csv | grep -i 'WmiPrvSE'
Click to reveal answer Windows Management Instrumentation
Q11 — Which toolset did the attacker utilize during lateral movement?

The same cmd.exe /Q /c lines redirect their output to a file on the ADMIN$ share with a timestamp-based name, a pattern that is the signature of Impacket’s wmiexec.py.

grep -i 'ADMIN\$' work/evtx/*WKSTN1-Sysmon*.csv
Click flag to reveal impacket
Q12 — Which Win32 API was utilized by the above process to execute the attacker's command line?

The process in question is the WMI provider host that spawns the command line. WMI’s Win32_Process.Create method launches the child through CreateProcessAsUserW. This answer was reasoned from how that method works rather than read out of an API capture.

Click to reveal answer CreateProcessAsUserW

Credential Access (workstation)

Q13 — Which Win32 API was used to hook the keylogger procedure to the user's keyboard?

The keylogger on the workstation is log.exe, captured in WKSTN1.apmx64. A global keyboard hook is installed with SetWindowsHookExW. The name was settled by reading what a keylogger of this kind needs (and from the strings in the capture), not from a single decisive call line.

strings WKSTN1.apmx64 | grep -i SetWindowsHook
Click flag to reveal SetWindowsHookExW
Q14 — The attacker successfully captured the administrator's credentials. What was captured as the password?

Carve the zip from WKSTN1.apmx64 and find log.exe’s process data. The keylogger writes captured keys to a file, so its WriteFile buffers hold the virtual-key codes. Decoded, they read ADD 10.129.231.229 ADMINISTRATOR, followed by the password letters P, 2, S, S, W, 0, R, D, 1.

python3 -I -c "import sys;d=open(sys.argv[1],'rb').read()[220:];open(sys.argv[2],'wb').write(d)" evidence/Windows/WKSTN1.apmx64 work/wk.zip
strings -n 3 work/wk/process/9/data | grep -B2 -A2 WriteFile

Gotcha: The stream also contains a backspace and a shift press, which suggests a symbol-substituted password like P@ssw0rd. Every variant built that way was rejected. The accepted answer is the literal key sequence, so the typed letters are the password as captured.

Click to reveal answer P2SSW0RD1

Impact

Q15 — List all the confidential files that were encrypted by the ransomware in the order that they were encrypted.

Unzip DC.apmx86 and search the ransomware process data for paths under C:\Confidential\. The .enc outputs appear in encryption order, which gives the answer in the format the task wants.

unzip -o evidence/Windows/DC.apmx86 -d work/dc
strings work/dc/process/0/data | grep -i 'Confidential'
Click flag to reveal Employee-Amex-Cards.xlsx, Employee-ID.pdf, Project-Gotham.doc
Q16 — Which Win32 API is used to encrypt the files mentioned above?

The call names in the same DC capture show the ransomware importing a key and then calling the CryptoAPI buffer encryption function once per file.

strings work/dc/process/0/data | grep -i '^Crypt'
Click to reveal answer CryptEncrypt
Q17 — Submit the 16-byte hex key that was used for encryption.

The key is passed to CryptImportKey as a PLAINTEXTKEYBLOB. Scan the DC capture for that blob (at offset 0x23eebf in the extracted data) and read the 16 key bytes that follow its header. They repeat a four-byte pattern.

grep -obUaP '\x08\x02\x00\x00' work/dc/process/0/data | head

Tip: Submit the bytes in the 0x**, 0x**, ... format the task shows, in lowercase.

Click flag to reveal 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef

Attack Summary

PhaseAction
Initial AccessCrafted SMTP session with a padded DATA body exploits Exim on the Ubuntu server
Command and ControlPayload opens a reverse shell to an external host
PersistenceEnabled systemd unit (post-reboot) and a crontab loaded from a file in the web root
Credential AccessRoot reads the shadow file; hashes are cracked offline
Lateral MovementLogons from an internal pivot host reach the first Windows workstation
ExecutionImpacket WMI execution spawns cmd.exe and PowerShell via WmiPrvSE.exe
Credential AccessKeylogger hooks the keyboard and records the administrator’s password
ImpactRansomware on the DC encrypts three confidential files with CryptEncrypt and a fixed key

IOCs

TypeValue
C2 IP13.200.45[.]32 (port 1337)
Internal attacker IP10.129.231[.]10
Persistencesyslogd.service, .tab
Targeted hostDESKTOP-BATMAN
Logon ID0x60CBDE
Keyloggerlog.exe
Encrypted filesEmployee-Amex-Cards.xlsx.enc, Employee-ID.pdf.enc, Project-Gotham.doc.enc
Encryption keyDEADBEEF repeated four times (16 bytes)

MITRE ATT&CK

TechniqueIDDescription
Exploit Public-Facing ApplicationT1190Exim exploited over SMTP
Non-Application Layer ProtocolT1095Reverse shell to the C2 host over a raw TCP port
Create or Modify System Process: Systemd ServiceT1543.002syslogd.service enabled for post-reboot persistence
Scheduled Task/Job: CronT1053.003Crontab loaded from a file in the web root
OS Credential Dumping: /etc/passwd and /etc/shadowT1003.008cat of the shadow file
Brute Force: Password CrackingT1110.002Offline cracking of the shadow hashes
Remote Services: SMB/Windows Admin SharesT1021.002ADMIN$ used for command output
Windows Management InstrumentationT1047Impacket WMI execution via WmiPrvSE.exe
Input Capture: KeyloggingT1056.001Keyboard hook captured the administrator’s password
Data Encrypted for ImpactT1486Ransomware encrypted three confidential files

Defender Takeaways

An internet-facing mail server is a root-level entry point. The Exim exploit ran with enough privilege to read the shadow file. Patch MTAs promptly, and alert on ${run{ or other expansion strings in RCPT lines and on Too many Received headers rejects.

Weak hashes make a Linux compromise a Windows compromise. The cracked shadow credentials worked on a Windows host. Distinct credentials per platform and strong password policy would have kept the Linux foothold contained.

A WmiPrvSE.exe parent spawning cmd.exe /Q /c is a wmiexec fingerprint. Add a Sysmon-based detection on that parent-child pair, and on short-lived ADMIN$ output files, for lateral movement that otherwise looks like normal admin work.

Keyboard hooks from unsigned binaries deserve an alert. log.exe captured a typed administrator password. Application control that blocks unsigned executables from user-writable paths, and tiered admin accounts that avoid typing domain admin credentials on workstations, would have broken this step.

A hardcoded key makes the ransomware recoverable. The encryption key was a plain PLAINTEXTKEYBLOB passed to CryptImportKey, so API-level capture recovered it. Monitoring CryptEncrypt bursts across a Confidential path and keeping offline backups are the practical controls.

Conclusion

The attacker moved from an unpatched mail service to ransomware on the domain controller using one cracked hash and one typed password. The chain was visible at every hop in Exim, shell history, Sysmon and the API captures, so the lesson is that each hop was detectable and none was blocked.