HOOKSSDT中加入了DPC之后 要取消DPC
首先找到DPCHookSSDT.sys的基地址和大小
通过枚举所有DPC的地址 将在范围之内的DPC定时器全部移除
枚举DPC:
WinXP:
1.首先要得到KiTimerTableListHead
在WinXP中只需要通过查找8d就可以定位到KiTimerTableListHead
1 BOOLEAN GetKiTimerTableListHeadInWinXP_X86(ULONG32* KiTimerTableListHead) 2 { 3 4 ULONG32 KeUpdateSystemTime = 0; 5 PUCHAR i = NULL; 6 7 KeUpdateSystemTime = (ULONG32)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeUpdateSystemTime"); 8 9 10 11 DbgPrint("KeUpdateSystemTime: 0X%08x ", KeUpdateSystemTime); 12 13 if (KeUpdateSystemTime) 14 { 15 16 PUCHAR StartSearchAddress = (PUCHAR)KeUpdateSystemTime; //fffff800`03ecf640 17 PUCHAR EndSearchAddress = StartSearchAddress + 0x500; 18 UCHAR v1=0; 19 for (i=StartSearchAddress;i<EndSearchAddress;i++) 20 { 21 /* 22 23 kd> u KeUpdateSystemTime l 50 24 nt!KeUpdateSystemTime: 25 804e35d8 b90000dfff mov ecx,0FFDF0000h 26 804e35dd 8b7908 mov edi,dword ptr [ecx+8] 27 804e35e0 8b710c mov esi,dword ptr [ecx+0Ch] 28 804e35e3 03f8 add edi,eax 29 804e35e5 83d600 adc esi,0 30 804e35e8 897110 mov dword ptr [ecx+10h],esi 31 804e35eb 897908 mov dword ptr [ecx+8],edi 32 804e35ee 89710c mov dword ptr [ecx+0Ch],esi 33 804e35f1 290514b05580 sub dword ptr [nt!KiTickOffset (8055b014)],eax 34 804e35f7 a100b05580 mov eax,dword ptr [nt!KeTickCount (8055b000)] 35 804e35fc 8bd8 mov ebx,eax 36 804e35fe 0f8f84000000 jg nt!KeUpdateSystemTime+0xb0 (804e3688) 37 804e3604 bb0000dfff mov ebx,0FFDF0000h 38 804e3609 8b4b14 mov ecx,dword ptr [ebx+14h] 39 804e360c 8b5318 mov edx,dword ptr [ebx+18h] 40 804e360f 030d10b05580 add ecx,dword ptr [nt!KeTimeAdjustment (8055b010)] 41 804e3615 83d200 adc edx,0 42 804e3618 89531c mov dword ptr [ebx+1Ch],edx 43 804e361b 894b14 mov dword ptr [ebx+14h],ecx 44 804e361e 895318 mov dword ptr [ebx+18h],edx 45 804e3621 8bd8 mov ebx,eax 46 804e3623 8bc8 mov ecx,eax 47 804e3625 8b1504b05580 mov edx,dword ptr [nt!KeTickCount+0x4 (8055b004)] 48 804e362b 83c101 add ecx,1 49 804e362e 83d200 adc edx,0 50 804e3631 891508b05580 mov dword ptr [nt!KeTickCount+0x8 (8055b008)],edx 51 804e3637 890d00b05580 mov dword ptr [nt!KeTickCount (8055b000)],ecx 52 804e363d 891504b05580 mov dword ptr [nt!KeTickCount+0x4 (8055b004)],edx 53 804e3643 50 push eax 54 804e3644 a10000dfff mov eax,dword ptr ds:[FFDF0000h] 55 804e3649 83c001 add eax,1 56 804e364c 7306 jae nt!KeUpdateSystemTime+0x7c (804e3654) 57 804e364e ff059c005680 inc dword ptr [nt!ExpTickCountAdjustmentCount (8056009c)] 58 804e3654 a198005680 mov eax,dword ptr [nt!ExpTickCountAdjustment (80560098)] 59 804e3659 0faf059c005680 imul eax,dword ptr [nt!ExpTickCountAdjustmentCount (8056009c)] 60 804e3660 03c1 add eax,ecx 61 804e3662 a30000dfff mov dword ptr ds:[FFDF0000h],eax 62 804e3667 58 pop eax 63 804e3668 25ff000000 and eax,0FFh 64 804e366d 8d0cc5a0355680 lea ecx,nt!KiTimerTableListHead (805635a0)[eax*8] 65 66 */ 67 if( MmIsAddressValid(i)) 68 { 69 v1=*i; 70 71 if(v1==0x8d) 72 { 73 memcpy(KiTimerTableListHead,i+3,4); 74 75 if (*KiTimerTableListHead && MmIsAddressValid((PVOID)*KiTimerTableListHead)) 76 { 77 return TRUE; 78 } 79 } 80 } 81 } 82 } 83 84 return FALSE; 85 }
2.TimerTableList为一个循环带空头的循环链表
通过循环遍历 枚举DPC的信息
1 BOOLEAN GetDPCTimerInformationInWinXP_X86(PLIST_ENTRY KiTimerTableListHead) 2 { 3 NTSTATUS Status = STATUS_UNSUCCESSFUL; 4 5 PLIST_ENTRY NextEntry; 6 ULONG n = 0; 7 8 if (KiTimerTableListHead && 9 MmIsAddressValid((PVOID)KiTimerTableListHead)) 10 { 11 ULONG i = 0; 12 KIRQL OldIrql = KeRaiseIrqlToDpcLevel(); 13 14 for (i=0;i<0x100;i++) 15 { 16 17 NextEntry = KiTimerTableListHead[i].Flink; 18 19 while (MmIsAddressValid(NextEntry) && &KiTimerTableListHead[i] != NextEntry ) 20 { 21 PKTIMER Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); 22 23 if (Timer && 24 MmIsAddressValid(Timer) && 25 MmIsAddressValid(Timer->Dpc) && 26 MmIsAddressValid(Timer->Dpc->DeferredRoutine)) 27 { 28 29 { 30 PKDPC Dpc = Timer->Dpc; //DPC 对象 31 PVOID TimerDispatch = Dpc->DeferredRoutine; //回调例程 32 33 34 35 DbgPrint("DPCObject:%p ",Dpc); 36 DbgPrint("DPCCallBack:%p ",TimerDispatch); 37 DbgPrint("TimerObject:%p ",Timer); 38 DbgPrint("倒计时:%d :",Timer->Period); 39 40 n++; //记录总数 41 } 42 } 43 44 NextEntry = NextEntry->Flink; 45 } 46 } 47 48 KeLowerIrql(OldIrql); 49 } 50 51 52 DbgPrint("个数:%d ",n); 53 return Status; 54 }
1 PVOID 2 GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName) 3 { 4 UNICODE_STRING uniVariableName; 5 PVOID VariableAddress = NULL; 6 7 if (wzVariableName && wcslen(wzVariableName) > 0) 8 { 9 RtlInitUnicodeString(&uniVariableName, wzVariableName); 10 11 //从Ntos模块的导出表中获得一个导出变量的地址 12 VariableAddress = MmGetSystemRoutineAddress(&uniVariableName); 13 } 14 15 return VariableAddress; 16 }
Win7_64:
在win7_64中 TimerTableList中存储的并不是一个真实的DPC
1 KDPC* TransTimerDPCEx(PKTIMER Timer,ULONG64 AddressOf_KiWaitNever, ULONG64 AddressOf_KiWaitAlways) 2 { 3 ULONG64 DPC = (ULONG64)Timer->Dpc; 4 DPC ^= AddressOf_KiWaitNever; 5 DPC = _rotl64(DPC, (UCHAR)(AddressOf_KiWaitNever & 0xFF)); 6 DPC ^= (ULONG64)Timer; 7 DPC = _byteswap_uint64(DPC); 8 DPC ^= AddressOf_KiWaitAlways; 9 return (KDPC*)DPC; 10 }
BOOLEAN FindKiWaitVariableAddress(PULONG64 *KiWaitNeverAddress, PULONG64 *KiWaitAlwaysAddress) { /* kd> u kesettimer l 50 nt!KeSetTimer: fffff800`03ef10a8 4883ec38 sub rsp,38h fffff800`03ef10ac 4c89442420 mov qword ptr [rsp+20h],r8 fffff800`03ef10b1 4533c9 xor r9d,r9d fffff800`03ef10b4 4533c0 xor r8d,r8d fffff800`03ef10b7 e814000000 call nt!KiSetTimerEx (fffff800`03ef10d0) fffff800`03ef10bc 4883c438 add rsp,38h fffff800`03ef10c0 c3 ret fffff800`03ef10c1 90 nop fffff800`03ef10c2 90 nop fffff800`03ef10c3 90 nop fffff800`03ef10c4 90 nop fffff800`03ef10c5 90 nop fffff800`03ef10c6 90 nop fffff800`03ef10c7 90 nop nt!KxWaitForLockChainValid: fffff800`03ef10c8 90 nop fffff800`03ef10c9 90 nop fffff800`03ef10ca 90 nop fffff800`03ef10cb 90 nop fffff800`03ef10cc 90 nop fffff800`03ef10cd 90 nop fffff800`03ef10ce 90 nop fffff800`03ef10cf 90 nop nt!KiSetTimerEx: fffff800`03ef10d0 48895c2408 mov qword ptr [rsp+8],rbx fffff800`03ef10d5 4889542410 mov qword ptr [rsp+10h],rdx fffff800`03ef10da 55 push rbp fffff800`03ef10db 56 push rsi fffff800`03ef10dc 57 push rdi fffff800`03ef10dd 4154 push r12 fffff800`03ef10df 4155 push r13 fffff800`03ef10e1 4156 push r14 fffff800`03ef10e3 4157 push r15 fffff800`03ef10e5 4883ec50 sub rsp,50h fffff800`03ef10e9 488b0518502200 mov rax,qword ptr [nt!KiWaitNever (fffff800`04116108)] fffff800`03ef10f0 488b1de9502200 mov rbx,qword ptr [nt!KiWaitAlways (fffff800`041161e0)] */ ULONG64 KeSetTimer = 0; PUCHAR StartSearchAddress = 0; PUCHAR EndSearchAddress = 0; INT64 iOffset = 0; PUCHAR i = NULL; KeSetTimer = (ULONG64)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeSetTimer"); StartSearchAddress = (PUCHAR)KeSetTimer; EndSearchAddress = StartSearchAddress + 0x500; for(i=StartSearchAddress; i<EndSearchAddress; i++) { if(*i==0x48 && *(i+1)==0x8B && *(i+2)==0x05) { memcpy(&iOffset,i+3,4); *KiWaitNeverAddress=(PULONG64)(iOffset + (ULONG64)i + 7); i=i+7; memcpy(&iOffset,i+3,4); *KiWaitAlwaysAddress=(PULONG64)(iOffset + (ULONG64)i + 7); return TRUE; } } return FALSE; }
1 BOOLEAN GetDPCTimerInformationInWin7_X64() 2 { 3 4 ULONG32 ulCPUNumber = KeNumberProcessors; 5 6 7 8 ULONG64 AddressOf_KPRCB = NULL; //CPU控制块 9 PUCHAR TimerEntries = NULL; 10 PLIST_ENTRY CurrentEntry = NULL; 11 PLIST_ENTRY NextEntry = NULL; 12 PULONG64 AddressOf_KiWaitAlways = NULL; 13 PULONG64 AddressOf_KiWaitNever = NULL; 14 int i = 0; 15 int j = 0; 16 int n = 0; 17 PKTIMER Timer; 18 for(j=0;j<ulCPUNumber; j++) 19 { 20 KeSetSystemAffinityThread(j+1); //使当前线程运行在第一个处理器上,因为只有第一个处理器的值才有效 21 22 AddressOf_KPRCB=(ULONG64)__readmsr(0xC0000101) + 0x20; //dt _KPRCB 23 24 KeRevertToUserAffinityThread(); ////恢复线程运行的处理器 25 26 TimerEntries=(PUCHAR)(*(ULONG64*)AddressOf_KPRCB + 0x2200 + 0x200); 27 /* 28 kd> dt _Kprcb 29 nt!_KPRCB 30 +0x000 MxCsr : Uint4B 31 +0x004 LegacyNumber : UChar 32 +0x005 ReservedMustBeZero : UChar 33 +0x006 InterruptRequest : UChar 34 +0x21ec UnusedPad : Uint4B 35 +0x21f0 PrcbPad50 : [2] Uint8B 36 +0x2200 TimerTable : _KTIMER_TABLE 37 38 39 kd> dt _KTIMER_TABLE 40 nt!_KTIMER_TABLE 41 +0x000 TimerExpiry : [64] Ptr64 _KTIMER 42 +0x200 TimerEntries : [256] _KTIMER_TABLE_ENTRY 43 44 45 kd> dt _KTIMER_TABLE_ENTRY 46 nt!_KTIMER_TABLE_ENTRY 47 +0x000 Lock : Uint8B 48 +0x008 Entry : _LIST_ENTRY 49 +0x018 Time : _ULARGE_INTEGER 50 */ 51 52 53 if(FindKiWaitVariableAddress(&AddressOf_KiWaitNever,&AddressOf_KiWaitAlways)==FALSE) 54 { 55 return FALSE; 56 } 57 for(i=0; i<0x100; i++) 58 { 59 typedef struct _KTIMER_TABLE_ENTRY 60 { 61 ULONG64 Lock; 62 LIST_ENTRY Entry; 63 ULARGE_INTEGER Time; 64 } KTIMER_TABLE_ENTRY, *PKTIMER_TABLE_ENTRY; 65 CurrentEntry = (PLIST_ENTRY)(TimerEntries + sizeof(KTIMER_TABLE_ENTRY) * i + 8); //这里是个数组 + 8 过Lock 66 NextEntry = CurrentEntry->Blink; 67 if( MmIsAddressValid(CurrentEntry) && MmIsAddressValid(NextEntry) ) 68 { 69 while( NextEntry != CurrentEntry ) 70 { 71 PKDPC RealDPC; 72 73 //获得首地址 74 Timer = CONTAINING_RECORD(NextEntry,KTIMER,TimerListEntry); 75 /* 76 kd> dt _KTIMER 77 nt!_KTIMER 78 +0x000 Header : _DISPATCHER_HEADER 79 +0x018 DueTime : _ULARGE_INTEGER 80 +0x020 TimerListEntry : _LIST_ENTRY 81 +0x030 Dpc : Ptr64 _KDPC 82 +0x038 Processor : Uint4B 83 +0x03c Period : Uint4B 84 */ 85 RealDPC=TransTimerDPCEx(Timer,*AddressOf_KiWaitNever,*AddressOf_KiWaitAlways); 86 if( MmIsAddressValid(Timer)&&MmIsAddressValid(RealDPC)&&MmIsAddressValid(RealDPC->DeferredRoutine)) 87 { 88 89 DbgPrint("DPCObject:%p ",(ULONG64)RealDPC); 90 DbgPrint("DPCCallBack:%p ",(ULONG64)RealDPC->DeferredRoutine); 91 DbgPrint("TimerObject:%p ",(ULONG64)Timer); 92 DbgPrint("倒计时:%d :",Timer->Period); 93 94 n++; 95 96 97 } 98 NextEntry = NextEntry->Blink; 99 } 100 } 101 } 102 } 103 104 DbgPrint("个数:%d ",n); 105 106 return TRUE; 107 }
获取驱动的模块信息:
通过DriverObject->DriverSection中的Ldr获取驱动信息
在x86和64位系统中
1 typedef struct _LDR_DATA_TABLE_ENTRY_WIN7_X64 2 { 3 LIST_ENTRY64 InLoadOrderLinks; 4 LIST_ENTRY64 InMemoryOrderLinks; 5 LIST_ENTRY64 InInitializationOrderLinks; 6 ULONG64 DllBase; 7 ULONG64 EntryPoint; 8 ULONG32 SizeOfImage; 9 UINT8 _PADDING0_[0x4]; 10 UNICODE_STRING64 FullDllName; 11 UNICODE_STRING64 BaseDllName; 12 ULONG32 Flags; 13 USHORT LoadCount; 14 USHORT TlsIndex; 15 union 16 { 17 LIST_ENTRY64 HashLinks; 18 struct 19 { 20 ULONG64 SectionPointer; 21 ULONG32 CheckSum; 22 UINT8 _PADDING1_[0x4]; 23 }; 24 }; 25 union 26 { 27 ULONG32 TimeDateStamp; 28 ULONG64 LoadedImports; 29 }; 30 }LDR_DATA_TABLE_ENTRY_WIN7_X64, *PLDR_DATA_TABLE_ENTRY_WIN7_X64; 31 32 33 34 typedef struct _LDR_DATA_TABLE_ENTRY_WINXP_X86 35 { 36 LIST_ENTRY32 InLoadOrderLinks; 37 LIST_ENTRY32 InMemoryOrderLinks; 38 LIST_ENTRY32 InInitializationOrderLinks; 39 ULONG32 DllBase; 40 ULONG32 EntryPoint; 41 ULONG32 SizeOfImage; 42 UNICODE_STRING32 FullDllName; 43 UNICODE_STRING32 BaseDllName; 44 ULONG32 Flags; 45 USHORT LoadCount; 46 USHORT TlsIndex; 47 union { 48 LIST_ENTRY32 HashLinks; 49 struct { 50 ULONG32 SectionPointer; 51 ULONG32 CheckSum; 52 }; 53 }; 54 union { 55 struct { 56 ULONG32 TimeDateStamp; 57 }; 58 struct { 59 ULONG32 LoadedImports; 60 }; 61 }; 62 } LDR_DATA_TABLE_ENTRY_WINXP_X86, *PLDR_DATA_TABLE_ENTRY_WINXP_X86; 63 64 65 #ifdef _WIN64 66 #define PLDR_DATA_TABLE_ENTRY PLDR_DATA_TABLE_ENTRY_WIN7_X64 67 #else 68 #define PLDR_DATA_TABLE_ENTRY PLDR_DATA_TABLE_ENTRY_WINXP_X86 69 #endif
1 BOOLEAN EnumDriverModuleInforByLdr(PDRIVER_OBJECT DriverObject) 2 { 3 BOOLEAN bRet = FALSE; 4 if (DriverObject) 5 { 6 PLDR_DATA_TABLE_ENTRY CurrentEntry = NULL, NextEntry = NULL; 7 8 CurrentEntry = NextEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection; 9 10 if (CurrentEntry->BaseDllName.Buffer&& 11 CurrentEntry->BaseDllName.Length>0 && 12 MmIsAddressValid((PVOID)CurrentEntry->BaseDllName.Buffer)) 13 { 14 DbgPrint("模块地址:%p ",CurrentEntry->DllBase); 15 DbgPrint("模块大小:%d ",CurrentEntry->SizeOfImage); 16 DbgPrint("模块名称:%wZ ",&CurrentEntry->BaseDllName); 17 } 18 19 NextEntry = (PLDR_DATA_TABLE_ENTRY)CurrentEntry->InLoadOrderLinks.Flink; 20 21 while((PLDR_DATA_TABLE_ENTRY)NextEntry!= CurrentEntry) 22 { 23 24 if (NextEntry->BaseDllName.Buffer&& 25 NextEntry->BaseDllName.Length>0 && 26 MmIsAddressValid((PVOID)NextEntry->BaseDllName.Buffer)) 27 { 28 DbgPrint("模块地址:%p ",NextEntry->DllBase); 29 DbgPrint("模块大小:%d ",NextEntry->SizeOfImage); 30 DbgPrint("模块名称:%wZ ",&NextEntry->BaseDllName); 31 } 32 33 NextEntry = (PLDR_DATA_TABLE_ENTRY)NextEntry->InLoadOrderLinks.Flink; 34 } 35 } 36 37 else 38 { 39 return FALSE; 40 } 41 42 return TRUE; 43 }
1 if (Timer&&MmIsAddressValid((PVOID)Timer)) 2 { 3 4 if (KeCancelTimer((PKTIMER)Timer)) 5 { 6 return STATUS_SUCCESS; 7 } 8 }
1 #ifndef CXX_REMOVEDPCRESUMESSDT_H 2 #define CXX_REMOVEDPCRESUMESSDT_H 3 4 #include <ntifs.h> 5 6 7 8 typedef struct _LDR_DATA_TABLE_ENTRY_WIN7_X64 9 { 10 LIST_ENTRY64 InLoadOrderLinks; 11 LIST_ENTRY64 InMemoryOrderLinks; 12 LIST_ENTRY64 InInitializationOrderLinks; 13 ULONG64 DllBase; 14 ULONG64 EntryPoint; 15 ULONG32 SizeOfImage; 16 UINT8 _PADDING0_[0x4]; 17 UNICODE_STRING64 FullDllName; 18 UNICODE_STRING64 BaseDllName; 19 ULONG32 Flags; 20 USHORT LoadCount; 21 USHORT TlsIndex; 22 union 23 { 24 LIST_ENTRY64 HashLinks; 25 struct 26 { 27 ULONG64 SectionPointer; 28 ULONG32 CheckSum; 29 UINT8 _PADDING1_[0x4]; 30 }; 31 }; 32 union 33 { 34 ULONG32 TimeDateStamp; 35 ULONG64 LoadedImports; 36 }; 37 }LDR_DATA_TABLE_ENTRY_WIN7_X64, *PLDR_DATA_TABLE_ENTRY_WIN7_X64; 38 39 40 41 typedef struct _LDR_DATA_TABLE_ENTRY_WINXP_X86 42 { 43 LIST_ENTRY32 InLoadOrderLinks; 44 LIST_ENTRY32 InMemoryOrderLinks; 45 LIST_ENTRY32 InInitializationOrderLinks; 46 ULONG32 DllBase; 47 ULONG32 EntryPoint; 48 ULONG32 SizeOfImage; 49 UNICODE_STRING32 FullDllName; 50 UNICODE_STRING32 BaseDllName; 51 ULONG32 Flags; 52 USHORT LoadCount; 53 USHORT TlsIndex; 54 union { 55 LIST_ENTRY32 HashLinks; 56 struct { 57 ULONG32 SectionPointer; 58 ULONG32 CheckSum; 59 }; 60 }; 61 union { 62 struct { 63 ULONG32 TimeDateStamp; 64 }; 65 struct { 66 ULONG32 LoadedImports; 67 }; 68 }; 69 } LDR_DATA_TABLE_ENTRY_WINXP_X86, *PLDR_DATA_TABLE_ENTRY_WINXP_X86; 70 71 72 #ifdef _WIN64 73 #define PLDR_DATA_TABLE_ENTRY PLDR_DATA_TABLE_ENTRY_WIN7_X64 74 #else 75 #define PLDR_DATA_TABLE_ENTRY PLDR_DATA_TABLE_ENTRY_WINXP_X86 76 #endif 77 78 VOID UnloadDriver(PDRIVER_OBJECT DriverObject); 79 80 BOOLEAN RemoveDPCByKernelModuleName(PDRIVER_OBJECT DriverObject,WCHAR* wzFindKernelModuleName); 81 BOOLEAN GetKiTimerTableListHeadInWinXP_X86(ULONG32* KiTimerTableListHead); 82 BOOLEAN GetDPCTimerInformationInWinXP_X86(PLIST_ENTRY KiTimerTableListHead,PVOID KernelModuleBase,ULONG32 ulKernelModuleSize,ULONG32* ulTimer); 83 BOOLEAN GetDPCTimerInformationInWin7_X64(PVOID KernelModuleBase,ULONG32 ulKernelModuleSize,ULONG64* ulTimer); 84 BOOLEAN FindKiWaitVariableAddress(PULONG64* AddressOf_KiWaitNever, PULONG64* AddressOf_KiWaitAlways); 85 KDPC* TransTimerDPCEx(PKTIMER Timer,ULONG64 AddressOf_KiWaitNever, ULONG64 AddressOf_KiWaitAlways); 86 PVOID 87 GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName); 88 89 BOOLEAN FindKernelModuleInformationInLdrByDriverName(PDRIVER_OBJECT DriverObject,WCHAR* wzFindKernelModuleName, 90 PVOID* KernelModuleBase,ULONG32* ulKernelModuleSize); 91 #endif
1 #ifndef CXX_REMOVEDPCRESUMESSDT_H 2 # include "RemoveDPCResumeSSDT.h" 3 #endif 4 5 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegisterPath) 6 { 7 8 WCHAR wzFindKernelModuleName[] = L"DPCHookSSDT.sys"; 9 RemoveDPCByKernelModuleName(DriverObject,wzFindKernelModuleName); 10 DriverObject->DriverUnload = UnloadDriver; 11 12 13 14 15 return STATUS_SUCCESS; 16 } 17 18 19 BOOLEAN RemoveDPCByKernelModuleName(PDRIVER_OBJECT DriverObject,WCHAR* wzFindKernelModuleName) 20 { 21 22 23 PVOID KernelModuleBase = NULL; 24 ULONG32 ulKernelModuleSize = 0; 25 26 27 28 #ifdef _WIN64 29 ULONG64 Timer = 0; 30 if(FindKernelModuleInformationInLdrByDriverName(DriverObject,wzFindKernelModuleName, 31 &KernelModuleBase,&ulKernelModuleSize)==FALSE) 32 { 33 return FALSE; 34 } 35 36 DbgPrint("模块的大小:%p ",ulKernelModuleSize); 37 DbgPrint("模块的的地址:%p ",KernelModuleBase); 38 if (GetDPCTimerInformationInWin7_X64(KernelModuleBase,ulKernelModuleSize,&Timer)==FALSE) 39 { 40 return STATUS_UNSUCCESSFUL; 41 } 42 DbgPrint("TimerObject: Win7_X64:%p ",Timer); 43 44 #else 45 ULONG32 KiTimerTableListHead = 0; 46 ULONG32 Timer = 0; 47 48 if(FindKernelModuleInformationInLdrByDriverName(DriverObject,wzFindKernelModuleName, 49 &KernelModuleBase,&ulKernelModuleSize)==FALSE) 50 { 51 return FALSE; 52 } 53 54 DbgPrint("模块的大小:%p ",ulKernelModuleSize); 55 DbgPrint("模块的的地址:%p ",KernelModuleBase); 56 57 if (GetKiTimerTableListHeadInWinXP_X86(&KiTimerTableListHead)==FALSE) 58 { 59 return STATUS_UNSUCCESSFUL; 60 } 61 62 DbgPrint("KiTimerTableListHead: WinXP_X86:%p ",KiTimerTableListHead); 63 64 if(GetDPCTimerInformationInWinXP_X86((PLIST_ENTRY)KiTimerTableListHead,KernelModuleBase,ulKernelModuleSize,&Timer)==FALSE) 65 { 66 return STATUS_UNSUCCESSFUL; 67 } 68 69 DbgPrint("TimerObject: WinXP_X86:%p ",Timer); 70 #endif 71 72 73 if (Timer&&MmIsAddressValid((PVOID)Timer)) 74 { 75 76 if (KeCancelTimer((PKTIMER)Timer)) 77 { 78 return STATUS_SUCCESS; 79 } 80 } 81 82 } 83 84 85 86 BOOLEAN FindKernelModuleInformationInLdrByDriverName(PDRIVER_OBJECT DriverObject,WCHAR* wzFindKernelModuleName, 87 PVOID* KernelModuleBase,ULONG32* ulKernelModuleSize) 88 { 89 90 ULONG32 ulLength = 0; 91 PLDR_DATA_TABLE_ENTRY CurrentEntry = NULL, NextEntry = NULL; 92 if (DriverObject) 93 { 94 95 ulLength = wcslen(wzFindKernelModuleName) * sizeof(WCHAR); 96 CurrentEntry = NextEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection; 97 98 NextEntry = (PLDR_DATA_TABLE_ENTRY)CurrentEntry->InLoadOrderLinks.Flink; 99 100 while((PLDR_DATA_TABLE_ENTRY)NextEntry!= CurrentEntry) 101 { 102 if (NextEntry->BaseDllName.Buffer&& 103 MmIsAddressValid((PVOID)NextEntry->BaseDllName.Buffer)&& 104 !_wcsnicmp(wzFindKernelModuleName,(WCHAR*)NextEntry->BaseDllName.Buffer, ulLength / sizeof(WCHAR))) 105 { 106 107 108 *KernelModuleBase = NextEntry->DllBase; 109 *ulKernelModuleSize = NextEntry->SizeOfImage; 110 break; 111 } 112 113 NextEntry = (PLDR_DATA_TABLE_ENTRY)NextEntry->InLoadOrderLinks.Flink; 114 } 115 } 116 117 else 118 { 119 return FALSE; 120 } 121 122 return TRUE; 123 } 124 125 126 127 128 BOOLEAN GetKiTimerTableListHeadInWinXP_X86(ULONG32* KiTimerTableListHead) 129 { 130 131 ULONG32 KeUpdateSystemTime = 0; 132 PUCHAR i = NULL; 133 134 KeUpdateSystemTime = (ULONG32)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeUpdateSystemTime"); 135 136 137 138 DbgPrint("KeUpdateSystemTime: WinXP_X86:%p ", KeUpdateSystemTime); 139 140 if (KeUpdateSystemTime) 141 { 142 143 PUCHAR StartSearchAddress = (PUCHAR)KeUpdateSystemTime; //fffff800`03ecf640 144 PUCHAR EndSearchAddress = StartSearchAddress + 0x500; 145 UCHAR v1=0; 146 for (i=StartSearchAddress;i<EndSearchAddress;i++) 147 { 148 /* 149 150 kd> u KeUpdateSystemTime l 50 151 nt!KeUpdateSystemTime: 152 804e35d8 b90000dfff mov ecx,0FFDF0000h 153 804e35dd 8b7908 mov edi,dword ptr [ecx+8] 154 804e35e0 8b710c mov esi,dword ptr [ecx+0Ch] 155 804e35e3 03f8 add edi,eax 156 804e35e5 83d600 adc esi,0 157 804e35e8 897110 mov dword ptr [ecx+10h],esi 158 804e35eb 897908 mov dword ptr [ecx+8],edi 159 804e35ee 89710c mov dword ptr [ecx+0Ch],esi 160 804e35f1 290514b05580 sub dword ptr [nt!KiTickOffset (8055b014)],eax 161 804e35f7 a100b05580 mov eax,dword ptr [nt!KeTickCount (8055b000)] 162 804e35fc 8bd8 mov ebx,eax 163 804e35fe 0f8f84000000 jg nt!KeUpdateSystemTime+0xb0 (804e3688) 164 804e3604 bb0000dfff mov ebx,0FFDF0000h 165 804e3609 8b4b14 mov ecx,dword ptr [ebx+14h] 166 804e360c 8b5318 mov edx,dword ptr [ebx+18h] 167 804e360f 030d10b05580 add ecx,dword ptr [nt!KeTimeAdjustment (8055b010)] 168 804e3615 83d200 adc edx,0 169 804e3618 89531c mov dword ptr [ebx+1Ch],edx 170 804e361b 894b14 mov dword ptr [ebx+14h],ecx 171 804e361e 895318 mov dword ptr [ebx+18h],edx 172 804e3621 8bd8 mov ebx,eax 173 804e3623 8bc8 mov ecx,eax 174 804e3625 8b1504b05580 mov edx,dword ptr [nt!KeTickCount+0x4 (8055b004)] 175 804e362b 83c101 add ecx,1 176 804e362e 83d200 adc edx,0 177 804e3631 891508b05580 mov dword ptr [nt!KeTickCount+0x8 (8055b008)],edx 178 804e3637 890d00b05580 mov dword ptr [nt!KeTickCount (8055b000)],ecx 179 804e363d 891504b05580 mov dword ptr [nt!KeTickCount+0x4 (8055b004)],edx 180 804e3643 50 push eax 181 804e3644 a10000dfff mov eax,dword ptr ds:[FFDF0000h] 182 804e3649 83c001 add eax,1 183 804e364c 7306 jae nt!KeUpdateSystemTime+0x7c (804e3654) 184 804e364e ff059c005680 inc dword ptr [nt!ExpTickCountAdjustmentCount (8056009c)] 185 804e3654 a198005680 mov eax,dword ptr [nt!ExpTickCountAdjustment (80560098)] 186 804e3659 0faf059c005680 imul eax,dword ptr [nt!ExpTickCountAdjustmentCount (8056009c)] 187 804e3660 03c1 add eax,ecx 188 804e3662 a30000dfff mov dword ptr ds:[FFDF0000h],eax 189 804e3667 58 pop eax 190 804e3668 25ff000000 and eax,0FFh 191 804e366d 8d0cc5a0355680 lea ecx,nt!KiTimerTableListHead (805635a0)[eax*8] 192 193 194 195 196 kd> dd 805635a0 197 805635a0 805635a0 805635a0 89b08c08 897e5700 198 805635b0 898954e0 898954e0 805635b8 805635b8 199 805635c0 805635c0 805635c0 805635c8 805635c8 200 805635d0 805635d0 805635d0 8056b718 8056b718 201 805635e0 805635e0 805635e0 895e1f80 895e1f80 202 805635f0 898dc5d8 89992d40 895c3800 895c3800 203 80563600 80563600 80563600 80563608 80563608 204 80563610 895efa98 897ea430 89a9fcf8 89893cf0 205 206 */ 207 if( MmIsAddressValid(i)) 208 { 209 v1=*i; 210 211 if(v1==0x8d) 212 { 213 memcpy(KiTimerTableListHead,i+3,4); 214 215 if (*KiTimerTableListHead && MmIsAddressValid((PVOID)*KiTimerTableListHead)) 216 { 217 return TRUE; 218 } 219 } 220 } 221 } 222 } 223 224 return FALSE; 225 } 226 227 228 229 230 231 232 BOOLEAN GetDPCTimerInformationInWinXP_X86(PLIST_ENTRY KiTimerTableListHead,PVOID KernelModuleBase,ULONG32 ulKernelModuleSize,ULONG32* ulTimer) 233 { 234 NTSTATUS Status = STATUS_UNSUCCESSFUL; 235 236 PLIST_ENTRY NextEntry; 237 ULONG n = 0; 238 239 if (KiTimerTableListHead && 240 MmIsAddressValid((PVOID)KiTimerTableListHead)) 241 { 242 ULONG i = 0; 243 KIRQL OldIrql = KeRaiseIrqlToDpcLevel(); 244 245 for (i=0;i<0x100;i++) 246 { 247 248 NextEntry = KiTimerTableListHead[i].Flink; //b0 249 250 while (MmIsAddressValid(NextEntry) && &KiTimerTableListHead[i] != NextEntry ) //a0!=b0 251 { 252 PKTIMER Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); 253 254 255 /* 256 kd> dt _KTIMER 257 nt!_KTIMER 258 +0x000 Header : _DISPATCHER_HEADER 259 +0x010 DueTime : _ULARGE_INTEGER 260 +0x018 TimerListEntry : _LIST_ENTRY 261 +0x020 Dpc : Ptr32 _KDPC 262 +0x024 Period : Int4B 263 264 */ 265 if (Timer && 266 MmIsAddressValid(Timer) && 267 MmIsAddressValid(Timer->Dpc) && 268 MmIsAddressValid(Timer->Dpc->DeferredRoutine)) 269 { 270 if ((ULONG32)Timer>=(ULONG32)KernelModuleBase&&(ULONG32)Timer<=(ULONG32)KernelModuleBase+ulKernelModuleSize) 271 { 272 273 *ulTimer = (ULONG32)Timer; 274 KeLowerIrql(OldIrql); 275 276 277 return TRUE; 278 } 279 } 280 281 NextEntry = NextEntry->Flink; 282 } 283 } 284 285 KeLowerIrql(OldIrql); 286 } 287 288 return FALSE; 289 } 290 291 292 293 294 PVOID 295 GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName) 296 { 297 UNICODE_STRING uniVariableName; 298 PVOID VariableAddress = NULL; 299 300 if (wzVariableName && wcslen(wzVariableName) > 0) 301 { 302 RtlInitUnicodeString(&uniVariableName, wzVariableName); 303 304 //从Ntos模块的导出表中获得一个导出变量的地址 305 VariableAddress = MmGetSystemRoutineAddress(&uniVariableName); 306 } 307 308 return VariableAddress; 309 } 310 311 312 313 314 BOOLEAN GetDPCTimerInformationInWin7_X64(PVOID KernelModuleBase,ULONG32 ulKernelModuleSize,ULONG64* ulTimer) 315 { 316 317 ULONG32 ulCPUNumber = KeNumberProcessors; //CPU个数 318 ULONG64 AddressOf_KPRCB = NULL; //CPU控制块 319 PUCHAR TimerEntries = NULL; 320 PLIST_ENTRY CurrentEntry = NULL; 321 PLIST_ENTRY NextEntry = NULL; 322 PULONG64 AddressOf_KiWaitAlways = NULL; 323 PULONG64 AddressOf_KiWaitNever = NULL; 324 int i = 0; 325 int j = 0; 326 int n = 0; 327 PKTIMER Timer; 328 for(j=0;j<ulCPUNumber; j++) 329 { 330 KeSetSystemAffinityThread(j+1); //使当前线程运行在第一个处理器上,因为只有第一个处理器的值才有效 331 332 AddressOf_KPRCB=(ULONG64)__readmsr(0xC0000101) + 0x20; //dt _KPRCB 333 334 KeRevertToUserAffinityThread(); ////恢复线程运行的处理器 335 336 TimerEntries=(PUCHAR)(*(ULONG64*)AddressOf_KPRCB + 0x2200 + 0x200); 337 /* 338 kd> dt _Kprcb 339 nt!_KPRCB 340 +0x000 MxCsr : Uint4B 341 +0x004 LegacyNumber : UChar 342 +0x005 ReservedMustBeZero : UChar 343 +0x006 InterruptRequest : UChar 344 +0x21ec UnusedPad : Uint4B 345 +0x21f0 PrcbPad50 : [2] Uint8B 346 +0x2200 TimerTable : _KTIMER_TABLE 347 348 349 kd> dt _KTIMER_TABLE 350 nt!_KTIMER_TABLE 351 +0x000 TimerExpiry : [64] Ptr64 _KTIMER 352 +0x200 TimerEntries : [256] _KTIMER_TABLE_ENTRY 353 354 355 kd> dt _KTIMER_TABLE_ENTRY 356 nt!_KTIMER_TABLE_ENTRY 357 +0x000 Lock : Uint8B 358 +0x008 Entry : _LIST_ENTRY 359 +0x018 Time : _ULARGE_INTEGER 360 */ 361 362 363 if(FindKiWaitVariableAddress(&AddressOf_KiWaitNever,&AddressOf_KiWaitAlways)==FALSE) 364 { 365 return FALSE; 366 } 367 for(i=0; i<0x100; i++) 368 { 369 typedef struct _KTIMER_TABLE_ENTRY 370 { 371 ULONG64 Lock; 372 LIST_ENTRY Entry; 373 ULARGE_INTEGER Time; 374 } KTIMER_TABLE_ENTRY, *PKTIMER_TABLE_ENTRY; 375 CurrentEntry = (PLIST_ENTRY)(TimerEntries + sizeof(KTIMER_TABLE_ENTRY) * i + 8); //这里是个数组 + 8 过Lock 376 NextEntry = CurrentEntry->Blink; 377 if( MmIsAddressValid(CurrentEntry) && MmIsAddressValid(NextEntry) ) 378 { 379 while( NextEntry != CurrentEntry ) 380 { 381 PKDPC RealDPC; 382 383 //获得首地址 384 Timer = CONTAINING_RECORD(NextEntry,KTIMER,TimerListEntry); 385 /* 386 kd> dt _KTIMER 387 nt!_KTIMER 388 +0x000 Header : _DISPATCHER_HEADER 389 +0x018 DueTime : _ULARGE_INTEGER 390 +0x020 TimerListEntry : _LIST_ENTRY 391 +0x030 Dpc : Ptr64 _KDPC 392 +0x038 Processor : Uint4B 393 +0x03c Period : Uint4B 394 */ 395 RealDPC=TransTimerDPCEx(Timer,*AddressOf_KiWaitNever,*AddressOf_KiWaitAlways); 396 if( MmIsAddressValid(Timer)&&MmIsAddressValid(RealDPC)&&MmIsAddressValid(RealDPC->DeferredRoutine)) 397 { 398 if ((ULONG64)Timer>=(ULONG64)KernelModuleBase&&(ULONG64)Timer<=(ULONG64)KernelModuleBase+ulKernelModuleSize) 399 { 400 401 *ulTimer = (ULONG64)Timer; 402 403 404 return TRUE; 405 } 406 407 } 408 NextEntry = NextEntry->Blink; 409 } 410 } 411 } 412 } 413 return FALSE; 414 } 415 416 417 418 419 420 BOOLEAN FindKiWaitVariableAddress(PULONG64* AddressOf_KiWaitNever, PULONG64* AddressOf_KiWaitAlways) 421 { 422 /* 423 kd> u kesettimer l 50 424 nt!KeSetTimer: 425 fffff800`03ef10a8 4883ec38 sub rsp,38h 426 fffff800`03ef10ac 4c89442420 mov qword ptr [rsp+20h],r8 427 fffff800`03ef10b1 4533c9 xor r9d,r9d 428 fffff800`03ef10b4 4533c0 xor r8d,r8d 429 fffff800`03ef10b7 e814000000 call nt!KiSetTimerEx (fffff800`03ef10d0) 430 fffff800`03ef10bc 4883c438 add rsp,38h 431 fffff800`03ef10c0 c3 ret 432 fffff800`03ef10c1 90 nop 433 fffff800`03ef10c2 90 nop 434 fffff800`03ef10c3 90 nop 435 fffff800`03ef10c4 90 nop 436 fffff800`03ef10c5 90 nop 437 fffff800`03ef10c6 90 nop 438 fffff800`03ef10c7 90 nop 439 nt!KxWaitForLockChainValid: 440 fffff800`03ef10c8 90 nop 441 fffff800`03ef10c9 90 nop 442 fffff800`03ef10ca 90 nop 443 fffff800`03ef10cb 90 nop 444 fffff800`03ef10cc 90 nop 445 fffff800`03ef10cd 90 nop 446 fffff800`03ef10ce 90 nop 447 fffff800`03ef10cf 90 nop 448 nt!KiSetTimerEx: 449 fffff800`03ef10d0 48895c2408 mov qword ptr [rsp+8],rbx 450 fffff800`03ef10d5 4889542410 mov qword ptr [rsp+10h],rdx 451 fffff800`03ef10da 55 push rbp 452 fffff800`03ef10db 56 push rsi 453 fffff800`03ef10dc 57 push rdi 454 fffff800`03ef10dd 4154 push r12 455 fffff800`03ef10df 4155 push r13 456 fffff800`03ef10e1 4156 push r14 457 fffff800`03ef10e3 4157 push r15 458 fffff800`03ef10e5 4883ec50 sub rsp,50h 459 fffff800`03ef10e9 488b0518502200 mov rax,qword ptr [nt!KiWaitNever (fffff800`04116108)] 460 fffff800`03ef10f0 488b1de9502200 mov rbx,qword ptr [nt!KiWaitAlways (fffff800`041161e0)] 461 */ 462 463 ULONG64 KeSetTimer = 0; 464 PUCHAR StartSearchAddress = 0; 465 PUCHAR EndSearchAddress = 0; 466 467 468 INT64 iOffset = 0; 469 470 PUCHAR i = NULL; 471 KeSetTimer = (ULONG64)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeSetTimer"); 472 473 474 StartSearchAddress = (PUCHAR)KeSetTimer; 475 EndSearchAddress = StartSearchAddress + 0x500; 476 477 478 479 for(i=StartSearchAddress; i<EndSearchAddress; i++) 480 { 481 if(*i==0x48 && *(i+1)==0x8B && *(i+2)==0x05) 482 { 483 memcpy(&iOffset,i+3,4); 484 *AddressOf_KiWaitNever=(PULONG64)(iOffset + (ULONG64)i + 7); 485 i=i+7; 486 memcpy(&iOffset,i+3,4); 487 *AddressOf_KiWaitAlways=(PULONG64)(iOffset + (ULONG64)i + 7); 488 return TRUE; 489 } 490 } 491 492 return FALSE; 493 } 494 495 496 497 KDPC* TransTimerDPCEx(PKTIMER Timer,ULONG64 AddressOf_KiWaitNever, ULONG64 AddressOf_KiWaitAlways) 498 { 499 ULONG64 DPC = (ULONG64)Timer->Dpc; 500 DPC ^= AddressOf_KiWaitNever; 501 DPC = _rotl64(DPC, (UCHAR)(AddressOf_KiWaitNever & 0xFF)); 502 DPC ^= (ULONG64)Timer; 503 DPC = _byteswap_uint64(DPC); 504 DPC ^= AddressOf_KiWaitAlways; 505 return (KDPC*)DPC; 506 } 507 508 VOID UnloadDriver(PDRIVER_OBJECT DriverObject) 509 { 510 511 }