使用内核内存

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")
//
// New and delete operators
//
_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 // DBG
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 // DBG
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(); //operator new(size_t size)
p->a = 10;
delete p; //void __cdecl operator delete(void* p,size_t a)