KPCR

Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html

KPCR

 1. IRQL

2. nt!KeNumberProcessors与nt!KiProcessorBlock

3. KPCR+0x34 KdVersionBlock

4. KeSetSystemAffinityThread() KeRevertToUserAffinityThread() 修改亲核性

5. DPC - 主要用于看门狗

6. MiProcessLoaderEntry

7.几个比较重要的知识点

 

1. IRQL

  在32位存储在KPCR+0x24中,但在64位存储在CR8寄存器中,这个要明确。

  IRQL 表示代码运行到什么级别,之后我们会详细说明的。

 

2. nt!KeNumberProcessors与nt!KiProcessorBlock

  KeNumberProcessors 显示存在几核CPU,要查看可以通过这个查看。

  

   KiProcessorBlock 显示其对应的KPCRB结构体的地址,注意 KPCR+0x120其指向KPCRB,因此获取KPCR要x-0x120。

  

  其中KeNumberProcessors是导出变量,直接导出使用即可。

  但是KiProcessorBlock需要手动寻找,其搜索路径如下,之后在代码中我们会在多核环境下遍历该KPCR数组。

  注意:该结构仅在0号CPU中运行,因此如果查找该结构,必须通过KeSetSystemAffinityThread()切换CPU到0号,然后再来查找有关CPU。

  

 

3. KPCR+0x34 KdVersionBlock

  该成员指向一个_DBGKD_GET_VERSION64结构体(其也存在*32后缀的结构体,但是在XP以后都为_DBGKD_GET_VERSION64,其与操作系统位数无关)。

  其存在两个重要的成员:ntoskrl.exe模块基址,模块加载链表。 我们之前讲到过使用NtQuerySystem和特征码搜索,现在又多了一种方法,这个是要明确的。

  

 

 

4. KeSetSystemAffinityThread() KeRevertToUserAffinityThread() 修改亲核性

  KeSetSystemAffinityThread 当前代码跑到几号核CPU上,设置为多少就跑到多少核上。

  KeRevertToUserAffinityThread 恢复到原来正在跑的线程。

 

5. DPC - 主要用于看门狗

  模拟键盘时,1分钟可以插入1000次,DPC级别,其DPC级别太高,则会让线程一直来处理DPC。

  Windows操作系统设置了DPC看门狗,当运行DPC超过多少时间,就会造成蓝屏。

  因此在写模拟键盘鼠标时,不要插入太多,同时也不要写延迟,这个要明确。

 

6. MiProcessLoaderEntry

  我们在驱动隐藏时看到这个函数,将驱动从链表中卸载,也同样可以卸载进程和线程,注意其传入的是一个链表,这个我们在之后的实验中会看到。

 

7.几个比较重要的知识点
  1)调用MiProcessLoaderEntry可以实现进程断链,之前我们实现驱动断链隐藏,但是同样的,在这里也可以实现进程断链。

    

  2)通过在2中讲到的nt!KiProcessorBlock,可以在多线程下遍历全部KPCR的数据,其代码如下:

// 遍历全部核的KPCR
NTSTATUS TraversProcessors() {

    // 先设置为0号CPU
    KeSetSystemAffinityThread(0);

    // 找到KiProcessorBlock,其kpcrb的数组
    PDBGKD_GET_VERSION64 pVersion;
    _asm {
        mov eax, dword ptr  fs: [0x34] ;
        mov pVersion, eax;
    }
    PULONG pDataList = (ULONG)pVersion->DebuggerDataList;
    PULONG kpcrb = (PULONG)*(PULONG)((PUCHAR)*(pDataList)+0x218);
    
    // 开始遍历各个kpcrb中的元素找到对应的数据
    for (int i = 0; i < KeNumberProcessors; i++) {
        PULONG CurrentKPCRB = kpcrb[i];
        DbgPrint("kpcrb:%x %p\r\n", kpcrb[i],kpcrb);
        DbgPrint("第%x号CPU的IDT表地址为:%x,GDT表地址为:%x\r\n",i, MACRO_GETIDTBYKPCR(kpcrb[i]),MACRO_GETGDTBYKPCR(kpcrb[i]));
    }

    // 恢复原来的核号
    KeRevertToUserAffinityThread();
    return STATUS_SUCCESS;
}

 

posted @ 2020-04-16 19:45  OneTrainee  阅读(1434)  评论(0编辑  收藏  举报