在内核中使用定时器、通知和回调
…学到一半打靶场去了
定时器
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); }
|
主要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);
|
- 后续可以通过
KeWait
来判断超时之类的
- 这个只会触发一次
放在工作队列线程池中运行
1 2
| ExInitializeWorkItem(&work_item, WorkItemRoutine, NULL); ExQueueWorkItem(&work_item, CriticalWorkQueue);
|
- 例程级别很低
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, PIMAGE_INFO ImageInfo ) { 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); }
}
PsSetLoadImageNotifyRoutine(ImageRoutine); PsRemoveLoadImageNotifyRoutine(ImageRoutine);
|
其他的也很类似