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 ...
随机推荐
- redis web 客户端工具 redis-admin
redis-admin是基于java的redis web客户端(redis client),以方便广大程序员使用redis为宗旨,集五种数据结构增删改查于一身. https://github.com/ ...
- Maven项目的发布,发布到Nexus
原文:http://blog.csdn.net/mexican_jacky/article/details/50277505 第一步: 配置信息如下: <!-- 发布项目的配置 --> ...
- Multipath多路径冗余全解
一.什么是multipath 普通的电脑主机都是一个硬盘挂接到一个总线上,这里是一对一的关系.而到了有光纤组成的SAN环境,由于主机和存储通过了光纤交换机连接,这样的话,就构成了多对多的关系.也就是说 ...
- armp启动
1.启动apahcehttpd.exe -k starthttpd.exe -k restart 重启httpd.exe -k install 安装 2.php启动apache.conf文件添加:Lo ...
- noip2016酱油记day1
真的是noip2016酱油记了. t1模拟,应该可以过. t2用了个简单的桶瞎搞,估计剩50pt了. t3直接不会写. 心好累... 考的分数肯定没去年高. 但不论如何,明天正常发挥就好. 正常发挥下 ...
- Java substring() 方法
Java String类 substring() 方法返回字符串的子字符串. 语法 public String substring(int beginIndex) 或 public String su ...
- 关于MySQL回滚机制
在事务中,每个正确的原子操作都会被顺序执行,直到遇到错误的原子操作,此时事务会将之前的操作进行回滚.回滚的意思是如果之前是插入操作,那么会执行删 除插入的记录,如果之前是update操作,也会执行up ...
- robotframework笔记6
测试文件结构 *** Settings *** Library OperatingSystem Library BuiltIn Resource ressources.py *** Variables ...
- 高性能Web服务端 PHP vs Node.js vs Nginx-Lua 的对比分析
1. ngx_lua nodejs php 比较 我在研究一阵子ngx_lua之后发现lua语法和js真的很像,同时ngx_lua模型也是单线程的异步的事件驱动的,工作原理和nodejs相同,代码甚至 ...
- ASP.NET MVC 5改进了基于过滤器的身份验证
ASP.NET MVC 5包含在最近发布的Visual Studio 2013开发者预览版中,它使开发人员可以应用身份验证过滤器,它们提供了使用各种第三方供应商或自定义的身份验证提供程序进行用户身份验 ...