📄 hookproc.c
字号:
/*
* Copyright (c) 2004 Security Architects Corporation. All rights reserved.
*
* Module Name:
*
* hookproc.c
*
* Abstract:
*
* This module implements various service operation (system call) hooking routines.
*
* Since not all the Zw* services are exported, we use a hack to find the required information.
* ntdll.dll contains stubs for calling all the system services. All stubs start with
* "mov eax, function_index" instruction where function_index is an index into a global
* system call table. By parsing ntdll.dll and extracting all the function indeces
* we can map all the Zw* names to their appropriate system call table indeces.
*
* Author:
*
* Eugene Tsyrklevich 16-Feb-2004
*
* Revision History:
*
* None.
*/
#include <NTDDK.h>
#include "hookproc.h"
#include "sysinfo.h"
#include "ntproto.h"
#include "learn.h"
#include "file.h"
#include "registry.h"
#include "section.h"
#include "sysinfo.h"
#include "semaphore.h"
#include "dirobj.h"
#include "symlink.h"
#include "mutant.h"
#include "event.h"
#include "port.h"
#include "job.h"
#include "token.h"
#include "timer.h"
#include "driverobj.h"
#include "process.h"
#include "procname.h"
#include "time.h"
#include "atom.h"
#include "vdm.h"
#include "debug.h"
#include "i386.h"
#include "misc.h"
#include "log.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, InitSyscallsHooks)
#pragma alloc_text (INIT, InstallSyscallsHooks)
#pragma alloc_text (PAGE, RemoveSyscallsHooks)
#endif
#if DBG
int HookedRoutineRunning = 0;
#endif
PCHAR NTDLL_Base;
int ZwCallsNumber = 0;
/*
* FindFunctionOffset()
*
* Description:
* Finds a Zw* system call offset in a system service table.
*
* Implementation of all the Zw* system services (such as ZwOpenFile or ZwCreateProcess())
* start with a "mov eax, function_offset" instruction. Function offset is extracted from
* the first instruction.
*
* Parameters:
* Function - Pointer to the function code.
*
* Returns:
* Integer function offset (-1 in case of a failure).
*/
/* "MOV EAX,IMM32" opcode */
#define OPCODE_MOV 0xB8
/* macro shortcut for bailing out of FindFunctionOffset in case of an error */
#define ABORT_FindFunctionOffset(msg) { \
LOG(LOG_SS_HOOKPROC, LOG_PRIORITY_DEBUG, ("Error occured in FindFunctionOffset():")); \
LOG(LOG_SS_HOOKPROC, LOG_PRIORITY_DEBUG, msg); \
return -1; \
}
int
FindFunctionOffset(PULONG_PTR Function)
{
PUCHAR Instruction;
ULONG num, ServiceIDNumber, ServiceTableIndex;
/*
* Make sure that the service code starts with a MOV EAX,IMM32 instruction:
*
* lkd> u ZwCreateFile
* nt!ZwCreateFile:
* 804f86f4 b825000000 mov eax,0x25
*/
Instruction = (PUCHAR) Function;
if (*Instruction != OPCODE_MOV)
ABORT_FindFunctionOffset(("Invalid opcode %x\n", *Instruction));
/*
* Extract the Service Descriptor Table index (4 bytes following the mov opcode)
*
* The index format is as follows:
*
* Leading 18 bits are all zeroes
* Following 2 bits are system service table index (3 bits on Win64)
* Following 12 bits are service number
*/
num = * (PULONG) ++Instruction;
/* only SERVICE_TABLE_INDEX_BITS LSB bits should be set */
ServiceTableIndex = num >> SERVICE_ID_NUMBER_BITS;
if (ServiceTableIndex >= NUMBER_SERVICE_TABLES)
ABORT_FindFunctionOffset(("Invalid SSDT index: %x (%x)\n", ServiceTableIndex, num));
/* XXX temporary? There exist 4 (8 on IA64) service tables. All the Zw* system services are in table 0 */
if (ServiceTableIndex != 0)
ABORT_FindFunctionOffset(("Invalid SSDT index2: %x (%x)\n", ServiceTableIndex, num));
/* Verify Service ID Number is in range */
ServiceIDNumber = num & SERVICE_ID_NUMBER_MASK;
//XXX shouldn't we be using the shadow table instead??
//shadow table Zw* base address is the same in addition to GUI table
if (ServiceIDNumber > KeServiceDescriptorTable[ServiceTableIndex].NumberOfServices)
ABORT_FindFunctionOffset(("Invalid service id number %d (max is %d)\n", ServiceIDNumber, KeServiceDescriptorTable[ServiceTableIndex].NumberOfServices));
return ServiceIDNumber;
}
#if 0
/*
* HookSystemService()
*
* Description:
* Replaces an existing sytem service pointer (n a global system service table) with another function pointer.
*
* Parameters:
* OldService - Pointer to the service code to mediate.
* NewService - Pointer to the new function code.
*
* Returns:
* Current OldService indexed system service function pointer.
*/
/* macro shortcut for bailing out of HookSystemService in case of an error */
#define ABORT_HookSystemService(msg) { \
LOG(LOG_SS_HOOKPROC, LOG_PRIORITY_DEBUG, ("Error occured in HookSystemService():")); \
LOG(LOG_SS_HOOKPROC, LOG_PRIORITY_DEBUG, (msg)); \
return NULL; \
}
PVOID
HookSystemService(PVOID OldService, PVOID NewService)
{
PULONG_PTR ssdt;
PULONG_PTR retptr = NULL;
ULONG ServiceIDNumber;
if (OldService == NULL || NewService == NULL)
ABORT_HookSystemService(("NULL detected. OldService=%x NewService=%x", OldService, NewService));
ServiceIDNumber = FindFunctionOffset(OldService);
if (ServiceIDNumber == -1)
ABORT_HookSystemService(("FindFunctionOffset(%x) failed", OldService));
ssdt = KeServiceDescriptorTable[0].ServiceTableBase;
retptr = (PULONG_PTR) ssdt[ServiceIDNumber];
if (retptr == NULL)
ABORT_HookSystemService(("ssdt[index] = NULL\n"));
if (((ULONG) retptr & SystemAddressStart) == 0)
ABORT_HookSystemService(("invalid code instruction specified\n"));
retptr = ExchangeReadOnlyMemoryPointer((PVOID *) &ssdt[ServiceIDNumber], NewService);
return retptr;
}
#endif
/*
* HookSystemServiceByIndex()
*
* Description:
* Replaces an existing sytem service (n a global system service table) with another function pointer.
*
* Parameters:
* ServiceIDNumber - Index of a system service to mediate.
* NewService - Pointer to the new function code.
*
* Returns:
* Current ServiceIDNumber indexed system service function pointer.
*/
/* macro shortcut for bailing out of HookSystemServiceByIndex in case of an error */
#define ABORT_HookSystemServiceByIndex(msg) { \
LOG(LOG_SS_HOOKPROC, LOG_PRIORITY_DEBUG, ("Error occured in HookSystemServiceByIndex():")); \
LOG(LOG_SS_HOOKPROC, LOG_PRIORITY_DEBUG, msg); \
return NULL; \
}
PVOID
HookSystemServiceByIndex(ULONG ServiceIDNumber, PVOID NewService)
{
PULONG_PTR ssdt;
PULONG_PTR retptr = NULL;
ULONG ServiceTableIndex = 0;
ssdt = KeServiceDescriptorTable[ServiceTableIndex].ServiceTableBase;
/* Verify Service ID Number is in range */
//XXX shouldn't we be using the shadow table instead??
if (ServiceIDNumber > KeServiceDescriptorTable[ServiceTableIndex].NumberOfServices)
ABORT_HookSystemServiceByIndex(("Invalid service id number %d (max is %d)\n", ServiceIDNumber, KeServiceDescriptorTable[ServiceTableIndex].NumberOfServices));
retptr = (PULONG_PTR) ssdt[ServiceIDNumber];
if (retptr == NULL)
ABORT_HookSystemServiceByIndex(("ssdt[index] = NULL\n"));
if (((ULONG) retptr & SystemAddressStart) == 0)
ABORT_HookSystemServiceByIndex(("invalid code instruction specified\n"));
retptr = ExchangeReadOnlyMemoryPointer((PVOID *) &ssdt[ServiceIDNumber], NewService);
return retptr;
}
#if 0
/*
* FindSystemServiceByIndex()
*
* Description:XXX
* Replaces an existing sytem service (n a global system service table) with another function pointer.
*
* Parameters:
* ServiceIDNumber - Index of a system service to mediate.
* NewService - Pointer to the new function code.
*
* Returns:
* Current ServiceIDNumber indexed system service function pointer.
*/
/* macro shortcut for bailing out of HookSystemServiceByIndex in case of an error */
#define ABORT_FindSystemServiceByIndex(msg) { LOG(LOG_SS_HOOKPROC, LOG_PRIORITY_DEBUG, ("Error occured in FindSystemServiceByIndex():")); LOG(LOG_SS_HOOKPROC, LOG_PRIORITY_DEBUG, msg); return NULL; }
PULONG
FindSystemServiceByIndex(ULONG ServiceIDNumber)
{
PULONG_PTR ssdt;
PULONG_PTR retptr = NULL;
ULONG ServiceTableIndex = 0;
ssdt = KeServiceDescriptorTable[ServiceTableIndex].ServiceTableBase;
/* Verify Service ID Number is in range */
//XXX shouldn't we be using the shadow table instead??
if (ServiceIDNumber > KeServiceDescriptorTable[ServiceTableIndex].NumberOfServices)
ABORT_FindSystemServiceByIndex(("Invalid service id number %d (max is %d)\n", ServiceIDNumber, KeServiceDescriptorTable[ServiceTableIndex].NumberOfServices));
retptr = (PULONG_PTR) ssdt[ServiceIDNumber];
if (retptr == NULL)
ABORT_FindSystemServiceByIndex(("ssdt[index] = NULL\n"));
if (((ULONG) retptr & SystemAddressStart) == 0)
ABORT_FindSystemServiceByIndex(("invalid code instruction specified\n"));
return (PULONG) ssdt[ServiceIDNumber];
}
#endif
/*
* HookSystemServiceByName()
*
* Description:
* Replaces an existing sytem service (n a global system service table) with another function pointer.
*
* Parameters:
* ServiceName - Name of a Zw* system service to mediate.
* HookFunction - Pointer to the mediator function code.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -