使用内核内存
wdm给出的使用内存池方法
申请内存
1 2 3 4 5 6 7 8 9
| PVOID AllocateBuffer(ULONG ViewSize) { PVOID VirtualAddress = ExAllocatePool(NonPagedPool, ViewSize); if (VirtualAddress != NULL) { RtlZeroMemory(VirtualAddress, ViewSize); } return VirtualAddress; }
|
释放内存
1 2 3 4
| VOID FreeBuffer(PVOID VirtualAddress) { ExFreePool(VirtualAddress); }
|
new 和delete 关键字在驱动里面是不可以使用,通过重载的方式即可在内核中使用,并通过c++编译器来编译。使用面向对象时,DriverEntry系列函数需要extern “C”
内部重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <ntddk.h>
class Myclass { public: Myclass() { KdPrint(("构造函数\n")); } ~Myclass() { KdPrint(("析构函数\n")); }
void * _cdecl operator new (size_t size,POOL_TYPE poolType= PagedPool) { KdPrint(("进入new\n")); return ExAllocatePoolWithTag(poolType,size,'a'); };
void _cdecl operator delete(void *p) { KdPrint(("进入delete\n")); if (p!=NULL) { ExFreePoolWithTag(p, 'a'); } }; };
VOID Unload(IN PDRIVER_OBJECT pDriverObject) { KdPrint(("Goodbye driver\n")); }
extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { DriverObject->DriverUnload = Unload; Myclass *pMyclass = new Myclass(); delete pMyclass; return STATUS_SUCCESS; }
|
全局重载 一个实例,可以直接套用Windows内核驱动中使用new和delete - PNPON内核开发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #pragma code_seg("PAGE")
_When_((PoolType & NonPagedPoolMustSucceed) != 0, __drv_reportError("Must succeed pool allocations are forbidden. " "Allocation failures cause a system crash")) void* __cdecl operator new(size_t Size, POOL_TYPE PoolType) { PAGED_CODE(); Size = (Size != 0) ? Size : 1; void* pObject = ExAllocatePoolWithTag(PoolType, Size, BDDTAG); #if DBG if (pObject != NULL) { RtlFillMemory(pObject, Size, 0xCD); } #endif return pObject; } _When_((PoolType & NonPagedPoolMustSucceed) != 0, __drv_reportError("Must succeed pool allocations are forbidden. " "Allocation failures cause a system crash")) void* __cdecl operator new[](size_t Size, POOL_TYPE PoolType) { PAGED_CODE(); Size = (Size != 0) ? Size : 1; void* pObject = ExAllocatePoolWithTag(PoolType, Size, BDDTAG); #if DBG if (pObject != NULL) { RtlFillMemory(pObject, Size, 0xCD); } #endif return pObject; } void __cdecl operator delete(void* pObject) { PAGED_CODE(); if (pObject != NULL) { ExFreePool(pObject); } } void __cdecl operator delete[](void* pObject) { PAGED_CODE(); if (pObject != NULL) { ExFreePool(pObject); } }
|
从代码来看,new和delete运算符的重载依然是对ExAllocatePoolWithTag和ExFreePool函数的封装。
这里说明一下,在dbg模式下,将分配的内存全部置为0xcd,这和应用层在调试模式下堆的内存初始化一样的道理。
0xcd其实这里是int指令的指令,再配合一个cd,就变成了int cd,说明直接行的是中断0xcd,这样CPU执行到此处就会出现中断异常。这和栈上的0xcc,int3的原理一致。
简单版。同样的,这种重载对于类也有效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void* __cdecl operator new(size_t size) { return ExAllocatePoolWithTag(NonPagedPool, size, 'yTag'); } void __cdecl operator delete(void* p,size_t a) { ExFreePool(p); } void* __cdecl operator new[](size_t size) { return ExAllocatePoolWithTag(NonPagedPool, size, 'yTag'); } void __cdecl operator delete[](void* p) { ExFreePool(p); } class CBase { public: int a; }; CBase* p = (CBase*)new CBase(); p->a = 10; delete p;
|