暂停系统中任意驱动的时钟--StopIoTimer

来源:互联网 发布:红颜知已歌曲 编辑:程序博客网 时间:2024/05/21 19:28

这篇文章主要说暂停IoTimer,可能有人说直接调用IoStopTimer就好了,不过,这篇文章说的是如何通过自己的驱动程序去停止其他驱动的时钟,比如说现在正在运行的一个驱动叫IoTimer.sys(上一篇文章介绍的的驱动程序),现在我们想要暂停它里面的时钟,在不卸载驱动的情况下,我们该怎么做呢?

现在我们就介绍一下方法:
在系统中,有一根双向链表链接这系统中的所有IoTimer,画张示意图说明一下:

系统中的IoTimer链表

现在有两个问题要解决:
1.怎么找到这个链表呢?
2.遍历链表,怎么确定哪个IoTimer就是IoTimer.sys里面的IoTimer呢*(IoTimer.sys是上一篇写的介绍IoTimer的使用示例生成的驱动,不知道的可以看一下上一篇博客)

现在我们一个一个问题解决:

第一个问题,找到链表头不就找到链表了嘛
现在分x86和x64两种情况说明怎么找链表头

x64
在IoInitializeTimer这个函数里面有一句代码
fffff800042db450 488d0d4974e0ff lea rcx,[nt!IopTimerQueueHead (fffff800040e28a0)]
这里写图片描述

IopTimerQueueHead 这个就是链表头节点
我们只要找到IoInitializeTimer这个函数,这个函数地址通过MmGetSystemRoutineAddress这个系统例程就可以得到,得到函数地址之后往下搜索, 找到488d0d后,得到488d0d后面的4974e0ff,这是一个相对偏移,要计算一下才可得到绝对地址,
4974e0ff+fffff800`042db450+7 就是IopTimerQueueHead 的地址。

再说说x86的情况
这里写图片描述

IoInitializeTimer这个函数里面有一句代码
83f94648 b98083f683 mov ecx,offset nt!IopTimerQueueHead (83f68380)
通过MmGetSystemRoutineAddress这个系统例程得到IoInitializeTimer地址函数,往下搜索b9,找到b9后,b9后面的8083f683就是IopTimerQueueHead 的地址,x86下不用计算,直接获得绝对地址。

第一个问题解决了
现在我们说说第二个问题
这个问题在x86和x64下是一样的,我就不分开写了

我们看一下IoTimer结构体和回头再第一张图

这里写图片描述

这里写图片描述

发现这个结构体里面有一个成员是TimerRoutine,这个成员指向IoTimer所关联的派遣函数,就是我们上一片所写的TimerRoutine函数,
既然这样我们可以判断这个成员里面的地址是不是在IoTimer.sys的范围内,从而判断是不是我们想要的IoTimer。

什么意思呢,就是说,我们可以获得IoTimer.sys的模块基地址,记为ModuleBase,获得IoTimer.sys的模块大小,记为ModuleSize(怎么获得,我就不说了,具体可以看代码)
我们判断 TimerRoutine大于ModuleBase&&
TimerRoutineModuleBase+ModuleSize 条件成立,那就找到时钟了。

时钟都得到了,那它就任由我们处置了,直接调用IoStopTimer就可以暂停时钟了。

打完收工,现在看代码!

#pragma once#include<ntifs.h>typedef struct _LDR_DATA_TABLE_ENTRY{    LIST_ENTRY  InLoadOrderLinks;   // 加载顺序    LIST_ENTRY  InMemoryOrderLinks; // 在内存中的顺序    LIST_ENTRY  InInitializationOrderLinks; // 初始化顺序    PVOID       DllBase;        // 模块的基地址    PVOID       EntryPoint;     // DriverEntry    ULONG32     SizeOfImage;    // 模块的大小#ifdef _WIN64    ULONG32   UnKnow0;#endif    UNICODE_STRING FullDllName; // 包含路径的名称    UNICODE_STRING BaseDllName; // 不包含路径的名称    UINT32      Flags;    UINT16      LoadCount;    UINT16      TlsIndex;    union    {        LIST_ENTRY  HashLinks;        struct        {            PVOID   SectionPointer;            UINT32  CheckSum;        };    };    union    {        UINT32      TimeDateStamp;        PVOID       LoadedImports;    };    PVOID        EntryPointActivationContext; // _ACTIVATION_CONTEXT*    PVOID        PatchInformation;    LIST_ENTRY   ForwarderLinks;    LIST_ENTRY   ServiceTagLinks;    LIST_ENTRY   StaticLinks;    PVOID        ContextInformation;    ULONG_PTR    OriginalBase;    LARGE_INTEGER  LoadTime;}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;/*Win7_x64kd> 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_OBJECTWin7_x86kd> dt _IO_TIMERntdll!_IO_TIMER+0x000 Type             : Int2B+0x002 TimerFlag        : Int2B+0x004 TimerList        : _LIST_ENTRY+0x00c TimerRoutine     : Ptr32     void+0x010 Context          : Ptr32 Void+0x014 DeviceObject     : Ptr32 _DEVICE_OBJECT*/typedef struct _IO_TIMER{    CHAR Type[2];    CHAR TimerFlag[2];#ifdef _WIN64    CHAR UnKnow[4];#endif // _WIN64    LIST_ENTRY ListEntry;    PVOID TimerRoutine;    PVOID Context;    DEVICE_OBJECT* DeviceObject;}IO_TIMER,*PIO_TIMER;typedefVOID(*pfnIoStopTimer)(    _In_ PDEVICE_OBJECT DeviceObject    );VOID DriverUnload(PDRIVER_OBJECT DriverObject);BOOLEAN GetKernelModuleInfoByDriverObject(PDRIVER_OBJECT DriverObject, WCHAR* ModuleName, PVOID* ModuleBase, ULONG_PTR* ModuleSize);PVOID GetExportVariableAddressFromNtosExportTableByVariableName(WCHAR * VariableName);BOOLEAN GetIoTimerInfoByModuleInfo(ULONG_PTR* Timer, ULONG_PTR ModuleBase, ULONG_PTR ModuleSize, PLIST_ENTRY* ListEntry);
#include"ResumeIoTimer.h"pfnIoStopTimer __f1 = NULL;NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath){    NTSTATUS   Status = STATUS_UNSUCCESSFUL;    WCHAR      ModuleName[] = L"IoTimerInlineHookx86.sys";    PVOID      ModuleBase = NULL;    ULONG_PTR  ModuleSize = 0;    ULONG_PTR  Timer;    PLIST_ENTRY ListEntry = { 0 };    DriverObject->DriverUnload = DriverUnload;    if (GetKernelModuleInfoByDriverObject(DriverObject, ModuleName, &ModuleBase, &ModuleSize) == FALSE)    {        return Status;    }    DbgPrint("ModuleBase is %p \r\n", ModuleBase);    DbgPrint("ModuleSize is %p \r\n", ModuleSize);    if (GetIoTimerInfoByModuleInfo(&Timer, ModuleBase, ModuleSize, &ListEntry) == FALSE)    {        return Status;    }    // 停止时钟    if (Timer != NULL&&MmIsAddressValid((PVOID)Timer))    {        IoStopTimer(((PIO_TIMER)Timer)->DeviceObject);        /*        要是害怕IoStopTimer被IAT钩子钩了,那可以这样:        __f1 = (pfnIoStopTimer)GetExportVariableFormNtosExportTableByVariableName(L"IoStopTimer");        if (__f1!=NULL)        {        __f1((PDEVICE_OBJECT)((PIO_TIMER)Timer)->DeviceObject);        }        */    }    // 删除时钟,当对方驱动卸载的时候会造成蓝屏/*  if (Timer != NULL&&MmIsAddressValid((PVOID)Timer))    {        RemoveEntryList(ListEntry);        ExFreePool((PVOID)Timer);    }*/    return STATUS_SUCCESS;}VOID DriverUnload(PDRIVER_OBJECT DriverObject){    DbgPrint("ByeByeDriver\r\n");}BOOLEAN GetIoTimerInfoByModuleInfo(ULONG_PTR* Timer,ULONG_PTR ModuleBase,ULONG_PTR ModuleSize,PLIST_ENTRY* ListEntry){    PVOID  IoInitTimer = NULL;    PUCHAR StartSearchAddress = NULL;    PUCHAR EndSearchAddress = NULL;    PUCHAR i = NULL;    UCHAR  v1 = 0;    UCHAR  v2 = 0;    UCHAR  v3 = 0;    INT32  Offset = 0;    PLIST_ENTRY IopTimerQueueHead = { 0 };    PLIST_ENTRY NextEntry = { 0 };    PIO_TIMER   IoTimer = NULL;    KIRQL OldIrql;    IoInitTimer = GetExportVariableAddressFromNtosExportTableByVariableName(L"IoInitializeTimer");    if (IoInitTimer == NULL)    {        return FALSE;    }#ifdef _WIN64    /*    kd> u IoInitializeTimer l 30nt!IoInitializeTimer:fffff800`042db3e0 48895c2408      mov     qword ptr [rsp+8],rbxfffff800`042db3e5 48896c2410      mov     qword ptr [rsp+10h],rbpfffff800`042db3ea 4889742418      mov     qword ptr [rsp+18h],rsifffff800`042db3ef 57              push    rdifffff800`042db3f0 4883ec20        sub     rsp,20hfffff800`042db3f4 488b5928        mov     rbx,qword ptr [rcx+28h]fffff800`042db3f8 498bf0          mov     rsi,r8fffff800`042db3fb 488bea          mov     rbp,rdxfffff800`042db3fe 488bf9          mov     rdi,rcxfffff800`042db401 4885db          test    rbx,rbxfffff800`042db404 753f            jne     nt!IoInitializeTimer+0x65 (fffff800`042db445)fffff800`042db406 8d5330          lea     edx,[rbx+30h]fffff800`042db409 33c9            xor     ecx,ecxfffff800`042db40b 41b8496f5469    mov     r8d,69546F49hfffff800`042db411 e8fa67d3ff      call    nt!ExAllocatePoolWithTag (fffff800`04011c10)fffff800`042db416 488bd8          mov     rbx,raxfffff800`042db419 4885c0          test    rax,raxfffff800`042db41c 7507            jne     nt!IoInitializeTimer+0x45 (fffff800`042db425)fffff800`042db41e b89a0000c0      mov     eax,0C000009Ahfffff800`042db423 eb41            jmp     nt!IoInitializeTimer+0x86 (fffff800`042db466)fffff800`042db425 33d2            xor     edx,edxfffff800`042db427 488bc8          mov     rcx,raxfffff800`042db42a 448d4230        lea     r8d,[rdx+30h]fffff800`042db42e e85d49c0ff      call    nt!memset (fffff800`03edfd90)fffff800`042db433 41bb09000000    mov     r11d,9fffff800`042db439 48897b28        mov     qword ptr [rbx+28h],rdifffff800`042db43d 6644891b        mov     word ptr [rbx],r11wfffff800`042db441 48895f28        mov     qword ptr [rdi+28h],rbxfffff800`042db445 488d5308        lea     rdx,[rbx+8]fffff800`042db449 4c8d05f0cde3ff  lea     r8,[nt!IopTimerLock (fffff800`04118240)]fffff800`042db450 488d0d4974e0ff  lea     rcx,[nt!IopTimerQueueHead (fffff800`040e28a0)]    */    StartSearchAddress = (PUCHAR)IoInitTimer;    EndSearchAddress = StartSearchAddress + PAGE_SIZE;    for (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(&Offset, i + 3, 4);                // 计算Timer链表的链表头                IopTimerQueueHead = (PLIST_ENTRY)((PUCHAR)i + 7 + Offset);                break;            }        }    }#else    /*    kd> u IoInitializeTimer l 30nt!IoInitializeTimer:83f945f3 8bff            mov     edi,edi83f945f5 55              push    ebp83f945f6 8bec            mov     ebp,esp83f945f8 56              push    esi83f945f9 8b7508          mov     esi,dword ptr [ebp+8]83f945fc 8b5618          mov     edx,dword ptr [esi+18h]83f945ff 85d2            test    edx,edx83f94601 7531            jne     nt!IoInitializeTimer+0x41 (83f94634)83f94603 68496f5469      push    69546F49h83f94608 6a18            push    18h83f9460a 52              push    edx83f9460b e8f5c9f8ff      call    nt!ExAllocatePoolWithTag (83f21005)83f94610 8bd0            mov     edx,eax83f94612 85d2            test    edx,edx83f94614 7507            jne     nt!IoInitializeTimer+0x2a (83f9461d)83f94616 b89a0000c0      mov     eax,0C000009Ah83f9461b eb37            jmp     nt!IoInitializeTimer+0x61 (83f94654)83f9461d 57              push    edi83f9461e 6a06            push    683f94620 59              pop     ecx83f94621 33c0            xor     eax,eax83f94623 8bfa            mov     edi,edx83f94625 f3ab            rep stos dword ptr es:[edi]83f94627 6a09            push    983f94629 58              pop     eax83f9462a 668902          mov     word ptr [edx],ax83f9462d 897214          mov     dword ptr [edx+14h],esi83f94630 895618          mov     dword ptr [esi+18h],edx83f94633 5f              pop     edi83f94634 8b450c          mov     eax,dword ptr [ebp+0Ch]83f94637 89420c          mov     dword ptr [edx+0Ch],eax83f9463a 8b4510          mov     eax,dword ptr [ebp+10h]83f9463d 894210          mov     dword ptr [edx+10h],eax83f94640 6840b7f683      push    offset nt!IopTimerLock (83f6b740)83f94645 83c204          add     edx,483f94648 b98083f683      mov     ecx,offset nt!IopTimerQueueHead (83f68380)    */    StartSearchAddress = (PUCHAR)IoInitTimer;    EndSearchAddress = StartSearchAddress + PAGE_SIZE;    for (i = StartSearchAddress; i < EndSearchAddress; i++)    {        if (MmIsAddressValid(i))        {            v1 = *i;            if (v1 == 0xb9)            {                // x86下是b9指令后面跟的是绝对地址                memcpy(&Offset, i + 1, 4);                // 计算Timer链表的链表头                IopTimerQueueHead = (PLIST_ENTRY)Offset;                break;            }        }    }#endif    // 遍历每个IoTimer,通过查看TimerRoutine是不是在Module之内,确定所要查找的Module    if (IopTimerQueueHead != NULL&&MmIsAddressValid((PVOID)IopTimerQueueHead))    {        OldIrql = KeRaiseIrqlToDpcLevel();        NextEntry = IopTimerQueueHead->Flink;        while (NextEntry!=IopTimerQueueHead&&MmIsAddressValid(NextEntry))        {            IoTimer = CONTAINING_RECORD(NextEntry, IO_TIMER, ListEntry);            // 找到某个模块内的时钟            if ((ULONG_PTR)(IoTimer->TimerRoutine) >= ModuleBase                && (ULONG_PTR)(IoTimer->TimerRoutine) <= ModuleBase + ModuleSize)            {                *Timer = (ULONG_PTR)IoTimer;                *ListEntry = NextEntry;                KeLowerIrql(OldIrql);                return TRUE;            }            NextEntry = NextEntry->Flink;        }        KeLowerIrql(OldIrql);        return FALSE;    }    else    {        return FALSE;    }}BOOLEAN GetKernelModuleInfoByDriverObject(PDRIVER_OBJECT DriverObject, WCHAR* ModuleName, PVOID* ModuleBase, ULONG_PTR* ModuleSize){    PLDR_DATA_TABLE_ENTRY CurrentEntry = NULL;    PLDR_DATA_TABLE_ENTRY NextEntry = NULL;    if (DriverObject == NULL && !MmIsAddressValid((PVOID)DriverObject))    {        return FALSE;    }    // DriverSection就是PLDR_DATA_TABLE_ENTRY结构    CurrentEntry = NextEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;    NextEntry = (PLDR_DATA_TABLE_ENTRY)CurrentEntry->InLoadOrderLinks.Flink;    while (CurrentEntry != NextEntry)    {        if (NextEntry->BaseDllName.Buffer&&            NextEntry->BaseDllName.Length>0 &&            MmIsAddressValid((PVOID)NextEntry->BaseDllName.Buffer)            && !wcsncmp(ModuleName, (WCHAR*)NextEntry->BaseDllName.Buffer, NextEntry->BaseDllName.Length))        {            *ModuleBase = NextEntry->DllBase;            *ModuleSize = NextEntry->SizeOfImage;            DbgPrint("ModuleBase is %p \r\n", *ModuleBase);            DbgPrint("ModuleSize is %p \r\n", *ModuleSize);            return TRUE;        }        NextEntry = NextEntry->InLoadOrderLinks.Flink;    }    return FALSE;}PVOID GetExportVariableAddressFromNtosExportTableByVariableName(WCHAR * VariableName){    PVOID VariableAddress = NULL;    UNICODE_STRING v1 = { 0 };    if (VariableName&& wcslen(VariableName) > 0)    {        RtlInitUnicodeString(&v1, VariableName);        VariableAddress = MmGetSystemRoutineAddress(&v1);    }    return VariableAddress;}
0 0
原创粉丝点击