diff options
Diffstat (limited to 'KMemDriver')
-rw-r--r-- | KMemDriver/KMemDriver.c | 298 | ||||
-rw-r--r-- | KMemDriver/KMemDriver.vcxproj | 1 | ||||
-rw-r--r-- | KMemDriver/KMemDriver.vcxproj.filters | 3 | ||||
-rw-r--r-- | KMemDriver/Memory.c | 165 | ||||
-rw-r--r-- | KMemDriver/VAD.c | 133 |
5 files changed, 302 insertions, 298 deletions
diff --git a/KMemDriver/KMemDriver.c b/KMemDriver/KMemDriver.c index c891736..786a68d 100644 --- a/KMemDriver/KMemDriver.c +++ b/KMemDriver/KMemDriver.c @@ -7,12 +7,6 @@ #define CHEAT_EXE L"kmem" -#ifdef _DEBUG_ -#define KDBG(fmt, ...) DbgPrint("KMemDriver[%01d]: " fmt, KeGetCurrentIrql(), __VA_ARGS__) -#else -#define KDBG(fmt, ...) -#endif - #ifndef _DEBUG_ #define FNZERO_MARKER() \ do { \ @@ -690,171 +684,6 @@ NTSTATUS UpdatePPEPIfRequired( return status; } -NTSTATUS GetPages( - IN PEPROCESS Process, - OUT MEMORY_BASIC_INFORMATION *mbiArr, - IN SIZE_T mbiArrLen, OUT SIZE_T *mbiUsed, - IN PVOID start_addr -) -{ - NTSTATUS status; - HANDLE procHandle; - SIZE_T i, mbiLength, mbiReturn; - ULONG_PTR baseAddr = (ULONG_PTR)start_addr; - - status = ObOpenObjectByPointer(Process, - OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, GENERIC_ALL, - *PsProcessType, KernelMode, &procHandle - ); - if (!NT_SUCCESS(status)) { - KDBG("ObOpenObjectByPointer failed with 0x%X\n", status); - return status; - } - - KDBG("ZwQueryVirtualMemory max entries: %u\n", mbiArrLen); - *mbiUsed = 0; - do { - mbiReturn = 0; - status = ZwQueryVirtualMemory(procHandle, (PVOID)baseAddr, - MemoryBasicInformation, mbiArr, sizeof *mbiArr * mbiArrLen, &mbiReturn); - mbiLength = mbiReturn / sizeof *mbiArr; - if (!NT_SUCCESS(status)) { - if (status == STATUS_INVALID_PARAMETER) - status = STATUS_SUCCESS; - else - KDBG("ZwQueryVirtualMemory failed with 0x%X\n", status); - break; - } - else { - for (i = 0; i < mbiLength; ++i) - KDBG("Page #%03u: base -> 0x%p, prot -> 0x%02X, size -> 0x%X\n", - (*mbiUsed) + i, (*(mbiArr + i)).BaseAddress, (*(mbiArr + i)).Protect, - (*(mbiArr + i)).RegionSize); - } - baseAddr += (SIZE_T)(mbiArr + mbiLength - 1)->RegionSize; - *mbiUsed += mbiLength; - mbiArr += mbiLength; - } while (*mbiUsed < mbiArrLen && mbiReturn > 0); - - ZwClose(procHandle); - return status; -} - -NTSTATUS GetModules( - IN PEPROCESS Process, - OUT PMODULE_DATA pmod, IN OUT SIZE_T *psiz, - IN SIZE_T start_index, - IN BOOLEAN isWow64 -) -{ - SIZE_T used = 0, index = 0; - INT waitCount = 0; - - if (isWow64) { - PPEB32 peb32 = (PPEB32)PsGetProcessWow64Process(Process); - if (!peb32) { - KDBG("PsGetProcessWow64Process failed"); - return STATUS_UNSUCCESSFUL; - } - - PPEB_LDR_DATA32 ldr32 = (PPEB_LDR_DATA32)peb32->Ldr; - - if (!ldr32) { - KDBG("peb32->Ldr is invalid"); - return STATUS_UNSUCCESSFUL; - } - - if (!ldr32->Initialized) { - while (!ldr32->Initialized && waitCount++ < 4) { - LARGE_INTEGER wait = { .QuadPart = -2500 }; - KeDelayExecutionThread(KernelMode, TRUE, &wait); - } - - if (!ldr32->Initialized) { - KDBG("ldr32->Initialized is 0"); - return STATUS_UNSUCCESSFUL; - } - } - - for (PLIST_ENTRY32 listEntry = (PLIST_ENTRY32)ldr32->InLoadOrderModuleList.Flink; - listEntry != &ldr32->InLoadOrderModuleList && used < *psiz; - listEntry = (PLIST_ENTRY32)listEntry->Flink, ++pmod, ++index) { - if (index < start_index) - continue; - used++; - - PLDR_DATA_TABLE_ENTRY32 ldrEntry32 = CONTAINING_RECORD(listEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks); - ANSI_STRING name; - UNICODE_STRING tmpUnicodeStr; - tmpUnicodeStr.Buffer = (PWCH)ldrEntry32->BaseDllName.Buffer; - tmpUnicodeStr.Length = ldrEntry32->BaseDllName.Length; - tmpUnicodeStr.MaximumLength = ldrEntry32->BaseDllName.MaximumLength; - if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name, &tmpUnicodeStr, TRUE))) { - RtlCopyMemory(pmod->BaseDllName, name.Buffer, - (name.Length > sizeof pmod->BaseDllName ? - sizeof pmod->BaseDllName : name.Length) - ); - RtlFreeAnsiString(&name); - } - pmod->DllBase = (PVOID)ldrEntry32->DllBase; - pmod->SizeOfImage = ldrEntry32->SizeOfImage; - KDBG("DLL32 #%02lu: base -> 0x%p, size -> 0x%06X, name -> '%s'\n", used, - pmod->DllBase, pmod->SizeOfImage, pmod->BaseDllName); - } - } - else { - PPEB peb = PsGetProcessPeb(Process); - if (!peb) { - KDBG("PsGetProcessPeb failed"); - return STATUS_UNSUCCESSFUL; - } - - PPEB_LDR_DATA ldr = peb->Ldr; - - if (!ldr) { - KDBG("peb->Ldr is invalid"); - return STATUS_UNSUCCESSFUL; - } - - if (!ldr->Initialized) { - while (!ldr->Initialized && waitCount++ < 4) { - LARGE_INTEGER wait = { .QuadPart = -2500 }; - KeDelayExecutionThread(KernelMode, TRUE, &wait); - } - - if (!ldr->Initialized) { - KDBG("ldr->Initialized is 0"); - return STATUS_UNSUCCESSFUL; - } - } - - for (PLIST_ENTRY listEntry = (PLIST_ENTRY)ldr->InLoadOrderModuleList.Flink; - listEntry != &ldr->InLoadOrderModuleList && used < *psiz; - listEntry = (PLIST_ENTRY)listEntry->Flink, ++pmod, ++index) { - if (index < start_index) - continue; - used++; - - PLDR_DATA_TABLE_ENTRY ldrEntry = CONTAINING_RECORD(listEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - ANSI_STRING name; - if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name, &ldrEntry->BaseDllName, TRUE))) { - RtlCopyMemory(pmod->BaseDllName, name.Buffer, - (name.Length > sizeof pmod->BaseDllName ? - sizeof pmod->BaseDllName : name.Length) - ); - RtlFreeAnsiString(&name); - } - pmod->DllBase = ldrEntry->DllBase; - pmod->SizeOfImage = ldrEntry->SizeOfImage; - KDBG("DLL #%02lu: base -> 0x%p, size -> 0x%06X, name -> '%s'\n", used, - pmod->DllBase, pmod->SizeOfImage, pmod->BaseDllName); - } - } - - *psiz = used; - return STATUS_SUCCESS; -} - static void fn_zero_text(PVOID fn_start) { SIZE_T i; @@ -896,133 +725,6 @@ NTSTATUS GetDriverObject( return status; } -TABLE_SEARCH_RESULT -VADFindNodeOrParent( - IN PMM_AVL_TABLE Table, - IN ULONG_PTR StartingVpn, - OUT PMMADDRESS_NODE *NodeOrParent -) -{ - PMMADDRESS_NODE Child; - PMMADDRESS_NODE NodeToExamine; - PMMVAD_SHORT VpnCompare; - ULONG_PTR startVpn; - ULONG_PTR endVpn; - - if (Table->NumberGenericTableElements == 0) { - return TableEmptyTree; - } - - NodeToExamine = (PMMADDRESS_NODE)GET_VAD_ROOT(Table); - - for (;;) { - - VpnCompare = (PMMVAD_SHORT)NodeToExamine; - startVpn = VpnCompare->StartingVpn; - endVpn = VpnCompare->EndingVpn; - - startVpn |= (ULONG_PTR)VpnCompare->StartingVpnHigh << 32; - endVpn |= (ULONG_PTR)VpnCompare->EndingVpnHigh << 32; - - KDBG("Examining Node 0x%p with start VA 0x%p and end VA 0x%p\n", VpnCompare, startVpn, endVpn); - - // - // Compare the buffer with the key in the tree element. - // - - if (StartingVpn < startVpn) { - - Child = NodeToExamine->LeftChild; - - if (Child != NULL) { - NodeToExamine = Child; - } - else { - - // - // Node is not in the tree. Set the output - // parameter to point to what would be its - // parent and return which child it would be. - // - - *NodeOrParent = NodeToExamine; - return TableInsertAsLeft; - } - } - else if (StartingVpn <= endVpn) { - - // - // This is the node. - // - - *NodeOrParent = NodeToExamine; - return TableFoundNode; - } - else { - - Child = NodeToExamine->RightChild; - - if (Child != NULL) { - NodeToExamine = Child; - } - else { - - // - // Node is not in the tree. Set the output - // parameter to point to what would be its - // parent and return which child it would be. - // - - *NodeOrParent = NodeToExamine; - return TableInsertAsRight; - } - } - } -} - -NTSTATUS VADFind( - IN PEPROCESS pProcess, - IN ULONG_PTR address, - OUT PMMVAD_SHORT* pResult -) -{ - NTSTATUS status = STATUS_SUCCESS; - ULONG_PTR vpnStart = address >> PAGE_SHIFT; - PMM_AVL_TABLE pTable = (PMM_AVL_TABLE)((PUCHAR)pProcess + VAD_TREE_1803); - PMM_AVL_NODE pNode = GET_VAD_ROOT(pTable); - - if (pProcess == NULL || pResult == NULL) - return STATUS_INVALID_PARAMETER; - - // Search VAD - if (VADFindNodeOrParent(pTable, vpnStart, &pNode) == TableFoundNode) - { - *pResult = (PMMVAD_SHORT)pNode; - } - else - { - KDBG("%s: VAD entry for address 0x%p not found\n", __FUNCTION__, address); - status = STATUS_NOT_FOUND; - } - - return status; -} - -NTSTATUS VADProtect( - IN PEPROCESS pProcess, - IN ULONG_PTR address, IN ULONG prot -) -{ - NTSTATUS status = STATUS_SUCCESS; - PMMVAD_SHORT pVadShort = NULL; - - status = VADFind(pProcess, address, &pVadShort); - if (NT_SUCCESS(status)) - pVadShort->u.VadFlags.Protection = prot; - - return status; -} - PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry(PVOID pHandleTable, HANDLE handle) { unsigned __int64 v2; // rdx diff --git a/KMemDriver/KMemDriver.vcxproj b/KMemDriver/KMemDriver.vcxproj index 7f1e95c..1d83e04 100644 --- a/KMemDriver/KMemDriver.vcxproj +++ b/KMemDriver/KMemDriver.vcxproj @@ -175,6 +175,7 @@ <ItemGroup> <ClCompile Include="KMemDriver.c" /> <ClCompile Include="Memory.c" /> + <ClCompile Include="VAD.c" /> </ItemGroup> <ItemGroup> <ClInclude Include="..\include\KMemDriver.h" /> diff --git a/KMemDriver/KMemDriver.vcxproj.filters b/KMemDriver/KMemDriver.vcxproj.filters index 527bb33..e69aafd 100644 --- a/KMemDriver/KMemDriver.vcxproj.filters +++ b/KMemDriver/KMemDriver.vcxproj.filters @@ -28,5 +28,8 @@ <ClCompile Include="Memory.c"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="VAD.c"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> </Project>
\ No newline at end of file diff --git a/KMemDriver/Memory.c b/KMemDriver/Memory.c index 2cecae8..9a2449e 100644 --- a/KMemDriver/Memory.c +++ b/KMemDriver/Memory.c @@ -5,6 +5,171 @@ #include <ntddk.h> #include <Ntstrsafe.h> +NTSTATUS GetPages( + IN PEPROCESS Process, + OUT MEMORY_BASIC_INFORMATION *mbiArr, + IN SIZE_T mbiArrLen, OUT SIZE_T *mbiUsed, + IN PVOID start_addr +) +{ + NTSTATUS status; + HANDLE procHandle; + SIZE_T i, mbiLength, mbiReturn; + ULONG_PTR baseAddr = (ULONG_PTR)start_addr; + + status = ObOpenObjectByPointer(Process, + OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, GENERIC_ALL, + *PsProcessType, KernelMode, &procHandle + ); + if (!NT_SUCCESS(status)) { + KDBG("ObOpenObjectByPointer failed with 0x%X\n", status); + return status; + } + + KDBG("ZwQueryVirtualMemory max entries: %u\n", mbiArrLen); + *mbiUsed = 0; + do { + mbiReturn = 0; + status = ZwQueryVirtualMemory(procHandle, (PVOID)baseAddr, + MemoryBasicInformation, mbiArr, sizeof *mbiArr * mbiArrLen, &mbiReturn); + mbiLength = mbiReturn / sizeof *mbiArr; + if (!NT_SUCCESS(status)) { + if (status == STATUS_INVALID_PARAMETER) + status = STATUS_SUCCESS; + else + KDBG("ZwQueryVirtualMemory failed with 0x%X\n", status); + break; + } + else { + for (i = 0; i < mbiLength; ++i) + KDBG("Page #%03u: base -> 0x%p, prot -> 0x%02X, size -> 0x%X\n", + (*mbiUsed) + i, (*(mbiArr + i)).BaseAddress, (*(mbiArr + i)).Protect, + (*(mbiArr + i)).RegionSize); + } + baseAddr += (SIZE_T)(mbiArr + mbiLength - 1)->RegionSize; + *mbiUsed += mbiLength; + mbiArr += mbiLength; + } while (*mbiUsed < mbiArrLen && mbiReturn > 0); + + ZwClose(procHandle); + return status; +} + +NTSTATUS GetModules( + IN PEPROCESS Process, + OUT PMODULE_DATA pmod, IN OUT SIZE_T *psiz, + IN SIZE_T start_index, + IN BOOLEAN isWow64 +) +{ + SIZE_T used = 0, index = 0; + INT waitCount = 0; + + if (isWow64) { + PPEB32 peb32 = (PPEB32)PsGetProcessWow64Process(Process); + if (!peb32) { + KDBG("PsGetProcessWow64Process failed"); + return STATUS_UNSUCCESSFUL; + } + + PPEB_LDR_DATA32 ldr32 = (PPEB_LDR_DATA32)peb32->Ldr; + + if (!ldr32) { + KDBG("peb32->Ldr is invalid"); + return STATUS_UNSUCCESSFUL; + } + + if (!ldr32->Initialized) { + while (!ldr32->Initialized && waitCount++ < 4) { + LARGE_INTEGER wait = { .QuadPart = -2500 }; + KeDelayExecutionThread(KernelMode, TRUE, &wait); + } + + if (!ldr32->Initialized) { + KDBG("ldr32->Initialized is 0"); + return STATUS_UNSUCCESSFUL; + } + } + + for (PLIST_ENTRY32 listEntry = (PLIST_ENTRY32)ldr32->InLoadOrderModuleList.Flink; + listEntry != &ldr32->InLoadOrderModuleList && used < *psiz; + listEntry = (PLIST_ENTRY32)listEntry->Flink, ++pmod, ++index) { + if (index < start_index) + continue; + used++; + + PLDR_DATA_TABLE_ENTRY32 ldrEntry32 = CONTAINING_RECORD(listEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks); + ANSI_STRING name; + UNICODE_STRING tmpUnicodeStr; + tmpUnicodeStr.Buffer = (PWCH)ldrEntry32->BaseDllName.Buffer; + tmpUnicodeStr.Length = ldrEntry32->BaseDllName.Length; + tmpUnicodeStr.MaximumLength = ldrEntry32->BaseDllName.MaximumLength; + if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name, &tmpUnicodeStr, TRUE))) { + RtlCopyMemory(pmod->BaseDllName, name.Buffer, + (name.Length > sizeof pmod->BaseDllName ? + sizeof pmod->BaseDllName : name.Length) + ); + RtlFreeAnsiString(&name); + } + pmod->DllBase = (PVOID)ldrEntry32->DllBase; + pmod->SizeOfImage = ldrEntry32->SizeOfImage; + KDBG("DLL32 #%02lu: base -> 0x%p, size -> 0x%06X, name -> '%s'\n", used, + pmod->DllBase, pmod->SizeOfImage, pmod->BaseDllName); + } + } + else { + PPEB peb = PsGetProcessPeb(Process); + if (!peb) { + KDBG("PsGetProcessPeb failed"); + return STATUS_UNSUCCESSFUL; + } + + PPEB_LDR_DATA ldr = peb->Ldr; + + if (!ldr) { + KDBG("peb->Ldr is invalid"); + return STATUS_UNSUCCESSFUL; + } + + if (!ldr->Initialized) { + while (!ldr->Initialized && waitCount++ < 4) { + LARGE_INTEGER wait = { .QuadPart = -2500 }; + KeDelayExecutionThread(KernelMode, TRUE, &wait); + } + + if (!ldr->Initialized) { + KDBG("ldr->Initialized is 0"); + return STATUS_UNSUCCESSFUL; + } + } + + for (PLIST_ENTRY listEntry = (PLIST_ENTRY)ldr->InLoadOrderModuleList.Flink; + listEntry != &ldr->InLoadOrderModuleList && used < *psiz; + listEntry = (PLIST_ENTRY)listEntry->Flink, ++pmod, ++index) { + if (index < start_index) + continue; + used++; + + PLDR_DATA_TABLE_ENTRY ldrEntry = CONTAINING_RECORD(listEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); + ANSI_STRING name; + if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name, &ldrEntry->BaseDllName, TRUE))) { + RtlCopyMemory(pmod->BaseDllName, name.Buffer, + (name.Length > sizeof pmod->BaseDllName ? + sizeof pmod->BaseDllName : name.Length) + ); + RtlFreeAnsiString(&name); + } + pmod->DllBase = ldrEntry->DllBase; + pmod->SizeOfImage = ldrEntry->SizeOfImage; + KDBG("DLL #%02lu: base -> 0x%p, size -> 0x%06X, name -> '%s'\n", used, + pmod->DllBase, pmod->SizeOfImage, pmod->BaseDllName); + } + } + + *psiz = used; + return STATUS_SUCCESS; +} + NTSTATUS KeReadVirtualMemory( IN PEPROCESS Process, IN PVOID SourceAddress, IN PVOID TargetAddress, IN PSIZE_T Size diff --git a/KMemDriver/VAD.c b/KMemDriver/VAD.c new file mode 100644 index 0000000..94c7397 --- /dev/null +++ b/KMemDriver/VAD.c @@ -0,0 +1,133 @@ +#include "KMemDriver.h" +#include "Imports.h" +#include "Native.h" + +#include <ntddk.h> +#include <Ntstrsafe.h> + +TABLE_SEARCH_RESULT +VADFindNodeOrParent( + IN PMM_AVL_TABLE Table, + IN ULONG_PTR StartingVpn, + OUT PMMADDRESS_NODE *NodeOrParent +) +{ + PMMADDRESS_NODE Child; + PMMADDRESS_NODE NodeToExamine; + PMMVAD_SHORT VpnCompare; + ULONG_PTR startVpn; + ULONG_PTR endVpn; + + if (Table->NumberGenericTableElements == 0) { + return TableEmptyTree; + } + + NodeToExamine = (PMMADDRESS_NODE)GET_VAD_ROOT(Table); + + for (;;) { + + VpnCompare = (PMMVAD_SHORT)NodeToExamine; + startVpn = VpnCompare->StartingVpn; + endVpn = VpnCompare->EndingVpn; + + startVpn |= (ULONG_PTR)VpnCompare->StartingVpnHigh << 32; + endVpn |= (ULONG_PTR)VpnCompare->EndingVpnHigh << 32; + + KDBG("Examining Node 0x%p with start VA 0x%p and end VA 0x%p\n", VpnCompare, startVpn, endVpn); + + // + // Compare the buffer with the key in the tree element. + // + + if (StartingVpn < startVpn) { + + Child = NodeToExamine->LeftChild; + + if (Child != NULL) { + NodeToExamine = Child; + } + else { + + // + // Node is not in the tree. Set the output + // parameter to point to what would be its + // parent and return which child it would be. + // + + *NodeOrParent = NodeToExamine; + return TableInsertAsLeft; + } + } + else if (StartingVpn <= endVpn) { + + // + // This is the node. + // + + *NodeOrParent = NodeToExamine; + return TableFoundNode; + } + else { + + Child = NodeToExamine->RightChild; + + if (Child != NULL) { + NodeToExamine = Child; + } + else { + + // + // Node is not in the tree. Set the output + // parameter to point to what would be its + // parent and return which child it would be. + // + + *NodeOrParent = NodeToExamine; + return TableInsertAsRight; + } + } + } +} + +NTSTATUS VADFind( + IN PEPROCESS pProcess, + IN ULONG_PTR address, + OUT PMMVAD_SHORT* pResult +) +{ + NTSTATUS status = STATUS_SUCCESS; + ULONG_PTR vpnStart = address >> PAGE_SHIFT; + PMM_AVL_TABLE pTable = (PMM_AVL_TABLE)((PUCHAR)pProcess + VAD_TREE_1803); + PMM_AVL_NODE pNode = GET_VAD_ROOT(pTable); + + if (pProcess == NULL || pResult == NULL) + return STATUS_INVALID_PARAMETER; + + // Search VAD + if (VADFindNodeOrParent(pTable, vpnStart, &pNode) == TableFoundNode) + { + *pResult = (PMMVAD_SHORT)pNode; + } + else + { + KDBG("%s: VAD entry for address 0x%p not found\n", __FUNCTION__, address); + status = STATUS_NOT_FOUND; + } + + return status; +} + +NTSTATUS VADProtect( + IN PEPROCESS pProcess, + IN ULONG_PTR address, IN ULONG prot +) +{ + NTSTATUS status = STATUS_SUCCESS; + PMMVAD_SHORT pVadShort = NULL; + + status = VADFind(pProcess, address, &pVadShort); + if (NT_SUCCESS(status)) + pVadShort->u.VadFlags.Protection = prot; + + return status; +}
\ No newline at end of file |