aboutsummaryrefslogtreecommitdiff
path: root/KMemDriver
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2019-08-23 23:30:10 +0200
committerToni Uhlig <matzeton@googlemail.com>2019-08-23 23:30:10 +0200
commit6491418d867739dbcecaedd9c363d5569f8fbf92 (patch)
treef5233f496e5a681f3a90a707e3e69d8df1071790 /KMemDriver
parenta3e36262204cc39ff1998cacbe4ceb35b9b073b5 (diff)
* moved KDBG to KMemDriver.h
* moved GetPages, GetModules to Memory.c * moved VAD routines to VAD.c
Diffstat (limited to 'KMemDriver')
-rw-r--r--KMemDriver/KMemDriver.c298
-rw-r--r--KMemDriver/KMemDriver.vcxproj1
-rw-r--r--KMemDriver/KMemDriver.vcxproj.filters3
-rw-r--r--KMemDriver/Memory.c165
-rw-r--r--KMemDriver/VAD.c133
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