MiniDumpWriteDump via Faultrep!CreateMinidump

I found out this old undocumented API “CreateMinidumpW” inside the faultrep.dll on Windows XP and Windows Server 2003. This API ends up calling the dbghelp!MiniDumpWriteDump to dump the process by dynamically loading the dbghelp.dll on runtime.

The function takes 3 arguments. I really have no clue what this 3rd argument’s structure is. I passed 0 as the pointer to the structure so by default we end up getting 0x21 as the MINIDUMP_TYPE.



This is the call stack

As you see it calls the dbghelp!MiniDumpWriteDump by loading the dbghelp.dll using the LoadLibraryExW API.

However, this function ‘faultrep.dll!InternalGenerateMinidumpEx’ doesn’t provide a full dump. As you can see it passes 0x21 or it compares the 3rd argument which is a structure and based on that value it passes 0x325.

What you could do is, patch it to a 0x2 to make it a ‘MiniDumpWithFullMemory’. You can find the 64-bit version of the patched DLL from here https://github.com/OsandaMalith/WindowsInternals/tree/master/CreateMinidump

This is the PoC of calling this API. You can copy the DLL from Windows XP and it will work fine. Not sure how this is useful. Just sharing what I found ๐Ÿ™‚

#include <windows.h>
#include <TlHelp32.h>
#include <iostream>
using namespace std;
/*
Title: Faultrep!CreateMinidump to get a full dump passing MiniDumpWithFullMemory as the MINIDUMP_TYPE.
Author: Osanda Malith Jayathissa (@OsandaMalith)
Research: https://osandamalith.com/2019/09/08/minidumpwritedump-via-faultrepcreateminidump/
The function CreateMinidump is only available in Windows XP and Windows Server 2003.
*/
typedef int(WINAPI *CreateMinidumpProc)(DWORD, LPCWSTR, struct tagSMDumpOptions *);
typedef NTSTATUS(WINAPI *_RtlAdjustPrivilege)(
ULONG Privilege, BOOL Enable,
BOOL CurrentThread, PULONG Enabled);
int _tmain(int argc, _TCHAR* argv[]) {
if (argc < 2) {
wcerr << "[~] Usage: " << argv[0] << " Process Name" << endl;
return -1;
}
DWORD PID = 0;
LPCWSTR Name = argv[1];
wstring FileName(Name);
LPCWSTR processName = L"";
ULONG t;
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 processEntry = {};
processEntry.dwSize = sizeof(PROCESSENTRY32);
wcout << "[~] Faultrep!CreateMinidump Undocumented API from Windows XP and Windows Server 2003" << endl;
wcout << "[+] Author: Osanda Malith Jayathissa (@OsandaMalith)" << endl;
wcout << "[+] Website: https://osandamalith.com" << endl;
if (Process32First(snapshot, (PROCESSENTRY32*)&processEntry)) {
while (_wcsicmp(processName, Name) != 0) {
Process32Next(snapshot, &processEntry);
processName = processEntry.szExeFile;
PID = processEntry.th32ProcessID;
}
wcout << "[+] Got " << Name << " PID: " << PID << endl;
}
else wcout << "[-] Process Name Not Found!" << endl;
_RtlAdjustPrivilege RtlAdjustPrivilege = (_RtlAdjustPrivilege)GetProcAddress(GetModuleHandle(L"ntdll"), "RtlAdjustPrivilege");
CreateMinidumpProc CreateMinidump = (CreateMinidumpProc)GetProcAddress(LoadLibrary(L"faultrep.dll"), "CreateMinidumpW");
RtlAdjustPrivilege(20, TRUE, FALSE, &t);
CreateMinidump(PID, (LPCWSTR)(FileName + L"_dump.dmp").c_str(), 0);
return 0;
}
view raw CreateMinidump.cpp hosted with ❤ by GitHub

UPDATE: I wrote a hot patch for both 32-bit and 64-bit faultrep DLLs. It will allow you to get a full process dump passing MiniDumpWithFullMemory as the MINIDUMP_TYPE. Tested on Windows XP 32-bit and 64-bit. On other systems by copying the original DLLs in the same folder will work fine. You can find the repo with DLL files from here https://github.com/OsandaMalith/WindowsInternals/tree/master/CreateMinidump/Hot%20Patch

#include <windows.h>
#include <TlHelp32.h>
#include <iostream>
using namespace std;
/*
Title: Faultrep!CreateMinidump Hot Patch to get a full dump passing MiniDumpWithFullMemory as the MINIDUMP_TYPE.
Author: Osanda Malith Jayathissa (@OsandaMalith)
Research: https://osandamalith.com/2019/09/08/minidumpwritedump-via-faultrepcreateminidump/
The function CreateMinidump is only available in Windows XP and Windows Server 2003.
If you want to get this working in other Windows systems, copy the DLL from XP or Server 2003 and place it in the same folder.
This DLL has no ASLR enabled and therfore the address are hardcoded.
32-bit Windows XP faultrep.dll = 6945AEBF push 21
32-bit Windows Server 2003 faultrep.dll = 6950BD5E add ecx,21
64-bit Windows XP faultrep.dll = 7FF6E010945 mov r9d,21
*/
typedef int(WINAPI *CreateMinidumpProc)(DWORD, LPCWSTR, struct tagSMDumpOptions *);
typedef NTSTATUS(WINAPI *_RtlAdjustPrivilege)(
ULONG Privilege, BOOL Enable,
BOOL CurrentThread, PULONG Enabled);
int _tmain(int argc, _TCHAR* argv[]) {
if (argc < 2) {
wcerr << "[~] Usage: " << argv[0] << " Process Name" << endl;
return -1;
}
DWORD PID = 0;
LPCWSTR Name = argv[1];
wstring FileName(Name);
LPCWSTR processName = L"";
ULONG t;
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 processEntry = {};
processEntry.dwSize = sizeof(PROCESSENTRY32);
wcout << "[~] Faultrep!CreateMinidump Undocumented API from Windows XP and Windows Server 2003" << endl;
wcout << "[+] Author: Osanda Malith Jayathissa (@OsandaMalith)" << endl;
wcout << "[+] Website: https://osandamalith.com" << endl;
if (Process32First(snapshot, (PROCESSENTRY32*)&processEntry)) {
while (_wcsicmp(processName, Name) != 0) {
Process32Next(snapshot, &processEntry);
processName = processEntry.szExeFile;
PID = processEntry.th32ProcessID;
}
wcout << "[+] Got " << Name << " PID: " << PID << endl;
}
else wcout << "[-] Process Name Not Found!" << endl;
_RtlAdjustPrivilege RtlAdjustPrivilege = (_RtlAdjustPrivilege)GetProcAddress(GetModuleHandle(L"ntdll"), "RtlAdjustPrivilege");
CreateMinidumpProc CreateMinidump = (CreateMinidumpProc)GetProcAddress(LoadLibrary(L"faultrep.dll"), "CreateMinidumpW");
{
#ifndef _WIN64
UCHAR *Patch = (UCHAR*)CreateMinidump + 0x72CC;
//Windows Server 2003
//UCHAR *Patch = (UCHAR*)CreateMinidump + 0x7C51;
#else
UCHAR *Patch = (UCHAR*)CreateMinidump + 0xBF47;
#endif
DWORD old;
VirtualProtect((LPVOID)Patch, sizeof(UCHAR), PAGE_EXECUTE_READWRITE, &old);
*Patch = 0x2; // MiniDumpWithFullMemory
}
wcout << "[+] Dumping" << endl;
RtlAdjustPrivilege(20, TRUE, FALSE, &t);
CreateMinidump(PID, (LPCWSTR)(FileName + L"_dump.dmp").c_str(), 0);
return 0;
}

Some uses ๐Ÿ˜‰

One thought on “MiniDumpWriteDump via Faultrep!CreateMinidump

Leave a Reply