驅動開發:內核枚舉IoTimer定時器( 二 )

lea rcx,[nt!IopTimerQueueHead (fffff805748639e0)]`更容易看到 。

驅動開發:內核枚舉IoTimer定時器

文章插圖
接著就是通過代碼實現對此處的定位,定位我們就采用特征碼搜索的方式,如下代碼是特征搜索部分 。
  • StartSearchAddress 代表開始位置
  • EndSearchAddress 代表結束位置,粗略計算0xff就可以定位到了 。
#include <ntifs.h>// 得到IoInitializeTimer基址// By: LyShark 內核開發系列教程PVOID GetIoInitializeTimerAddress(){ PVOID VariableAddress = 0; UNICODE_STRING uioiTime = { 0 }; RtlInitUnicodeString(&uioiTime, L"IoInitializeTimer"); VariableAddress = (PVOID)MmGetSystemRoutineAddress(&uioiTime); if (VariableAddress != 0) {return VariableAddress; } return 0;}VOID UnDriver(PDRIVER_OBJECT driver){ DbgPrint(("Uninstall Driver Is OK \n"));}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath){ DbgPrint(("hello lyshark.com \n")); // 得到基址 PUCHAR IoInitializeTimer = GetIoInitializeTimerAddress(); DbgPrint("IoInitializeTimer Address = %p \n", IoInitializeTimer); INT32 iOffset = 0; PLIST_ENTRY IoTimerQueueHead = NULL; PUCHAR StartSearchAddress = IoInitializeTimer; PUCHAR EndSearchAddress = IoInitializeTimer + 0xFF; UCHAR v1 = 0, v2 = 0, v3 = 0; for (PUCHAR i = StartSearchAddress; i < EndSearchAddress; i++) {if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2)){v1 = *i;v2 = *(i + 1);v3 = *(i + 2);// 三個特征碼if (v1 == 0x48 && v2 == 0x8d && v3 == 0x0d){memcpy(&iOffset, i + 3, 4);IoTimerQueueHead = (PLIST_ENTRY)(iOffset + (ULONG64)i + 7);DbgPrint("IoTimerQueueHead = %p \n", IoTimerQueueHead);break;}} } Driver->DriverUnload = UnDriver; return STATUS_SUCCESS;}搜索三個特征碼v1 == 0x48 && v2 == 0x8d && v3 == 0x0d從而得到內存位置,運行驅動對比下 。
  • 運行代碼會取出lea指令后面的操作數 , 而不是取出lea指令的內存地址 。

驅動開發:內核枚舉IoTimer定時器

文章插圖
最后一步就是枚舉部分 , 我們需要前面提到的IO_TIMER結構體定義 。
  • PIO_TIMER Timer = CONTAINING_RECORD(NextEntry, IO_TIMER, TimerList) 得到結構體,循環輸出即可 。
// By: LyShark 內核開發系列教程// https://www.cnblogs.com/LyShark/articles/16784393.html#include <ntddk.h>#include <ntstrsafe.h>typedef struct _IO_TIMER{INT16Type;INT16TimerFlag;LONG32Unknown;LIST_ENTRYTimerList;PVOIDTimerRoutine;PVOIDContext;PVOIDDeviceObject;}IO_TIMER, *PIO_TIMER;// 得到IoInitializeTimer基址PVOID GetIoInitializeTimerAddress(){PVOID VariableAddress = 0;UNICODE_STRING uioiTime = { 0 };RtlInitUnicodeString(&uioiTime, L"IoInitializeTimer");VariableAddress = (PVOID)MmGetSystemRoutineAddress(&uioiTime);if (VariableAddress != 0){return VariableAddress;}return 0;}VOID UnDriver(PDRIVER_OBJECT driver){DbgPrint("卸載完成... \n");}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath){DbgPrint(("hello lyshark.com \n"));// 得到基址PUCHAR IoInitializeTimer = GetIoInitializeTimerAddress();DbgPrint("IoInitializeTimer Address = %p \n", IoInitializeTimer);// 搜索IoTimerQueueHead地址/*nt!IoInitializeTimer+0x5d:fffff806`349963cd 488d5008leardx,[rax+8]fffff806`349963d1 48897018movqword ptr [rax+18h],rsifffff806`349963d5 4c8d05648de0fflear8,[nt!IopTimerLock (fffff806`3479f140)]fffff806`349963dc 48897820movqword ptr [rax+20h],rdifffff806`349963e0 488d0d99f6cdfflearcx,[nt!IopTimerQueueHead (fffff806`34675a80)]fffff806`349963e7 e8c43598ffcallnt!ExInterlockedInsertTailList (fffff806`343199b0)fffff806`349963ec 33c0xoreax,eax*/INT32 iOffset = 0;PLIST_ENTRY IoTimerQueueHead = NULL;PUCHAR StartSearchAddress = IoInitializeTimer;PUCHAR EndSearchAddress = IoInitializeTimer + 0xFF;UCHAR v1 = 0, v2 = 0, v3 = 0;for (PUCHAR i = StartSearchAddress; i < EndSearchAddress; i++){if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2)){v1 = *i;v2 = *(i + 1);v3 = *(i + 2);// fffff806`349963e0 48 8d 0d 99 f6 cd fflea rcx,[nt!IopTimerQueueHead (fffff806`34675a80)]if (v1 == 0x48 && v2 == 0x8d && v3 == 0x0d){memcpy(&iOffset, i + 3, 4);IoTimerQueueHead = (PLIST_ENTRY)(iOffset + (ULONG64)i + 7);DbgPrint("IoTimerQueueHead = %p \n", IoTimerQueueHead);break;}}}// 枚舉列表KIRQL OldIrql;// 獲得特權級OldIrql = KeRaiseIrqlToDpcLevel();if (IoTimerQueueHead && MmIsAddressValid((PVOID)IoTimerQueueHead)){PLIST_ENTRY NextEntry = IoTimerQueueHead->Flink;while (MmIsAddressValid(NextEntry) && NextEntry != (PLIST_ENTRY)IoTimerQueueHead){PIO_TIMER Timer = CONTAINING_RECORD(NextEntry, IO_TIMER, TimerList);if (Timer && MmIsAddressValid(Timer)){DbgPrint("IO對象地址: %p \n", Timer);}NextEntry = NextEntry->Flink;}}// 恢復特權級KeLowerIrql(OldIrql);Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;}

推薦閱讀