SSDT Hook后, 如果要跳过函数开始的一些opcode, 就只能跳到没有call语句之前的代码.
因为call有重定位问题,即使opcode一样,call的实际地址也是不同的.
#include <Ntddk.h>
#include <stdlib.h>
#include <stdio.h>
typedef char CHAR;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int size_t;
typedef unsigned long DWORD;
#define MAXBYTE 0xff
#define MAKEDWORD(L, H) (((WORD)((DWORD_PTR)(L) & 0xffff)) | ((DWORD)((WORD)((DWORD_PTR)(H) & 0xffff))) << 16)
#pragma pack(push)
#pragma pack(1)
typedef struct _SYSTEM_SERVICE_TABLE {
PVOID ServiceTableBase; //这个指向系统服务函数地址表
PULONG ServiceCounterTableBase;
ULONG NumberOfService; //服务函数的个数,NumberOfService*4 就是整个地址表的大小
ULONG ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;
typedef struct _SERVICE_DESCRIPTOR_TABLE {
SYSTEM_SERVICE_TABLE ntoskrnel; //ntoskrnl.exe的服务函数
SYSTEM_SERVICE_TABLE win32k; //win32k.sys的服务函数,(gdi.dll/user.dll的内核支持)
SYSTEM_SERVICE_TABLE NotUsed1;
SYSTEM_SERVICE_TABLE NotUsed2;
} SYSTEM_DESCRIPTOR_TABLE, *PSYSTEM_DESCRIPTOR_TABLE;
#pragma pack(pop)
extern PSYSTEM_DESCRIPTOR_TABLE KeServiceDescriptorTable;
SYSTEM_SERVICE_TABLE* g_pSST = NULL;
// typedef NTSTATUS (__stdcall *PFN_ZwOpenProcess)(
// __out PHANDLE ProcessHandle,
// __in ACCESS_MASK DesiredAccess,
// __in POBJECT_ATTRIBUTES ObjectAttributes,
// __in_opt PCLIENT_ID ClientId
// );
// PFN_ZwOpenProcess g_pfn = NULL;
DWORD g_dwSsdtFunIndexAddr_NtOpenProcess = 0;
DWORD g_dwPfnNtOpenProcessOrg = 0;
// naked 函数内不能初始化变量
// 在裸函数内使用的变量必须在函数外定义
DWORD g_dwAddrJmp_MyNtOpenProcess = 0x805c22a0;
__declspec(naked) NTSTATUS __stdcall MyNtOpenProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
{
/**
kd> u 805C2296
nt!NtOpenProcess:
805c2296 68c4000000 push 0C4h
805c229b 68a8aa4d80 push offset nt!ObWatchHandles+0x25c (804daaa8)
// 用 __asm + _emit, 在InlineHook函数后,可以跳到任意地址
// 但是call指令有重定位问题, 如果不修正, 只能在call之前打住
// 跳到这
805c22a0 e86b6cf7ff call nt!_SEH_prolog (80538f10)
805c22a5 33f6 xor esi,esi
805c22a7 8975d4 mov dword ptr [ebp-2Ch],esi
805c22aa 33c0 xor eax,eax
805c22ac 8d7dd8 lea edi,[ebp-28h]
805c22af ab stos dword ptr es:[edi]
*/
__asm {
// 这里可以用int 3来调试
// int 3
// 68c4000000
// 805c2296 68c4000000 push 0C4h
_emit 0x68
_emit 0xc4
_emit 0x00
_emit 0x00
_emit 0x00
// 68a8aa4d80
// 805c229b 68a8aa4d80 push offset nt!ObWatchHandles+0x25c (804daaa8)
_emit 0x68
_emit 0xa8
_emit 0xaa
_emit 0x4d
_emit 0x80
// e86b6cf7ff
// 805c22a0 e86b6cf7ff call nt!_SEH_prolog (80538f10)
// f8dc841a e86b6cf7ff call f8d3f08a
// call 指令涉及到重定位了, opcode一模一样也不是相同的反汇编指令
// 怪不得人家只跳过前10个字节
// _emit 0xe8
// _emit 0x6b
// _emit 0x6c
// _emit 0xf7
// _emit 0xff
pushf
pusha
}
// do my hook task
// 调用 KdPrint 可以正常打印
KdPrint(("MyNtOpenProcess\r\n"));
__asm {
popa
popf
jmp g_dwAddrJmp_MyNtOpenProcess
}
// return STATUS_SUCCESS;
// return 0;
}
void fnHook_SSDT()
{
DWORD dwAddr = 0;
do {
if (NULL == KeServiceDescriptorTable) {
break;
}
g_pSST = &KeServiceDescriptorTable->ntoskrnel;
if (NULL == g_pSST) {
break;
}
KdPrint(("g_pSST = %p\r\n", g_pSST));
if (NULL == g_pSST->ServiceTableBase) {
break;
}
KdPrint(("g_pSST->ServiceTableBase = %p\r\n", g_pSST->ServiceTableBase));
// 0x7a is OpenProcess Index On SSDT
dwAddr = (DWORD)g_pSST->ServiceTableBase + 0x7a * sizeof(DWORD);
if (0 == dwAddr) {
break;
}
// 要换的就是g_dwSsdtFunIndexAddr_NtOpenProcess地址中的内容
g_dwSsdtFunIndexAddr_NtOpenProcess = dwAddr;
KdPrint(("g_dwSsdtFunIndexAddr_NtOpenProcess = %p\r\n", g_dwSsdtFunIndexAddr_NtOpenProcess));
g_dwPfnNtOpenProcessOrg = *((DWORD*)(g_dwSsdtFunIndexAddr_NtOpenProcess));
KdPrint(("g_dwPfnNtOpenProcessOrg = %p\r\n", g_dwPfnNtOpenProcessOrg));
/**
>> DriverEntry
g_pSST = 80553FA0
g_pSST->ServiceTableBase = 80502B8C
g_dwSsdtFunIndexAddr_NtOpenProcess = 80502D74
g_dwPfnNtOpenProcessOrg = 805C2296
kd> u 805C2296
nt!NtOpenProcess:
805c2296 68c4000000 push 0C4h
805c229b 68a8aa4d80 push offset nt!ObWatchHandles+0x25c (804daaa8)
805c22a0 e86b6cf7ff call nt!_SEH_prolog (80538f10)
805c22a5 33f6 xor esi,esi
805c22a7 8975d4 mov dword ptr [ebp-2Ch],esi
805c22aa 33c0 xor eax,eax
805c22ac 8d7dd8 lea edi,[ebp-28h]
805c22af ab stos dword ptr es:[edi]
*/
__asm { //去掉内存保护
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
*((DWORD*)(g_dwSsdtFunIndexAddr_NtOpenProcess)) = (DWORD)MyNtOpenProcess;
__asm { //恢复内存保护
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
KdPrint(("Hook By MyNtOpenProcess = %p\r\n", MyNtOpenProcess));
} while (0);
}
void fnUnHook_SSDT()
{
__asm { //去掉内存保护
cli
mov eax, cr0
and eax, not 10000h
mov cr0, eax
}
*((DWORD*)(g_dwSsdtFunIndexAddr_NtOpenProcess)) = (DWORD)g_dwPfnNtOpenProcessOrg;
__asm { //恢复内存保护
mov eax, cr0
or eax, 10000h
mov cr0, eax
sti
}
KdPrint(("UnHook By g_dwPfnNtOpenProcessOrg = %p\r\n", g_dwPfnNtOpenProcessOrg));
}
VOID fnDrvUnLoad(__in struct _DRIVER_OBJECT* DriverObject)
{
KdPrint((">> fnDrvUnLoad"));
fnUnHook_SSDT();
}
NTSTATUS fnDrvDisPatch(__in struct _DEVICE_OBJECT* DeviceObject, __inout struct _IRP* Irp)
{
KdPrint((">> fnDrvDisPatch"));
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(__in struct _DRIVER_OBJECT* DriverObject, __in PUNICODE_STRING RegistryPath)
{
KdPrint((">> DriverEntry"));
DriverObject->DriverUnload = fnDrvUnLoad;
DriverObject->MajorFunction[IRP_MJ_CREATE] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_READ] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_WRITE] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_SET_EA] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_POWER] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CHANGE] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_QUERY_QUOTA] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_SET_QUOTA] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_PNP] = fnDrvDisPatch;
DriverObject->MajorFunction[IRP_MJ_MAXIMUM_FUNCTION] = fnDrvDisPatch;
fnHook_SSDT();
return STATUS_SUCCESS;
}