申请内存

在c语言中我们使用malloc 来分配内存块,但是Windows内核模式下不能使用,没有c runtime。
在内核中,使用ExAllocCatePoolWithTag函数,返回PVOID指针,
它有3个参数,内存类型,长度标签:

  • ExAllocatePoolWithTag(NonPagedPool,length,tag);
  • 如果空闲内存不够,函数会返回null,我们需要用if语句判断释放申请成功
    • 内存有多种类型,常用的是NopagedPool和PagedPool
    • 内存是非常稀缺的,使用时才分配,不用就释放掉
  • length:申请内存大小
  • tag参数可以帮助调试程序
    • tag是ascii 字符的 0x20(空格)到0x126 波浪号范围内的值

释放内存

可以使用ExFreePool 释放,也可以使用ExFreeWithTag 释放
ExFreePool()只有一个参数,申请内存的地址

填充内存

  1. RtlZeroMemory(deststring.Buffer,length);
  2. RtlFillMemory(deststring.Buffer, length,0x90); //填充为nop

复制内存

  1. RtlCopyMemory(deststring.Buffer,sourstring.Buffer,length);
  2. RtlMoveMemory(deststring.Buffer, sourstring.Buffer, length);

两者区别:当源地址和目的地址内存重叠时,RtlCopyMemory会失败,但是rtlmoveMemory会成功,
因此,不确定内存是否重叠时,应该使用RtlMoveMemory

代码

  1. #include <ntddk.h>
  2. #define Mytag 'abc'
  3. VOID Unload(IN PDRIVER_OBJECT DriverObject) {
  4. DbgPrint("driver unload\r\n");
  5. }
  6. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegisteryPath) {
  7. DriverObject->DriverUnload = Unload;
  8. UNICODE_STRING sourstring = RTL_CONSTANT_STRING(L"hello drivertyty");
  9. UNICODE_STRING deststring = { 0 };
  10. ULONG length;
  11. length = sourstring.Length;
  12. deststring.Buffer = (PWCHAR)ExAllocatePoolWithTag(NonPagedPool,length,Mytag);
  13. if (NULL!=deststring.Buffer)
  14. {
  15. RtlZeroMemory(deststring.Buffer,length);
  16. RtlFillMemory(deststring.Buffer, length,0x90);
  17. deststring.Length = deststring.MaximumLength = length;
  18. RtlCopyUnicodeString(&deststring, &sourstring);
  19. RtlCopyMemory(deststring.Buffer,sourstring.Buffer,length);
  20. RtlMoveMemory(deststring.Buffer, sourstring.Buffer, length);
  21. DbgPrint("string is %wZ \r\n", &deststring);
  22. ExFreePool(deststring.Buffer);
  23. }
  24. return STATUS_SUCCESS;
  25. }

windows poolheader内存池