Joe1sn's Cabinet

windows内核驱动 8-计时器与通知

在内核中使用定时器、通知和回调

…学到一半打靶场去了

定时器

CPU最短能统计时间为100纳秒 100ns

内核中使用LARGEINT来表示时间长度

1s = -10 *1000 * 1000

基于设备的IO定时器

DriverEntry里面尝试一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
VOID TimeWorker(PVOID CONTEXT) {
DbgPrint("Irql: %d\n", KeGetCurrentIrql());
DbgPrint("Process: %s\n", PsGetProcessImageFileName(PsGetCurrentProcess()));
}
NTSTATUS
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
// ...
IoInitializeTimer(pDevice, TimeWorker, NULL);
IoStartTimer(pDevice);
}
Unload(){
IoStopTimer(DriverObject->DeviceObject);
}

image-20240327161718432

主要API

  • IoInitializeTimer:创建定时

  • IoStartTimer:开启定时

  • IoStopTimer:关闭定时

技巧

  • 同时启用两个定时器可以关闭PCHUNTER
  • 做认证

结合DPC的定时器

1
2
3
4
5
6
7
8
9
10
11
12
//全局变量
KDPC kDPC = { 0 };
LARGE_INTEGER DpcTime = { 0 };

KeInitializeTimer(&keTimer);
KDPC kDPC = { 0 };
KeInitializeDpc(&kDPC, &DpcRoutineFunc, NULL);
LARGE_INTEGER DpcTime = { 0 };
DpcTime.QuadPart = -10 * 1000 * 2000;
KeSetTimer(&keTimer, DpcTime, &kDPC);

KeCancelTimer(&keTimer);

image-20240327164409369

  • 后续可以通过KeWait来判断超时之类的
  • 这个只会触发一次

放在工作队列线程池中运行

1
2
ExInitializeWorkItem(&work_item, WorkItemRoutine, NULL);
ExQueueWorkItem(&work_item, CriticalWorkQueue);

image-20240327170200351

  • 例程级别很低
  • WorkItemRoutine别陷入死循环,同步

通知

通知:发生某一件事变更,知道事情变更,但不能操作变更的结果。PsCreateNotify

回调:能拦截相关信息,更改流程和结果。

windows内核驱动 6-链表与进程讲了部分

模块加载回调:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
VOID ImageRoutine(
PUNICODE_STRING FullImageName,
HANDLE ProcessId, // pid into which image is being mapped
PIMAGE_INFO ImageInfo
) {
//DbgPrint("Triigered callback\n");
PEPROCESS temppe = NULL;
NTSTATUS status = STATUS_SUCCESS;
status = PsLookupProcessByProcessId(ProcessId, &temppe);
if (NT_SUCCESS(status)) {
ObDereferenceObject(temppe);
PUCHAR imagename = PsGetProcessImageFileName(temppe);
DbgPrint("[%s] load [%wZ] with baseaddr [%llx]\n", imagename, FullImageName, ImageInfo->ImageBase);
}
//DbgPrint("FullImageName: %wZ---PID: %d\n", FullImageName, ProcessId);

}


PsSetLoadImageNotifyRoutine(ImageRoutine);
PsRemoveLoadImageNotifyRoutine(ImageRoutine);

image-20240327175140251

其他的也很类似