[Completely solved]:
[Following this my way]
- call a Handler ( CmRegisterCallbacksEx, MiniFilter, NDIS(all of the callout), bla bla)
- Allocate to the Memory (in my case use it 'ExAllocatedWithTag' and NonPagedPool(but <= DISPATCH_LEVEL) or PagedPool(but == PASSIVE_LEVEL)
- start MAPPING
- Allocated Mem(kernel virtual memory) -> call MmGetPhysicalAddress() -> call MmMapIoSpace() if when you allocated with NonPagedPool
- Allocated Mem(Kernel virtual memory) -> call IoAllocatedMdi() -> MmProbeAndLockPages(recommend 'IoWriteAccess') -> call MmGetPhysicalAddress() -> call MmMapIoSpace() if when you allocated with PagedPool
- initialize the KEVENT
- copy (5) mapped address to the other thread ( call PsCreateSystemThread() ) and start(create) thread
- Locking to the KEVENT
- in (7) thread, copied the data from mapped address
- UnLock(Release) to the KEVENT in (7) thread
- FREE all allocated address
[SIMPLE_CODE]
#include "notifyroutine.h"
#pragma warning(disable:4189)
#pragma warning(disable:4996)
#pragma warning(disable:4100)
LARGE_INTEGER Cookie_for_unload = { 0, };
NTSTATUS Registry_Event_Loader(PDRIVER_OBJECT Input_Driver_Obj) {
UNICODE_STRING altitude;
RtlInitUnicodeString(&altitude, L"390596");
return CmRegisterCallbackEx(
ExRegistryCallback_for_monitor,
&altitude,
Input_Driver_Obj,
NULL,
&Cookie_for_unload,
NULL
);
}
typedef struct data {
KEVENT event;
PHYSICAL_ADDRESS data_phy_data;
PUCHAR data;
PVOID mappedAddress; // MmMapIoSpace로 매핑된 주소 저장
SIZE_T mappingSize; // 매핑된 크기 저장
} data, * Pdata;
VOID test(Pdata data) {
PUCHAR test_alloc = NULL;
// NonPagedPool에 복사 버퍼를 할당합니다.
test_alloc = ExAllocatePoolWithTag(NonPagedPool, 999, 'REG3');
if (!test_alloc) {
goto Exit;
}
if (data->mappedAddress) {
RtlCopyMemory(test_alloc, data->mappedAddress, 999);
}
// ... test_alloc 사용 ...
Exit:
if (test_alloc) {
ExFreePoolWithTag(test_alloc, 'REG3');
}
KeSetEvent(&data->event, IO_NO_INCREMENT, FALSE);
}
NTSTATUS ExRegistryCallback_for_monitor(PVOID CallbackContext, PVOID Argument1, PVOID Argument2) {
UNREFERENCED_PARAMETER(CallbackContext);
UNREFERENCED_PARAMETER(Argument1);
UNREFERENCED_PARAMETER(Argument2);
Pdata alloc = NULL;
PUCHAR DATA = NULL;
NTSTATUS status = STATUS_SUCCESS;
alloc = ExAllocatePoolWithTag(NonPagedPool, sizeof(data), 'REG');
if (!alloc) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
DATA = ExAllocatePoolWithTag(NonPagedPool, 999, 'REG2');
if (!DATA) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
alloc->data_phy_data = MmGetPhysicalAddress(DATA);
alloc->data = DATA;
alloc->mappingSize = 999;
// 물리 주소 범위를 가상 주소 공간에 매핑합니다.
alloc->mappedAddress = MmMapIoSpace(alloc->data_phy_data, alloc->mappingSize, MmNonCached);
if (!alloc->mappedAddress) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
KeInitializeEvent(&alloc->event, SynchronizationEvent, FALSE);
HANDLE handle;
//PETHREAD threadObject;
status = PsCreateSystemThread(&handle, THREAD_ALL_ACCESS, NULL, NULL, NULL, (PKSTART_ROUTINE)test, alloc);
if (!NT_SUCCESS(status)) {
goto Exit;
}
ZwClose(handle);
// 스레드가 종료될 때까지 기다립니다.
KeWaitForSingleObject(&alloc->event, Executive, KernelMode, FALSE, NULL);
Exit:
// 리소스를 해제합니다.
if (alloc && alloc->mappedAddress) {
MmUnmapIoSpace(alloc->mappedAddress, alloc->mappingSize);
}
if (DATA) {
ExFreePoolWithTag(DATA, 'REG2');
}
if (alloc) {
ExFreePoolWithTag(alloc, 'REG');
}
return status;
}
This is a method for transferring dynamically allocated data from the callback function to external threads, which uses the "physical memory mapping" function to solve the exponential growth problem of anomalous "NonPagedPools".