typedef struct _KTIMER {
DISPATCHER_HEADER Header;
ULARGE_INTEGER DueTime;
LIST_ENTRY TimerListEntry;
struct _KDPC *Dpc;
#if !defined(KENCODED_TIMER_PROCESSOR)
ULONG Processor;
#endif
ULONG Period;
} KTIMER, *PKTIMER, *PRKTIMER;
一、枚举所有KTIMER
通过这个结构体我们可以看出来DPC是KTIMER的一个成员,也就是说只要找到我们想要移除的KTIMER之后,移除KTIMER就可以移除DPC了,那么问题就来了,我们怎么找到KTIMER呢,而且系统里面有很多的KTIMER结构,就算找到了,怎么确定找到的KTIMER就是我们要移除的KTIMER呢。
所以我们可以理一下移除DPC的步骤:
1.先找到所有的KTIMER。
2.从所有的KTIMER中一个一个的找我们所要想要移除的KTIMER。(当然,如果一击即中,直接把我们所要移除的KTIMER从系统中拽出来,不用暴力枚举所有的KTIMER,那就最好了,不过好像没有办法这么做,网上也没有类似的方法,基本上都是暴力枚举所有KTIMER)
3.移除KTIMER。
说起来容易,那怎么寻找呢,原来,系统中有一个链表,这个链表将所有的KTIMER串起来,链表头存在于一个数组中,这个数组叫TimerEntries,256个数组成员,每一个成员都是一个链表头。这个数组存在于TimerTable数组中,TimerEntries是 TimerTable的第二数组成员,TimerTable这个数组存在结构体KPRCB的0x2200(x64)或0x1960(x86)处,而KPRCB结构体指针又存在于结构体KPCR的0x20处。KPCR结构体在64位中是在寄存器msr[c0000101]的位置,在32位中是在fs寄存器中。
关于KPRC等的解释可以看后面的脚注1。
好了,我们可以通过画图理一遍思路。
我们可以再通过Windbg调试看一下具体的信息:
X64:
读msr寄存器
kd> rdmsr 0xc0000101
msr[c0000101] = fffff800`04055d00
KPCR 结构体
kd> dt _KPCR fffff800`04055d00
ntdll!_KPCR
+0x000 NtTib : _NT_TIB
+0x000 GdtBase : 0xfffff800`00b95000 _KGDTENTRY64
+0x008 TssBase : 0xfffff800`00b96080 _KTSS64
+0x010 UserRsp : 0x30ffb48
+0x018 Self : 0xfffff800`04055d00 _KPCR
+0x020 CurrentPrcb : 0xfffff800`04055e80 _KPRCB
......
KPRCB 结构体
kd> dt _KPRCB 0xfffff800`04055e80
ntdll!_KPRCB
+0x000 MxCsr : 0x1f80
+0x004 LegacyNumber : 0 ''
+0x005 ReservedMustBeZero : 0 ''
+0x006 InterruptRequest : 0 ''
.....
+0x2200 TimerTable : _KTIMER_TABLE
......