In this Sherlock players will learn to capture a users movements by Wi-Fi patterns and trace a users web usage tracking downloads and program executions.
A KAPE collection from a Windows laptop was used to rebuild a suspect’s movements on 30 May 2025 from Wi-Fi artifacts alone. The WLAN and NetworkProfile event logs, the registry’s NetworkList and DHCP interface values, and the saved wireless profiles placed the machine at two cafés in sequence, with lease times and gateway MACs for each. Browser history from Edge and Brave showed the research trail (a speech on YouTube, a book on Wikipedia), the downloads made at each venue, and a Reddit account. A manifesto draft started at the first café left a shortcut and an NTFS-resident copy of its text, and a VirtualBox VM was created after the second connection. The first café’s location had to be placed from the Windows location service cache and open-source listings.
KAPEOUT.zip, extracted to kape/KAPEOUT/C/ → registry hives, event logs, user profile data, $MFTWindows/System32/winevt/logs → parse with EvtxECmdSYSTEM, SOFTWARE and their .LOG1/.LOG2 transaction logs → regipy, replay the logs before readingProgramData → read as textHistory, Login Data and Web Data → copy out and open with sqlite3Recent → LECmd / JLECmd$MFT → strings / grep for resident content and file namesNetCore.etl, Wifi.etl → no parser used, strings onlyTimestamp note: The machine’s local time is UTC-6. Every answer in this case is the UTC value as EvtxECmd and the registry epoch values print it.
The computer name lives in the SYSTEM hive under ControlSet001\Control\ComputerName\ComputerName. The hive in a KAPE collection is dirty, so replay it with its .LOG1/.LOG2 first. The Computer field in the parsed event logs shows the same name in a different case, which confirms it.
python3 -I -c "from regipy.registry import RegistryHive as R; print(R('SYSTEM').get_key('\\ControlSet001\\Control\\ComputerName\\ComputerName').get_values())"
EvtxECmd -d kape/KAPEOUT/C/Windows/System32/winevt/logs --csv work/evtx
Parse the event logs and filter the Microsoft-Windows-WLAN-AutoConfig/Operational channel for the day. The earliest connection event (8001) at 18:22:48 UTC names the profile, and the saved profile XML stores the SSID as hex, which decodes to the same name.
EvtxECmd -d kape/KAPEOUT/C/Windows/System32/winevt/logs --csv work/evtx
DHCP lease times are stored per interface in the SYSTEM hive as LeaseObtainedTime epoch values. Convert the value attached to the first café’s interface to UTC.
python3 -I -c "import datetime as d; print(d.datetime.fromtimestamp(1748629368, d.UTC))"
Tip: The lease lands in the same second as the WLAN AutoConfig connect event from Q2, which is a quick sanity check.
The live hive no longer holds this lease, since the interface was reused for later connections. Strings carved from the SYSTEM transaction logs show a 172.16.100.x address beside the gateway 172.16.100.254, and the one address in that subnet that is not the gateway is the client’s. This one was reasoned from carved DHCP strings rather than read from a clean key.
strings -e l SYSTEM.LOG1 SYSTEM.LOG2 | grep -E '172\.16\.100\.'
Gotcha: The
SYSTEMhive’s ownDhcpIPAddressvalues belong to later connections, so only the transaction logs still carry the first café’s lease.
SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\Unmanaged holds one key per network, with the gateway MAC in DefaultGatewayMac. The key for the first café (the second profile of that name, ArboretumCoffee 2) holds e4d12496a5d1, which is the answer in the dash-separated format.
python3 -I -c "from regipy.registry import RegistryHive as R; [print(s.name, s.get_value('DefaultGatewayMac').hex()) for s in R('SOFTWARE').get_key('\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Signatures\\Unmanaged').iter_subkeys()]"
Event 10000 is a network connect and 10001 a disconnect, both written by the NetworkProfile provider to its own operational channel. Reference knowledge; the channel name is what EvtxECmd prints in the Channel column for those events.
In the parsed NetworkProfile events, find the 10001 disconnect for the first café’s profile. It lands at 18:55:45 UTC, which is after the last download made there (Q10).
grep -E 'NetworkProfile' work/evtx/*.csv | grep -E ',1000[01],'
The next 10000 connect event in the same channel is for the second venue’s profile, two seconds after the WLAN AutoConfig connect in Q14.
grep -E 'NetworkProfile' work/evtx/*.csv | grep -E ',1000[01],'
The second WLAN AutoConfig 8001 event, at 19:05:24 UTC, names the new profile. It matches the profile name in the NetworkProfile 10000 from Q13.
grep -E 'WLAN-AutoConfig' work/evtx/*.csv | grep -E ',8001,'
The Tcpip\Parameters\Interfaces\{GUID} key holds DhcpIPAddress for the interface. Take the value that belongs to the Happy Trails connection.
python3 -I -c "from regipy.registry import RegistryHive as R; [print(s.name, s.get_value('DhcpIPAddress')) for s in R('SYSTEM').get_key('\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces').iter_subkeys()]"
Gotcha:
stringsonNetCore.etlalso turns up a192.168.10.xaddress that is not this lease. Only the registry value ties to the interface.
The current LeaseObtainedTime in the live hive is the later Snack Attack Guest connection, not Happy Trails. Compare the original SYSTEM against the log-replayed copy: the Happy Trails lease only survives in the transaction logs, as epoch 1748631962, which is 19:06:02 UTC.
python3 -I -c "import datetime as d; print(d.datetime.fromtimestamp(1748631962, d.UTC))"
Gotcha: The lease time in the live registry belongs to a later network. Replay or carve the
.LOG1/.LOG2files for the earlier one.
Same NetworkList\Signatures\Unmanaged source as Q5, now the key for the Happy Trails network: DefaultGatewayMac is 4cba7de18c30.
python3 -I -c "from regipy.registry import RegistryHive as R; [print(s.name, s.get_value('DefaultGatewayMac').hex()) for s in R('SOFTWARE').get_key('\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Signatures\\Unmanaged').iter_subkeys()]"
Gotcha: The captive-portal URL in the browser history carries an
ap=parameter with a MAC. That is the access point’s radio address, not the gateway MAC the registry stores, and it is not the expected answer.
Nothing in the host names a street, so this needs location data. The Windows location service cache (LfSvc) stores Wi-Fi tiles whose file names are Bing Maps quadkeys; decoding them puts the machine in Fort Collins, Colorado. A business listing for Arboretum Coffee (frankiapp.com/business/arboretum-coffee-763976) gives the address, 221 W Prospect Rd. The street is reasoned from the tile region plus the listing, not read from an artifact.
grep -ril 'arboretum' kape/ | head
Run LECmd over the Recent folder. A shortcut in it points to a text file on the user’s OneDrive desktop, C:\Users\Ernes\OneDrive\Desktop, with a title that reads like a manifesto.
LECmd -d kape/KAPEOUT/C/Users/Ernes/AppData/Roaming/Microsoft/Windows/Recent --csv work/lnk
The file itself was not collected, but a short text file is small enough to be resident in its $MFT record. Search the MFT for the file name and read the content out of that record.
strings -e l kape/KAPEOUT/C/\$MFT | grep -n 'Chains Not Seen'
Edge History, urls table, around 18:37 UTC. A YouTube watch page for a Malcolm X speech is the first research visit.
sqlite3 work/br/Edge_History "select datetime(last_visit_time/1000000-11644473600,'unixepoch'), title from urls where url like '%youtube%' order by 1"
Same Edge database a few minutes later (18:40 UTC): a Wikipedia article for a novel.
sqlite3 work/br/Edge_History "select datetime(last_visit_time/1000000-11644473600,'unixepoch'), title from urls where url like '%wikipedia%' order by 1"
Brave’s History after the move to the second café contains visits to a single forum site.
sqlite3 work/br/Brave_History "select datetime(last_visit_time/1000000-11644473600,'unixepoch'), url from urls order by 1"
Brave’s Login Data and Web Data hold saved logins and autofill entries for the account used on the site from Q19.
sqlite3 work/br/Login_Data "select origin_url, username_value from logins"
A VirtualBox VM leaves a .vbox definition file. Scan the $MFT for it; the VM’s name is the file’s base name.
strings -e l kape/KAPEOUT/C/\$MFT | grep -i '\.vbox'
Edge History, downloads table, sorted by time. The last row before the 18:55:45 disconnect from Q12 is at 18:51:25 UTC.
sqlite3 work/br/Edge_History "select datetime(start_time/1000000-11644473600,'unixepoch'), target_path from downloads order by 1"
The previous download installed Brave, so the downloads at the second venue are in Brave’s History. The first one is at 19:08:06 UTC, shortly after the connection in Q13.
sqlite3 work/br/Brave_History "select datetime(start_time/1000000-11644473600,'unixepoch'), target_path from downloads order by 1"
Wireless profiles sit under ProgramData\Microsoft\Wlansvc\Profiles\Interfaces\{interface GUID}\, one GUID-named XML per saved network. Grep for the first café’s SSID to find the right file.
grep -rl 'ArboretumCoffee' kape/KAPEOUT/C/ProgramData/Microsoft/Wlansvc/Profiles/
The same profile XML has an <authentication> element under authEncryption.
grep -o '<authentication>[^<]*' kape/KAPEOUT/C/ProgramData/Microsoft/Wlansvc/Profiles/Interfaces/*/{BAC95378-DC6B-4464-918E-4E005F747786}.xml
| Phase | Action |
|---|---|
| Discovery | Laptop InvisibleChains joins the first café’s Wi-Fi and takes a DHCP lease |
| Collection | Starts a manifesto draft in a text file on the OneDrive desktop |
| Collection | Watches a speech on YouTube and reads a Wikipedia article on a novel |
| Command and Control | Downloads the Brave browser installer, the last download at the first café |
| Discovery | Disconnects from the first café |
| Discovery | Joins the second café’s Wi-Fi and takes a new lease |
| Command and Control | Downloads the VirtualBox installer in Brave |
| Collection | Visits Reddit and logs in under a saved account |
| Defense Evasion | Creates a VirtualBox VM |
| Timestamp (UTC) | Event |
|---|---|
| 2025-05-30 18:22:48 | First café connection and DHCP lease |
| 2025-05-30 18:37 | YouTube speech watched in Edge |
| 2025-05-30 18:40 | Wikipedia article on the novel opened |
| 2025-05-30 18:51:25 | Last Edge download at the first café |
| 2025-05-30 18:55:45 | Disconnect from the first café |
| 2025-05-30 19:05:24 | WLAN AutoConfig connect to the second café |
| 2025-05-30 19:05:26 | NetworkProfile connect event for the second café |
| 2025-05-30 19:06:02 | Second café DHCP lease obtained |
| 2025-05-30 19:08:06 | VirtualBox installer downloaded in Brave |
| Type | Value |
|---|---|
| Host | INVISIBLECHAINS |
| SSID | ArboretumCoffee, Happy Trails Guest |
| Gateway MAC | E4-D1-24-96-A5-D1, 4C-BA-7D-E1-8C-30 |
| IP | 172.16.100[.]16, 192.168.10[.]100 |
| File | C:\Users\Ernes\OneDrive\Desktop\The Chains Not Seen.txt |
| File | BraveBrowserSetup.exe, VirtualBox-7.1.8-168469-Win.exe |
| VM | LastHope.vbox |
| Account | Reddit FinanciallyFree3636 |
| Profile | {BAC95378-DC6B-4464-918E-4E005F747786}.xml |
| Technique | ID | Description |
|---|---|---|
| System Network Configuration Discovery: Wi-Fi Discovery | T1016.002 | Wi-Fi profiles, leases and gateway MACs reconstruct movement between venues |
| Browser Information Discovery | T1217 | Edge and Brave history show the research trail and forum visit |
| Data from Local System | T1005 | Manifesto draft recovered from its shortcut and resident $MFT content |
| Ingress Tool Transfer | T1105 | Browser and VirtualBox installers downloaded |
| Hide Artifacts: Run Virtual Instance | T1564.006 | LastHope VirtualBox VM created |
| Credentials from Password Stores | T1555 | Saved Wi-Fi profile and browser logins hold credentials |
Wi-Fi history is a movement log, and it survives in several places. NetworkProfile 10000/10001 give connect and disconnect to the second, WLAN AutoConfig names the SSID, and NetworkList keeps the gateway MAC. Together they place a device at a venue without any network capture.
Dirty registry hives hide evidence. The live SYSTEM hive held only the latest lease; the earlier one existed in the transaction logs. Always replay .LOG1/.LOG2 before querying a KAPE-collected hive, and compare before and after.
Resident $MFT data and shortcuts outlive deleted or uncollected files. The manifesto text was readable from its MFT record and its path from a Recent shortcut, even though the file was not collected. Treat Recent, $MFT and OneDrive metadata as content sources, not just name sources.
Wireless profiles and browser stores keep credentials. The profile XML names the authentication method and holds the encrypted key, and Brave’s Login Data and Web Data expose account names. Collect these on seizure and protect them as sensitive.
Location can be recovered from the OS location cache. The LfSvc Wi-Fi tiles narrowed the machine to a city, which a public business listing then narrowed to a street. Disable the location service on devices where that trail matters.
Two Wi-Fi connections, a few browser databases and an NTFS record were enough to place the suspect in two specific cafés, show what they researched and installed at each, and recover the opening of a manifesto. No single artifact told the whole story; the value was in lining them up on one UTC clock.