KPRC

来源:互联网 发布:企业应用开发实战源码 编辑:程序博客网 时间:2024/06/03 21:18

点击打开链接

由于Windows需要支持多个CPU, 因此Windows内核中为此定义了一套以处理器控制区(Processor Control Region)即KPCR为枢纽的数据结构, 使每个CPU都有个KPCR. 其中KPCR这个结构中有一个域KPRCB(Kernel Processor Control Block)结构, 这个结构扩展了KPCR. 这两个结构用来保存与线程切换相关的全局信息.

通常fs段寄存器在内核模式下指向KPCR, 用户模式下指向TEB.

KPCR结构如下:


其中比较重要的是KdVersionBlock这个指针, 它指向一个DBGKD_GET_VERSION64这个结构.

这个结构体里面包含了一些重要信息。如:PsLoadedModuleList ,它是Windows加载的所有内核模块构成的链表的表头。



由此可以看到,两个处理器对应的KPCR结构是有区别的,只有第一个处理器的KPCR域KdVersionBlock才指向DBGKD_GET_VERSION64这个结构。


下面我们通过具体的代码举个例子,通过KPCR枚举到Ntoskrnl的基地址:



[cpp] view plaincopyprint?
  1. /*
  2. * AUTHOR : 莫灰灰
  3. * BLOG : http://blog.csdn.net/hu3167343
  4. * DESCRIBE : KPCR->KdVersionBlock->PsLoadedModuleList->ntoskrnl base address
  5. */
  6. #include "ntddk.h"
  7. NTKERNELAPI VOID KeSetSystemAffinityThread ( KAFFINITY Affinity );
  8. NTKERNELAPI VOID KeRevertToUserAffinityThread (VOID );
  9. VOID
  10. DriverUnload(IN PDRIVER_OBJECT pDriverObj)
  11. {
  12. KdPrint(("Unloaded Success\r\n"));
  13. return;
  14. }
  15. NTSTATUS
  16. DriverEntry(IN PDRIVER_OBJECT pDriverObj, IN PUNICODE_STRING pRegistryString)
  17. {
  18. NTSTATUS status = STATUS_SUCCESS;
  19. ULONG FSAddr;
  20. pDriverObj->DriverUnload = DriverUnload;
  21. KeSetSystemAffinityThread(1); //使当前线程运行在第一个处理器上
  22. __asm{
  23. push eax
  24. mov eax, fs:[0x34] ;得到KdVersionBlock的地址
  25. add eax,18h ;得到指向PsLoadedModuleList的地址
  26. mov eax,[eax] ;得到PsLoadedModuleList的地址
  27. mov eax,[eax] ;取出PsLoadedModuleList里面的内容, 即KLDR_DATA_TABLE_ENTRY结构
  28. mov eax,[eax+18h] ;取出DllBase, 即ntoskrnl.exe的基地址
  29. mov FSAddr, eax
  30. pop eax
  31. }
  32. KeRevertToUserAffinityThread();//恢复线程运行的处理器
  33. KdPrint(("0x%08X\n", FSAddr));
  34. return STATUS_SUCCESS;
  35. }  

0 0