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)
{ }
RemoveDPC的更多相关文章
- 浅谈DPCHookSSDT和RemoveDPC
最近学了DPC这一对,把Win7 32位和64位都做了,查阅了大量的资料,并且进行了大量调试,理一下思路,为了后面更好的学习. 转载请注明出处:http://www.cnblogs.com/littl ...
随机推荐
- [转载] 分析Linux内核创建一个新进程的过程
http://blog.luoyuanhang.com/2015/07/27/%E5%88%86%E6%9E%90Linux%E5%86%85%E6%A0%B8%E5%88%9B%E5%BB%BA%E ...
- Java用通配符 获得泛型的协变和逆变
Java对应泛型的协变和逆变
- 高质量JavaScript代码书写基本要点
翻译-高质量JavaScript代码书写基本要点 by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/ ...
- [Hibernate] - EAGER and LAZY
Hibernate中的字段映射中的Fetch有两种方式:EAGER和LAZY Eager:全部抓取 Lazy:延迟抓取 如果在字段中声明为Eager,那么在取得当前Bean时,同时会抓取Bean中的关 ...
- TortoiseSVN文档
https://tortoisesvn.net/docs/release/TortoiseSVN_zh_CN/index.html TortoiseSVN 针对 Windows 平台的 Subvers ...
- angularJS中ng-change的用法
<html> <head> <meta charset="utf-8"> <script src="http://apps.bd ...
- IE6 + png24 透明图片(滤镜)
IE6 + png24 透明图片(滤镜) .IE6png{_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true ...
- 【转】 Linux下的多线程编程
作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/原文链接:http://www.cnblogs.com/gnuhpc/archive/2012/12/07/280 ...
- 2D客户端+微端技术总结
本人于2013年9月23号加入一个页游项目组, 并作为项目组的客户端小组的主程, 带领一个4个人(峰值)的前端小组, 进行微端的开发.微端项目于2014年8月底大体完成, 历时11个月.9月份之后微端 ...
- c语言数据结构:递归的替代-------回溯算法
1.要理解回溯就必须清楚递归的定义和过程. 递归算法的非递归形式可采用回溯算法.主要考虑的问题在于: 怎样算完整的一轮操作. 执行的操作过程中怎样保存当前的状态以确保以后回溯访问. 怎样返回至上一次未 ...