Challenge Info
Spoiler
Reminiscent hands you a memory dump of a recruiter’s VM plus the email that started the infection, and asks you to carve the malware out of memory, decode it, and find the flag.
In the contrary the official HTB path and description of the challenge goes as follows:
Suspicious traffic was detected from a recruiter’s virtual PC. A memory dump of the offending VM was captured before it was removed from the network for imaging and analysis. Our recruiter mentioned he received an email from someone regarding their resume. A copy of the email was recovered and is provided for reference. Find and decode the source of the malware to find the flag.
Artifacts Provided
- flounder-pc-memdump.elf — full memory capture of the recruiter’s VM.
- imageinfo.txt —
Volatilityimageinfooutput for the dump, pointing straight atWin7SP1x64. - Resume.eml — the phishing email itself.
Analysis
The email
The .eml is a plain resume pitch, nothing attached directly — just a link:
From: Brian Loodworm <[email protected]>
To: [email protected]
Subject: Resume
Hi Frank, someone told me you would be great to review my resume..
Could you have a look?
resume.zip [1]
[1] http://10.10.99.55:8080/resume.zip
No attachment to pull apart on disk — the payload was fetched live and has to be carved back out of memory instead.
Recon — pstree
Since imageinfo.txt already hands us the profile, no need to burn time re-running imageinfo:
volatility -f flounder-pc-memdump.elf --profile=Win7SP1x64 pstree
0xfffffa80020bb630:explorer.exe 2044 2012 36 926 2017-10-04 18:04:41 UTC+0000
. 0xfffffa80022622e0:VBoxTray.exe 1476 2044 13 146 2017-10-04 18:04:42 UTC+0000
. 0xfffffa80007e0b30:thunderbird.ex 2812 2044 50 534 2017-10-04 18:06:24 UTC+0000
. 0xfffffa800224e060:powershell.exe 496 2044 12 300 2017-10-04 18:06:58 UTC+0000
.. 0xfffffa8000839060:powershell.exe 2752 496 20 396 2017-10-04 18:07:00 UTC+0000
thunderbird.exe is the mail client that opened the link, and it’s the direct parent of a powershell.exe, which itself spawned a second powershell.exe. Two stages of PowerShell hanging off a mail client is exactly the shape of a malicious-attachment-turned-loader.
netscan backs this up — the box talked to 10.10.99.55 on both :80 and :8080 from a powershell.exe-owned socket, matching the link in the email:
0x1fc04490 TCPv4 10.10.100.43:49246 10.10.99.55:80 CLOSED 2752 powershell.exe
0x1fc3d320 TCPv4 10.10.100.43:49247 10.10.99.55:80 CLOSED 2752 powershell.exe
Carving the “resume”
We know a file named resume-something has to be sitting on disk, so filescan for it:
volatility -f flounder-pc-memdump.elf --profile=Win7SP1x64 filescan | grep resume
0x000000001e1f6200 1 0 R--r-- \Device\HarddiskVolume2\Users\user\Desktop\resume.pdf.lnk
0x000000001e8feb70 1 1 R--rw- \Device\HarddiskVolume2\Users\user\Desktop\resume.pdf.lnk
Not a PDF — a .pdf.lnk. A Windows shortcut wearing a document’s extension, banking on Explorer’s default “hide known file extensions” to make it look like resume.pdf. .lnk files carry their own Target/argument fields, so it doesn’t need a dropped EXE — the shortcut itself is the payload.
timeliner corroborates the whole delivery-to-execution chain via USER ASSIST:
2017-10-03 02:09:48 UTC C:\Users\user\AppData\Local\Temp\Temp1_resume[1].zip\resume.pdf.lnk (extracted from the downloaded zip)
2017-10-03 02:25:04 UTC C:\share\resume.pdf.lnk
2017-10-04 17:58:03 UTC C:\Users\user\Desktop\resume\resume.pdf.lnk
2017-10-04 18:06:58 UTC C:\Users\user\Desktop\resume.pdf.lnk (Count: 3 — the execution that shows up in pstree)
Dumped both offsets with dumpfiles:
volatility -f flounder-pc-memdump.elf --profile=Win7SP1x64 dumpfiles -Q 0x000000001e1f6200 -D .
Two files drop out — file.496.0xfffffa80017dcc60.resume.pdf.lnk.vacb and file.496.0xfffffa80022ac740.resume.pdf.lnk.dat. Same underlying data, the .vacb one just has extra null-byte padding at the end.
Stage 1 — the LNK’s embedded command
.lnk files store their target/argument strings UTF-16LE, so strings -el (not plain strings) is what actually pulls anything readable out:
strings -el file.496.0xfffffa80022ac740.resume.pdf.lnk.dat
..\..\..\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
-win hidden -Ep ByPass $r =
[Text.Encoding]::ASCII.GetString([Convert]::FromBase64String('JHN0UCwkc2lQ...'));
iex $r;
Base64-decoding that blob gives a small self-referencing loader:
| |
The .lnk file is its own dropper: no second file to fetch, no on-disk staging beyond the shortcut. It reopens itself, seeks to byte offset 3230, reads 9676 bytes, and treats that region of its own file as a UTF-16-encoded base64 blob to iex. That’s the second powershell.exe we saw in pstree — same file, same offsets, self-hosted second stage.
Stage 2 — Empire-style beacon, RC4 keystream
Same strings -el dump of the .dat file has that second blob sitting further down — a much larger base64 chunk. Decoded and read through [Text.Encoding]::Unicode.GetString(...) to reverse the UTF-16LE:
| |
Textbook Empire staging behavior: it flips off ScriptBlockLogging and force-fails the AMSI init field via reflection before doing anything else, so none of this shows up in the usual telemetry. $R is a hand-rolled RC4 (KSA + PRGA, byte-for-byte) keyed with a static ASCII string, used to decrypt whatever /login/process.php returns before IEX-ing it — the first 4 bytes of the response are treated as extra IV material appended to the key.
None of that second network round-trip matters for the flag, though — it’s sitting in plaintext right there in the decoded script:Spoiler
$flag='HTB{$_j0G_y0uR_M3m0rY_$}'.
Full chain
Resume.eml
└─ link → resume.zip (fetched, never touches disk as a zip)
└─ resume.pdf.lnk (Desktop, double-extension disguise)
└─ PowerShell #1 (base64, UTF-16) — self-seeks its own .lnk file at offset 3230/9676
└─ PowerShell #2 (base64, UTF-16) — AMSI bypass, ScriptBlockLogging off, RC4-keyed Empire beacon
└─ FLAG (plaintext in the decoded script, before the C2 round-trip even matters)
.lnk never drops a second file. Stage 1 reopens itself and reads its own bytes at a hardcoded offset for stage 2. Any tooling that only inspects a .lnk’s Target/Arguments fields and ignores trailing bytes appended past the structure it expects will walk straight past the actual payload.