// HackTheBox  ·  writeup

CrashDump

HackTheBox Easy PythonstringsWinDbg
Malware Analysis

Scenario

A malware analysis challenge focused on examining a user-mode process dump using WinDbg. The objective is to navigate process structures, inspect loaded modules, analyze memory regions within the dump, identify injected shellcode, and extract indicators that reveal the threat actor’s activity.

Executive Summary

A user ran a dropper from their Downloads folder. It stayed small, with only a handful of threads, and opened a named pipe for inter-process communication. It then injected shellcode into a notepad process by allocating a private read-write-execute region and starting a thread in it. That shellcode is a Cobalt Strike beacon, identifiable by its embedded beacon DLL, post-exploitation pipe names and HTTP check-in URLs, and it beacons to a hard-coded C2 address. Everything came out of two minidumps, using a small structure parser for the stream data and strings for the memory contents.

Artifacts

Tooling note: No WinDbg or minidump library was available on the analysis box, so the streams (SystemInfo, ModuleList, ThreadList, MiscInfo, ThreadInfoList, MemoryInfoList) were read with a short struct-based Python parser. The same data is one lm, ~ or !address away in WinDbg.

Discovery

Q1 — Provide the operating system version.

The SystemInfo stream of the dump holds the OS build the process ran on. Read the major, minor and build numbers there; the ntdll.dll file version in the module list tells the same story and gives the revision field the format mask asks for.

python3 -I tools/md.py evidence/update.DMP
Click flag to reveal 10.0.10240.16384

Execution

Q2 — Provide the full path of the malicious executable used to gain initial access.

The module list of update.DMP starts with the main image. It sits in a user profile’s Downloads folder, not a system path, and its name is built to look like a routine updater.

python3 -I tools/md.py evidence/update.DMP | grep -i mod
Click to reveal answer C:\Users\s1rx\Downloads\update.exe
Q3 — How many threads did the malicious process use?

The ThreadList stream holds one record per thread alive at dump time. Count them for update.DMP.

python3 -I tools/md.py evidence/update.DMP | grep -c '^thr'
Click flag to reveal 6

Command and Control

Q4 — Provide the named pipe (IPC channel) used by the malicious process.

Pipe names are plain strings in process memory. Searching the dump for the \\.\pipe\ prefix surfaces one custom name that does not belong to Windows. It is shaped like a Microsoft Security Essentials pipe to blend in.

strings -a -el evidence/update.DMP | grep -i 'pipe'
Click to reveal answer MSSE-1641-server

Defense Evasion

Q5 — Provide the PID of the injected process. Provide the Answer in decimal.

The second dump is a notepad process, which has no business holding an executable private region. Its PID is in the MiscInfo stream, already in decimal.

python3 -I tools/md.py evidence/notepad.DMP
Click flag to reveal 2336
Q6 — At what time was the last thread created for the injected process? Provide the timestamp in UTC.

The ThreadInfoList stream carries a creation time for every thread. Sort the notepad threads by it and take the newest, thread 720, created at 01:09:12.931. Drop the milliseconds to match the format mask.

python3 -I tools/md.py evidence/notepad.DMP | grep '^ti'
Click to reveal answer 2025-11-05 01:09:12
Q7 — Provide the BaseAddress of the injected shellcode.

The MemoryInfoList stream lists region protections. Filter notepad.DMP for private (non-image, non-mapped) regions that are executable. The small RWX page at 0xb120870000 is the shellcode; WinDbg’s !address shows it as b120870000`, with the backtick the mask expects.

python3 -I tools/md.py evidence/notepad.DMP | grep '^reg'

Note: This pick rests on the region being the only small private RWX allocation, which fits an injected stage rather than anything notepad allocates itself. It was reasoned from the region list rather than read from a labelled artifact.

Click flag to reveal b1`20870000

Command and Control

Q8 — Provide the C2 server IP address.

Beacon configuration and its HTTP request paths are readable in the shellcode’s memory. Search for URLs and the address that the check-in paths point at.

strings -a evidence/notepad.DMP | grep -iE 'https?://|submit.php'
Click to reveal answer 101.10.25.4
Q9 — Provide the name of the C2 framework used by the threat actor.

Three markers agree: a beacon.x64.dll reflective payload name, postex_ pipe names used for post-exploitation jobs, and submit.php?id= as the beacon’s result-posting URL. All three are Cobalt Strike defaults.

strings -a evidence/notepad.DMP | grep -iE 'beacon|postex_|submit.php'
Click flag to reveal Cobalt Strike

Attack Summary

PhaseAction
Executionupdate.exe runs from the user’s Downloads folder
Command and ControlProcess opens the named pipe MSSE-1641-server
Defense EvasionShellcode is placed in a private RWX region in notepad.exe (PID 2336) and a thread is started in it
Command and ControlCobalt Strike beacon checks in over HTTP to the C2 address

IOCs

TypeValue
FileC:\Users\s1rx\Downloads\update.exe
Named pipe\\.\pipe\MSSE-1641-server
IP (C2)101[.]10[.]25[.]4
Memory region0xb120870000 in notepad.exe (PID 2336)
URL pathsubmit.php?id=

MITRE ATT&CK

TechniqueIDDescription
User Execution: Malicious FileT1204.002update.exe run from Downloads
Process InjectionT1055Shellcode in a private RWX region inside notepad.exe
Inter-Process CommunicationT1559Custom named pipe used by the dropper and Cobalt Strike post-ex pipes
Application Layer Protocol: Web ProtocolsT1071.001HTTP beaconing to the C2

Defender Takeaways

A notepad process with an executable private region is injected. Notepad has no reason to hold a small private RWX allocation. Scanning memory for private executable regions in processes that should not JIT, or alerting on VirtualAllocEx plus CreateRemoteThread into a different process, catches this stage.

Pipe names that imitate security products are still pipe names. A MSSE-<digits>-server pipe is a known Cobalt Strike default. Sysmon pipe events (17 and 18) matched against a list of default C2 pipe patterns, including postex_, flag the beacon without any payload analysis.

Strings in a process dump are enough to name the framework. The beacon DLL name, post-exploitation pipes and default URL paths survived in memory unencrypted. Capturing a dump of a suspicious process early gives responders the C2 address and family within minutes.

A fresh executable named update.exe in Downloads should not run. Application control that limits execution from user-writable paths would have blocked the first step.

Conclusion

A downloaded fake updater was enough to land a Cobalt Strike beacon inside notepad. The process dumps held everything needed to name the family and the C2 without running anything, because the beacon’s defaults were never hidden in memory.