RemoveDPC

时间:2023-03-09 17:31:17
RemoveDPC

HOOKSSDT中加入了DPC之后 要取消DPC

首先找到DPCHookSSDT.sys的基地址和大小

通过枚举所有DPC的地址  将在范围之内的DPC定时器全部移除

枚举DPC:

WinXP:

1.首先要得到KiTimerTableListHead

在WinXP中只需要通过查找8d就可以定位到KiTimerTableListHead

 BOOLEAN GetKiTimerTableListHeadInWinXP_X86(ULONG32* KiTimerTableListHead)
{ ULONG32 KeUpdateSystemTime = ;
PUCHAR i = NULL; KeUpdateSystemTime = (ULONG32)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeUpdateSystemTime"); DbgPrint("KeUpdateSystemTime: 0X%08x\n", KeUpdateSystemTime); if (KeUpdateSystemTime)
{ PUCHAR StartSearchAddress = (PUCHAR)KeUpdateSystemTime; //fffff800`03ecf640
PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
UCHAR v1=;
for (i=StartSearchAddress;i<EndSearchAddress;i++)
{
/* kd> u KeUpdateSystemTime l 50
nt!KeUpdateSystemTime:
804e35d8 b90000dfff mov ecx,0FFDF0000h
804e35dd 8b7908 mov edi,dword ptr [ecx+8]
804e35e0 8b710c mov esi,dword ptr [ecx+0Ch]
804e35e3 03f8 add edi,eax
804e35e5 83d600 adc esi,0
804e35e8 897110 mov dword ptr [ecx+10h],esi
804e35eb 897908 mov dword ptr [ecx+8],edi
804e35ee 89710c mov dword ptr [ecx+0Ch],esi
804e35f1 290514b05580 sub dword ptr [nt!KiTickOffset (8055b014)],eax
804e35f7 a100b05580 mov eax,dword ptr [nt!KeTickCount (8055b000)]
804e35fc 8bd8 mov ebx,eax
804e35fe 0f8f84000000 jg nt!KeUpdateSystemTime+0xb0 (804e3688)
804e3604 bb0000dfff mov ebx,0FFDF0000h
804e3609 8b4b14 mov ecx,dword ptr [ebx+14h]
804e360c 8b5318 mov edx,dword ptr [ebx+18h]
804e360f 030d10b05580 add ecx,dword ptr [nt!KeTimeAdjustment (8055b010)]
804e3615 83d200 adc edx,0
804e3618 89531c mov dword ptr [ebx+1Ch],edx
804e361b 894b14 mov dword ptr [ebx+14h],ecx
804e361e 895318 mov dword ptr [ebx+18h],edx
804e3621 8bd8 mov ebx,eax
804e3623 8bc8 mov ecx,eax
804e3625 8b1504b05580 mov edx,dword ptr [nt!KeTickCount+0x4 (8055b004)]
804e362b 83c101 add ecx,1
804e362e 83d200 adc edx,0
804e3631 891508b05580 mov dword ptr [nt!KeTickCount+0x8 (8055b008)],edx
804e3637 890d00b05580 mov dword ptr [nt!KeTickCount (8055b000)],ecx
804e363d 891504b05580 mov dword ptr [nt!KeTickCount+0x4 (8055b004)],edx
804e3643 50 push eax
804e3644 a10000dfff mov eax,dword ptr ds:[FFDF0000h]
804e3649 83c001 add eax,1
804e364c 7306 jae nt!KeUpdateSystemTime+0x7c (804e3654)
804e364e ff059c005680 inc dword ptr [nt!ExpTickCountAdjustmentCount (8056009c)]
804e3654 a198005680 mov eax,dword ptr [nt!ExpTickCountAdjustment (80560098)]
804e3659 0faf059c005680 imul eax,dword ptr [nt!ExpTickCountAdjustmentCount (8056009c)]
804e3660 03c1 add eax,ecx
804e3662 a30000dfff mov dword ptr ds:[FFDF0000h],eax
804e3667 58 pop eax
804e3668 25ff000000 and eax,0FFh
804e366d 8d0cc5a0355680 lea ecx,nt!KiTimerTableListHead (805635a0)[eax*8] */
if( MmIsAddressValid(i))
{
v1=*i; if(v1==0x8d)
{
memcpy(KiTimerTableListHead,i+,); if (*KiTimerTableListHead && MmIsAddressValid((PVOID)*KiTimerTableListHead))
{
return TRUE;
}
}
}
}
} return FALSE;
}

2.TimerTableList为一个循环带空头的循环链表

通过循环遍历 枚举DPC的信息

  BOOLEAN GetDPCTimerInformationInWinXP_X86(PLIST_ENTRY KiTimerTableListHead)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL; PLIST_ENTRY NextEntry;
ULONG n = ; if (KiTimerTableListHead &&
MmIsAddressValid((PVOID)KiTimerTableListHead))
{
ULONG i = ;
KIRQL OldIrql = KeRaiseIrqlToDpcLevel(); for (i=;i<0x100;i++)
{ NextEntry = KiTimerTableListHead[i].Flink; while (MmIsAddressValid(NextEntry) && &KiTimerTableListHead[i] != NextEntry )
{
PKTIMER Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); if (Timer &&
MmIsAddressValid(Timer) &&
MmIsAddressValid(Timer->Dpc) &&
MmIsAddressValid(Timer->Dpc->DeferredRoutine))
{ {
PKDPC Dpc = Timer->Dpc; //DPC 对象
PVOID TimerDispatch = Dpc->DeferredRoutine; //回调例程 DbgPrint("DPCObject:%p\r\n",Dpc);
DbgPrint("DPCCallBack:%p\r\n",TimerDispatch);
DbgPrint("TimerObject:%p\r\n",Timer);
DbgPrint("倒计时:%d\r\n:",Timer->Period); n++; //记录总数
}
} NextEntry = NextEntry->Flink;
}
} KeLowerIrql(OldIrql);
} DbgPrint("个数:%d\r\n",n);
return Status;
}

遍历TimerTableList

 PVOID
GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName)
{
UNICODE_STRING uniVariableName;
PVOID VariableAddress = NULL; if (wzVariableName && wcslen(wzVariableName) > )
{
RtlInitUnicodeString(&uniVariableName, wzVariableName); //从Ntos模块的导出表中获得一个导出变量的地址
VariableAddress = MmGetSystemRoutineAddress(&uniVariableName);
} return VariableAddress;
}

从Ntos模块的导出表中获得一个导出变量的地址

Win7_64:

在win7_64中 TimerTableList中存储的并不是一个真实的DPC

 KDPC* TransTimerDPCEx(PKTIMER Timer,ULONG64 AddressOf_KiWaitNever, ULONG64 AddressOf_KiWaitAlways)
{
ULONG64 DPC = (ULONG64)Timer->Dpc;
DPC ^= AddressOf_KiWaitNever;
DPC = _rotl64(DPC, (UCHAR)(AddressOf_KiWaitNever & 0xFF));
DPC ^= (ULONG64)Timer;
DPC = _byteswap_uint64(DPC);
DPC ^= AddressOf_KiWaitAlways;
return (KDPC*)DPC;
}

转化为真正的DPC

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 = ;
PUCHAR StartSearchAddress = ;
PUCHAR EndSearchAddress = ; INT64 iOffset = ; PUCHAR i = NULL;
KeSetTimer = (ULONG64)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeSetTimer"); StartSearchAddress = (PUCHAR)KeSetTimer;
EndSearchAddress = StartSearchAddress + 0x500; for(i=StartSearchAddress; i<EndSearchAddress; i++)
{
if(*i==0x48 && *(i+)==0x8B && *(i+)==0x05)
{
memcpy(&iOffset,i+,);
*KiWaitNeverAddress=(PULONG64)(iOffset + (ULONG64)i + );
i=i+;
memcpy(&iOffset,i+,);
*KiWaitAlwaysAddress=(PULONG64)(iOffset + (ULONG64)i + );
return TRUE;
}
} return FALSE;
}
 BOOLEAN GetDPCTimerInformationInWin7_X64()
{ ULONG32 ulCPUNumber = KeNumberProcessors; ULONG64 AddressOf_KPRCB = NULL; //CPU控制块
PUCHAR TimerEntries = NULL;
PLIST_ENTRY CurrentEntry = NULL;
PLIST_ENTRY NextEntry = NULL;
PULONG64 AddressOf_KiWaitAlways = NULL;
PULONG64 AddressOf_KiWaitNever = NULL;
int i = ;
int j = ;
int n = ;
PKTIMER Timer;
for(j=;j<ulCPUNumber; j++)
{
KeSetSystemAffinityThread(j+); //使当前线程运行在第一个处理器上,因为只有第一个处理器的值才有效 AddressOf_KPRCB=(ULONG64)__readmsr(0xC0000101) + 0x20; //dt _KPRCB KeRevertToUserAffinityThread(); ////恢复线程运行的处理器 TimerEntries=(PUCHAR)(*(ULONG64*)AddressOf_KPRCB + 0x2200 + 0x200);
/*
kd> dt _Kprcb
nt!_KPRCB
+0x000 MxCsr : Uint4B
+0x004 LegacyNumber : UChar
+0x005 ReservedMustBeZero : UChar
+0x006 InterruptRequest : UChar
+0x21ec UnusedPad : Uint4B
+0x21f0 PrcbPad50 : [2] Uint8B
+0x2200 TimerTable : _KTIMER_TABLE kd> dt _KTIMER_TABLE
nt!_KTIMER_TABLE
+0x000 TimerExpiry : [64] Ptr64 _KTIMER
+0x200 TimerEntries : [256] _KTIMER_TABLE_ENTRY kd> dt _KTIMER_TABLE_ENTRY
nt!_KTIMER_TABLE_ENTRY
+0x000 Lock : Uint8B
+0x008 Entry : _LIST_ENTRY
+0x018 Time : _ULARGE_INTEGER
*/ if(FindKiWaitVariableAddress(&AddressOf_KiWaitNever,&AddressOf_KiWaitAlways)==FALSE)
{
return FALSE;
}
for(i=; i<0x100; i++)
{
typedef struct _KTIMER_TABLE_ENTRY
{
ULONG64 Lock;
LIST_ENTRY Entry;
ULARGE_INTEGER Time;
} KTIMER_TABLE_ENTRY, *PKTIMER_TABLE_ENTRY;
CurrentEntry = (PLIST_ENTRY)(TimerEntries + sizeof(KTIMER_TABLE_ENTRY) * i + ); //这里是个数组 + 8 过Lock
NextEntry = CurrentEntry->Blink;
if( MmIsAddressValid(CurrentEntry) && MmIsAddressValid(NextEntry) )
{
while( NextEntry != CurrentEntry )
{
PKDPC RealDPC; //获得首地址
Timer = CONTAINING_RECORD(NextEntry,KTIMER,TimerListEntry);
/*
kd> dt _KTIMER
nt!_KTIMER
+0x000 Header : _DISPATCHER_HEADER
+0x018 DueTime : _ULARGE_INTEGER
+0x020 TimerListEntry : _LIST_ENTRY
+0x030 Dpc : Ptr64 _KDPC
+0x038 Processor : Uint4B
+0x03c Period : Uint4B
*/
RealDPC=TransTimerDPCEx(Timer,*AddressOf_KiWaitNever,*AddressOf_KiWaitAlways);
if( MmIsAddressValid(Timer)&&MmIsAddressValid(RealDPC)&&MmIsAddressValid(RealDPC->DeferredRoutine))
{ DbgPrint("DPCObject:%p\r\n",(ULONG64)RealDPC);
DbgPrint("DPCCallBack:%p\r\n",(ULONG64)RealDPC->DeferredRoutine);
DbgPrint("TimerObject:%p\r\n",(ULONG64)Timer);
DbgPrint("倒计时:%d\r\n:",Timer->Period); n++; }
NextEntry = NextEntry->Blink;
}
}
}
} DbgPrint("个数:%d\r\n",n); return TRUE;
}

枚举DPC信息

获取驱动的模块信息:

通过DriverObject->DriverSection中的Ldr获取驱动信息

在x86和64位系统中

 typedef struct _LDR_DATA_TABLE_ENTRY_WIN7_X64
{
LIST_ENTRY64 InLoadOrderLinks;
LIST_ENTRY64 InMemoryOrderLinks;
LIST_ENTRY64 InInitializationOrderLinks;
ULONG64 DllBase;
ULONG64 EntryPoint;
ULONG32 SizeOfImage;
UINT8 _PADDING0_[0x4];
UNICODE_STRING64 FullDllName;
UNICODE_STRING64 BaseDllName;
ULONG32 Flags;
USHORT LoadCount;
USHORT TlsIndex;
union
{
LIST_ENTRY64 HashLinks;
struct
{
ULONG64 SectionPointer;
ULONG32 CheckSum;
UINT8 _PADDING1_[0x4];
};
};
union
{
ULONG32 TimeDateStamp;
ULONG64 LoadedImports;
};
}LDR_DATA_TABLE_ENTRY_WIN7_X64, *PLDR_DATA_TABLE_ENTRY_WIN7_X64; typedef struct _LDR_DATA_TABLE_ENTRY_WINXP_X86
{
LIST_ENTRY32 InLoadOrderLinks;
LIST_ENTRY32 InMemoryOrderLinks;
LIST_ENTRY32 InInitializationOrderLinks;
ULONG32 DllBase;
ULONG32 EntryPoint;
ULONG32 SizeOfImage;
UNICODE_STRING32 FullDllName;
UNICODE_STRING32 BaseDllName;
ULONG32 Flags;
USHORT LoadCount;
USHORT TlsIndex;
union {
LIST_ENTRY32 HashLinks;
struct {
ULONG32 SectionPointer;
ULONG32 CheckSum;
};
};
union {
struct {
ULONG32 TimeDateStamp;
};
struct {
ULONG32 LoadedImports;
};
};
} LDR_DATA_TABLE_ENTRY_WINXP_X86, *PLDR_DATA_TABLE_ENTRY_WINXP_X86; #ifdef _WIN64
#define PLDR_DATA_TABLE_ENTRY PLDR_DATA_TABLE_ENTRY_WIN7_X64
#else
#define PLDR_DATA_TABLE_ENTRY PLDR_DATA_TABLE_ENTRY_WINXP_X86
#endif

PLDR_DATA_TABLE_ENTRY

 BOOLEAN EnumDriverModuleInforByLdr(PDRIVER_OBJECT DriverObject)
{
BOOLEAN bRet = FALSE;
if (DriverObject)
{
PLDR_DATA_TABLE_ENTRY CurrentEntry = NULL, NextEntry = NULL; CurrentEntry = NextEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection; if (CurrentEntry->BaseDllName.Buffer&&
CurrentEntry->BaseDllName.Length> &&
MmIsAddressValid((PVOID)CurrentEntry->BaseDllName.Buffer))
{
DbgPrint("模块地址:%p\r\n",CurrentEntry->DllBase);
DbgPrint("模块大小:%d\r\n",CurrentEntry->SizeOfImage);
DbgPrint("模块名称:%wZ\r\n",&CurrentEntry->BaseDllName);
} NextEntry = (PLDR_DATA_TABLE_ENTRY)CurrentEntry->InLoadOrderLinks.Flink; while((PLDR_DATA_TABLE_ENTRY)NextEntry!= CurrentEntry)
{ if (NextEntry->BaseDllName.Buffer&&
NextEntry->BaseDllName.Length> &&
MmIsAddressValid((PVOID)NextEntry->BaseDllName.Buffer))
{
DbgPrint("模块地址:%p\r\n",NextEntry->DllBase);
DbgPrint("模块大小:%d\r\n",NextEntry->SizeOfImage);
DbgPrint("模块名称:%wZ\r\n",&NextEntry->BaseDllName);
} NextEntry = (PLDR_DATA_TABLE_ENTRY)NextEntry->InLoadOrderLinks.Flink;
}
} else
{
return FALSE;
} return TRUE;
}

在Ldr中获取驱动模块信息

 if (Timer&&MmIsAddressValid((PVOID)Timer))
{ if (KeCancelTimer((PKTIMER)Timer))
{
return STATUS_SUCCESS;
}
}

移除DPC

 #ifndef CXX_REMOVEDPCRESUMESSDT_H
#define CXX_REMOVEDPCRESUMESSDT_H #include <ntifs.h> typedef struct _LDR_DATA_TABLE_ENTRY_WIN7_X64
{
LIST_ENTRY64 InLoadOrderLinks;
LIST_ENTRY64 InMemoryOrderLinks;
LIST_ENTRY64 InInitializationOrderLinks;
ULONG64 DllBase;
ULONG64 EntryPoint;
ULONG32 SizeOfImage;
UINT8 _PADDING0_[0x4];
UNICODE_STRING64 FullDllName;
UNICODE_STRING64 BaseDllName;
ULONG32 Flags;
USHORT LoadCount;
USHORT TlsIndex;
union
{
LIST_ENTRY64 HashLinks;
struct
{
ULONG64 SectionPointer;
ULONG32 CheckSum;
UINT8 _PADDING1_[0x4];
};
};
union
{
ULONG32 TimeDateStamp;
ULONG64 LoadedImports;
};
}LDR_DATA_TABLE_ENTRY_WIN7_X64, *PLDR_DATA_TABLE_ENTRY_WIN7_X64; typedef struct _LDR_DATA_TABLE_ENTRY_WINXP_X86
{
LIST_ENTRY32 InLoadOrderLinks;
LIST_ENTRY32 InMemoryOrderLinks;
LIST_ENTRY32 InInitializationOrderLinks;
ULONG32 DllBase;
ULONG32 EntryPoint;
ULONG32 SizeOfImage;
UNICODE_STRING32 FullDllName;
UNICODE_STRING32 BaseDllName;
ULONG32 Flags;
USHORT LoadCount;
USHORT TlsIndex;
union {
LIST_ENTRY32 HashLinks;
struct {
ULONG32 SectionPointer;
ULONG32 CheckSum;
};
};
union {
struct {
ULONG32 TimeDateStamp;
};
struct {
ULONG32 LoadedImports;
};
};
} LDR_DATA_TABLE_ENTRY_WINXP_X86, *PLDR_DATA_TABLE_ENTRY_WINXP_X86; #ifdef _WIN64
#define PLDR_DATA_TABLE_ENTRY PLDR_DATA_TABLE_ENTRY_WIN7_X64
#else
#define PLDR_DATA_TABLE_ENTRY PLDR_DATA_TABLE_ENTRY_WINXP_X86
#endif VOID UnloadDriver(PDRIVER_OBJECT DriverObject); BOOLEAN RemoveDPCByKernelModuleName(PDRIVER_OBJECT DriverObject,WCHAR* wzFindKernelModuleName);
BOOLEAN GetKiTimerTableListHeadInWinXP_X86(ULONG32* KiTimerTableListHead);
BOOLEAN GetDPCTimerInformationInWinXP_X86(PLIST_ENTRY KiTimerTableListHead,PVOID KernelModuleBase,ULONG32 ulKernelModuleSize,ULONG32* ulTimer);
BOOLEAN GetDPCTimerInformationInWin7_X64(PVOID KernelModuleBase,ULONG32 ulKernelModuleSize,ULONG64* ulTimer);
BOOLEAN FindKiWaitVariableAddress(PULONG64* AddressOf_KiWaitNever, PULONG64* AddressOf_KiWaitAlways);
KDPC* TransTimerDPCEx(PKTIMER Timer,ULONG64 AddressOf_KiWaitNever, ULONG64 AddressOf_KiWaitAlways);
PVOID
GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName); BOOLEAN FindKernelModuleInformationInLdrByDriverName(PDRIVER_OBJECT DriverObject,WCHAR* wzFindKernelModuleName,
PVOID* KernelModuleBase,ULONG32* ulKernelModuleSize);
#endif
 #ifndef CXX_REMOVEDPCRESUMESSDT_H
# include "RemoveDPCResumeSSDT.h"
#endif NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegisterPath)
{ WCHAR wzFindKernelModuleName[] = L"DPCHookSSDT.sys";
RemoveDPCByKernelModuleName(DriverObject,wzFindKernelModuleName);
DriverObject->DriverUnload = UnloadDriver; return STATUS_SUCCESS;
} BOOLEAN RemoveDPCByKernelModuleName(PDRIVER_OBJECT DriverObject,WCHAR* wzFindKernelModuleName)
{ PVOID KernelModuleBase = NULL;
ULONG32 ulKernelModuleSize = ; #ifdef _WIN64
ULONG64 Timer = ;
if(FindKernelModuleInformationInLdrByDriverName(DriverObject,wzFindKernelModuleName,
&KernelModuleBase,&ulKernelModuleSize)==FALSE)
{
return FALSE;
} DbgPrint("模块的大小:%p\r\n",ulKernelModuleSize);
DbgPrint("模块的的地址:%p\r\n",KernelModuleBase);
if (GetDPCTimerInformationInWin7_X64(KernelModuleBase,ulKernelModuleSize,&Timer)==FALSE)
{
return STATUS_UNSUCCESSFUL;
}
DbgPrint("TimerObject: Win7_X64:%p\r\n",Timer); #else
ULONG32 KiTimerTableListHead = ;
ULONG32 Timer = ; if(FindKernelModuleInformationInLdrByDriverName(DriverObject,wzFindKernelModuleName,
&KernelModuleBase,&ulKernelModuleSize)==FALSE)
{
return FALSE;
} DbgPrint("模块的大小:%p\r\n",ulKernelModuleSize);
DbgPrint("模块的的地址:%p\r\n",KernelModuleBase); if (GetKiTimerTableListHeadInWinXP_X86(&KiTimerTableListHead)==FALSE)
{
return STATUS_UNSUCCESSFUL;
} DbgPrint("KiTimerTableListHead: WinXP_X86:%p\r\n",KiTimerTableListHead); if(GetDPCTimerInformationInWinXP_X86((PLIST_ENTRY)KiTimerTableListHead,KernelModuleBase,ulKernelModuleSize,&Timer)==FALSE)
{
return STATUS_UNSUCCESSFUL;
} DbgPrint("TimerObject: WinXP_X86:%p\r\n",Timer);
#endif if (Timer&&MmIsAddressValid((PVOID)Timer))
{ if (KeCancelTimer((PKTIMER)Timer))
{
return STATUS_SUCCESS;
}
} } BOOLEAN FindKernelModuleInformationInLdrByDriverName(PDRIVER_OBJECT DriverObject,WCHAR* wzFindKernelModuleName,
PVOID* KernelModuleBase,ULONG32* ulKernelModuleSize)
{ ULONG32 ulLength = ;
PLDR_DATA_TABLE_ENTRY CurrentEntry = NULL, NextEntry = NULL;
if (DriverObject)
{ ulLength = wcslen(wzFindKernelModuleName) * sizeof(WCHAR);
CurrentEntry = NextEntry = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection; NextEntry = (PLDR_DATA_TABLE_ENTRY)CurrentEntry->InLoadOrderLinks.Flink; while((PLDR_DATA_TABLE_ENTRY)NextEntry!= CurrentEntry)
{
if (NextEntry->BaseDllName.Buffer&&
MmIsAddressValid((PVOID)NextEntry->BaseDllName.Buffer)&&
!_wcsnicmp(wzFindKernelModuleName,(WCHAR*)NextEntry->BaseDllName.Buffer, ulLength / sizeof(WCHAR)))
{ *KernelModuleBase = NextEntry->DllBase;
*ulKernelModuleSize = NextEntry->SizeOfImage;
break;
} NextEntry = (PLDR_DATA_TABLE_ENTRY)NextEntry->InLoadOrderLinks.Flink;
}
} else
{
return FALSE;
} return TRUE;
} BOOLEAN GetKiTimerTableListHeadInWinXP_X86(ULONG32* KiTimerTableListHead)
{ ULONG32 KeUpdateSystemTime = ;
PUCHAR i = NULL; KeUpdateSystemTime = (ULONG32)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeUpdateSystemTime"); DbgPrint("KeUpdateSystemTime: WinXP_X86:%p\r\n", KeUpdateSystemTime); if (KeUpdateSystemTime)
{ PUCHAR StartSearchAddress = (PUCHAR)KeUpdateSystemTime; //fffff800`03ecf640
PUCHAR EndSearchAddress = StartSearchAddress + 0x500;
UCHAR v1=;
for (i=StartSearchAddress;i<EndSearchAddress;i++)
{
/* kd> u KeUpdateSystemTime l 50
nt!KeUpdateSystemTime:
804e35d8 b90000dfff mov ecx,0FFDF0000h
804e35dd 8b7908 mov edi,dword ptr [ecx+8]
804e35e0 8b710c mov esi,dword ptr [ecx+0Ch]
804e35e3 03f8 add edi,eax
804e35e5 83d600 adc esi,0
804e35e8 897110 mov dword ptr [ecx+10h],esi
804e35eb 897908 mov dword ptr [ecx+8],edi
804e35ee 89710c mov dword ptr [ecx+0Ch],esi
804e35f1 290514b05580 sub dword ptr [nt!KiTickOffset (8055b014)],eax
804e35f7 a100b05580 mov eax,dword ptr [nt!KeTickCount (8055b000)]
804e35fc 8bd8 mov ebx,eax
804e35fe 0f8f84000000 jg nt!KeUpdateSystemTime+0xb0 (804e3688)
804e3604 bb0000dfff mov ebx,0FFDF0000h
804e3609 8b4b14 mov ecx,dword ptr [ebx+14h]
804e360c 8b5318 mov edx,dword ptr [ebx+18h]
804e360f 030d10b05580 add ecx,dword ptr [nt!KeTimeAdjustment (8055b010)]
804e3615 83d200 adc edx,0
804e3618 89531c mov dword ptr [ebx+1Ch],edx
804e361b 894b14 mov dword ptr [ebx+14h],ecx
804e361e 895318 mov dword ptr [ebx+18h],edx
804e3621 8bd8 mov ebx,eax
804e3623 8bc8 mov ecx,eax
804e3625 8b1504b05580 mov edx,dword ptr [nt!KeTickCount+0x4 (8055b004)]
804e362b 83c101 add ecx,1
804e362e 83d200 adc edx,0
804e3631 891508b05580 mov dword ptr [nt!KeTickCount+0x8 (8055b008)],edx
804e3637 890d00b05580 mov dword ptr [nt!KeTickCount (8055b000)],ecx
804e363d 891504b05580 mov dword ptr [nt!KeTickCount+0x4 (8055b004)],edx
804e3643 50 push eax
804e3644 a10000dfff mov eax,dword ptr ds:[FFDF0000h]
804e3649 83c001 add eax,1
804e364c 7306 jae nt!KeUpdateSystemTime+0x7c (804e3654)
804e364e ff059c005680 inc dword ptr [nt!ExpTickCountAdjustmentCount (8056009c)]
804e3654 a198005680 mov eax,dword ptr [nt!ExpTickCountAdjustment (80560098)]
804e3659 0faf059c005680 imul eax,dword ptr [nt!ExpTickCountAdjustmentCount (8056009c)]
804e3660 03c1 add eax,ecx
804e3662 a30000dfff mov dword ptr ds:[FFDF0000h],eax
804e3667 58 pop eax
804e3668 25ff000000 and eax,0FFh
804e366d 8d0cc5a0355680 lea ecx,nt!KiTimerTableListHead (805635a0)[eax*8] kd> dd 805635a0
805635a0 805635a0 805635a0 89b08c08 897e5700
805635b0 898954e0 898954e0 805635b8 805635b8
805635c0 805635c0 805635c0 805635c8 805635c8
805635d0 805635d0 805635d0 8056b718 8056b718
805635e0 805635e0 805635e0 895e1f80 895e1f80
805635f0 898dc5d8 89992d40 895c3800 895c3800
80563600 80563600 80563600 80563608 80563608
80563610 895efa98 897ea430 89a9fcf8 89893cf0 */
if( MmIsAddressValid(i))
{
v1=*i; if(v1==0x8d)
{
memcpy(KiTimerTableListHead,i+,); if (*KiTimerTableListHead && MmIsAddressValid((PVOID)*KiTimerTableListHead))
{
return TRUE;
}
}
}
}
} return FALSE;
} BOOLEAN GetDPCTimerInformationInWinXP_X86(PLIST_ENTRY KiTimerTableListHead,PVOID KernelModuleBase,ULONG32 ulKernelModuleSize,ULONG32* ulTimer)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL; PLIST_ENTRY NextEntry;
ULONG n = ; if (KiTimerTableListHead &&
MmIsAddressValid((PVOID)KiTimerTableListHead))
{
ULONG i = ;
KIRQL OldIrql = KeRaiseIrqlToDpcLevel(); for (i=;i<0x100;i++)
{ NextEntry = KiTimerTableListHead[i].Flink; //b0 while (MmIsAddressValid(NextEntry) && &KiTimerTableListHead[i] != NextEntry ) //a0!=b0
{
PKTIMER Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); /*
kd> dt _KTIMER
nt!_KTIMER
+0x000 Header : _DISPATCHER_HEADER
+0x010 DueTime : _ULARGE_INTEGER
+0x018 TimerListEntry : _LIST_ENTRY
+0x020 Dpc : Ptr32 _KDPC
+0x024 Period : Int4B */
if (Timer &&
MmIsAddressValid(Timer) &&
MmIsAddressValid(Timer->Dpc) &&
MmIsAddressValid(Timer->Dpc->DeferredRoutine))
{
if ((ULONG32)Timer>=(ULONG32)KernelModuleBase&&(ULONG32)Timer<=(ULONG32)KernelModuleBase+ulKernelModuleSize)
{ *ulTimer = (ULONG32)Timer;
KeLowerIrql(OldIrql); return TRUE;
}
} NextEntry = NextEntry->Flink;
}
} KeLowerIrql(OldIrql);
} return FALSE;
} PVOID
GetExportVariableAddressFormNtosExportTableByVariableName(WCHAR *wzVariableName)
{
UNICODE_STRING uniVariableName;
PVOID VariableAddress = NULL; if (wzVariableName && wcslen(wzVariableName) > )
{
RtlInitUnicodeString(&uniVariableName, wzVariableName); //从Ntos模块的导出表中获得一个导出变量的地址
VariableAddress = MmGetSystemRoutineAddress(&uniVariableName);
} return VariableAddress;
} BOOLEAN GetDPCTimerInformationInWin7_X64(PVOID KernelModuleBase,ULONG32 ulKernelModuleSize,ULONG64* ulTimer)
{ ULONG32 ulCPUNumber = KeNumberProcessors; //CPU个数
ULONG64 AddressOf_KPRCB = NULL; //CPU控制块
PUCHAR TimerEntries = NULL;
PLIST_ENTRY CurrentEntry = NULL;
PLIST_ENTRY NextEntry = NULL;
PULONG64 AddressOf_KiWaitAlways = NULL;
PULONG64 AddressOf_KiWaitNever = NULL;
int i = ;
int j = ;
int n = ;
PKTIMER Timer;
for(j=;j<ulCPUNumber; j++)
{
KeSetSystemAffinityThread(j+); //使当前线程运行在第一个处理器上,因为只有第一个处理器的值才有效 AddressOf_KPRCB=(ULONG64)__readmsr(0xC0000101) + 0x20; //dt _KPRCB KeRevertToUserAffinityThread(); ////恢复线程运行的处理器 TimerEntries=(PUCHAR)(*(ULONG64*)AddressOf_KPRCB + 0x2200 + 0x200);
/*
kd> dt _Kprcb
nt!_KPRCB
+0x000 MxCsr : Uint4B
+0x004 LegacyNumber : UChar
+0x005 ReservedMustBeZero : UChar
+0x006 InterruptRequest : UChar
+0x21ec UnusedPad : Uint4B
+0x21f0 PrcbPad50 : [2] Uint8B
+0x2200 TimerTable : _KTIMER_TABLE kd> dt _KTIMER_TABLE
nt!_KTIMER_TABLE
+0x000 TimerExpiry : [64] Ptr64 _KTIMER
+0x200 TimerEntries : [256] _KTIMER_TABLE_ENTRY kd> dt _KTIMER_TABLE_ENTRY
nt!_KTIMER_TABLE_ENTRY
+0x000 Lock : Uint8B
+0x008 Entry : _LIST_ENTRY
+0x018 Time : _ULARGE_INTEGER
*/ if(FindKiWaitVariableAddress(&AddressOf_KiWaitNever,&AddressOf_KiWaitAlways)==FALSE)
{
return FALSE;
}
for(i=; i<0x100; i++)
{
typedef struct _KTIMER_TABLE_ENTRY
{
ULONG64 Lock;
LIST_ENTRY Entry;
ULARGE_INTEGER Time;
} KTIMER_TABLE_ENTRY, *PKTIMER_TABLE_ENTRY;
CurrentEntry = (PLIST_ENTRY)(TimerEntries + sizeof(KTIMER_TABLE_ENTRY) * i + ); //这里是个数组 + 8 过Lock
NextEntry = CurrentEntry->Blink;
if( MmIsAddressValid(CurrentEntry) && MmIsAddressValid(NextEntry) )
{
while( NextEntry != CurrentEntry )
{
PKDPC RealDPC; //获得首地址
Timer = CONTAINING_RECORD(NextEntry,KTIMER,TimerListEntry);
/*
kd> dt _KTIMER
nt!_KTIMER
+0x000 Header : _DISPATCHER_HEADER
+0x018 DueTime : _ULARGE_INTEGER
+0x020 TimerListEntry : _LIST_ENTRY
+0x030 Dpc : Ptr64 _KDPC
+0x038 Processor : Uint4B
+0x03c Period : Uint4B
*/
RealDPC=TransTimerDPCEx(Timer,*AddressOf_KiWaitNever,*AddressOf_KiWaitAlways);
if( MmIsAddressValid(Timer)&&MmIsAddressValid(RealDPC)&&MmIsAddressValid(RealDPC->DeferredRoutine))
{
if ((ULONG64)Timer>=(ULONG64)KernelModuleBase&&(ULONG64)Timer<=(ULONG64)KernelModuleBase+ulKernelModuleSize)
{ *ulTimer = (ULONG64)Timer; return TRUE;
} }
NextEntry = NextEntry->Blink;
}
}
}
}
return FALSE;
} BOOLEAN FindKiWaitVariableAddress(PULONG64* AddressOf_KiWaitNever, PULONG64* AddressOf_KiWaitAlways)
{
/*
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 = ;
PUCHAR StartSearchAddress = ;
PUCHAR EndSearchAddress = ; INT64 iOffset = ; PUCHAR i = NULL;
KeSetTimer = (ULONG64)GetExportVariableAddressFormNtosExportTableByVariableName(L"KeSetTimer"); StartSearchAddress = (PUCHAR)KeSetTimer;
EndSearchAddress = StartSearchAddress + 0x500; for(i=StartSearchAddress; i<EndSearchAddress; i++)
{
if(*i==0x48 && *(i+)==0x8B && *(i+)==0x05)
{
memcpy(&iOffset,i+,);
*AddressOf_KiWaitNever=(PULONG64)(iOffset + (ULONG64)i + );
i=i+;
memcpy(&iOffset,i+,);
*AddressOf_KiWaitAlways=(PULONG64)(iOffset + (ULONG64)i + );
return TRUE;
}
} return FALSE;
} KDPC* TransTimerDPCEx(PKTIMER Timer,ULONG64 AddressOf_KiWaitNever, ULONG64 AddressOf_KiWaitAlways)
{
ULONG64 DPC = (ULONG64)Timer->Dpc;
DPC ^= AddressOf_KiWaitNever;
DPC = _rotl64(DPC, (UCHAR)(AddressOf_KiWaitNever & 0xFF));
DPC ^= (ULONG64)Timer;
DPC = _byteswap_uint64(DPC);
DPC ^= AddressOf_KiWaitAlways;
return (KDPC*)DPC;
} VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{ }