在内核中使用定时器、通知和回调
…学到一半打靶场去了
定时器
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-链表与进程讲了部分
模块加载回调:
使用PsGetProcessImageFileName需要添加声明
1
| PCHAR PsGetProcessImageFileName(PEPROCESS EProcess);
|
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);
|

其他的也很类似
PsSetCreateThreadNotifyRoutine
对应的注销语句PsRemoveCreateThreadNotifyRoutine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #include <ntifs.h>
PCHAR PsGetProcessImageFileName(PEPROCESS EProcess);
VOID MyCreateThreadNotify( HANDLE ProcessId, HANDLE ThreadId, BOOLEAN Create) {
if (Create) { PEPROCESS temppe = NULL; NTSTATUS status = STATUS_SUCCESS; status = PsLookupProcessByProcessId(ProcessId, &temppe); if (NT_SUCCESS(status)) { ObDereferenceObject(temppe); PCHAR imageName = PsGetProcessImageFileName(temppe); DbgPrint("[%s] create thread <%d>\n", imageName, ThreadId); } } }
VOID DriverUnload(PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); DbgPrint("Driver Stopping -> %wZ\n", &DriverObject->DriverName); PsRemoveCreateThreadNotifyRoutine(MyCreateThreadNotify); }
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath);
DbgPrint("Driver Running -> %wZ\n", &DriverObject->DriverName); DriverObject->DriverUnload = DriverUnload;
NTSTATUS status = STATUS_SUCCESS; status = PsSetCreateThreadNotifyRoutine(MyCreateThreadNotify);
return STATUS_SUCCESS; }
|

利用掩码设置0b111,全部写0,移除回调,但是只能停止已经注册掉的开关
