NtCreateThread
NtProtectVirtualMemory
NtQueueApcThread
NtTerminateProcess
NtWriteVitualMemory
Ke386IoSetAccessProcess
KeAttachProcess
KeInitalizeApc
KeStackAttachProcess
ObCheckObjectAccess
ZwOpenSection
这些函数被挂钩,全部都是头部push retn的形式挂钩
SSDT HOOk可以绕过上面Nt开头的函数。
下面的函数没法绕,已经挂了头部了,貌似改任何字节都给检测出来。估计得挂G。P_K驱动的函数才行
随便写个驱动,能分析10分钟左右,够用了。(其实就跟XT直接恢复的效果一样,自己动手写下也是种收获吧)
上代码:
#include <windef.h>
#include <stdio.h>
#include <string.h>
typedef struct _ServiceDescriptorTable {
PVOID ServiceTableBase; //System Service Dispatch Table 的基地址
PVOID ServiceCounterTable;//包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。
unsigned int NumberOfServices;//由 ServiceTableBase 描述的服务的数目。
PVOID ParamTableBase; //包含每个系统服务参数字节数表的基地址-系统服务参数表
}*PServiceDescriptorTable;
extern "C" extern PServiceDescriptorTable KeServiceDescriptorTable;
extern "C" __declspec(dllimport) _stdcall KeAddSystemServiceTable(PVOID, PVOID, PVOID, PVOID, PVOID);
BOOL MyHook_flag=FALSE;
LONG ssdt_start;
LONG ssdt_No_53;
LONG ssdt_No_137;
LONG ssdt_No_180;
LONG ssdt_No_257;
LONG ssdt_No_277;
LONG NtCreateThreadAddr;
LONG ntCreateThreadPush1;
LONG ntCreateThreadPush2;
LONG ntCreateThread_7;
LONG NtProtectVirtualMemoryAddr;
LONG ntProtectVirtualMemoryParam1;
LONG ntProtectVirtualMemoayParam2;
LONG ntProtectVirtualMemory_7;
LONG NtQueueAqcThreadAddr;
LONG ntQueueAqcThread_6;
LONG NtTerminateProcessAddr;
LONG ntTerminateProcess_8;
LONG NtWriteVirtualMemoryAddr;
LONG ntWriteVirtualMemoryParam1;
LONG ntWriteVirtualMemoryParam2;
LONG ntWriteVirtualMemory_7;
LONG Ke386IoSetAccessProcessAddr;
LONG ke386IoSetAccessProcess_7;
LONG KeAttachProcessAddr;
LONG keAttachProcess_6;
LONG KeInitializeApcAddr;
LONG keInitializeApc_8;
LONG KeStackAttachProcessAddr;
LONG keStackAttachProcess_6;
LONG ObCheckObjectAccessAddr;
LONG obCheckObjectAccess_8;
LONG ZwOpenSectionAddr;
LONG zwOpenSection_9;
VOID getKernelFunctionAddr();
VOID MyHook();
VOID unpass();
__declspec(naked) VOID MyNtCreateThread(){
__asm{
push ntCreateThreadPush1
push ntCreateThreadPush2
jmp ntCreateThread_7
}
}
__declspec(naked) VOID MyNtVirtualProtectMemory(){
__asm{
push ntProtectVirtualMemoryParam1
push ntProtectVirtualMemoayParam2
jmp ntProtectVirtualMemory_7
}
}
__declspec(naked) VOID MyNtQueueAqcThread(){
__asm{
mov edi,edi
push ebp
mov ebp,esp
push ecx
jmp ntQueueAqcThread_6
}
}
__declspec(naked) VOID MyNtTerminateProcess(){
__asm{
mov edi,edi
push ebp
mov ebp,esp
sub esp,0x10
jmp ntTerminateProcess_8
}
}
__declspec(naked) VOID MyNtWriteVirtualMemory(){
__asm{
push ntWriteVirtualMemoryParam1
push ntWriteVirtualMemoryParam2
jmp ntWriteVirtualMemory_7
}
}
__declspec(naked) VOID MyKe386IoSetAccessProcess(){
__asm{
mov edi,edi
push ebp
mov ebp,esp
xor ecx,ecx
jmp ke386IoSetAccessProcess_7
}
}
__declspec(naked) VOID MyKeAttachProcess(){
__asm{
mov edi,edi
push ebp
mov ebp,esp
push esi
jmp keAttachProcess_6
}
}
__declspec(naked) VOID MyKeInitialzeApc(){
__asm{
mov edi,edi
push ebp
mov ebp,esp
mov eax,dword ptr[ebp+8]
jmp keInitializeApc_8
}
}
__declspec(naked) VOID MyStackAttachProcess(){
__asm{
mov edi,edi
push ebp
mov ebp,esp
push esi
jmp keStackAttachProcess_6
}
}
__declspec(naked) VOID MyObCheckObjectAccess(){
__asm{
mov edi,edi
push ebp
mov ebp,esp
sub esp,0x10
jmp obCheckObjectAccess_8
}
}
__declspec(naked) VOID MyZwOpenSection(){
__asm{
mov eax,0x7d
lea edx,dword ptr[esp+4]
jmp zwOpenSection_9
}
}
VOID pass(){
if ( TRUE == MyHook_flag )
{
KdPrint(("Hook Already\n"));
return;
}
MyHook_flag = TRUE;
getKernelFunctionAddr();
MyHook();
}
VOID MyHook(){
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h //and eax,0FFFEFFFFh
mov cr0,eax
mov eax,ssdt_No_53
mov ebx,MyNtCreateThread
mov dword ptr [eax], ebx
mov eax,ssdt_No_137
mov ebx,MyNtVirtualProtectMemory
mov dword ptr [eax],ebx
mov eax,ssdt_No_180
mov ebx,MyNtQueueAqcThread
mov dword ptr[eax],ebx
mov eax,ssdt_No_257
mov ebx,MyNtTerminateProcess
mov dword ptr[eax],ebx
mov eax,ssdt_No_277
mov ebx,MyNtWriteVirtualMemory
mov dword ptr[eax],ebx
mov eax,Ke386IoSetAccessProcessAddr
mov byte ptr[eax],0x68
mov ebx,MyKe386IoSetAccessProcess
// sub ebx,eax
// sub ebx,5
mov dword ptr[eax+1],ebx
mov byte ptr[eax+5],0xc3
mov eax,KeAttachProcessAddr
mov byte ptr[eax],0x68
mov ebx,MyKeAttachProcess
// sub ebx,eax
// sub ebx,5
mov dword ptr[eax+1],ebx
mov byte ptr[eax+5],0xc3
mov eax,KeInitializeApcAddr
mov byte ptr[eax],0x68
mov ebx,MyKeInitialzeApc
// sub ebx,eax
// sub ebx,5
mov dword ptr[eax+1],ebx
mov byte ptr[eax+5],0xc3
mov eax,KeStackAttachProcessAddr
mov byte ptr[eax],0x68
mov ebx,MyStackAttachProcess
// sub ebx,eax
// sub ebx,5
mov dword ptr[eax+1],ebx
mov byte ptr[eax+5],0xc3
mov eax,ObCheckObjectAccessAddr
mov byte ptr[eax],0x68
mov ebx,MyObCheckObjectAccess
// sub ebx,eax
// sub ebx,5
mov dword ptr[eax+1],ebx
mov byte ptr[eax+5],0xc3
mov eax,ZwOpenSectionAddr
mov byte ptr[eax],0x68
mov ebx,MyZwOpenSection
// sub ebx,eax
// sub ebx,5
mov dword ptr[eax+1],ebx
mov byte ptr[eax+5],0xc3
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
VOID unpass(){
if ( FALSE == MyHook_flag )
{
KdPrint(("Not Hook Yet\n"));
return;
}
KdPrint(("Unhook Ok\n"));
MyHook_flag = FALSE;
__asm //去掉页面保护
{
cli
mov eax,cr0
and eax,not 10000h //and eax,0FFFEFFFFh
mov cr0,eax
mov ebx,ssdt_No_53//ntCreateThread
mov eax,NtCreateThreadAddr
mov [ebx],eax
mov ebx,ssdt_No_137//ntProtectVirtualMemory
mov eax,NtProtectVirtualMemoryAddr
mov [ebx],eax
mov ebx,ssdt_No_180//ntNtQueueAqcThread
mov eax,NtQueueAqcThreadAddr
mov [ebx],eax
mov ebx,ssdt_No_257//ntTerminalProcess
mov eax,NtTerminateProcessAddr
mov [ebx],eax
mov ebx,ssdt_No_277
mov eax,NtWriteVirtualMemoryAddr
mov [ebx],eax
mov ebx,Ke386IoSetAccessProcessAddr
mov dword ptr[ebx],0x8b55ff8b
mov dword ptr[ebx+4],0x57c933ec
mov ebx,KeAttachProcessAddr
mov dword ptr[ebx],0x8b55ff8b
mov word ptr[ebx+4],0x56ec
mov ebx,KeInitializeApcAddr//mov edi,edi;push ebp;mov ebp,esp;mov eax,[ebp+8]
mov dword ptr[ebx],0x8b55ff8b
mov dword ptr[ebx+4],0x08458bec
mov ebx,KeStackAttachProcessAddr
mov dword ptr[ebx],0x8b55ff8b
mov word ptr[ebx+4],0x56ec
mov ebx,ObCheckObjectAccessAddr
mov dword ptr[ebx],0x8b55ff8b
mov dword ptr[ebx+4],0x10ec83ec
mov ebx,ObCheckObjectAccessAddr
mov dword ptr[ebx],0x8b55ff8b
mov dword ptr[ebx+4],0x10ec83ec
mov dword ptr[ebx+8],0x5608458b
mov ebx,ZwOpenSectionAddr
mov dword ptr[ebx],0x7db8
mov dword ptr[ebx+4],0x24548d00
mov byte ptr[ebx+8],0x04
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}
VOID getKernelFunctionAddr(){
UNICODE_STRING Ke386IoSetAccessProcessStr;
UNICODE_STRING KeAttachProcessStr;
UNICODE_STRING KeInitializeApcStr;
UNICODE_STRING KeStackAttachProcessStr;
UNICODE_STRING ObCheckObjectAccessStr;
UNICODE_STRING ZwOpenSectionStr;
RtlInitUnicodeString(&Ke386IoSetAccessProcessStr,L"Ke386IoSetAccessProcess");
RtlInitUnicodeString(&KeAttachProcessStr,L"KeAttachProcess");
RtlInitUnicodeString(&KeInitializeApcStr,L"KeInitializeApc");
RtlInitUnicodeString(&KeStackAttachProcessStr,L"KeStackAttachProcess");
RtlInitUnicodeString(&ObCheckObjectAccessStr,L"ObCheckObjectAccess");
RtlInitUnicodeString(&ZwOpenSectionStr,L"ZwOpenSection");
Ke386IoSetAccessProcessAddr = (LONG)MmGetSystemRoutineAddress(&Ke386IoSetAccessProcessStr);
KeAttachProcessAddr = (LONG)MmGetSystemRoutineAddress(&KeAttachProcessStr);
KeInitializeApcAddr = (LONG)MmGetSystemRoutineAddress(&KeInitializeApcStr);
KeStackAttachProcessAddr = (LONG)MmGetSystemRoutineAddress(&KeStackAttachProcessStr);
ObCheckObjectAccessAddr = (LONG)MmGetSystemRoutineAddress(&ObCheckObjectAccessStr);
ZwOpenSectionAddr = (LONG)MmGetSystemRoutineAddress(&ZwOpenSectionStr);
ke386IoSetAccessProcess_7 = Ke386IoSetAccessProcessAddr + 7;
keAttachProcess_6 = KeAttachProcessAddr + 6;
keInitializeApc_8 = KeInitializeApcAddr + 8;
keStackAttachProcess_6 = KeStackAttachProcessAddr + 6;
obCheckObjectAccess_8 = ObCheckObjectAccessAddr + 8;
zwOpenSection_9 = ZwOpenSectionAddr + 9;
KdPrint(("Ke386IoSetAccessProcess=%X\n",Ke386IoSetAccessProcessAddr));
KdPrint(("KeAttachProcess=%X\n",KeAttachProcessAddr));
KdPrint(("KeInitializeApc=%X\n",KeInitializeApcAddr));
KdPrint(("KeStackAttachProcess=%X\n",KeStackAttachProcessAddr));
KdPrint(("ObCheckObjectAccess=%X\n",ObCheckObjectAccessAddr));
KdPrint(("ZwOpenSection=%X\n",ZwOpenSectionAddr));
ssdt_start = (LONG)KeServiceDescriptorTable->ServiceTableBase;
ssdt_No_53 = ssdt_start + 53*4;
ssdt_No_137 = ssdt_start + 137*4;
ssdt_No_180 = ssdt_start + 180*4;
ssdt_No_257 = ssdt_start + 257*4;
ssdt_No_277 = ssdt_start + 277*4;
NtCreateThreadAddr = *(LONG*)ssdt_No_53;
ntCreateThreadPush1 = *(BYTE*)(*(LONG*)ssdt_No_53+1);
ntCreateThreadPush2 = *(LONG*)(*(LONG*)ssdt_No_53+3);
ntCreateThread_7 = NtCreateThreadAddr+7;
NtProtectVirtualMemoryAddr = *(LONG*)ssdt_No_137;
ntProtectVirtualMemoryParam1 = *(BYTE*)(*(LONG*)ssdt_No_137+1);
ntProtectVirtualMemoayParam2 = *(LONG*)(*(LONG*)ssdt_No_137+3);
ntProtectVirtualMemory_7 = NtProtectVirtualMemoryAddr+7;
NtQueueAqcThreadAddr=*(LONG*)ssdt_No_180;
ntQueueAqcThread_6=NtQueueAqcThreadAddr+6;
NtTerminateProcessAddr=*(LONG*)ssdt_No_257;
ntTerminateProcess_8=NtTerminateProcessAddr+8;
NtWriteVirtualMemoryAddr = *(LONG*)ssdt_No_277;
ntWriteVirtualMemoryParam1 = *(BYTE*)(*(LONG*)ssdt_No_277+1);
ntWriteVirtualMemoryParam2 = *(LONG*)(*(LONG*)ssdt_No_277+3);
ntWriteVirtualMemory_7 = NtWriteVirtualMemoryAddr+7;
}