暂停系统中任意驱动的时钟--StopIoTimer
来源:互联网 发布:红颜知已歌曲 编辑:程序博客网 时间:2024/05/21 19:28
这篇文章主要说暂停IoTimer,可能有人说直接调用IoStopTimer就好了,不过,这篇文章说的是如何通过自己的驱动程序去停止其他驱动的时钟,比如说现在正在运行的一个驱动叫IoTimer.sys(上一篇文章介绍的的驱动程序),现在我们想要暂停它里面的时钟,在不卸载驱动的情况下,我们该怎么做呢?
现在我们就介绍一下方法:
在系统中,有一根双向链表链接这系统中的所有IoTimer,画张示意图说明一下:
现在有两个问题要解决:
1.怎么找到这个链表呢?
2.遍历链表,怎么确定哪个IoTimer就是IoTimer.sys里面的IoTimer呢*(IoTimer.sys是上一篇写的介绍IoTimer的使用示例生成的驱动,不知道的可以看一下上一篇博客)
现在我们一个一个问题解决:
第一个问题,找到链表头不就找到链表了嘛
现在分x86和x64两种情况说明怎么找链表头
x64
在IoInitializeTimer这个函数里面有一句代码
fffff800042db450 488d0d4974e0ff lea rcx,[nt!IopTimerQueueHead (fffff800
040e28a0)]
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;}
- 暂停系统中任意驱动的时钟--StopIoTimer
- linux中CPU各个模块的时钟驱动函数分析
- 系统的功能(“暂停”)
- 带修改暂停启动的动态数码管时钟
- S3C2410的时钟驱动分析
- 2812的时钟系统
- stm32的时钟系统
- hi3531的时钟系统
- S5PV210的时钟系统
- s3c2440的系统时钟
- 系统时钟的配置
- stm32的时钟系统
- STM32的时钟系统
- STM32的时钟系统
- STM32 的时钟系统
- 系统时钟的初始化
- STM32的时钟系统
- 系统(“暂停”
- 在虚拟机(CentOS)上配置fastdfs+nginx
- 插入排序之shell排序分析及源码演示
- python 基础教程 24章 虚拟茶话会 async1
- 如何启用设置org.slf4j.Logger打印并输出日志
- jquery实现iframe效果
- 暂停系统中任意驱动的时钟--StopIoTimer
- 多态
- 百度登陆窗口的设计
- python 基础教程 24章 虚拟茶话会 async2
- 移除时钟KTIMER和DPC
- javascript中静态方法、实例方法、内部方法和原型的一点见解
- Android广播机制 简介
- 广度优先搜索:迷宫最少步数
- python 基础教程 24章 虚拟茶话会 async3