登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 52|回复: 0

Win64驱动开发教程05-内核里使用内存

[复制链接]

68

主题

2

回帖

91

积分

网站编辑

积分
91
发表于 6 天前 | 显示全部楼层 |阅读模式


程序的本质,就是内存里的一串串的数字(它们被 CPU 当作指令解析,才能够有意义,否则就是一坨垃圾);因此在正式讲解驱动编程之前,首先讲解内存使用。


内存使用,无非就是申请、复制、设置、释放。在 C 语言里,它们对应的函数是:malloc、memcpymemsetfree;在内核编程里,他们分别对应 ExAllocatePoolRtlMoveMemoryRtlFillMemoryExFreePool。它们的原型分别是:


PVOID ExAllocatePool(POOL_TYPE PoolType, SIZE_T NumberOfBytes);
VOID RtlMoveMemory(PVOID Destination, PVOID Source, SIZE_T Length);
VOID RtlFillMemory(PVOID Destination, SIZE_T Length, UCHAR Fill);
VOID ExFreePool(PVOID P);




需要注意的是,RtlFillMemory 和 memset 的原型不同、ExAllocatePool 和 malloc 的原型也不同。前者只是参数前后调换了一下位置,但是后者则多了一个参数:PoolType。这个PoolType 也是必须了解的。PoolType MSDN 的介绍上有 N 种,其实常用的只有 2 种:
PagedPool 和 NonPagedPool。PagedPool 是分页内存,简单来说就是物理内存不够时,会把这片内存移动到硬盘上,而 NonPagedPool 是无论物理内存如何紧缺,都绝对不把这片内存的内容移动到硬盘上。在往下讲之前,先补充一个知识,就是我们操作的内存,都是虚拟内存,和物理内存是两码事。但虚拟内存的数据是放在物理内存上的,两者存在映射关系,一般来说,一片物理内存可以映射为多片虚拟内存,但一片虚拟内存必定只对应一片物理内。假设虚拟内存是 0Xfffff80001234567 在物理内存的地址是 0x123456,当物理内存不够用时,物理内存 0x123456 的原始内容就挪到硬盘上,然后把另外一片急需要用的内容移到物理内存里。此时,当你再读取 0Xfffff80001234567 的内容时,就会引发缺页异常,系统就会把在硬盘上的内容再次放到物理内存中(如果这个过程失败,一般就死机了)。以上说了这么多废话,总结两句:1.NonPagedPool 的总量是有限的(具体大小和你物理内存的大小相关),而 PagedPool 的总量较多。申请了内存忘记释放都会造成内存泄漏,但是很明显忘记释放 NonPagedPool 的后果要严重得多;2.一般来说,PagedPool 用来放数据(比如你用ZwQuerySystemInformation 枚举内核模块,可以申请一大片 PagedPool 存放返回的数据),NonPagedPool 用来放代码(你写内核 shellcode 并需要执行时,必须使用 NonPagedPool存放 shellcode)。以我的经验来说,访问到切换出去的内存没事,但是执行到切换出去的内存必然蓝屏(这只是我的经验,正确性待定)3.在用户态,内存是有属性的,有的内存片只能读 不 能 写 不 能 执 行 ( PAGE_READ ), 有 的 内 存 片 可 以 读 可 以 写也可以执行PAGE_READ_WRITE_EXECUTE)。在内核里,PagedPool NonPagedPool 都是可读可写可执行的,而且没有类似 VirtualProtect 之类的函数


示例代码:
  1. void test()
  2. {
  3. PVOID ptr1 = ExAllocatePool(PagedPool,0x100);
  4. PVOID ptr2 = ExAllocatePool(NonPagedPool,0x200);
  5. RtlFillMemory(ptr2,0x200,0x90);
  6. RtlMoveMemory(ptr1,ptr2,0x50);
  7. ExFreePool(ptr1);
  8. ExFreePool(ptr2);
  9. }
复制代码
  1. KIRQL WPOFFx64()
  2. {
  3. KIRQL irql=KeRaiseIrqlToDpcLevel();
  4. UINT64 cr0=__readcr0();
  5. cr0 &= 0xfffffffffffeffff;
  6. __writecr0(cr0);
  7. _disable();
  8. return irql;
  9. }
  10. void WPONx64(KIRQL irql)
  11. {
  12. UINT64 cr0=__readcr0();
  13. cr0 |= 0x10000;
  14. _enable();
  15. __writecr0(cr0);
  16. KeLowerIrql(irql);
  17. }
  18. void test()
  19. {
  20. KIRQL irql=WPOFF();
  21. RtlMoveMemory(NtOpenProcess,HookCode,15);
  22. WPON(irql);
  23. }
复制代码
  1. BOOLEAN SafeCopyMemory( PVOID pDestination, PVOID pSourceAddress, SIZE_T SizeOfCopy )
  2. {
  3. PMDL pMdl = NULL;
  4. PVOID pSafeAddress = NULL;
  5. if( !MmIsAddressValid(pDestination) || !MmIsAddressValid(pSourceAddress) )
  6. return FALSE;
  7. pMdl = IoAllocateMdl(pDestination, (ULONG)SizeOfCopy, FALSE, FALSE, NULL );
  8. if( !pMdl )
  9. return FALSE;
  10. __try
  11. {
  12. MmProbeAndLockPages( pMdl, KernelMode, IoReadAccess );
  13. }
  14. __except(EXCEPTION_EXECUTE_HANDLER)
  15. {
  16. IoFreeMdl( pMdl );
  17. return FALSE;
  18. }
  19. pSafeAddress = MmGetSystemAddressForMdlSafe( pMdl, NormalPagePriority );
  20. if( !pSafeAddress )
  21. return FALSE;
  22. __try
  23. {
  24. RtlMoveMemory(pSafeAddress, pSourceAddress, SizeOfCopy );
  25. }
  26. __except(EXCEPTION_EXECUTE_HANDLER)
  27. {
  28. ;
  29. }
  30. MmUnlockPages( pMdl );
  31. IoFreeMdl( pMdl );
  32. return TRUE;
  33. }
复制代码


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2025-1-18 10:01 , Processed in 0.061511 second(s), 26 queries .

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表