diff options
author | segfault <toni@impl.cc> | 2021-01-11 13:24:35 +0100 |
---|---|---|
committer | segfault <toni@impl.cc> | 2021-01-11 13:24:35 +0100 |
commit | 89ec896bede35949a43a41e779aadb11fe16f9a2 (patch) | |
tree | 5edea9bf65457340d2891d2864233b6f4a40c943 | |
parent | 0ede1cd40edc539764de998e373acd57f87403f1 (diff) |
Added new MemDriverLib functions to determine if a page is freed/reserved.
* added PAGES/RPM tests
* increased memory for ZwQuerySystemInformation in GetProcesses
-rw-r--r-- | IntegrationTest/IntegrationTest.cpp | 74 | ||||
-rw-r--r-- | KMemDriver/KMemDriver.c | 9 | ||||
-rw-r--r-- | include/KInterface.h | 10 |
3 files changed, 85 insertions, 8 deletions
diff --git a/IntegrationTest/IntegrationTest.cpp b/IntegrationTest/IntegrationTest.cpp index 4f87819..a254e85 100644 --- a/IntegrationTest/IntegrationTest.cpp +++ b/IntegrationTest/IntegrationTest.cpp @@ -2,14 +2,17 @@ #include "KInterface.h" #include <iostream> +#include <map> -#define PRINT_CHECK_MSG(message) std::wcout << L ## message +#define PRINT_CHECK_MSG(message) std::wcout << L ## message ## " " #define PRINT_FAIL_MSG() std::wcout << L" [FAIL]" << std::endl #define PRINT_OK_MSG() std::wcout << L" [ OK ]" << std::endl #define KM_ASSERT_EQUAL(equal, condition, message) \ do { PRINT_CHECK_MSG(message); if ((condition) != (equal)) { \ PRINT_FAIL_MSG(); goto error; } else { PRINT_OK_MSG(); } \ } while (0) +#define KM_ASSERT_EQUAL_NO_MSG(equal, condition) \ + do { if ((condition) != (equal)) { goto error; } } while (0) #define KM_TEST_SUITE(condition, message) \ do { \ PRINT_CHECK_MSG("--- TestSuite " ## message ## " ---\n"); \ @@ -167,6 +170,72 @@ error: return false; } +static std::map<HANDLE, bool> GetCurrentHeaps() +{ + std::map<HANDLE, bool> retval; + SIZE_T const max_heaps = 64; + HANDLE heaps[max_heaps]; + DWORD count = GetProcessHeaps(max_heaps, heaps); + + if (count > 0) { + for (SIZE_T j = 0; j < count; ++j) { + retval[heaps[j]] = true; + } + } + return retval; +} + +static bool test_PagesRPM(KInterface& ki, HANDLE pid) +{ + { + std::vector<MEMORY_BASIC_INFORMATION> pages; + KM_ASSERT_EQUAL(true, ki.Pages(pid, pages), "Kernel Interface Pages"); + KM_ASSERT_EQUAL(0, ki.getLastNtStatus(), "Last NtStatus"); + for (auto& page : pages) { + std::map<HANDLE, bool> heaps = GetCurrentHeaps(); + if (heaps.find(page.BaseAddress) != heaps.end()) { + continue; + } + if (KInterface::PageIsFreed(page) == true || KInterface::PageIsPrivateReserved(page) == true) { + continue; + } + BYTE buf[4096]; + SIZE_T siz = (page.RegionSize > sizeof(buf) ? sizeof(buf) : page.RegionSize); + KM_ASSERT_EQUAL_NO_MSG(true, ki.RPM(pid, page.BaseAddress, buf, siz, NULL)); + KM_ASSERT_EQUAL_NO_MSG(0, ki.getLastNtStatus()); + } + + std::vector<MEMORY_BASIC_INFORMATION> vq_pages; + MEMORY_BASIC_INFORMATION page; + SIZE_T base = NULL; + while (VirtualQuery((LPVOID)base, &page, sizeof(page)) > 0) { + std::map<HANDLE, bool> vq_heaps = GetCurrentHeaps(); + base += page.RegionSize; + if (vq_heaps.find(page.BaseAddress) != vq_heaps.end()) { + continue; + } + vq_pages.push_back(page); + } + + for (SIZE_T i = 0; i < vq_pages.size(); ++i) { + if (vq_pages[i].BaseAddress != pages[i].BaseAddress) { + /* not optimal as we do test all pages */ + break; + } + KM_ASSERT_EQUAL_NO_MSG(vq_pages[i].Protect, pages[i].Protect); + KM_ASSERT_EQUAL_NO_MSG(vq_pages[i].RegionSize, pages[i].RegionSize); + KM_ASSERT_EQUAL_NO_MSG(vq_pages[i].State, pages[i].State); + KM_ASSERT_EQUAL_NO_MSG(vq_pages[i].Type, pages[i].Type); + } + + KM_ASSERT_EQUAL_NO_MSG(pages.size(), pages.size()); + } + + return true; +error: + return false; +} + int main() { HANDLE this_pid = (HANDLE)((ULONG_PTR)GetCurrentProcessId()); @@ -188,6 +257,7 @@ int main() KM_TEST_SUITE(test_Pages(ki, this_pid), "Pages"); KM_TEST_SUITE(test_VirtualMemory(ki, this_pid), "VirtualMemory"); KM_TEST_SUITE(test_MemoryReadWrite(ki, this_pid), "MemoryReadWrite"); + KM_TEST_SUITE(test_PagesRPM(ki, this_pid), "ModulesPagesRPM"); KM_ASSERT_EQUAL(true, ki.Ping(), "Kernel Interface PING - PONG #4"); KM_ASSERT_EQUAL(true, ki.Exit(), "Kernel Interface Driver Shutdown"); } @@ -199,5 +269,5 @@ int main() error: ki.Exit(); std::wcout << std::endl << "KMemDriver Shutdown [PRESS RETURN KEY TO EXIT]" << std::endl; - getchar(); + std::getchar(); }
\ No newline at end of file diff --git a/KMemDriver/KMemDriver.c b/KMemDriver/KMemDriver.c index f574e17..edcf834 100644 --- a/KMemDriver/KMemDriver.c +++ b/KMemDriver/KMemDriver.c @@ -179,6 +179,7 @@ NTSTATUS GetProcesses(OUT PROCESS_DATA* procs, IN OUT SIZE_T* psiz) return status; } + mem_needed += 16 * sizeof(SYSTEM_PROCESS_INFORMATION); if (mem_needed / sizeof(SYSTEM_PROCESS_INFORMATION) > max_siz / sizeof(PROCESS_DATA)) { KDBG("NtQuerySystemInformation buffer too small\n", status); return STATUS_BUFFER_TOO_SMALL; @@ -554,11 +555,11 @@ NTSTATUS KRThread(IN PVOID pArg) } ULONG new_prot = PAGE_EXECUTE_READWRITE, old_prot = 0; KeProtectVirtualMemory(lastPROC, rr->Address, rr->SizeReq, new_prot, &old_prot); - KDBG("RPM to 0x%p size 0x%X bytes (protection before/after: 0x%X/0x%X)\n", - rr->Address, rr->SizeReq, old_prot, new_prot); rr->StatusRes = KeReadVirtualMemory(lastPEP, (PVOID)rr->Address, (PVOID)((ULONG_PTR)shm_buf + sizeof * rr), &siz); KeRestoreProtectVirtualMemory(lastPROC, rr->Address, rr->SizeReq, old_prot); + KDBG("RPM to 0x%p size 0x%X bytes returned 0x%X (protection before/after: 0x%X/0x%X)\n", + rr->Address, rr->SizeReq, rr->StatusRes, old_prot, new_prot); if (NT_SUCCESS(rr->StatusRes)) { rr->SizeRes = siz; @@ -589,11 +590,11 @@ NTSTATUS KRThread(IN PVOID pArg) } ULONG new_prot = PAGE_EXECUTE_READWRITE, old_prot = 0; KeProtectVirtualMemory(lastPROC, wr->Address, wr->SizeReq, new_prot, &old_prot); - KDBG("WPM to 0x%p size 0x%X bytes (protection before/after: 0x%X/0x%X)\n", - wr->Address, wr->SizeReq, old_prot, new_prot); wr->StatusRes = KeWriteVirtualMemory(lastPEP, (PVOID)((ULONG_PTR)shm_buf + sizeof * wr), (PVOID)wr->Address, &siz); KeRestoreProtectVirtualMemory(lastPROC, wr->Address, wr->SizeReq, old_prot); + KDBG("WPM to 0x%p size 0x%X bytes returned 0x%X (protection before/after: 0x%X/0x%X)\n", + wr->Address, wr->SizeReq, wr->StatusRes, old_prot, new_prot); if (NT_SUCCESS(wr->StatusRes)) { wr->SizeRes = siz; diff --git a/include/KInterface.h b/include/KInterface.h index 19c9268..55137e8 100644 --- a/include/KInterface.h +++ b/include/KInterface.h @@ -100,12 +100,18 @@ public: UINT32 getLastPingValue(); UINT32 getLastNtStatus(); + static bool PageIsFreed(MEMORY_BASIC_INFORMATION& page) { + return (page.Protect & PAGE_NOACCESS) != 0; + } + static bool PageIsPrivateReserved(MEMORY_BASIC_INFORMATION& page) { + return page.Protect == 0; + } SendRecvReturn RecvWait(DWORD timeout = DEFAULT_TIMEOUT_MS); - void StartPingThread(void (__cdecl *onTimeout)(void)); + void StartPingThread(void(__cdecl* onTimeout)(void)); private: SendRecvReturn SendRecvWait(UINT32 type, DWORD timeout = DEFAULT_TIMEOUT_MS); - void PingThread(void (__cdecl *onTimeout)(void)); + void PingThread(void(__cdecl* onTimeout)(void)); PVOID m_shmem = NULL; HANDLE m_kevent = NULL, m_uevent = NULL; |