iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言驱动开发内核枚举IoTimer定时器怎么实现
  • 408
分享到

C语言驱动开发内核枚举IoTimer定时器怎么实现

2023-07-04 12:07:23 408人浏览 泡泡鱼
摘要

本篇内容主要讲解“C语言驱动开发内核枚举ioTimer定时器怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言驱动开发内核枚举IoTimer定时器怎么实现”吧!正文IoTimer内核定

本篇内容主要讲解“C语言驱动开发内核枚举ioTimer定时器怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言驱动开发内核枚举IoTimer定时器怎么实现”吧!

正文

IoTimer内核定时器其实就是在内核中实现的时钟,该定时器的枚举非常简单,因为在IoInitializeTimer初始化部分就可以找到IopTimerQueueHead地址,该变量内存储的就是定时器的链表头部。枚举IO定时器的案例并不多见,即便有也是无法使用过时的,此教程学到肯定就是赚到了。

C语言驱动开发内核枚举IoTimer定时器怎么实现

枚举Io定时器过程

  • 找到IoInitializeTimer函数,该函数可以通过MmGetSystemRoutineAddress得到。

  • 找到地址以后,我们向下增加0xFF偏移量,并搜索特征定位到IopTimerQueueHead链表头。

  • 将链表头转换为IO_TIMER结构体,并循环链表头输出。

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

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

接着我们需要得到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定时器的所需结构体。

lyshark.com: kd> dt _IO_TIMERntdll!_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

C语言驱动开发内核枚举IoTimer定时器怎么实现

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

GetIoInitializeTimerAddress()函数

#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;}

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

C语言驱动开发内核枚举IoTimer定时器怎么实现

nt!IoInitializeTimer+0x5d 输出位置

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

lyshark.com: kd> uf IoInitializeTimernt!IoInitializeTimer+0x5d:fffff805`74b85bed 488d5008        lea     rdx,[rax+8]fffff805`74b85bf1 48897018        mov     qWord ptr [rax+18h],rsifffff805`74b85bf5 4c8d054475e0ff  lea     r8,[nt!IopTimerLock (fffff805`7498d140)]fffff805`74b85bfc 48897820        mov     qword ptr [rax+20h],rdifffff805`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)]更容易看到。

C语言驱动开发内核枚举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指令的内存地址。

C语言驱动开发内核枚举IoTimer定时器怎么实现

IO_TIMER结构体定义

最后一步就是枚举部分,我们需要前面提到的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{  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.com \n"));  // 得到基址  PUCHAR IoInitializeTimer = GetIoInitializeTimerAddress();  DbgPrint("IoInitializeTimer Address = %p \n", IoInitializeTimer);  // 搜索IoTimerQueueHead地址    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定时器所以输出结果是空的:

C语言驱动开发内核枚举IoTimer定时器怎么实现

到此,相信大家对“C语言驱动开发内核枚举IoTimer定时器怎么实现”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: C语言驱动开发内核枚举IoTimer定时器怎么实现

本文链接: https://www.lsjlt.com/news/344892.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C语言驱动开发内核枚举IoTimer定时器怎么实现
    本篇内容主要讲解“C语言驱动开发内核枚举IoTimer定时器怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言驱动开发内核枚举IoTimer定时器怎么实现”吧!正文IoTimer内核定...
    99+
    2023-07-04
  • C语言驱动开发内核枚举IoTimer定时器解析
    目录正文枚举Io定时器过程GetIoInitializeTimerAddress()函数特征搜索部分IO_TIMER结构体定义正文 今天继续分享内核枚举系列知识,这次我们来学习如何通...
    99+
    2022-11-13
    C语言 内核枚举IoTimer定时器 C语言 内核枚举
  • C语言驱动开发之内核使用IO/DPC定时器详解
    本章将继续探索驱动开发中的基础部分,定时器在内核中同样很常用,在内核中定时器可以使用两种,即IO定时器,以及DPC定时器,一般来说IO定时器是DDK中提供的一种,该定时器可以为间隔为...
    99+
    2023-05-14
    C语言内核使用IO/DPC定时器 C语言 内核 IO/DPC定时器 C语言 内核 定时器
  • C语言驱动开发之通过ReadFile与内核层通信
    驱动与应用程序的通信是非常有必要的,内核中执行代码后需要将其动态显示给应用层,但驱动程序与应用层毕竟不在一个地址空间内,为了实现内核与应用层数据交互则必须有通信的方法,微软为我们提供...
    99+
    2024-04-02
  • C语言驱动开发内核特征码扫描PE代码怎么写
    今天小编给大家分享一下C语言驱动开发内核特征码扫描PE代码怎么写的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。正文为了后续教...
    99+
    2023-07-04
  • C语言驱动开发内核特征码扫描PE代码段
    目录正文特征码字符串解析与扫描实现UtilLySharkSearchPattern如何定位特征RtlImageNtHeader对其PE头部解析正文 在笔者上一篇文章《驱动开发:内核特...
    99+
    2022-11-13
    C语言 内核特征码扫描PE C语言 PE扫描
  • C语言驱动开发之内核通过PEB获取进程参数
    PEB结构(Process Envirorment Block Structure)其中文名是进程环境块信息,进程环境块内部包含了进程运行的详细参数信息,每一个进程在运行后都会存在一...
    99+
    2022-11-13
    C语言 驱动开发获取进程参数 C语言 获取进程参数 C语言 驱动开发
  • c语言定时器功能怎么实现
    在C语言中,可以使用``头文件中的`sleep()`函数来实现简单的定时器功能。`sleep()`函数用于使程序暂停执行一段时间,参...
    99+
    2023-08-30
    c语言
  • C语言内核使用IO/DPC定时器的方法是什么
    本篇内容介绍了“C语言内核使用IO/DPC定时器的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!首先来看IO定时器是如何使用的,I...
    99+
    2023-07-05
  • Linux内核定时器与延迟工作怎么实现
    本篇内容介绍了“Linux内核定时器与延迟工作怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!内核定时器软件上的定时器最终要依靠硬件时...
    99+
    2023-06-16
  • 怎么用C语言实现经典多级时间轮定时器
    本篇内容介绍了“怎么用C语言实现经典多级时间轮定时器”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!多级时间...
    99+
    2024-04-02
  • 怎么使用C语言实现计时器
    本篇内容主要讲解“怎么使用C语言实现计时器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用C语言实现计时器”吧!实现思路简单介绍一下我的实现思路:本文包括三个版本,分别是极简版、普通版、高...
    99+
    2023-06-25
  • 怎么用C语言实现开发飞机游戏
    这篇“怎么用C语言实现开发飞机游戏”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么用C语言实现开发飞机游戏”文章吧。一、前...
    99+
    2023-06-29
  • Android开发中怎么在App中实现一个内语言切换功能
    这期内容当中小编将会给大家带来有关Android开发中怎么在App中实现一个内语言切换功能,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。代码实现:布局文件(Data-Binding模式),很简单就是两行文...
    99+
    2023-05-31
    app android pp
  • C语言操作时间函数之怎么实现定时执行某个任务小程序
    本篇内容主要讲解“C语言操作时间函数之怎么实现定时执行某个任务小程序”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言操作时间函数之怎么实现定时执行某个任务小程序”吧!时间概述由上图可知:通过...
    99+
    2023-06-16
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作