mirror-ac/driver/pool.c

309 lines
7.6 KiB
C
Raw Permalink Normal View History

2023-08-26 14:07:06 +02:00
#include "pool.h"
2023-08-28 11:17:38 +02:00
#include "callbacks.h"
2024-08-01 06:21:53 +02:00
#include "crypt.h"
2023-12-29 17:20:32 +01:00
#include "ia32.h"
#include "imports.h"
2024-07-22 12:43:09 +02:00
#include "lib/stdlib.h"
2024-08-04 07:15:37 +02:00
#include <intrin.h>
2023-09-27 15:10:12 +02:00
#define PML4_ENTRY_COUNT 512
#define PDPT_ENTRY_COUNT 512
2023-12-13 05:06:27 +01:00
#define PD_ENTRY_COUNT 512
#define PT_ENTRY_COUNT 512
2023-09-27 15:10:12 +02:00
2024-08-04 07:15:37 +02:00
#define LARGE_PAGE_2MB_ENTRIES 0x200
2023-09-27 15:10:12 +02:00
#define LARGE_PAGE_1GB_ENTRIES 0x40000
2024-08-04 07:15:37 +02:00
#define IS_VALID_PAGE(pt, idx) ((pt)[(index)].Present)
#define IS_LARGE_PAGE(pt) ((pt).LargePage)
2023-12-13 05:06:27 +01:00
2024-08-04 07:15:37 +02:00
STATIC PVOID local_page_copy_buf = NULL;
2023-12-13 05:06:27 +01:00
2024-08-04 07:15:37 +02:00
/*
* Using MmGetPhysicalMemoryRangesEx2(), we can get a block of structures that
* describe the physical memory layout. With each physical page base we are
* going to enumerate, we want to make sure it lies within an appropriate region
* of physical memory, so this function is to check for exactly that.
*/
2023-12-13 05:06:27 +01:00
STATIC
BOOLEAN
2024-08-04 07:15:37 +02:00
PoolpIsAddressInPhysicalRange(
2024-08-01 06:21:53 +02:00
_In_ UINT64 PhysicalAddress,
2024-08-04 07:15:37 +02:00
_In_ PPHYSICAL_MEMORY_RANGE PhysicalMemoryRanges)
2023-08-30 11:19:41 +02:00
{
2024-08-04 07:15:37 +02:00
ULONG index = 0;
UINT64 start = 0;
UINT64 end = 0;
2023-10-10 15:52:42 +02:00
2024-08-04 07:15:37 +02:00
while (PhysicalMemoryRanges[index].NumberOfBytes.QuadPart) {
start = PhysicalMemoryRanges[index].BaseAddress.QuadPart;
end = start + PhysicalMemoryRanges[index].NumberOfBytes.QuadPart;
2023-08-30 11:19:41 +02:00
2024-08-04 07:15:37 +02:00
if (PhysicalAddress >= start && PhysicalAddress <= end)
return TRUE;
2023-08-30 11:19:41 +02:00
2024-08-04 07:15:37 +02:00
index++;
2024-04-13 10:23:14 +02:00
}
return FALSE;
2023-09-15 22:25:02 +02:00
}
2023-09-27 06:22:14 +02:00
STATIC
2024-08-04 07:15:37 +02:00
BOOLEAN
PoolpScanLargePage(
2024-08-01 06:21:53 +02:00
_In_ UINT64 PageBase,
2024-08-04 07:15:37 +02:00
_In_ UINT32 PageSize,
_In_ PAGE_CALLBACK Callback,
_In_opt_ PVOID Context)
2023-08-26 15:29:12 +02:00
{
2024-08-04 07:15:37 +02:00
UINT64 page = 0;
BOOLEAN stop = FALSE;
2023-08-26 17:48:50 +02:00
2024-08-04 07:15:37 +02:00
if (!PageBase || !ImpMmIsAddressValid(PageBase))
return FALSE;
2024-04-13 10:23:14 +02:00
2024-08-04 07:15:37 +02:00
for (UINT32 page_index = 0; page_index < PageSize; page_index++) {
page = PageBase + (page_index * PAGE_SIZE);
2024-04-13 10:23:14 +02:00
2024-08-04 07:15:37 +02:00
if (Callback(page, PAGE_SIZE, Context))
2024-04-13 10:23:14 +02:00
return TRUE;
}
2023-08-26 17:48:50 +02:00
2024-04-13 10:23:14 +02:00
return FALSE;
2023-08-26 15:29:12 +02:00
}
2023-09-27 06:22:14 +02:00
STATIC
2024-08-04 07:15:37 +02:00
BOOLEAN
PoolpScanPageTable(
_In_ PTE_64 Pte, _In_ PAGE_CALLBACK Callback, _In_opt_ PVOID Context)
2023-09-15 22:25:02 +02:00
{
2024-08-04 07:15:37 +02:00
UINT64 page = 0;
PHYSICAL_ADDRESS pa = {0};
NTSTATUS status = STATUS_UNSUCCESSFUL;
MM_COPY_ADDRESS addr = {0};
UINT32 bytes = 0;
pa.QuadPart = Pte.PageFrameNumber << PAGE_4KB_SHIFT;
page = MmGetVirtualForPhysical(pa);
if (!page || !ImpMmIsAddressValid(page)) {
addr.PhysicalAddress = pa;
status = MmCopyMemory(
local_page_copy_buf,
addr,
2024-08-01 06:21:53 +02:00
PAGE_SIZE,
2024-08-04 07:15:37 +02:00
MM_COPY_MEMORY_PHYSICAL,
&bytes);
if (!NT_SUCCESS(status))
return FALSE;
DEBUG_VERBOSE(
"valid mm page: %llx, pa: %llx, copied: %lx",
local_page_copy_buf,
pa.QuadPart,
bytes);
return Callback(local_page_copy_buf, PAGE_SIZE, Context);
2024-04-13 10:23:14 +02:00
}
2024-08-04 07:15:37 +02:00
return Callback(page, PAGE_SIZE, Context);
2023-09-15 22:25:02 +02:00
}
2023-09-27 06:22:14 +02:00
STATIC
2024-08-04 07:15:37 +02:00
BOOLEAN
PoolpScanPageDirectory(
_In_ PDE_64 Pde, _In_ PAGE_CALLBACK Callback, _In_opt_ PVOID Context)
2023-08-26 14:07:06 +02:00
{
2024-08-04 07:15:37 +02:00
PTE_64* pt = NULL;
PDE_2MB_64 pdel = {0};
PHYSICAL_ADDRESS pa = {0};
if (IS_LARGE_PAGE(Pde)) {
pdel.AsUInt = Pde.AsUInt;
pa.QuadPart = pdel.PageFrameNumber << PAGE_2MB_SHIFT;
return PoolpScanLargePage(
ImpMmGetVirtualForPhysical(pa),
LARGE_PAGE_2MB_ENTRIES,
Callback,
Context);
2024-04-13 10:23:14 +02:00
}
2023-08-26 14:07:06 +02:00
2024-08-04 07:15:37 +02:00
pa.QuadPart = Pde.PageFrameNumber << PAGE_4KB_SHIFT;
pt = ImpMmGetVirtualForPhysical(pa);
2023-08-26 14:07:06 +02:00
2024-08-04 07:15:37 +02:00
if (!pt || !ImpMmIsAddressValid(pt))
return FALSE;
2023-08-30 15:38:12 +02:00
2024-08-04 07:15:37 +02:00
for (UINT32 index = 0; index < PT_ENTRY_COUNT; index++) {
if (!IS_VALID_PAGE(pt, index))
2024-04-13 10:23:14 +02:00
continue;
2023-08-26 14:07:06 +02:00
2024-08-04 07:15:37 +02:00
// DEBUG_VERBOSE(
// "------> pt va: %llx, pte: %llx, index: %lx",
// pt,
// pt[index],
// index);
2023-09-03 19:33:27 +02:00
2024-08-04 07:15:37 +02:00
if (PoolpScanPageTable(pt[index], Callback, Context))
return TRUE;
2024-04-13 10:23:14 +02:00
}
2023-08-26 14:07:06 +02:00
2024-08-04 07:15:37 +02:00
return FALSE;
2023-08-28 11:17:38 +02:00
}
2023-08-27 07:49:59 +02:00
2023-09-27 06:22:14 +02:00
STATIC
2024-08-04 07:15:37 +02:00
BOOLEAN
PoolpScanPageDirectoryPointerTable(
_In_ PDPTE_64 Pdpte, _In_ PAGE_CALLBACK Callback, _In_opt_ PVOID Context)
2023-08-28 11:17:38 +02:00
{
2024-08-04 07:15:37 +02:00
PDE_64* pd = NULL;
PDPTE_1GB_64 pdptel = {0};
PHYSICAL_ADDRESS pa = {0};
if (IS_LARGE_PAGE(Pdpte)) {
pdptel.AsUInt = Pdpte.AsUInt;
pa.QuadPart = pdptel.PageFrameNumber << PAGE_1GB_SHIFT;
return PoolpScanLargePage(
ImpMmGetVirtualForPhysical(pa),
LARGE_PAGE_1GB_ENTRIES,
Callback,
Context);
}
pa.QuadPart = Pdpte.PageFrameNumber << PAGE_4KB_SHIFT;
pd = ImpMmGetVirtualForPhysical(pa);
if (!pd || !ImpMmIsAddressValid(pd))
return FALSE;
2023-10-10 15:52:42 +02:00
2024-08-04 07:15:37 +02:00
for (UINT32 index = 0; index < PD_ENTRY_COUNT; index++) {
if (!IS_VALID_PAGE(pd, index))
continue;
2023-10-10 19:49:17 +02:00
2024-08-04 07:15:37 +02:00
// DEBUG_VERBOSE(
// "----> pd va: %llx, pde: %llx, index: %lx",
// pd,
// pd[index],
// index);
2023-10-07 07:27:22 +02:00
2024-08-04 07:15:37 +02:00
if (PoolpScanPageDirectory(pd[index], Callback, Context))
return TRUE;
}
2023-10-07 07:27:22 +02:00
2024-08-04 07:15:37 +02:00
return FALSE;
2023-08-28 11:17:38 +02:00
}
2023-08-27 07:49:59 +02:00
2023-09-27 06:22:14 +02:00
STATIC
2024-08-04 07:15:37 +02:00
BOOLEAN
PoolpScanPageMapLevel4(
_In_ PML4E_64 Pml4e, _In_ PAGE_CALLBACK Callback, _In_opt_ PVOID Context)
2023-08-28 11:17:38 +02:00
{
2024-08-04 07:15:37 +02:00
BOOLEAN stop = FALSE;
PDPTE_64* pdpt = NULL;
PHYSICAL_ADDRESS pa = {0};
pa.QuadPart = Pml4e.PageFrameNumber << PAGE_4KB_SHIFT;
pdpt = ImpMmGetVirtualForPhysical(pa);
2024-04-13 10:23:14 +02:00
2024-08-04 07:15:37 +02:00
if (!pdpt || !ImpMmIsAddressValid(pdpt))
return FALSE;
2024-04-13 10:23:14 +02:00
2024-08-04 07:15:37 +02:00
for (UINT32 index = 0; index < PDPT_ENTRY_COUNT; index++) {
if (!IS_VALID_PAGE(pdpt, index))
continue;
2024-04-13 10:23:14 +02:00
2024-08-04 07:15:37 +02:00
// DEBUG_VERBOSE(
// "--> pdpt va: %llx, pdpte: %llx, index: %lx",
// pdpt,
// pdpt[index],
// index);
2024-04-13 10:23:14 +02:00
2024-08-04 07:15:37 +02:00
if (PoolpScanPageDirectoryPointerTable(pdpt[index], Callback, Context))
return TRUE;
2024-04-13 10:23:14 +02:00
}
2024-08-04 07:15:37 +02:00
return FALSE;
2023-08-26 14:07:06 +02:00
}
2023-10-05 08:27:17 +02:00
NTSTATUS
2024-08-04 07:15:37 +02:00
PoolScanSystemSpace(_In_ PAGE_CALLBACK Callback, _In_opt_ PVOID Context)
2023-08-26 14:07:06 +02:00
{
2024-08-04 07:15:37 +02:00
NT_ASSERT(Callback != NULL);
2023-10-10 15:52:42 +02:00
2024-08-04 07:15:37 +02:00
CR3 cr3 = {0};
PML4E_64* pml4 = NULL;
PHYSICAL_ADDRESS pa = {0};
2023-08-26 14:07:06 +02:00
2024-08-04 07:15:37 +02:00
if (!Callback)
return STATUS_INVALID_PARAMETER;
2023-08-26 14:07:06 +02:00
2024-08-04 07:15:37 +02:00
cr3.AsUInt = __readcr3();
pa.QuadPart = cr3.AddressOfPageDirectory << PAGE_4KB_SHIFT;
pml4 = ImpMmGetVirtualForPhysical(pa);
2023-08-26 14:07:06 +02:00
2024-08-04 07:15:37 +02:00
// DEBUG_VERBOSE("system cr3: %llx", cr3.AsUInt);
2023-08-28 11:17:38 +02:00
2024-08-04 07:15:37 +02:00
if (!pml4 || !ImpMmIsAddressValid(pml4))
return STATUS_UNSUCCESSFUL;
2023-08-28 11:17:38 +02:00
2024-08-04 07:15:37 +02:00
for (UINT32 index = 490; index < PML4_ENTRY_COUNT; index++) {
if (!IS_VALID_PAGE(pml4, index))
continue;
2023-08-28 11:17:38 +02:00
2024-08-04 07:15:37 +02:00
// DEBUG_VERBOSE(
// "pml4 va: %llx, pml4e: %llx, index: %lx",
// pml4,
// pml4[index],
// index);
2023-08-26 14:07:06 +02:00
2024-08-04 07:15:37 +02:00
if (PoolpScanPageMapLevel4(pml4[index], Callback, Context))
break;
}
2023-08-26 14:07:06 +02:00
2024-08-04 07:15:37 +02:00
return STATUS_SUCCESS;
}
2023-08-28 11:17:38 +02:00
2024-08-04 07:15:37 +02:00
/* Credits to Samuel Tulach c:
* https://tulach.cc/detecting-manually-mapped-drivers/ */
2023-08-28 17:00:52 +02:00
2024-08-04 07:15:37 +02:00
// #36aae000 4d 5a 90
#define GADGET_BYTE_ONE 0x4D // 0xFF
#define GADGET_BYTE_TWO 0x5A // 0x25
#define GADGET_BYTE_THREE 0x90 // 0x25
2023-08-28 17:00:52 +02:00
2024-08-04 07:15:37 +02:00
STATIC
BOOLEAN
PoolScanForManualMappedDriverCallback(
_In_ UINT64 Page, _In_ UINT32 PageSize, _In_opt_ PVOID Context)
{
PCHAR byte = (PCHAR)Page;
2023-08-28 17:00:52 +02:00
2024-08-04 07:15:37 +02:00
// DEBUG_VERBOSE("--------> page: %llx", Page);
2024-05-11 14:54:58 +02:00
2024-08-04 07:15:37 +02:00
for (UINT32 index = 0; index < PageSize - 1; index++) {
if (byte[index] == GADGET_BYTE_ONE &&
byte[index + 1] == GADGET_BYTE_TWO &&
byte[index + 2] == GADGET_BYTE_THREE) {
DEBUG_VERBOSE("FOUND!");
2023-12-13 05:06:27 +01:00
}
2024-04-13 10:23:14 +02:00
}
2023-08-28 11:17:38 +02:00
2024-08-04 07:15:37 +02:00
return FALSE;
2023-11-08 16:02:17 +01:00
}
NTSTATUS
2024-08-04 07:15:37 +02:00
PoolScanForManualMappedDrivers()
2023-11-08 16:02:17 +01:00
{
2024-08-01 06:21:53 +02:00
NTSTATUS status = STATUS_UNSUCCESSFUL;
2024-08-04 07:15:37 +02:00
DEBUG_VERBOSE("scanning for gadget");
local_page_copy_buf =
ImpExAllocatePool2(POOL_FLAG_NON_PAGED, PAGE_SIZE, POOL_TAG_INTEGRITY);
PoolScanSystemSpace(PoolScanForManualMappedDriverCallback, NULL);
DEBUG_VERBOSE("fnished scanning");
ImpExFreePoolWithTag(local_page_copy_buf, POOL_TAG_INTEGRITY);
}