当前位置: 首页 > news >正文

新乡营销网站建设公司广告推广代运营公司

新乡营销网站建设公司,广告推广代运营公司,宣武做网站,苏州大型网站建设内核I/O定时器(Kernel I/O Timer)是Windows内核中的一个对象,它允许内核或驱动程序设置一个定时器,以便在指定的时间间隔内调用一个回调函数。通常,内核I/O定时器用于周期性地执行某个任务,例如检查驱动程序…

内核I/O定时器(Kernel I/O Timer)是Windows内核中的一个对象,它允许内核或驱动程序设置一个定时器,以便在指定的时间间隔内调用一个回调函数。通常,内核I/O定时器用于周期性地执行某个任务,例如检查驱动程序的状态、收集性能数据等。

今天继续分享内核枚举系列知识,这次我们来学习如何通过代码的方式枚举内核IoTimer定时器,内核定时器其实就是在内核中实现的时钟,该定时器的枚举非常简单,因为在IoInitializeTimer初始化部分就可以找到IopTimerQueueHead地址,该变量内存储的就是定时器的链表头部。


内核I/O定时器通常由内核或驱动程序创建,使用KeInitializeTimerEx函数进行初始化。然后,使用KeSetTimerEx函数启动定时器,以指定间隔和回调函数。每次定时器超时时,回调函数都会被调用,然后定时器重新启动以等待下一个超时。

内核I/O定时器是内核中常见的机制之一,它允许内核和驱动程序实现各种功能,如性能监视、定时执行任务等。但是,使用内核I/O定时器必须小心谨慎,因为它们可能会影响系统的性能和稳定性,特别是当存在大量定时器时。

枚举Io定时器过程是这样的:

  • 1.找到IoInitializeTimer函数,该函数可以通过MmGetSystemRoutineAddress得到。
  • 2.找到地址以后,我们向下增加0xFF偏移量,并搜索特征定位到IopTimerQueueHead链表头。
  • 3.将链表头转换为IO_TIMER结构体,并循环链表头输出。

这里解释一下为什么要找IoInitializeTimer这个函数他是一个初始化函数,既然是初始化里面一定会涉及到链表的存储问题,找到他就能找到定时器链表基址,该函数的定义如下。

NTSTATUS IoInitializeTimer(IN PDEVICE_OBJECT  DeviceObject,     // 设备对象指针IN PIO_TIMER_ROUTINE  TimerRoutine,  // 定时器例程IN PVOID  Context                    // 传给定时器例程的函数);

接着我们需要得到IO定时器的结构定义,在DEVICE_OBJECT设备对象指针中存在一个Timer属性。

kd> dt _DEVICE_OBJECT
ntdll!_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定时器的所需结构体。

kd> dt _IO_TIMER
ntdll!_IO_TIMER+0x000 Type             : Int2B+0x002 TimerFlag        : Int2B+0x008 TimerList        : _LIST_ENTRY+0x018 TimerRoutine     : Ptr64     void +0x020 Context          : Ptr64 Void+0x028 DeviceObject     : Ptr64 _DEVICE_OBJECT

如上方的基础知识有了也就够了,接着就是实际开发部分,首先我们需要编写一个GetIoInitializeTimerAddress()函数,让该函数可以定位到IoInitializeTimer所在内核中的基地址上面,具体实现调用代码如下所示。

#include <ntifs.h>// 得到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(("Uninstall Driver Is OK \n"));
}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{DbgPrint(("hello lyshark \n"));// 得到基址PUCHAR IoInitializeTimer = GetIoInitializeTimerAddress();DbgPrint("IoInitializeTimer Address = %p \n", IoInitializeTimer);Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;
}

运行这个驱动程序,然后对比下是否一致:

接着我们在反汇编代码中寻找IoTimerQueueHead,此处在LyShark系统内这个偏移位置是nt!IoInitializeTimer+0x5d 具体输出位置如下。

kd> uf IoInitializeTimernt!IoInitializeTimer+0x5d:
fffff805`74b85bed 488d5008        lea     rdx,[rax+8]
fffff805`74b85bf1 48897018        mov     qword ptr [rax+18h],rsi
fffff805`74b85bf5 4c8d054475e0ff  lea     r8,[nt!IopTimerLock (fffff805`7498d140)]
fffff805`74b85bfc 48897820        mov     qword ptr [rax+20h],rdi
fffff805`74b85c00 488d0dd9ddcdff  lea     rcx,[nt!IopTimerQueueHead (fffff805`748639e0)]
fffff805`74b85c07 e8141e98ff      call    nt!ExInterlockedInsertTailList (fffff805`74507a20)
fffff805`74b85c0c 33c0            xor     eax,eax

在WinDBG中标注出颜色lea rcx,[nt!IopTimerQueueHead (fffff805748639e0)]更容易看到。

接着就是通过代码实现对此处的定位,定位我们就采用特征码搜索的方式,如下代码是特征搜索部分。

  • StartSearchAddress 代表开始位置
  • EndSearchAddress 代表结束位置,粗略计算0xff就可以定位到了。
#include <ntifs.h>// 得到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(("Uninstall Driver Is OK \n"));
}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{DbgPrint(("hello lyshark \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指令的内存地址。

最后一步就是枚举部分,我们需要前面提到的IO_TIMER结构体定义。

  • PIO_TIMER Timer = CONTAINING_RECORD(NextEntry, IO_TIMER, TimerList) 得到结构体,循环输出即可。
#include <ntddk.h>
#include <ntstrsafe.h>typedef struct _IO_TIMER
{INT16        Type;INT16        TimerFlag;LONG32       Unknown;LIST_ENTRY   TimerList;PVOID        TimerRoutine;PVOID        Context;PVOID        DeviceObject;
}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 \n"));// 得到基址PUCHAR IoInitializeTimer = GetIoInitializeTimerAddress();DbgPrint("IoInitializeTimer Address = %p \n", IoInitializeTimer);// 搜索IoTimerQueueHead地址/*nt!IoInitializeTimer+0x5d:fffff806`349963cd 488d5008        lea     rdx,[rax+8]fffff806`349963d1 48897018        mov     qword ptr [rax+18h],rsifffff806`349963d5 4c8d05648de0ff  lea     r8,[nt!IopTimerLock (fffff806`3479f140)]fffff806`349963dc 48897820        mov     qword ptr [rax+20h],rdifffff806`349963e0 488d0d99f6cdff  lea     rcx,[nt!IopTimerQueueHead (fffff806`34675a80)]fffff806`349963e7 e8c43598ff      call    nt!ExInterlockedInsertTailList (fffff806`343199b0)fffff806`349963ec 33c0            xor     eax,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 ff  lea 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;
}

运行这段源代码,并可得到以下输出,由于没有IO定时器所以输出结果是空的:

至此IO定时器的枚举就介绍完了,在教程中你已经学会了使用特征码定位这门技术,相信你完全可以输出内核中想要得到的任何结构体。

http://www.tj-hxxt.cn/news/15658.html

相关文章:

  • 海南所有的网站建设类公司百度安装app
  • 怎么样可以做网站充值代理淘宝店铺转让价格表
  • 公司网站做百度推广需要交费吗软文广告文案
  • wordpress自定义头像seo网站推广工具
  • 个性网站首页荆门刚刚发布的
  • 佛山网站推广优化公司搭建网站的步骤和顺序
  • 怎么做国内外网站网络推广外包
  • 优秀企业网站的特点北京网站优化经理
  • 桂电做网站的毕设容易过嘛中国网站建设公司前十名
  • 从零开始做网站百度用户服务中心电话
  • 对网站建设的要求环球资源网站网址
  • 建网站需要域名注册公司网站
  • 发布外链网站互联网舆情监测系统
  • 做nba直播网站有哪些人营销软文的范文
  • 怎么自学做网站app推广公司怎么对接业务
  • 火车头 wordpress4.8搜索引擎优化公司
  • 深圳手机集团网站建设新闻最新消息
  • wordpress文章关键字替换百度关键词优化首选667seo
  • 做商业地产常用的网站百度推广外包
  • 好的摄影作品网站b站24小时自助下单平台网站
  • 网站有风险提示怎么办最好的seo外包
  • 河北智能网站建设平台seo工程师是做什么的
  • 制作app的流程哪家公司做推广优化好
  • 北京网站推广排名中山口碑seo推广
  • 海淘网站是谁做的seo关键词选取工具
  • 企业网站建设的主要目的是日喀则网站seo
  • 一个网站如何做cdn加速器加快实施创新驱动发展战略
  • 知名b2b网站windows优化大师官方网站
  • 做新闻网站犯法吗seo 工具
  • seo短视频网页入口引流网佛山网络公司 乐云seo