In this Sherlock, you’ll tackle the aftermath of a sophisticated phishing attack targeted at a new joiner at Forela. The unsuspecting newcomer, while downloading their onboarding documentation, has inadvertently opened a malicious attachment. The Sherlock, which sits at an easy level of difficulty, involves players analyzing the event utilizing the limited artifacts provided.
A new joiner at Forela was phished with a fake onboarding package and downloaded a malicious HTA from a Google Drive style download link, alongside a legitimate-looking PowerPoint. The only evidence is a single $MFT, but it holds enough: the HTA’s Zone.Identifier stream preserves where the file came from, and the record’s attributes show a gap between how much disk the file occupies and how big it really is. The user also kept a plaintext notes file with their work credentials; it was deleted, but because the content is small enough to live inside the MFT record, the password is still recoverable. The $MFT also allows a count of what remains in the user profile.
evidence/mft.raw.bz2 → decompress with bzip2, hash with md5sum, parse with MFTECmd. Single $MFT image, nothing elsework/mft/mft.csv → query with Python. Does not expose resident file content, so small files need the raw recordFormat note: The pptx timestamp is submitted as
DD/MM/YYYY HH:mm:ss, the reverse of the ISO order MFTECmd prints.
The evidence ships bzip2-compressed. Hash the decompressed $MFT, not the archive, since the archive hash is a different value.
bzip2 -dc evidence/mft.raw.bz2 > work/mft/MFT.raw; md5sum work/mft/MFT.raw
Gotcha:
md5sumon the.bz2gives the wrong answer; decompress first.
Parse the MFT to CSV with MFTECmd and list the directories directly under \Users. Only one real profile folder exists, and it is the user whose Downloads folder holds everything else in this case.
MFTECmd -f work/mft/MFT.raw --csv work/mft
This one was reasoned rather than read from a single artifact field, and HTB accepted the result. Filter the CSV to entries whose parent path starts with .\Users, then keep only in-use records that are not directories and not alternate data streams. Deleted records (such as the credentials note) are excluded because they no longer remain, and Zone.Identifier streams are excluded because they are not separate files.
python3 -I count_users.py work/mft/mft.csv
Gotcha: Counting every row under
.\Usersover-counts. Directories, ADS rows and deleted entries all sit in the same CSV.
From Q2, look in the user’s Downloads folder in the parsed CSV. The one .hta file there has a Zone.Identifier alternate data stream beside it, which marks it as a browser download.
MFTECmd -f work/mft/MFT.raw --csv work/mft
MFTECmd shows the content of small Zone.Identifier streams in the CSV. Read the stream attached to the HTA: ZoneId=3 is the Internet zone.
MFTECmd -f work/mft/MFT.raw --csv work/mft
The same Onboarding.hta:Zone.Identifier stream carries a HostUrl field with the full download link. Copy it exactly, including the query string.
MFTECmd -f work/mft/MFT.raw --csv work/mft
The allocated size is the on-disk size of the $DATA attribute, which MFTECmd’s CSV does not report for this file. Parse the raw MFT record for the HTA (record 103820) directly and read the $DATA attribute’s allocated size.
python3 -I parse_record.py work/mft/MFT.raw 103820
The real size is the FileSize column in the MFTECmd CSV for the same record. It is much smaller than the allocated cluster from Q6, which is normal slack.
MFTECmd -f work/mft/MFT.raw --csv work/mft
Find Proposal.pptx in the user’s Downloads folder. The Created0x10 timestamp (the $STANDARD_INFORMATION creation time) is 2023-04-05 13:11:49 UTC, which is when the browser wrote the file. Reformat it to the required day-first layout.
MFTECmd -f work/mft/MFT.raw --csv work/mft
A deleted notes.txt sits in the user’s Work folder. The file is tiny, so its content is resident inside the MFT record itself (record 110620) and survives deletion. MFTECmd does not print resident data for this record, so parse the raw record and read the $DATA attribute directly.
python3 -I parse_record.py work/mft/MFT.raw 110620
Tip: Small deleted text files are worth checking in the raw record. Resident content does not need any cluster recovery.
| Phase | Action |
|---|---|
| Initial Access | Phishing lure leads the new joiner to download Onboarding.hta from a Google-hosted link |
| Initial Access | Legitimate-looking Proposal.pptx downloaded to the same folder |
| Credential Access | Plaintext work credentials sit in Work\notes.txt |
| Defense Evasion | Notes file deleted, but its resident content remains in the MFT record |
| Type | Value |
|---|---|
| File | Onboarding.hta (1144 bytes, ZoneId 3) |
| File | Proposal.pptx |
| URL | hxxps[://]doc-10-8k-docs[.]googleusercontent[.]com/docs/securesc/9p3kedtu9rd1pnhecjfevm1clqmh1kc1/9mob6oj9jdbq89eegoedo0c9f3fpmrnj/1680708975000/04991425918988780232/11676194732725945250Z/1hsQhtmZJW9xZGgniME93H3mXZIV4OKgX |
| Hash (MD5, MFT) | 3730c2fedcdc3ecd9b83cbea08373226 |
| Technique | ID | Description |
|---|---|---|
| Phishing: Spearphishing Link | T1566.002 | Onboarding lure points the user at a download link |
| User Execution: Malicious File | T1204.002 | HTA delivered to the Downloads folder for the user to open |
| Ingress Tool Transfer | T1105 | HTA and PPTX pulled to disk from the Internet zone |
| Unsecured Credentials: Credentials In Files | T1552.001 | Work password stored in a plaintext notes file |
| Indicator Removal: File Deletion | T1070.004 | Notes file deleted, content still resident in the MFT |
Zone.Identifier is an origin record that outlives the download. The HTA’s ZoneId and HostUrl survive in the MFT as a stream, so even with no browser history or network logs the download source is recoverable. Collecting $MFT early gives a source URL for every browser-downloaded file.
HTA delivery should be blocked before it reaches users. .hta files have almost no legitimate use for a new joiner. Blocking the extension at the mail and web gateway, and removing the default mshta.exe association, closes this path.
Deleting a small file does not remove its content. Files of roughly 700 bytes or less are stored resident in the MFT record, so a deleted notes file still gives up its text. Treat deletion of credential files as incomplete remediation and rotate the password regardless.
Plaintext credentials in user folders are a standing risk. A password manager removes the reason to keep a notes.txt, and file-content scanning for password-like strings would have flagged this one.
One
$MFTwas enough to name the user, the HTA, its download source, and a password the user thought they had deleted. The origin data was inZone.Identifierand the secret was resident in a deleted record, so deletion and a missing browser history did not hide either.