今天继续分享内核枚举系列知识,这次我们来学习如何通过代码的方式枚举内核IoTimer
定时器,内核定时器其实就是在内核中实现的时钟,该定时器的枚举非常简单,因为在IoInitializeTimer
初始化部分就可以找到IopTimerQueueHead
地址,该变量内存储的就是定时器的链表头部 。枚举IO定时器的案例并不多见,即便有也是无法使用过时的,此教程学到肯定就是赚到了 。
文章插图
枚举Io定时器过程是这样的:
- 1.找到
IoInitializeTimer
函数,该函数可以通过MmGetSystemRoutineAddress
得到 。 - 2.找到地址以后,我们向下增加
0xFF
偏移量,并搜索特征定位到IopTimerQueueHead
链表头 。 - 3.将链表头转换为
IO_TIMER
结构体,并循环链表头输出 。
IoInitializeTimer
这个函数他是一个初始化函数,既然是初始化里面一定会涉及到链表的存储问题,找到他就能找到定时器链表基址,该函数的定义如下 。NTSTATUSIoInitializeTimer(IN PDEVICE_OBJECTDeviceObject,// 设备对象指针IN PIO_TIMER_ROUTINETimerRoutine,// 定时器例程IN PVOIDContext// 传给定时器例程的函数);
接着我们需要得到IO定时器的结构定义,在DEVICE_OBJECT
设备对象指针中存在一个Timer
属性 。lyshark.com: kd> dt _DEVICE_OBJECTntdll!_DEVICE_OBJECT+0x000 Type: Int2B+0x002 Size: Uint2B+0x004 ReferenceCount: Int4B+0x008 DriverObject: Ptr64 _DRIVER_OBJECT+0x010 NextDevice: Ptr64 _DEVICE_OBJECT+0x018 AttachedDevice: Ptr64 _DEVICE_OBJECT+0x020 CurrentIrp: Ptr64 _IRP+0x028 Timer: Ptr64 _IO_TIMER+0x030 Flags: Uint4B+0x034 Characteristics: Uint4B+0x038 Vpb: Ptr64 _VPB+0x040 DeviceExtension: Ptr64 Void+0x048 DeviceType: Uint4B+0x04c StackSize: Char+0x050 Queue: <anonymous-tag>+0x098 AlignmentRequirement : Uint4B+0x0a0 DeviceQueue: _KDEVICE_QUEUE+0x0c8 Dpc: _KDPC+0x108 ActiveThreadCount : Uint4B+0x110 SecurityDescriptor : Ptr64 Void+0x118 DeviceLock: _KEVENT+0x130 SectorSize: Uint2B+0x132 Spare1: Uint2B+0x138 DeviceObjectExtension : Ptr64 _DEVOBJ_EXTENSION+0x140 Reserved: Ptr64 Void
文章插图
这里的这个
+0x028 Timer
定时器是一个结构体_IO_TIMER
其就是IO定时器的所需结构体 。【驱动开发:内核枚举IoTimer定时器】
lyshark.com: kd> dt _IO_TIMERntdll!_IO_TIMER+0x000 Type: Int2B+0x002 TimerFlag: Int2B+0x008 TimerList: _LIST_ENTRY+0x018 TimerRoutine: Ptr64void+0x020 Context: Ptr64 Void+0x028 DeviceObject: Ptr64 _DEVICE_OBJECT
文章插图
如上方的基础知识有了也就够了,接着就是实际开发部分,首先我们需要编写一个
GetIoInitializeTimerAddress()
函数,让该函数可以定位到IoInitializeTimer
所在内核中的基地址上面,具体实现调用代码如下所示 。#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); Driver->DriverUnload = UnDriver; return STATUS_SUCCESS;}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 钩子 【pytest官方文档】解读-插件开发之hooks 函数
- 开发商不给签购房合同怎么办
- 15 基于SqlSugar的开发框架循序渐进介绍-- 整合代码生成工具进行前端界面的生成
- 驱动开发:内核遍历进程VAD结构体
- [Android开发学iOS系列] 快速上手UIKit
- [Android开发学iOS系列] ViewController
- 驱动开发:内核中实现Dump进程转储
- GitHub 供应链安全已支持 Dart 开发者生态
- 驱动开发:内核R3与R0内存映射拷贝
- [Android开发学iOS系列] iOS写UI的几种方式