How to dump lsass via spoolsv with DLL side-loading.
To my surprise, this is an effective way to dump lsass without being detected by either Windows Defender or CrowdStrike Falcon (for now).
Generally spoolsv.exe will load C:\Windows\System32\WSDPrintProxy.DLL
and/or C:\Windows\System32\spool\prtprocs\x64\winprint.dll
every time the computer boots. By leveraging DLL-side loading and replacing WSDPrintProxy.DLL or winprint.dll with a DLL of our own creation, we can gain privileged code execution in the spoolsv process, obtain a handle to lsass, and call MiniDumpWriteDump
.
If you've configured a printer through the Windows "add a printer" functionality, generally spoolsv will load WSDPrintProxy.DLL every time the computer boots. On some computers spoolsv doesn't appear to load WSDPrintProxy.DLL at all though, and I'm not sure why. In those cases, you may have better luck with winprint.dll.
Credits to: ired.team for their code on MiniDumpWriteDump and minidumpCallback.
Apologies in advance for my spaghetti code.
When the case DLL_PROCESS_ATTACH
is triggered, the dump
function is called. The dump
function does some setup of structures, finds the PID of lsass, obtains a handle to lsass with process access rights PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE
, and then calls MiniDumpWriteDump
.
Instead of passing a handle to an output file as an argument to MiniDumpWriteDump
, we instead pass a pointer to a MINIDUMP_CALLBACK_INFORMATION
structure that contains the member CallbackRoutine
which contains a pointer to our callback function minidumpCallback
.
This callback is necessary because we need to save the output of MiniDumpWriteDump
to memory and XOR it before writing the dump file to disk. AVs & EDRs will actually detect lsass dump files based on signatures if not obfuscated in some way, even if the initial dump of lsass went undetected.
Compile in release mode.
WSDPrintProxy.DLL is owned by NT SERVICE\TrustedInstaller
by default, so we'll need to take ownership first before we can make changes to it.
Assuming we're a local administrator, we can edit the ACLs to give the administrators group full access.
We'll probably want to make a copy of the legitmate WSDPrintProxy.DLL so we can restore it later after dumping lsass.
Now we'll move our malicious version of WSDPrintProxy.DLL into place.
Now we can either wait for the system to be shutdown/rebooted, or we can force a reboot manually. Running net stop spooler
and net start spooler
will not work, it must be a reboot.
After rebooting, we find our XOR'd dump file written to C:.
At this point, we can transfer the dump file to a Linux machine under our control and use the little xor_decrypt.py
script I made to decrypt the dump file, then we can use pypykatz
to parse the dump file.