驱动开发:内核枚举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;}

推荐阅读