Hollow Service is a Windows host forensics lab that covers the compromise of an internal IIS application on a Windows 10 workstation via a KAPE triage collection. The attacker uploaded and renamed an ASPX webshell, executed an encoded PowerShell stager, abused SeImpersonatePrivilege for token impersonation (T1134.001), performed a per-user UAC bypass (T1548.002) to reach SYSTEM, dumped LSASS memory, and left behind local credential findings. Players will investigate the IIS access log, MFT and USN records, Sysmon and Security event logs, Prefetch, Amcache, and registry hives to reconstruct the attack chain.
An external host abused the upload page of an internal IIS application to drop an ASPX webshell, then renamed it to something more innocuous. Through the webshell the attacker ran an encoded PowerShell one-liner that pulled a stager from a remote server. The IIS worker account held a token-impersonation privilege, so a PrintSpoofer binary dropped into the Temp directory was used to move toward SYSTEM, alongside a per-user UAC bypass through a hijacked registry handler. With elevated rights the attacker dumped LSASS memory using a built-in Windows DLL. Local account hashes recovered from the registry hives show one standard user with no password at all.
u_ex260516.log → read with grep. W3C format, so the status and substatus columns sit side by sidewinevt/logs → parse with EvtxECmd. Security 4688 with command-line auditing carries most of the chainMFTECmd for file creation times and namesAmcacheParser for the SHA1 of executables that ransecretsdumpTimestamp note: The Sysmon log only starts around 11:02 on the collection day, after most of the attack. Use Security 4688 events for anything earlier.
Search the IIS log for the upload page the application exposes. Every request to /internalapp/upload.aspx, and the later webshell requests, comes from the same client address in the c-ip column, so it is the attacker’s source.
grep -i internalapp u_ex260516.log
From Q1 we have the attacker IP. The first GET to upload.aspx at 10:36:17 returns 404 3 50. The columns are sc-status sc-substatus sc-win32-status, so the substatus is the middle value, not the 404 and not the trailing win32 code.
grep -i 'GET /internalapp/upload.aspx' u_ex260516.log | head -1
Gotcha: The three numbers after the user agent and referer are status, substatus, win32 status. Reading the first or last one gives the wrong field.
A POST to the upload page at 10:43:36 is followed by GET /internalapp/uploads/shell.aspx?cmd=whoami, so the upload landed in the application’s uploads folder. The path is confirmed on disk by a Security 4688 event at 10:43:50, where csc.exe compiles shell.aspx for the first time, which is ASP.NET compiling a freshly requested page.
grep -E 'POST /internalapp/upload.aspx|shell.aspx' u_ex260516.log
From Q3 the shell started as shell.aspx. Parse the $MFT and look in the uploads directory: a second ASPX file was created at 10:43:36, the same second as the upload, and the later webshell requests in the IIS log use that name instead. The new name is reasoned from the MFT creation time and the request pattern, rather than read from an explicit rename record.
MFTECmd -f '$MFT' --csv work/mft --csvf mft.csv
The renamed webshell takes its command in the query string, and one request carries a powershell -enc payload. PowerShell encodes -EncodedCommand as UTF-16LE base64, so decode it with base64 -d and convert with iconv. The result is an IEX download cradle.
echo '<base64 from the IIS query string>' | base64 -d | iconv -f utf-16le -t utf-8
The host in the download URL from Q5 is the stager’s server, so the C2 address is read straight from the decoded command.
Parse the event logs and list process creations in the attack window. Children of w3wp.exe (the webshell’s whoami, cmd and powershell) all carry the same account in Security 4688, and Sysmon event 1 shows the same user. That is the app pool identity.
EvtxECmd -d winevt/logs --csv work/evtx
From Q7 the shell runs as the service account. At 10:52:57 that account runs whoami /priv, and the listing includes the privilege that PrintSpoofer-style tools need to impersonate a SYSTEM token. Service accounts normally get it by default, which is why the escalation works from a webshell.
grep -i 'whoami' work/evtx/*.csv | grep -i svcapp
A new binary appears in C:\Windows\Temp\ named MicrosoftEdgeUpdate.exe, a name chosen to blend in. AmcacheParser gives its SHA1 (188098b9caf3bc4d1b68dcad50d2e1cbd2e9d519). VirusTotal names the file as PrintSpoofer64.exe, with a hacktool PrintSpoofer threat label.
AmcacheParser -f Amcache.hve --csv work/amc/out
bin/vt 188098b9caf3bc4d1b68dcad50d2e1cbd2e9d519
PrintSpoofer coerces a SYSTEM service to connect to an attacker-controlled named pipe, then impersonates the resulting token. That is Access Token Manipulation: Token Impersonation/Theft. This comes from reference knowledge, not an artifact.
Security 4688 at 10:58:44 records a reg add under the current user’s classes hive, followed by fodhelper.exe. Fodhelper auto-elevates and reads the ms-settings handler from HKCU before HKLM, so a command planted there runs elevated. The key is the command subkey of that handler.
grep -iE 'reg add|fodhelper' work/evtx/*.csv
Copy the SAM and SYSTEM hives to a writable folder (secretsdump needs write access) and dump the local hashes. One non-default user has the NT hash of an empty password, 31d6cfe0d16ae931b73c59d7e0c089c0.
secretsdump.py -sam SAM -system SYSTEM LOCAL
Hint: Compare each non-built-in user’s NT hash with the well-known empty-string hash. Built-in accounts like Guest also show it, so filter those out.
Security 4688 at 11:00:50, after the escalation, shows rundll32.exe calling the MiniDump export of comsvcs.dll with the LSASS process ID, writing the dump to C:\Windows\Temp. The command-line field holds the full string, so copy it verbatim.
grep -i 'comsvcs' work/evtx/*.csv
| Phase | Action |
|---|---|
| Initial Access | Attacker probes the app’s upload page and gets a 404 with a substatus |
| Initial Access | ASPX webshell uploaded to the uploads folder and tested with whoami |
| Defense Evasion | Webshell renamed to a plausible filename |
| Execution | Encoded PowerShell IEX cradle sent through the webshell to a remote server |
| Discovery | whoami /priv run as the IIS service account |
| Privilege Escalation | PrintSpoofer dropped to C:\Windows\Temp under an Edge updater name |
| Privilege Escalation | ms-settings handler hijacked and fodhelper.exe launched for a UAC bypass |
| Credential Access | LSASS dumped with comsvcs.dll MiniDump |
| Timestamp | Event |
|---|---|
| 2026-05-16 10:36:17 | First GET to /internalapp/upload.aspx returns 404 3 50 |
| 2026-05-16 10:43:36 | Webshell uploaded; status.aspx created in the MFT |
| 2026-05-16 10:43:50 | csc.exe compiles the uploaded shell |
| 2026-05-16 10:52:57 | whoami /priv run as the service account |
| 2026-05-16 10:58:44 | reg add of the ms-settings handler, then fodhelper.exe |
| 2026-05-16 11:00:50 | LSASS dumped with comsvcs.dll MiniDump |
| Type | Value |
|---|---|
| IP (attacker, IIS client) | 192.168.100[.]2 |
| IP (C2 / stager host) | 46.101.189[.]224 |
| URL | hxxp[://]46[.]101[.]189[.]224/svc |
| File | C:\inetpub\internalapp\uploads\shell.aspx |
| File | status.aspx |
| File | C:\Windows\Temp\MicrosoftEdgeUpdate.exe (PrintSpoofer) |
| SHA1 | 188098b9caf3bc4d1b68dcad50d2e1cbd2e9d519 |
| File | C:\Windows\Temp\lsass.dmp |
| Registry key | HKCU\Software\Classes\ms-settings\Shell\Open\command |
| Account | DESKTOP-B36HA4E\svcapp (IIS worker), Joe (blank password) |
| Technique | ID | Description |
|---|---|---|
| Server Software Component: Web Shell | T1505.003 | ASPX shell uploaded through the internal application |
| Masquerading: Match Legitimate Name or Location | T1036.005 | Webshell renamed; PrintSpoofer saved under an Edge updater name |
| Command and Scripting Interpreter: PowerShell | T1059.001 | Encoded IEX download cradle |
| Ingress Tool Transfer | T1105 | Stager and PrintSpoofer brought onto the host |
| Access Token Manipulation: Token Impersonation/Theft | T1134.001 | PrintSpoofer abusing SeImpersonatePrivilege |
| Abuse Elevation Control Mechanism: Bypass UAC | T1548.002 | ms-settings handler hijack with fodhelper.exe |
| OS Credential Dumping: LSASS Memory | T1003.001 | comsvcs.dll MiniDump of LSASS |
| Valid Accounts: Local Accounts | T1078.003 | Local account with an empty password found in SAM |
An upload page that stores executable types in a web-served folder is a webshell waiting to happen. The application accepted an .aspx file and left it where IIS would run it. Restrict uploads to an allowlist of extensions, store them outside the web root, and deny script execution on the uploads directory.
The app pool identity held SeImpersonatePrivilege, so any code execution in the site was one step from SYSTEM. Run application pools as ApplicationPoolIdentity or a managed service account with the minimum rights, and alert on whoami /priv and unexpected binaries launched from w3wp.exe.
Process creation with command-line auditing carried the whole story. Security 4688 with command lines caught the encoded PowerShell, the reg add on the ms-settings handler and the comsvcs.dll dump, while Sysmon only covered the last stretch. Deploy Sysmon before an incident, not after, and alert on rundll32 loading comsvcs.dll with MiniDump.
Per-user registry handlers make a cheap UAC bypass. Writes to HKCU\Software\Classes\ms-settings\Shell\Open\command followed by fodhelper.exe are rare in normal use and make a precise detection. Setting UAC to always notify closes this class of auto-elevate abuse.
A local account with no password is a free foothold. The SAM dump shows one user with an empty NT hash. Enforce a password policy that blocks blank passwords and remove unused local accounts.
The attacker went from a single file upload to a LSASS dump on the same host in under half an hour, using a webshell, a download cradle, a public escalation tool and a built-in Windows DLL. The service account’s token privilege and the unrestricted upload folder were the two weaknesses that made every later step easy.