xp下枚举KTIMER计时器(包含DPC计时器)

[此次枚举发生在  32BIT XP sp3 下,别的版本暂时没有试验过]


【前提】

DPC定时器  中描述,KeSetTimerEx中,引用到了 KiInsertTreeTimer ,这个符号是个 FASTCAL L型的函数调用,但是

其并没有使用EDX。 第一个参数 通过 ECX 将 KTIMER的指针传入, 第二个,第三个参数 靠压栈实现,这两个参数就是 LARGE_INTEGER的

数据结构。




可以看见KiInsertTreeTimer 仅仅做了些参数处理,几乎原封不动的传入了下一层去处理


KiInsertTimerTable函数



看来根据DueTime来决定插入的顺序的,该插入链表最后的节点开始



我们看见了_KiTimerTableListHead这个符号



对着这个符号双击一下,跳到定义处





1.找出链表头数组的大小,双击交叉引用的KiInitSystem()+77,进入相关引用处



2.找出数组的地址,双击交叉引用KeUpdateSystemTime+95处,发现确实引用了,用WinDbg看下这个函数

KeUpdateSystemTime l30    L30表示30行显示,L40则显示40行




直接算偏移 0X804E4267- 0X804E41CF= 0X95 + 3   即是 ULONG  数组地址= * (ULONG*)  ((ULONG)KeUpdateSystemTime + 0X98  )


贴一段简码

#include <ntddk.h>

//KTIMER 的结构定义
typedef struct _M_KTIMER{
	DISPATCHER_HEADER	Header;
	ULARGE_INTEGER	DueTime;
	LIST_ENTRY		TimerListEntry;
	KDPC*			Dpc;
	ULONG			Period;
}M_KTIMER, *PM_KTIMER;

VOID  DriverUnload(PDRIVER_OBJECT pDriverObj){
	return;
}

//获取KeUpdateSystemTime函数地址
ULONG GetKeUpdataSystemTimeFuncAddr(){
	UNICODE_STRING ustrFunc = { 0 };
	RtlInitUnicodeString(&ustrFunc, L"KeUpdateSystemTime");
	return (ULONG )MmGetSystemRoutineAddress(&ustrFunc);
}

VOID EnuerateKTIMER(){
	
	/*XP-SP3上,直接硬编码偏移得到
	kd> u KeUpdateSystemTime l40
nt!KeUpdateSystemTime:
804e41cf b90000dfff      mov     ecx,0FFDF0000h
804e41d4 8b7908          mov     edi,dword ptr [ecx+8]
804e41d7 8b710c          mov     esi,dword ptr [ecx+0Ch]
804e41da 03f8            add     edi,eax
804e41dc 83d600          adc     esi,0
804e41df 897110          mov     dword ptr [ecx+10h],esi
804e41e2 897908          mov     dword ptr [ecx+8],edi
804e41e5 89710c          mov     dword ptr [ecx+0Ch],esi
804e41e8 290594305580    sub     dword ptr [nt!KiTickOffset (80553094)],eax
804e41ee a180305580      mov     eax,dword ptr [nt!KeTickCount (80553080)]
804e41f3 8bd8            mov     ebx,eax
804e41f5 0f8f84000000    jg      nt!KeUpdateSystemTime+0xb0 (804e427f)
804e41fb bb0000dfff      mov     ebx,0FFDF0000h
804e4200 8b4b14          mov     ecx,dword ptr [ebx+14h]
804e4203 8b5318          mov     edx,dword ptr [ebx+18h]
804e4206 030d90305580    add     ecx,dword ptr [nt!KeTimeAdjustment (80553090)]
804e420c 83d200          adc     edx,0
804e420f 89531c          mov     dword ptr [ebx+1Ch],edx
804e4212 894b14          mov     dword ptr [ebx+14h],ecx
804e4215 895318          mov     dword ptr [ebx+18h],edx
804e4218 8bd8            mov     ebx,eax
804e421a 8bc8            mov     ecx,eax
804e421c 8b1584305580    mov     edx,dword ptr [nt!KeTickCount+0x4 (80553084)]
804e4222 83c101          add     ecx,1
804e4225 83d200          adc     edx,0
804e4228 891588305580    mov     dword ptr [nt!KeTickCount+0x8 (80553088)],edx
804e422e 890d80305580    mov     dword ptr [nt!KeTickCount (80553080)],ecx
804e4234 891584305580    mov     dword ptr [nt!KeTickCount+0x4 (80553084)],edx
804e423a 50              push    eax
804e423b a10000dfff      mov     eax,dword ptr ds:[FFDF0000h]
804e4240 83c001          add     eax,1
804e4243 7306            jae     nt!KeUpdateSystemTime+0x7c (804e424b)
804e4245 ff051c7e5580    inc     dword ptr [nt!ExpTickCountAdjustmentCount (80557e1c)]
804e424b a1187e5580      mov     eax,dword ptr [nt!ExpTickCountAdjustment (80557e18)]
804e4250 0faf051c7e5580  imul    eax,dword ptr [nt!ExpTickCountAdjustmentCount (80557e1c)]
804e4257 03c1            add     eax,ecx
804e4259 a30000dfff      mov     dword ptr ds:[FFDF0000h],eax
804e425e 58              pop     eax
804e425f 25ff000000      and     eax,0FFh
804e4264 8d0cc520b35580  lea     ecx,nt!KiTimerTableListHead (8055b320)[eax*8]

偏移  804e4264+3-804e41cf=98H
	*/

	LIST_ENTRY* XPKtimerListArray = (LIST_ENTRY*)(*(ULONG*)(GetKeUpdataSystemTimeFuncAddr() + 0X98) );
	static ULONG index = 0;
	//XPKtimerListArray是一个100H 大小的数组

	//打印 所有链表头
	/*
		for (ULONG i = 0; i < 0X100; i++, XPKtimerListArray++){
			KdPrint(("[0X%08X] 0X%08X - 0X%08X\n", XPKtimerListArray, XPKtimerListArray->Flink, XPKtimerListArray->Blink));
		}
	*/

	// 100h个头部全部都枚举了,PCHunter中只枚举DPC计时器,换句话说和DPC绑定了的KTIMER,但是100H个链表中,是所有的
	// KTIMER,而不管有没有绑定KTIMER
	for (ULONG i = 0; i < 0X100; i++, XPKtimerListArray++){	
		if (XPKtimerListArray->Flink == XPKtimerListArray )
			continue;//说明此链表头没有被插入节点
		else{
			LIST_ENTRY* currListHead = XPKtimerListArray->Flink;
			do{
				
				PM_KTIMER pTimer = (PM_KTIMER)((ULONG)currListHead - 0X18);
				PKDPC dpc = pTimer->Dpc;
				ULONG routine;
				char  importance;
				//对有没有绑定DPC进行区分,
				if ((ULONG)dpc == 0){
					routine = 0;
					importance = 0;
				}
				else{
					routine = (ULONG)(dpc->DeferredRoutine);
					importance = dpc->Importance;
				}
				
				ULONG period = pTimer->Period;
				ULARGE_INTEGER li = pTimer->DueTime;

				KdPrint(("[KTIMER %d]->0X%08X DPC:0X%08X DPCRoutine:0X%08X Importance:%d Period:0X%08X\n", 
					index, pTimer,dpc, routine, importance, period));

				currListHead = currListHead->Flink;
				index++;
			} while (currListHead != XPKtimerListArray);
		}
	}
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath){
	pDriverObj->DriverUnload = DriverUnload;
	EnuerateKTIMER();
	return STATUS_SUCCESS;
}


实验数据 可以看见有 207项而PCHunter中只有50多项,仔细观察,发现PCHunter只计数了带DPC的KTIMER计时器,也就是DPC计时器



如果你不相信枚举正确我有一个好办法检测,首先如果是在双击调试下,在DbgView上打印出了结果的话,那么WinDbg上也会打印




,将之复制到记事本,分别就PCHunter中的定时器对象栏下,上,中,下,抽样几个数据去搜索下:这里我就演示一下效果


要记得每次搜索前,将光标重新置位到最前,表示从头开始搜索



OVER 。再次说明下,实验发生在32 BIT XP 下,有可能你做起来并不如意,可能原因:

1.IDA符号原因

2.windbg符号原因

3.双机调试原因

4.windows版本原因

其他的好像没有了。。。3ks for watching。。。。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值