In this Sherlock, Players will investigate an incident inspired by rise of malicious google ads for softwares mostly used by individuals like streaming, productivity or note taking applications. Players will analyze windows artifacts to uncover all stages of cyber kill chain.
A streamer looking for OBS Studio landed on a lookalike download site and pulled a trojanised installer archive. The browser left no usable history for the download, but the NTFS journal and the zip’s Zone.Identifier stream still recorded the rename and the origin. Running the installer dropped a legitimate OBS alongside a backdoor in a gibberish-named folder in the user profile. The backdoor was kept alive by a scheduled task named after a trusted Windows component, then resolved a random-looking domain and an S3 bucket, both visible in the DNS client log. The analyst’s later triage left its own traces in the same image, which identifies who collected it and from where.
MFTECmd for the file table and the USN journal (-m $MFT resolves parent paths). Small streams and text files are resident inside the MFT, so strings works on it tooWindows\prefetch → PECmdAmcacheParser, gives the SHA-1 of executed binariesWindows\System32\winevt\Logs → EvtxECmd. The DNS-Client channel (event 3008) is the useful onegrepRBCmd, SBECmd, LECmd, regipyTimestamp note: Q3 wants
YYYY-MM-DD hh:mm:ss. The USN journal stores UTC, so use the parsed value as is.
The Edge History database for Simon.stark has no entry for the OBS download, so browser artifacts are a dead end. The downloaded zip carries a Zone.Identifier alternate data stream, and that stream is small enough to be resident in the $MFT. It holds the HostUrl the browser stamped on the file, which is the full download link.
MFTECmd -f '$MFT' --csv work/mft --csvf mft.csv
strings -a '$MFT' | grep -i HostUrl | grep -i obs
Gotcha: Searching browser history and WebCache for the URL finds nothing useful. The mark-of-the-web stream in the MFT is what survives.
Take the domain from the Q4 URL and look for it in the DNS-Client log. Event 3008 records the query name and the addresses it resolved to, so the lookup for the lookalike domain gives the hosting IP directly.
EvtxECmd -d Logs --csv work/evtx
grep -i obsproicet work/evtx/*.csv | grep 3008
From Q5 we have the server IP. pfirewall.log logs each connection with its source port, and the download shows up as a run of consecutive ephemeral ports from the workstation to port 80 on that server. Filter on the IP, sort by source port and take the top one.
grep 13.232.96.186 pfirewall.log | sort -k6 -n
The USN journal logs every file create and rename. Parse $J against the MFT and filter for zip names containing obs. The browser first writes a .zip.part file in Downloads, and the rename that drops the .part suffix gives the original name.
MFTECmd -f '$J' -m '$MFT' --csv work --csvf usn.csv
python3 -I -c "import csv,sys;[print(r['UpdateTimestamp'],r['UpdateReasons'],r['Name']) for r in csv.DictReader(open('work/usn.csv',encoding='utf-8-sig')) if '.zip' in r['Name'].lower() and 'obs' in r['Name'].lower()]"
Same USN data, next entry in the chain. A RenameOldName record for the original zip is followed by a RenameNewName record in a different directory. Because the journal was parsed with -m $MFT, the parent path is resolved and the full destination path reads straight off the row.
python3 -I -c "import csv;[print(r['UpdateTimestamp'],r['UpdateReasons'],r['ParentPath'],r['Name']) for r in csv.DictReader(open('work/usn.csv',encoding='utf-8-sig')) if 'Rename' in r['UpdateReasons'] and '.zip' in r['Name'].lower()]"
The timestamp on the Q2 RenameNewName record is the answer. The earlier .part to final-name rename in Downloads happened roughly a minute and a half before it, so check that you are reading the second rename, not the browser finishing the download.
grep -i 'Obs Streaming Software.zip' work/usn.csv | grep -i RenameNewName
Gotcha: The journal holds two renames for this file. The download-complete rename is the first one; the user’s own move into
Documents\Streaming Softwareis the one this question wants.
The zip was extracted next to itself under Documents\Streaming Software. AmcacheParser records the SHA-1 of executables that ran, and the installer obs-studio-28.1.2-full-installer-x64.exe is listed there under the extracted folder.
AmcacheParser -f Amcache.hve --csv work/amc
grep -i 'obs-studio-28.1.2-full-installer' work/amc/*UnassociatedFileEntries.csv
Parse prefetch and look at what ran just after the installer. Alongside the real OBS binaries there is a prefetch entry for an executable with a long nonsense name, and its FilesLoaded list points at a folder with an equally nonsense name directly under the user profile. The MFT confirms the file exists at that path.
PECmd -d Windows/prefetch --csv work/pf -q
python3 -I -c "import csv;[print(r['LastRun'],r['ExecutableName'],r['SourceFilename']) for r in csv.DictReader(open('work/pf/'+__import__('os').listdir('work/pf')[0],encoding='utf-8-sig')) if 'LAT TAKEWODE' in r['ExecutableName'] or 'OBS-STUDIO' in r['ExecutableName']]"
Tip: Sort prefetch by last run time around the installer’s execution. A random-looking executable name in a random-looking user-profile folder is the outlier.
A prefetch filename is <EXE>-<8 hex>.pf, and the hash is derived from the executable’s path. The backdoor from Q8 has its own .pf file, and the suffix is the answer.
ls Windows/prefetch | grep -i 'LAT TAKEWODE'
Scheduled tasks are stored as UTF-16 XML under Windows\System32\Tasks. Decode them and look for the one whose <Command> is the Q8 backdoor. Its task name imitates a built-in Windows component, so it blends in with the normal task list.
iconv -f UTF-16 -t UTF-8 Windows/System32/Tasks/* | grep -i -B2 -A2 'Miloyeki'
Back in the EvtxECmd output, list DNS-Client 3008 events around the backdoor’s creation. Unfiltered, the list floods with normal browsing, so narrow it to the minutes after the backdoor first ran. One query stands out as a long random label on a random TLD, and the format mask (25 characters, a dot, 10 characters) matches it. This was identified by timing and shape rather than by a resolver verdict in the log.
grep 3008 work/evtx/*.csv | grep '2023-05-05 10:23'
Same DNS-Client log, a few seconds after the Q11 lookup. An amazonaws.com S3 hostname is queried, and its shape fits the format mask. As with Q11 the evidence is timing and the mask; DNS shows the lookup, not any data leaving.
grep 3008 work/evtx/*.csv | grep -i amazonaws
A short text note such as Week 1 plan.txt is small enough to be resident in the $MFT, so its contents can be read without the file’s data clusters. Grep the MFT for the note’s name and for topic-style keywords, and the plan’s text appears next to its record.
strings -a '$MFT' | grep -i -E 'week ?1|topic'
No log names the analyst outright, so this one was reasoned. Security event 4648 (explicit credential logon) shows simon.stark authenticating to a second domain account on DESKTOP-887GK2L at the time the triage tools ran, and a profile for that account exists on the machine. That account’s name is the analyst’s.
grep -i 4648 work/evtx/*.csv | grep -i DESKTOP-887GK2L
Note: This answer comes from the 4648 target account and the profile folder, not from an artifact that states the analyst’s role.
Event logs, LNK files, jump lists, RunMRU and TypedPaths gave nothing for the share. The path survived in the shellbags of the Simon.stark UsrClass.dat, which record folders the account browsed, including network ones. SBECmd only reads the hive cleanly when the transaction logs sit beside it, so copy the hives with their .LOG1/.LOG2 files into a scratch directory first. Using the Q14 account name, the folder trail runs down a share on DESKTOP-887GK2L into the analyst’s Forela-Triage-Workstation folder.
SBECmd -d /tmp/sbin --csv work/sb
Gotcha: Parsing the hive in place, without its transaction logs, misses the most recent shellbag entries.
| Phase | Action |
|---|---|
| Initial Access | Malicious ad or lookalike site delivers a trojanised OBS Studio zip from obsproicet[.]net |
| Initial Access | Zip downloaded over several parallel HTTP connections, then renamed and moved into Documents\Streaming Software |
| Execution | Installer from the zip runs, installing real OBS and a backdoor in a gibberish-named profile folder |
| Persistence | Scheduled task named COMSurrogate launches the backdoor |
| Command and Control | Backdoor queries a random-looking domain |
| Exfiltration | Backdoor resolves an S3 bucket hostname |
| Response | Analyst CyberJunkie triages the host from a network share containing acquisition tools |
| Type | Value |
|---|---|
| URL | hxxp[://]obsproicet[.]net/download/v28_23/OBS-Studio-28.1.2-Full-Installer-x64.zip |
| Domain | obsproicet[.]net |
| IP | 13.232.96[.]186 |
| Domain (random) | oaueeewy3pdy31g3kpqorpc4e[.]qopgwwytep |
| Domain (S3) | bbuseruploads[.]s3[.]amazonaws[.]com |
| SHA-1 (installer) | 35e3582a9ed14f8a4bb81fd6aca3f0009c78a3a1 |
| File (backdoor) | C:\Users\Simon.stark\Miloyeki ker konoyogi\lat takewode libigax weloj jihi quimodo datex dob cijoyi mawiropo.exe |
| Prefetch | D8A6D943 |
| Scheduled task | COMSurrogate |
| Technique | ID | Description |
|---|---|---|
| Drive-by Compromise | T1189 | Streamer reached a lookalike OBS download site |
| User Execution: Malicious File | T1204.002 | User ran the installer from the downloaded zip |
| Scheduled Task/Job: Scheduled Task | T1053.005 | Task launches the backdoor |
| Masquerading: Match Legitimate Name or Location | T1036.005 | Task named after a Windows COM component |
| Dynamic Resolution: Domain Generation Algorithms | T1568.002 | Random-looking domain queried by the backdoor |
| Exfiltration to Cloud Storage | T1567.002 | S3 bucket contacted for upload |
Browser history is not the only record of a download. Edge history held nothing, yet the Zone.Identifier stream in the MFT and the USN journal preserved the origin URL and the rename chain. Collect $MFT and $J as a standard part of triage, and treat resident ADS content as a source for download provenance.
Trojanised installers beat reputation checks that only look at the vendor name. The bundle ran a legitimate OBS install alongside the backdoor, so the user saw a working app. Block executables from user-writable folders and from freshly downloaded archives, and use application control that keys on publisher and hash, not filename.
A scheduled task named after a Windows component should still be checked against its command line. COMSurrogate sounds routine, but its action pointed at an executable in the user profile. Alert on tasks whose action runs from a profile directory, regardless of task name.
DNS-Client logging gave the clearest C2 and exfil signal. Event 3008 showed a random-label domain and an S3 hostname seconds after the backdoor ran. Forwarding that channel and flagging high-entropy names and cloud-storage lookups from non-browser processes would have caught the backdoor on its first run.
Triage activity leaves artifacts too. The responder’s access to a share and use of explicit credentials appeared in shellbags and Security 4648. Record who collects evidence and from where, so those traces are not mistaken for attacker activity.
A fake OBS download gave the attacker a backdoor that looked like a working streaming install, with persistence under a trusted-sounding task name. The file-system journals and DNS client log rebuilt the whole chain after the fact, even though the browser itself had recorded nothing.