Bitdefender Hypervisor Memory Introspection
detours.c File Reference

The guest detour API implementation. More...

#include "detours.h"
#include "decoder.h"
#include "guests.h"
#include "introcpu.h"
#include "memcloak.h"
#include "slack.h"
#include "lixmodule.h"
#include "kernvm.h"
#include "alerts.h"
#include "introcrt.h"

Go to the source code of this file.

Data Structures

struct  _DETOURS_STATE
 Holds information about the currently set detours. More...
 

Macros

#define DETOUR_MAX_FUNCTION_SIZE   24
 The maximum size of the original function code we will replace. More...
 
#define for_each_detour(_var_name)   list_for_each (gDetours.DetoursList, DETOUR, _var_name)
 Iterates the linked list in gDetours. More...
 

Typedefs

typedef struct _DETOURS_STATE DETOURS_STATE
 Holds information about the currently set detours. More...
 
typedef struct _DETOURS_STATEPDETOURS_STATE
 

Functions

static INTSTATUS IntDetDisableLixHypercall (DETOUR *Detour)
 Disables a Linux detour hypercall. More...
 
static INTSTATUS IntDetDisableWinHypercall (DETOUR *Detour)
 Disables a Windows detour hypercall. More...
 
static INTSTATUS IntDetEnableHypercall (DETOUR *Detour)
 Enables a detour hypercall. More...
 
static void IntDetRemoveBranch (DETOUR *Detour)
 Restores the original instructions of a hooked function. More...
 
static void IntDetRemoveHandler (DETOUR *Detour)
 Removes a detour handler from the guest. More...
 
static void IntDetRemoveDetour (DETOUR *Detour)
 Removes and frees a detour. More...
 
static void IntDetPermanentlyDisableDetour (DETOUR *Detour)
 Removes a detour from the guest. More...
 
INTSTATUS IntDetDisableDetour (DETOUR_TAG Tag)
 Disables a detour based on its tag. More...
 
INTSTATUS IntDetEnableDetour (DETOUR_TAG Tag)
 Enables a detour based on its tag. More...
 
static INTSTATUS IntDetCreateObjectLix (QWORD FunctionAddress, const LIX_FN_DETOUR *FnDetour, LIX_GUEST_DETOUR *DetourStruct, DETOUR **Detour)
 Create a DETOUR structure using the information from LIX_FN_DETOUR. More...
 
static INTSTATUS IntDetRelocate (DETOUR *Detour, BYTE *FunctionCode, DWORD FunctionSize, DWORD *InstrCount)
 Relocate the over-written instruction from detoured function. More...
 
static DETOURIntDetFindByTag (DETOUR_TAG Tag)
 Searches a detour by its tag. More...
 
static INTSTATUS IntDetHandleWrite (void *Hook, QWORD PhysicalAddress, QWORD RegionVirtualAddress, void *CloakHandle, INTRO_ACTION *Action)
 Handle the writes over bytes modified from detoured function. More...
 
static INTSTATUS IntDetPatchFunction (DETOUR *Detour, BYTE *FunctionCode, DWORD FunctionSize)
 Patch the first instruction of the function with a 'JMP' to our handler. More...
 
static INTSTATUS IntDetSendIntegrityAlert (char *FunctionName, QWORD FunctionAddress, QWORD DetourAddress)
 Sends an integrity alert if the provieded function is already hooked. More...
 
INTSTATUS IntDetSetLixHook (QWORD FunctionAddress, const LIX_FN_DETOUR *FnDetour, BOOLEAN *MultipleInstructions)
 Detours a function from guest. More...
 
INTSTATUS IntDetSetHook (QWORD FunctionAddress, QWORD ModuleBase, API_HOOK_DESCRIPTOR *Descriptor, API_HOOK_HANDLER *Handler)
 Will inject code inside the guest. More...
 
INTSTATUS IntDetSetReturnValue (DETOUR const *Detour, IG_ARCH_REGS *Registers, QWORD ReturnValue)
 Sets the return value for a hooked guest function. More...
 
INTSTATUS IntDetCallCallback (void)
 Calls the appropriate detour handler for hypercall. More...
 
INTSTATUS IntDetModifyPublicData (DETOUR_TAG Tag, void const *Data, DWORD DataSize, char const *PublicDataName)
 Modifies public parts of a detour handler. More...
 
void IntDetDisableAllHooks (void)
 Removes all detours from the guest. More...
 
void IntDetUninit (void)
 Uninitializes the detour module. More...
 
void IntDetDumpDetours (void)
 Prints all the detours in the gDetours list of detours. More...
 
BOOLEAN IntDetIsPtrInRelocatedCode (QWORD Ptr, DETOUR_TAG *Tag)
 Checks if a guest pointer is inside the modified prologue of a function. More...
 
BOOLEAN IntDetIsPtrInHandler (QWORD Ptr, THS_PTR_TYPE Type, DETOUR_TAG *Tag)
 Checks if a guest pointer is inside a detour handler. More...
 
QWORD IntDetRelocatePtrIfNeeded (QWORD Ptr)
 Returns the new value Ptr should have if it is currently pointing inside a relocated prologue. More...
 
INTSTATUS IntDetGetAddrAndTag (QWORD Ptr, QWORD *Address, DWORD *Size, DETOUR_TAG *Tag)
 Checks if Ptr is inside a detour handler and returns the detour's handler address, size and tag. More...
 
INTSTATUS IntDetGetByTag (DETOUR_TAG Tag, QWORD *Address, DWORD *Size)
 Get a detour handler address and size by its tag. More...
 
INTSTATUS IntDetGetFunctionAddressByTag (DETOUR_TAG Tag, QWORD *FunctionAddress)
 Get a detour function address by its tag. More...
 
static INTSTATUS IntDetGetArgumentInternal (DWORD Arg, BYTE const *StackBuffer, DWORD StackBufferSize, QWORD *Value)
 Reads the value of an argument passed from a detour. More...
 
INTSTATUS IntDetGetArgument (void const *Detour, DWORD Index, BYTE const *StackBuffer, DWORD StackBufferSize, QWORD *Value)
 Reads the specified argument for a detour. More...
 
INTSTATUS IntDetGetArguments (void const *Detour, DWORD Argc, QWORD *Argv)
 Reads multiple arguments from a detour. More...
 
INTSTATUS IntDetPatchArgument (void const *Detour, DWORD Index, QWORD Value)
 Modifies the value of a detour argument. More...
 

Variables

static DETOURS_STATE gDetours
 The global detour state. More...
 

Detailed Description

The guest detour API implementation.

Definition in file detours.c.

Macro Definition Documentation

◆ DETOUR_MAX_FUNCTION_SIZE

#define DETOUR_MAX_FUNCTION_SIZE   24

The maximum size of the original function code we will replace.

Definition at line 24 of file detours.c.

Referenced by IntDetPatchFunction(), IntDetSetHook(), and IntDetSetLixHook().

◆ for_each_detour

#define for_each_detour (   _var_name)    list_for_each (gDetours.DetoursList, DETOUR, _var_name)

Iterates the linked list in gDetours.

Can be used to safely iterate the detour list. The current detour pointed to by _var_name can safely be removed from the list, but note that removing other detours while iterating the list using this macro is not a valid operation and can corrupt the list.

Parameters
[in]_var_nameThe name of the variable in which the DETOUR pointer will be placed. This variable will be declared by the macro an available only in the context created by the macro.

Definition at line 54 of file detours.c.

Referenced by IntDetCallCallback(), IntDetDisableAllHooks(), IntDetDumpDetours(), IntDetGetAddrAndTag(), IntDetIsPtrInHandler(), IntDetIsPtrInRelocatedCode(), IntDetRelocatePtrIfNeeded(), and IntDetUninit().

Typedef Documentation

◆ DETOURS_STATE

typedef struct _DETOURS_STATE DETOURS_STATE

Holds information about the currently set detours.

◆ PDETOURS_STATE

typedef struct _DETOURS_STATE * PDETOURS_STATE

Function Documentation

◆ IntDetCallCallback()

INTSTATUS IntDetCallCallback ( void  )

Calls the appropriate detour handler for hypercall.

This will iterate the list of detours and will call the first one that matches the hypercall. In order to match a detour must have the same hypercall type as the hypercall that was issued, must have the HypercallAddress equal to the RIP from which the hypercall was issued, and must have a valid callback. If it is not disabled, it is called. Even if it is disabled the search stops after the first match.

If the detour is enabled, its HitCount is incremented. If the callback returns INT_STATUS_DISABLE_DETOUR_ON_RET the hypercall is disabled, but the detour is not removed from the guest memory and it will still be executed by the guest. If it returns INT_STATUS_REMOVE_DETOUR_AND_SET_RIP the detour is removed from the guest (this is available only for detours with a hypercallTypeInt3 hypercall type). Other return values are ignored and are not even logged.

Return values
INT_STATUS_SUCCESSin case of success. This does not take into account error encountered by the detour callback.
INT_STATUS_NOT_FOUNDif no matching detour was found. This means that the hypercall was not issued by a detour.
INT_STATUS_NO_DETOUR_EMUif no emulation is needed. This means that the detour callback returned INT_STATUS_REMOVE_DETOUR_AND_SET_RIP and the detour was removed and the guest RIP was moved to point back to the original function address, meaning that the guest should be let to execute the original function, and emulation is not needed, because there is nothing to emulate.

Definition at line 1596 of file detours.c.

Referenced by IntHandleBreakpoint(), and IntHandleIntroCall().

◆ IntDetCreateObjectLix()

static INTSTATUS IntDetCreateObjectLix ( QWORD  FunctionAddress,
const LIX_FN_DETOUR FnDetour,
LIX_GUEST_DETOUR DetourStruct,
DETOUR **  Detour 
)
static

Create a DETOUR structure using the information from LIX_FN_DETOUR.

Parameters
[in]FunctionAddressThe guest virtual address of the function to be hooked
[in]FnDetourPointer to a structure that describes the hook.
[out]DetourStructOn success, a structure that describes the detour that is injected in guest.
[out]DetourOn success, the DETOUR structure used by detour-mechanism.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf HpAllocWithTag fails.

Definition at line 394 of file detours.c.

Referenced by IntDetSetLixHook().

◆ IntDetDisableAllHooks()

void IntDetDisableAllHooks ( void  )

Removes all detours from the guest.

This will restore the original contents of the hooked functions, will remove the detour handlers, and will free any resources associated with the detours, except the detour structures. No safeness checks are done. If a guest thread is currently running inside a detour handler or returns to it the guest will be left in an unstable state.

Definition at line 1848 of file detours.c.

Referenced by IntGuestPrepareUninit().

◆ IntDetDisableDetour()

INTSTATUS IntDetDisableDetour ( DETOUR_TAG  Tag)

Disables a detour based on its tag.

After the detour is disabled, its handler will no longer issue hypercalls, but it will still be present inside the guest and the guest will still execute it. If it has any side effects, those will still be visible inside the guest.

Parameters
[in]TagThe tag of the detour which will be disabled.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_INVALID_PARAMETER_1if Tag is not less than detTagMax.
INT_STATUS_NOT_NEEDED_HINTif no detour exists for the given tag.

Definition at line 324 of file detours.c.

Referenced by IntWinApiUpdateHooks().

◆ IntDetDisableLixHypercall()

static INTSTATUS IntDetDisableLixHypercall ( DETOUR Detour)
static

Disables a Linux detour hypercall.

This is done by overwriting the LIX_GUEST_DETOUR.EnableOptions field with 0. After this function exists, the DETOUR.Disabled field will be set to True.

Parameters
[in,out]DetourThe detour for which the hypercall is disabled.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the LixGuestDetour address not valid.

Definition at line 58 of file detours.c.

Referenced by IntDetPermanentlyDisableDetour().

◆ IntDetDisableWinHypercall()

static INTSTATUS IntDetDisableWinHypercall ( DETOUR Detour)
static

Disables a Windows detour hypercall.

This is done by replacing the hypercall instruction with NOPs. If the hypercall type is hypercallTypeInt3, a single NOP (0x90) is used to replace the INT3 instruction. If hypercall type is hypercallTypeVmcall, a "long" NOP is used (0x66 0x66 0x90). This is done because replacing an instruction with an instruction of the same size is safer. After this function exists, the DETOUR.Disabled field will be set to True.

Parameters
[in,out]DetourThe detour for which the hypercall is disabled.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_NOT_NEEDED_HINTif the detour those not have a memory cloak handle or if the detour does not have a hypercall instruction.

Definition at line 98 of file detours.c.

Referenced by IntDetDisableDetour(), and IntDetPermanentlyDisableDetour().

◆ IntDetDumpDetours()

void IntDetDumpDetours ( void  )

Prints all the detours in the gDetours list of detours.

Definition at line 1895 of file detours.c.

Referenced by IntGuestUninit().

◆ IntDetEnableDetour()

INTSTATUS IntDetEnableDetour ( DETOUR_TAG  Tag)

Enables a detour based on its tag.

After the detour is enabled, its handler will start to issue hypercalls.

Parameters
[in]TagThe tag of the detour which will be enabled.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_INVALID_PARAMETER_1if Tag is not less than detTagMax.
INT_STATUS_NOT_NEEDED_HINTif no detour exists for the given tag.

Definition at line 361 of file detours.c.

Referenced by IntWinApiUpdateHooks().

◆ IntDetEnableHypercall()

static INTSTATUS IntDetEnableHypercall ( DETOUR Detour)
static

Enables a detour hypercall.

This is done by replacing the NOPs at the hypercall offset with the proper hypercall instruction. If the hypercall type is hypercallTypeInt3 this will be a INT3 (0xCC) instruction. If the hypercall type is hypercallTypeVmcall this will be a VMCALL (0x0F 0x01 0xC1) instruction. For other hypercall types no change is done. After this function exists, the DETOUR.Disabled field will be set to False.

Parameters
[in,out]DetourThe detour for which the hypercall is disabled.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_NOT_NEEDED_HINTif the detour those not have a memory cloak handle or if the detour does not have a hypercall instruction.

Definition at line 155 of file detours.c.

Referenced by IntDetEnableDetour().

◆ IntDetFindByTag()

static DETOUR* IntDetFindByTag ( DETOUR_TAG  Tag)
static

Searches a detour by its tag.

Parameters
[in]TagThe tag of the detour.
Returns
A pointer to a DETOUR structure for the given tag, if it exists.

Definition at line 623 of file detours.c.

Referenced by IntDetGetByTag(), IntDetGetFunctionAddressByTag(), and IntDetHandleWrite().

◆ IntDetGetAddrAndTag()

INTSTATUS IntDetGetAddrAndTag ( QWORD  Ptr,
QWORD Address,
DWORD Size,
DETOUR_TAG Tag 
)

Checks if Ptr is inside a detour handler and returns the detour's handler address, size and tag.

Parameters
[in]PtrGuest virtual address to check.
[out]AddressIf Ptr is inside a detour handler, will contain the start of the handler. May be NULL.
[out]SizeIf Ptr is inside a detour handler, will contain the size of the handler. May be NULL.
[out]TagIf Ptr is inside a detour handler, will contain the tag of the detour. May be NULL.
Return values
INT_STATUS_SUCCESSif Ptr is inside a detour handler.
INT_STATUS_NOT_FOUNDif Ptr is not inside a detour handler.

Definition at line 2074 of file detours.c.

Referenced by IntRtlpVirtualUnwindCheckAccess().

◆ IntDetGetArgument()

INTSTATUS IntDetGetArgument ( void const *  Detour,
DWORD  Index,
BYTE const *  StackBuffer,
DWORD  StackBufferSize,
QWORD Value 
)

Reads the specified argument for a detour.

Parameters
[in]DetourThe detour for which to read the argument.
[in]IndexThe number of the argument to read.
[in]StackBufferIf the argument is on the stack and this is not NULL, it will be used instead of reading the argument from the guest memory. If multiple calls are made for the same detour, it is worth it to read the guest stack once and passing it as a buffer to all calls made to this function.
[in]StackBufferSizeThe size of the stack buffer. If the argument is outside the size of the stack buffer, it will be taken directly from the guest memory.
[out]ValueOn success, the value of the argument.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_INVALID_PARAMETER_1if Detour is NULL.
INT_STATUS_INVALID_PARAMETER_2if Index is equal or grater than DET_ARGS_MAX.
INT_STATUS_INVALID_PARAMETER_3if Value is NULL.
INT_STATUS_NOT_INITIALIZEDif the Detour is not properly uninitialized.

Definition at line 2237 of file detours.c.

Referenced by IntDriverUnloadHandler(), IntWinProcHandleTerminate(), IntWinProcSwapIn(), IntWinProcSwapOut(), IntWinVadHandleInsertMap(), IntWinVadHandleInsertPrivate(), and IntWinVadHandleVirtualProtect().

◆ IntDetGetArgumentInternal()

static INTSTATUS IntDetGetArgumentInternal ( DWORD  Arg,
BYTE const *  StackBuffer,
DWORD  StackBufferSize,
QWORD Value 
)
static

Reads the value of an argument passed from a detour.

Parameters
[in]ArgArgument encoding as taken from a DETOUR_ARGS structure.
[in]StackBufferOptional buffer containing the guest stack. If the argument is on the stack, will use this buffer instead of reading it directly from the guest.
[in]StackBufferSizeThe size of the StackBuffer. If the argument is outside the size of the stack buffer, it will be taken directly from the guest memory.
[out]ValueOn success, will contain the argument value.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_INVALID_INTERNAL_STATEif the argument encoding is corrupted.

Definition at line 2170 of file detours.c.

Referenced by IntDetGetArgument(), and IntDetGetArguments().

◆ IntDetGetArguments()

INTSTATUS IntDetGetArguments ( void const *  Detour,
DWORD  Argc,
QWORD Argv 
)

Reads multiple arguments from a detour.

Iterates over the arguments in Detour and calls IntDetGetArgumentInternal for each one. If one or more arguments are on the stack, the function will calculate the size of the stack that must be read in order to have access on all of them, and map it a single time, before calling it.

Parameters
[in]DetourThe detour for which to read the arguments.
[in]ArgcThe number of arguments to read.
[out]ArgvOn success, will contain the first Argc arguments from this detour. If the detour has less than Argc arguments, the function stops reading when it reaches the last argument. This buffer should be large enough to contain Argc 64-bit integers, even for 32-bit guests.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_INVALID_PARAMETER_1if Detour is NULL.
INT_STATUS_INVALID_PARAMETER_2if Argc is 0 or not less than DET_ARGS_MAX.
INT_STATUS_INVALID_PARAMETER_3if Argv is NULL.
INT_STATUS_NOT_INITIALIZEDif Detour is not fully initialized yet.
INT_STATUS_INVALID_INTERNAL_STATEif the caller requested more arguments than there are available.

Definition at line 2296 of file detours.c.

Referenced by IntDriverLoadHandler(), IntWinHandleException(), IntWinPoolHandleAlloc(), IntWinPoolHandleFree(), IntWinProcHandleCopyMemory(), IntWinProcHandleCreate(), IntWinProcHandleInstrument(), IntWinThrHandleQueueApc(), IntWinThrHandleThreadHijack(), IntWinVadHandleCommit(), IntWinVadHandleDeleteVaRange(), IntWinVadHandleFinishVadDeletion(), IntWinVadHandleInsert(), and IntWinVadHandleVirtualProtect().

◆ IntDetGetByTag()

INTSTATUS IntDetGetByTag ( DETOUR_TAG  Tag,
QWORD Address,
DWORD Size 
)

Get a detour handler address and size by its tag.

Parameters
[in]TagDetour tag.
[out]AddressOn success, the address of the detour handler.
[out]SizeOn success, the size of the detour handler. May be NULL.
Return values
INT_STATUS_SUCCESSif there is a detour for the given tag.
INT_STATUS_NOT_FOUNDif there is no detour for the given tag.

Definition at line 2110 of file detours.c.

Referenced by IntLixPatchSwapgs().

◆ IntDetGetFunctionAddressByTag()

INTSTATUS IntDetGetFunctionAddressByTag ( DETOUR_TAG  Tag,
QWORD FunctionAddress 
)

Get a detour function address by its tag.

Parameters
[in]TagDetour tag.
[out]FunctionAddressOn success, the address of the function which was detoured.
Return values
INT_STATUS_SUCCESSif there is a detour for the given tag.
INT_STATUS_NOT_FOUNDif there is no detour for the given tag.

Definition at line 2144 of file detours.c.

Referenced by IntWinModIsKernelWriteInjection().

◆ IntDetHandleWrite()

static INTSTATUS IntDetHandleWrite ( void *  Hook,
QWORD  PhysicalAddress,
QWORD  RegionVirtualAddress,
void *  CloakHandle,
INTRO_ACTION Action 
)
static

Handle the writes over bytes modified from detoured function.

Allow the write only if the originator is an active patch (ftrace or text_poke).

If the write is allowed the content of the active patch is relocated inside our detour-handler

Parameters
[in]HookThe hook object for which this callback was invoked.
[in]PhysicalAddressThe modified guest physical address.
[in]RegionVirtualAddressThe modified guest virtual address.
[in]CloakHandleThe memcloak object for which this callback was invoked.
[out]ActionThe taken action.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETER_1If Hook is invalid.
INT_STATUS_INVALID_PARAMETER_4If CloakHandle is invalid.
INT_STATUS_INVALID_PARAMETER_6If Action is invalid.

Definition at line 644 of file detours.c.

Referenced by IntDetPatchFunction().

◆ IntDetIsPtrInHandler()

BOOLEAN IntDetIsPtrInHandler ( QWORD  Ptr,
THS_PTR_TYPE  Type,
DETOUR_TAG Tag 
)

Checks if a guest pointer is inside a detour handler.

Parameters
[in]PtrThe guest virtual address to check.
[in]TypeThe type of pointer Ptr is. This is used only for logging purposes.
[out]TagIf Ptr is inside a detour handler, will contain the tag of the detour set for it. May be NULL.
Returns
True if Ptr is inside a detour handler prologue, False if it is not.

Definition at line 1980 of file detours.c.

Referenced by IntThrSafeIsLiveRIPInIntro(), and IntThrSafeIsStackPtrInIntro().

◆ IntDetIsPtrInRelocatedCode()

BOOLEAN IntDetIsPtrInRelocatedCode ( QWORD  Ptr,
DETOUR_TAG Tag 
)

Checks if a guest pointer is inside the modified prologue of a function.

Parameters
[in]PtrThe guest virtual address to check.
[out]TagIf Ptr is inside a modified function prologue, will contain the tag of the detour set for it. May be NULL.
Returns
True if Ptr is inside a modified function prologue, False if it is not.

Definition at line 1942 of file detours.c.

Referenced by IntLixPatchHandler().

◆ IntDetModifyPublicData()

INTSTATUS IntDetModifyPublicData ( DETOUR_TAG  Tag,
void const *  Data,
DWORD  DataSize,
char const *  PublicDataName 
)

Modifies public parts of a detour handler.

A detour that allows for external changes exposes the parts of its handler that can be changed as public data by describing them inside the API_HOOK_HANDLER.PublicDataOffsets array. An external caller only needs the detour tag and the name of the data region that it wants to change. The data is modified using the memory cloaking mechanism, see Memory cloaking.

Parameters
[in]TagThe tag of the detour.
[in]DataBuffer with the new contents of the detour handler.
[in]DataSizeThe size of the Data buffer. Must not be larger than the size of the public data region.
[in]PublicDataNameNULL-terminated string of the public data name. This is case sensitive.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_INVALID_PARAMETER_1if Tag is not less than detTagMax.
INT_STATUS_INVALID_PARAMETER_2if Data is NULL.
INT_STATUS_INVALID_PARAMETER_3if DataSize is 0.
INT_STATUS_INVALID_PARAMETER_4if PublicDataName is NULL.
INT_STATUS_NOT_INITIALIZED_HINTif no detour is found for Tag.
INT_STATUS_NOT_FOUNDif no public data region is found for PublicDataName.
INT_STATUS_INVALID_DATA_SIZEif DataSize is larger than the size of the public data region.

Definition at line 1751 of file detours.c.

Referenced by IntWinAgentActivatePendingAgent(), IntWinAgentHandleLoader1Hypercall(), IntWinAgentRemove(), IntWinPowDisableSpinWait(), and IntWinPowEnableSpinWait().

◆ IntDetPatchArgument()

INTSTATUS IntDetPatchArgument ( void const *  Detour,
DWORD  Index,
QWORD  Value 
)

Modifies the value of a detour argument.

Parameters
[in]DetourThe detour for which to modify the value of an argument.
[in]IndexThe index of the argument.
[in]ValueThe value of the argument. For 32-bit guests, the upper 32-bits of the value are ignored.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_INVALID_PARAMETER_1if Detour is NULL.
INT_STATUS_INVALID_PARAMETER_2if Index is not less than the argument count of the detour.
INT_STATUS_NOT_INITIALIZEDif the Detour is not fully initialized yet.
INT_STATUS_INVALID_INTERNAL_STATEif the argument encoding is corrupted.

Definition at line 2410 of file detours.c.

Referenced by IntWinPoolHandleAlloc().

◆ IntDetPatchFunction()

static INTSTATUS IntDetPatchFunction ( DETOUR Detour,
BYTE FunctionCode,
DWORD  FunctionSize 
)
static

Patch the first instruction of the function with a 'JMP' to our handler.

This function over-write the first 5 bytes from the function with a rip-relative 'JMP' instruction to our handler and if the relocated code is larger than 5 bytes, the function over-writes (Detour->RelocatedCodeLength - 5) bytes with 'NOP' instructions.

Memory cloaking (see Memory cloaking) will be used to hide the pieces of code modified during this process.

Parameters
[in]DetourThe structure that describes a detour.
[in]FunctionCodeA buffer that contains the first FunctionSize bytes of detoured function.
[in]FunctionSizeThe size of the FunctionCode buffer.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 816 of file detours.c.

Referenced by IntDetSetLixHook().

◆ IntDetPermanentlyDisableDetour()

static void IntDetPermanentlyDisableDetour ( DETOUR Detour)
static

Removes a detour from the guest.

This will restore the original contents of the hooked function, will remove the detour handler, and will free any resources associated with this detour, except the detour itself. No safeness checks are done. If a guest thread is currently running inside the detour handler or returns to it the guest will be left in an unstable state.

Parameters
[in,out]DetourThe detour to be removed.

Definition at line 296 of file detours.c.

Referenced by IntDetCallCallback(), and IntDetDisableAllHooks().

◆ IntDetRelocate()

static INTSTATUS IntDetRelocate ( DETOUR Detour,
BYTE FunctionCode,
DWORD  FunctionSize,
DWORD InstrCount 
)
static

Relocate the over-written instruction from detoured function.

This function relocate at least 5 bytes from the provided FunctionCode; the length of the relocated code may be larger only if the first instructions of the function has a length grater than 5 bytes. If the decoded instruction is rip-relative, the supported instructions are 'CALL', 'JMP', 'MOV', 'CMP' and 'JMP'; for these instruction the relative address is computed to our handler-address. If the decoded instruction is not rip-relative, every byte of it is copied to the out handler-address.

Parameters
[in]DetourThe structure that describes a detour.
[in]FunctionCodeA buffer that contains the first FunctionSize bytes of detoured function.
[in]FunctionSizeThe size of the FunctionCode buffer.
[in,out]InstrCountThe number of the relocated instructions.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_SUPPORTEDIf an instruction of the function is nut supported.

Definition at line 452 of file detours.c.

Referenced by IntDetHandleWrite(), and IntDetSetLixHook().

◆ IntDetRelocatePtrIfNeeded()

QWORD IntDetRelocatePtrIfNeeded ( QWORD  Ptr)

Returns the new value Ptr should have if it is currently pointing inside a relocated prologue.

Parameters
[in]PtrGuest virtual address to check.
Returns
The new Ptr value.

Definition at line 2048 of file detours.c.

Referenced by IntThrSafeMoveReturn(), and IntThrSafeMoveRip().

◆ IntDetRemoveBranch()

static void IntDetRemoveBranch ( DETOUR Detour)
static

Restores the original instructions of a hooked function.

This will restore the bytes we replaced with the jump to our detour handler. It does not remove the detour handler itself, but the handler will no longer be executed by the guest (unless a guest thread is currently executing it). It does nothing if the detour does not have a memory cloak handle for the original function.

Parameters
[in,out]DetourThe detour for which to restore the original function. After this function returns, the FunctionCloakHandle will be set to NULL.

Definition at line 212 of file detours.c.

Referenced by IntDetPermanentlyDisableDetour(), and IntDetRemoveDetour().

◆ IntDetRemoveDetour()

static void IntDetRemoveDetour ( DETOUR Detour)
static

Removes and frees a detour.

This will restore the original contents of the hooked function, will remove the detour handler, and will free any resources associated with this detour, including the detour itself. No safeness checks are done. If a guest thread is currently running inside the detour handler or returns to it the guest will be left in an unstable state.

Parameters
[in,out]DetourThe detour to be removed. After this function returns this pointer is no longer valid.
Postcondition
Detour is NULL.

Definition at line 271 of file detours.c.

Referenced by IntDetSetHook(), IntDetSetLixHook(), and IntDetUninit().

◆ IntDetRemoveHandler()

static void IntDetRemoveHandler ( DETOUR Detour)
static

Removes a detour handler from the guest.

If a memory cloak handle exists for the detour handler, the original contents of that memory region will be restored. Any slack space allocated for this detour will also be freed. Note that the jump to the detour handler present at the beginning of the hooked function will not be removed. IntDetRemoveBranch should be called before calling this function. No safeness checks are done. If a guest thread is currently running inside the detour handler or returns to it the guest will be left in an unstable state.

Parameters
[in,out]DetourThe detour for which the handler is removed. After this function returns, the fields HandlerCloakHandle and HandlerAddress will be set to NULL.

Definition at line 238 of file detours.c.

Referenced by IntDetRemoveDetour().

◆ IntDetSendIntegrityAlert()

static INTSTATUS IntDetSendIntegrityAlert ( char *  FunctionName,
QWORD  FunctionAddress,
QWORD  DetourAddress 
)
static

Sends an integrity alert if the provieded function is already hooked.

Parameters
[in]FunctionNameThe name of the hooked function.
[in]FunctionAddressThe guest virtual address of the function.
[in]DetourAddressThe guest virtual address to which the function is detoured.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 876 of file detours.c.

Referenced by IntDetSetHook(), and IntDetSetLixHook().

◆ IntDetSetHook()

INTSTATUS IntDetSetHook ( QWORD  FunctionAddress,
QWORD  ModuleBase,
API_HOOK_DESCRIPTOR Descriptor,
API_HOOK_HANDLER Handler 
)

Will inject code inside the guest.

This function will inject a piece of code (the detour handler) inside the guest virtual address space. This can be used to hook a function, but it is not mandatory for this to be a classic function hook. When hooking a function, it will replace at least the first 5 bytes from FunctionAddress with a jump to the hook handler. At least 5 bytes are replaced because that is the size of the injected jump, but more bytes may be replaced if the instructions over-written inside the guest have a larger total length. The original instructions will be relocated after the detour handler and will be followed by a jump back to the remaining function body. If the original instructions are RIP-relative the function will fail.

In order to find a place for the detour handler inside the module in which the hook function resides, the slack.c functionality is used. If no specific API is hooked, the detour will be placed inside the core guest kernel module.

Memory cloaking (see Memory cloaking) will be used to hide the pieces of code modified and injected during this process.

Errors encountered for Descriptors that have the NotCritical field set to False are treated as fatal errors and introcore will be stopped.

If a pre- or post-hook callback exists in the Descriptor it is called. The pre-hook callback is called before the hook is written inside the guest. If it returns INT_STATUS_NOT_NEEDED_HINT, the hook is no longer set, even if it is a critical hook and this is not treated as an error. If an error is returned, the hook will no longer be set, but if the hook is critical this will be treated as an error to set the hook. The post-hook callback return value is ignored.

A detour successfully set can be found in the gDetours list of detours.

Parameters
[in]FunctionAddressThe guest virtual address of the function to be hooked. Can be 0, in which case no function will be hooked, but the detour will still be injected inside the guest.
[in]ModuleBaseThe guest virtual address of the module in which the detour should be placed. If a function is hooked this should be the module that owns that function. If 0 the kernel module will be used.
[in]DescriptorPointer to a structure that describes the hook and the detour handler.
[in]HandlerThe descriptor of the detour handler to be injected inside the guest.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_INVALID_PARAMETER_3if Descriptor is NULL or if its tag is not less than detTagMax.
INT_STATUS_BUFFER_OVERFLOWif the function hooked is inside the Windows kernel, but its address points outside the kernel buffer.
INT_STATUS_NOT_SUPPORTEDif the function is already hooked. This is detected by checking if the function starts with a 0xE9 (a JMP instruction). This means that we already hooked this function, and hooking it again is an error, or a driver inside the guest hooked it, in which case the kernel can not be trusted and it may be already compromised. The same status value is returned if the total size of the handler (including the relocated instructions) is larger than DETOUR_MAX_HANDLER_SIZE.
INT_STATUS_INSUFFICIENT_RESOURCESif not enough memory is available.

Definition at line 1061 of file detours.c.

Referenced by IntLixPatchSwapgs(), and IntWinApiHook().

◆ IntDetSetLixHook()

INTSTATUS IntDetSetLixHook ( QWORD  FunctionAddress,
const LIX_FN_DETOUR FnDetour,
BOOLEAN MultipleInstructions 
)

Detours a function from guest.

The detours content are injected in guest by the 'init' agent (see IntLixGuestAllocateDeploy). Each detour has one structure of type LIX_GUEST_DETOUR assigned; LIX_GUEST_DETOUR structures is ordered by the DETOUR_ID enum.

The function fetches the LIX_GUEST_DETOUR structure (index-based) and fill the FunctionAddress field with the original function address plus the length of the relocated code.

The EnableFlags is used by each detour (in guest) to check if the hypercall is enabled.

The over-written code from original function is relocated by calling the IntDetRelocate function and the 'JMP' instruction that detours the function is set calling the IntDetPatchFunction function.

Parameters
[in]FunctionAddressThe guest virtual address of the function to be hooked
[in]FnDetourPointer to a structure that describes the hook.
[out]MultipleInstructionsOn success, true if multiple instruction is over-written, otherwise false.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETER_1If FunctionAddress is invalid.
INT_STATUS_INVALID_PARAMETER_2If FnDetour is invalid.

Definition at line 942 of file detours.c.

Referenced by IntLixApiHook().

◆ IntDetSetReturnValue()

INTSTATUS IntDetSetReturnValue ( DETOUR const *  Detour,
IG_ARCH_REGS Registers,
QWORD  ReturnValue 
)

Sets the return value for a hooked guest function.

This allows introcore to set a specific return value for a hooked guest function. Note that the in-guest handler must be aware of this and must be able to properly handle this, usually by returning early from the hooked guest function.

Parameters
[in]DetourThe detour for which the return value is changed.
[in,out]RegistersThe register state to be used. If NULL, the current register state from the current VCPU will be used.
[in]ReturnValueThe return value. If the detour hypercall type is hypercallTypeInt3 this will be set in the RAX register. If the hypercall type is hypercallTypeVmcall this will be set in the RSI register. Other hypercall types are not supported. For 32-bit guests, the upper 32-bits of the return value are ignored.
Return values
INT_STATUS_SUCCESSin case of success.
INT_STATUS_NOT_SUPPORTEDif the hypercall type is not hypercallTypeInt3 or hypercallTypeVmcall.

Definition at line 1528 of file detours.c.

Referenced by IntLixAccessRemoteVmHandler(), IntLixCrashHandle(), IntLixTaskHandleExec(), IntLixTaskHandlePtrace(), IntLixTaskHandleVmRw(), IntWinProcHandleCopyMemory(), IntWinProcHandleInstrument(), IntWinThrHandleQueueApc(), and IntWinThrHandleThreadHijack().

◆ IntDetUninit()

void IntDetUninit ( void  )

Uninitializes the detour module.

Will iterate over the global detour list in gDetours and will call IntDetRemoveDetour for each detour. After this function returns, gDetours will be completely reset and no active detours will be remaining. No safeness checks are done. If a guest thread is currently running inside a detour handler or returns to it the guest will be left in an unstable state.

Definition at line 1868 of file detours.c.

Referenced by IntGuestUninit().

Variable Documentation

◆ gDetours

DETOURS_STATE gDetours
static
Initial value:
=
{
}
static DETOURS_STATE gDetours
The global detour state.
Definition: detours.c:40
LIST_HEAD DetoursList
List of detours. Each entry is a DETOUR structure.
Definition: detours.c:31
#define LIST_HEAD_INIT(Name)
Definition: introlists.h:39

The global detour state.

Definition at line 40 of file detours.c.