Bitdefender Hypervisor Memory Introspection
detours.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #ifndef _DETOURS_H_
6 #define _DETOURS_H_
7 
21 
27 
28 #include "thread_safeness.h"
29 #include "handlers.h"
30 
32 
39 #define DET_ARG_REGS(Arg) (gGuest.Guest64 ? ((DWORD)(Arg) < 16) : ((DWORD)(Arg) < 8))
40 
49 #define DET_ARG_STACK(Index) (((DWORD)(Index) << 16) | 0xFFFF)
50 
57 #define DET_ARG_ON_STACK(Arg) (((Arg) & 0xFFFF) == 0xFFFF)
58 
66 #define DET_ARG_STACK_OFFSET(Arg) (((Arg) >> 16) * gGuest.WordSize)
67 
69 #define DET_ARGS_MAX 8
70 
72 #define DET_ARGS_DEFAULT_LIX {.Argc = DET_ARGS_MAX, .Argv = {NDR_RDI, NDR_RSI, NDR_RDX, NDR_RCX, \
73  NDR_R8, NDR_R9, DET_ARG_STACK(1), DET_ARG_STACK(2)}}
74 
80 #define DET_ARGS_DEFAULT_WIN64 {.Argc = DET_ARGS_MAX, .Argv = {NDR_RCX, NDR_RDX, NDR_R8, NDR_R9, \
81  DET_ARG_STACK(5), DET_ARG_STACK(6), DET_ARG_STACK(7), DET_ARG_STACK(8)}}
82 
86 #define DET_ARGS_DEFAULT_WIN86 {.Argc = DET_ARGS_MAX, \
87  .Argv = {DET_ARG_STACK(1), DET_ARG_STACK(2), DET_ARG_STACK(3), DET_ARG_STACK(4),\
88  DET_ARG_STACK(5), DET_ARG_STACK(6), DET_ARG_STACK(7), DET_ARG_STACK(8)}}
89 
108 typedef struct _DETOUR_ARGS
109 {
112 } DETOUR_ARGS;
113 
119 typedef enum
120 {
160 
170 
174 
177 
179 } DETOUR_TAG;
180 
184 typedef enum
185 {
193 
194 #define DETOUR_MAX_HANDLER_SIZE 512
195 #define DETOUR_MAX_HANDLERS 8
196 
213  _In_ void *Detour
214  );
215 
233  _In_ QWORD FunctionAddress,
234  _In_ void *Handler,
235  _In_ void *Descriptor
236  );
237 
251  _In_ void *Handler
252  );
253 
255 #define PUBLIC_DATA_MAX_NAME_SIZE 16
256 #define PUBLIC_DATA_MAX_DESCRIPTORS 5
258 
264 typedef struct _API_HOOK_PUBLIC_DATA
265 {
273 
274 // Handler code. If the NtBuildNumber is zero, the handler can be used for Windows guests with any NtBuildNumber.
275 // If the NtBuildNumber is NOT zero, the handler can be used only for Windows guests that have the exact same
276 // NtBuildNumber. For this reason, the generic handler must be placed the last one: we could have a special handler
277 // for Windows with NtBuildNumber 10000 for example, and a generic handler that works for all other Windows
278 // guests.
279 
283 typedef struct _API_HOOK_HANDLER
284 {
311 
314 #define DETOUR_MIN_VERSION_ANY 0
315 #define DETOUR_MAX_VERSION_ANY 0xFFFFFFFF
318 
321 #define DETOUR_INVALID_HYPERCALL 0xFF
322 
324 
329 typedef struct _API_HOOK_DESCRIPTOR
330 {
352 
390 
391 
407 typedef INTSTATUS
409  _In_ void *Detour
410  );
411 
412 
416 typedef struct _LIX_FN_DETOUR
417 {
419  char *FunctionName;
420  char *HijackFunctionName;
424 } LIX_FN_DETOUR;
425 
426 
427 
429 #define DETOUR_ENABLE_ALWAYS 0xFFFFFFFFFFFFFFFF
430 
436 typedef struct _DETOUR
437 {
442 
445 
452 
461 
464 
467 
478 
483 
492 
499 
501  PAPI_HOOK_DESCRIPTOR Descriptor;
503 } DETOUR, *PDETOUR;
504 
505 
506 INTSTATUS
508  _In_ QWORD FunctionAddress,
509  _In_ QWORD ModuleBase,
510  _Inout_ API_HOOK_DESCRIPTOR *Descriptor,
511  _Inout_ API_HOOK_HANDLER *Handler
512  );
513 
514 INTSTATUS
516  _In_ QWORD FunctionAddress,
517  _In_ const LIX_FN_DETOUR *FnDetour,
518  _Out_ BOOLEAN *MultipleInstructions
519  );
520 
521 INTSTATUS
523  _In_ DETOUR const *Detour,
524  _Inout_opt_ IG_ARCH_REGS *Registers,
525  _In_ QWORD ReturnValue
526  );
527 
528 INTSTATUS
530  void
531  );
532 
533 INTSTATUS
535  _In_ DETOUR_TAG Tag
536  );
537 
538 INTSTATUS
540  _In_ DETOUR_TAG Tag
541  );
542 
543 void
545  void
546  );
547 
548 void
550  void
551  );
552 
553 void
555  void
556  );
557 
558 BOOLEAN
560  _In_ QWORD Ptr,
561  _In_ THS_PTR_TYPE Type,
562  _Out_opt_ DETOUR_TAG *Tag
563  );
564 
565 BOOLEAN
567  _In_ QWORD Ptr,
568  _Out_opt_ DETOUR_TAG *Tag
569  );
570 
571 QWORD
573  _In_ QWORD Ptr
574  );
575 
576 INTSTATUS
578  _In_ QWORD Ptr,
579  _Out_ QWORD *Address,
580  _Out_ DWORD *Size,
581  _Out_ DETOUR_TAG *Tag
582  );
583 
584 INTSTATUS
586  _In_ DETOUR_TAG Tag,
587  _Out_ QWORD *Address,
588  _Out_opt_ DWORD *Size
589  );
590 
591 INTSTATUS
593  _In_ void const *Detour,
594  _In_ DWORD Index,
595  _In_opt_ BYTE const *StackBuffer,
596  _In_ DWORD StackBufferSize,
597  _Out_ QWORD *Value
598  );
599 
600 INTSTATUS
602  _In_ void const *Detour,
603  _In_ DWORD Argc,
604  _Out_writes_(Argc) QWORD *Argv
605  );
606 
607 INTSTATUS
609  _In_ void const *Detour,
610  _In_ DWORD Index,
611  _In_ QWORD Value
612  );
613 
614 INTSTATUS
616  _In_ DETOUR_TAG Tag,
617  _In_ void const *Data,
618  _In_ DWORD DataSize,
619  _In_ char const *PublicDataName
620  );
621 
622 INTSTATUS
624  _In_ DETOUR_TAG Tag,
625  _Out_ QWORD *FunctionAddress
626  );
627 
628 #endif // _DETOURS_H_
uint16_t * PWCHAR
Definition: intro_types.h:63
QWORD LixGuestDetour
The address of the linux-detour header.
Definition: detours.h:463
BOOLEAN IntDetIsPtrInRelocatedCode(QWORD Ptr, DETOUR_TAG *Tag)
Checks if a guest pointer is inside the modified prologue of a function.
Definition: detours.c:1942
#define _In_opt_
Definition: intro_sal.h:16
PWCHAR ModuleName
NULL-terminated string of the kernel module in which the function is found.
Definition: detours.h:332
#define _Out_
Definition: intro_sal.h:22
_Bool BOOLEAN
Definition: intro_types.h:58
QWORD HandlerAddress
The guest virtual address of the detour handler.
Definition: detours.h:454
INTSTATUS IntDetEnableDetour(DETOUR_TAG Tag)
Enables a detour based on its tag.
Definition: detours.c:361
DWORD HandlersCount
The number of valid entries inside the Handlers array.
Definition: detours.h:381
QWORD EnableFlags
Core activation and protection flags that must be set in order to set and activate this hook...
Definition: detours.h:373
BYTE NrPublicDataOffsets
The number of valid entries inside the PublicDataOffsets array.
Definition: detours.h:480
DWORD Argc
The number of valid entries inside the Argv array.
Definition: detours.h:110
struct _API_HOOK_HANDLER * PAPI_HOOK_HANDLER
uint8_t BYTE
Definition: intro_types.h:47
BYTE HypercallOffset
The offset inside the handler at which the hypercall instruction is placed.
Definition: detours.h:303
#define _In_
Definition: intro_sal.h:21
DWORD MaxVersion
The maximum version of the OS for which this handler works.
Definition: detours.h:292
INTSTATUS(* PFUNC_PostDetourCallback)(void *Handler)
The type of a callback invoked after a detour is set.
Definition: detours.h:250
Described a detour handler.
Definition: detours.h:283
QWORD HitCount
The number of times this detour issued a hypercall.
Definition: detours.h:498
Describes a detour set inside the guest memory.
Definition: detours.h:436
DWORD MinVersion
The minimum version of the OS for which this handler works.
Definition: detours.h:288
void IntDetUninit(void)
Uninitializes the detour module.
Definition: detours.c:1868
INTSTATUS IntDetSetReturnValue(DETOUR const *Detour, IG_ARCH_REGS *Registers, QWORD ReturnValue)
Sets the return value for a hooked guest function.
Definition: detours.c:1528
QWORD HypercallAddress
The guest virtual address at which the hypercall is placed.
Definition: detours.h:449
struct _DETOUR_ARGS DETOUR_ARGS
Describes the arguments passed by a in-guest detour handler to introcore.
struct _API_HOOK_PUBLIC_DATA API_HOOK_PUBLIC_DATA
Public data which allows for external modification to a in-guest hook handler.
int INTSTATUS
The status data type.
Definition: introstatus.h:24
struct _DETOUR DETOUR
Describes a detour set inside the guest memory.
QWORD EnableFlags
These are checked against the current options from gGuest.
Definition: detours.h:423
DWORD CodeLength
The size of the handler. Must not be larger than DETOUR_MAX_HANDLER_SIZE.
Definition: detours.h:294
#define DETOUR_MAX_HANDLERS
The maximum number of handlers a detour can have.
Definition: detours.h:195
QWORD DisableFlags
Core activation and protection flags that will cause introcore to skip this hook. ...
Definition: detours.h:367
#define _Out_writes_(expr)
Definition: intro_sal.h:28
The detour will use a INT3 instruction in order to notify introcore about an event.
Definition: detours.h:189
PFUNC_DetourCallback Callback
Callback to be invoked when the detour issues a hypercall. May be NULL.
Definition: detours.h:441
DWORD MaxVersion
The maximum OS version for which this hook should be applied.
Definition: detours.h:345
PFUNC_DetourCallback Callback
Callback to be invoked when the detour issues a hypercall. May be NULL.
Definition: detours.h:347
void * FunctionCloakHandle
The memory cloak handle used to hide the modified function start. See Memory cloaking.
Definition: detours.h:494
No hypercall. This detour does not generate events.
Definition: detours.h:187
#define _Inout_opt_
Definition: intro_sal.h:31
BYTE HypercallOffset
Offset, relative to HandlerAddress, where the hypercall instruction is found.
Definition: detours.h:472
#define _Inout_
Definition: intro_sal.h:20
DETOUR_ARGS Arguments
Encoding of the arguments needed by introcore from the hooked function.
Definition: detours.h:379
#define _Out_opt_
Definition: intro_sal.h:30
DWORD Argv[DET_ARGS_MAX]
Argument encoding. See DET_ARG_REGS and DET_ARG_ON_STACK.
Definition: detours.h:111
INTSTATUS IntDetModifyPublicData(DETOUR_TAG Tag, void const *Data, DWORD DataSize, char const *PublicDataName)
Modifies public parts of a detour handler.
Definition: detours.c:1751
INTSTATUS IntDetGetAddrAndTag(QWORD Ptr, QWORD *Address, DWORD *Size, DETOUR_TAG *Tag)
Checks if Ptr is inside a detour handler and returns the detour&#39;s handler address, size and tag.
Definition: detours.c:2074
Public data which allows for external modification to a in-guest hook handler.
Definition: detours.h:264
unsigned long long QWORD
Definition: intro_types.h:53
PAPI_HOOK_DESCRIPTOR Descriptor
The hook descriptor for which this hook was set.
Definition: detours.h:501
HYPERCALL_TYPE HypercallType
The type of the hypercall that this detour uses.
Definition: detours.h:466
void IntDetDumpDetours(void)
Prints all the detours in the gDetours list of detours.
Definition: detours.c:1895
Must always be the last one.
Definition: detours.h:178
INTSTATUS IntDetSetHook(QWORD FunctionAddress, QWORD ModuleBase, API_HOOK_DESCRIPTOR *Descriptor, API_HOOK_HANDLER *Handler)
Will inject code inside the guest.
Definition: detours.c:1061
#define DETOUR_MAX_HANDLER_SIZE
The maximum size of a in-guest detour handler.
Definition: detours.h:194
BOOLEAN IntDetIsPtrInHandler(QWORD Ptr, THS_PTR_TYPE Type, DETOUR_TAG *Tag)
Checks if a guest pointer is inside a detour handler.
Definition: detours.c:1980
INTSTATUS IntDetSetLixHook(QWORD FunctionAddress, const LIX_FN_DETOUR *FnDetour, BOOLEAN *MultipleInstructions)
Detours a function from guest.
Definition: detours.c:942
HYPERCALL_TYPE HypercallType
The type of hypercall used.
Definition: detours.h:296
char * PCHAR
Definition: intro_types.h:56
QWORD FunctionAddress
The guest virtual address of the hooked function.
Definition: detours.h:451
INTSTATUS IntDetGetArgument(void const *Detour, DWORD Index, BYTE const *StackBuffer, DWORD StackBufferSize, QWORD *Value)
Reads the specified argument for a detour.
Definition: detours.c:2237
INTSTATUS(* PFUNC_PreDetourCallback)(QWORD FunctionAddress, void *Handler, void *Descriptor)
The type of a callback invoked before setting a detour.
Definition: detours.h:232
INTSTATUS IntDetCallCallback(void)
Calls the appropriate detour handler for hypercall.
Definition: detours.c:1596
PFUNC_PostDetourCallback PostCallback
Callback to be invoked after the detour has been set. May be NULL.
Definition: detours.h:351
PFUNC_PreDetourCallback PreCallback
Callback to be invoked before the detour is written inside the guest. May be NULL.
Definition: detours.h:349
Describes a function that is not exported.
Definition: winguest.h:101
HYPERCALL_TYPE
The type of the hypercall used by a detour.
Definition: detours.h:184
DWORD HandlerSize
The size of the detour handler.
Definition: detours.h:460
INTSTATUS IntDetPatchArgument(void const *Detour, DWORD Index, QWORD Value)
Modifies the value of a detour argument.
Definition: detours.c:2410
DWORD MinVersion
The minimum OS version for which this hook should be applied.
Definition: detours.h:341
INTSTATUS IntDetDisableDetour(DETOUR_TAG Tag)
Disables a detour based on its tag.
Definition: detours.c:324
uint32_t DWORD
Definition: intro_types.h:49
INTSTATUS IntDetGetArguments(void const *Detour, DWORD Argc, QWORD *Argv)
Reads multiple arguments from a detour.
Definition: detours.c:2296
LIST_ENTRY Link
The link inside the DETOURS_STATE.DetoursList list.
Definition: detours.h:439
BYTE JumpBackOffset
Offset, relative to HandlerAddress, where the jump that returns control to the hooked function is fou...
Definition: detours.h:470
BOOLEAN Exported
True if this function is exported by the module that owns it.
Definition: detours.h:358
struct _API_HOOK_DESCRIPTOR API_HOOK_DESCRIPTOR
Describes a function to be hooked.
DETOUR_ID Id
The DETOUR_ID of the linux detour descriptor.
Definition: detours.h:418
Describes the arguments passed by a in-guest detour handler to introcore.
Definition: detours.h:108
void IntDetDisableAllHooks(void)
Removes all detours from the guest.
Definition: detours.c:1848
THS_PTR_TYPE
The type of pointer to be checked.
WIN_UNEXPORTED_FUNCTION * Patterns
Array of code patterns used to find this function.
Definition: detours.h:377
QWORD ModuleBase
The guest virtual address of the base of the kernel module that owns the hooked function.
Definition: detours.h:491
BYTE PublicDataOffset
The offset at which the data is available inside the detour handler.
Definition: detours.h:269
BYTE RelocatedCodeLength
The size of the relocated code.
Definition: detours.h:477
void * HandlerCloakHandle
The memory cloak handle used to hide the detour handler. See Memory cloaking.
Definition: detours.h:496
INTSTATUS(* PFUNC_DetourCallback)(void *Detour)
The type of a detour callback.
Definition: detours.h:212
char * FunctionName
Definition: detours.h:419
const LIX_FN_DETOUR * LixFnDetour
Definition: detours.h:502
struct _LIX_FN_DETOUR LIX_FN_DETOUR
Describes a Linux-function to be hooked.
Definition: detours.h:31
BYTE RelocatedCodeOffset
The offset inside the handler at which the original instructions were relocated.
Definition: detours.h:305
BYTE NrPublicDataOffsets
The number of valid entries inside the PublicDataOffsets array.
Definition: detours.h:309
struct _API_HOOK_DESCRIPTOR * PAPI_HOOK_DESCRIPTOR
BOOLEAN NotCritical
If True, this hook is not critical.
Definition: detours.h:362
PFUNC_LixDetourCallback Callback
Callback to be invoked when the detour issues a hypercall.
Definition: detours.h:422
QWORD IntDetRelocatePtrIfNeeded(QWORD Ptr)
Returns the new value Ptr should have if it is currently pointing inside a relocated prologue...
Definition: detours.c:2048
INTSTATUS(* PFUNC_LixDetourCallback)(void *Detour)
The type of a linux-detour callback.
Definition: detours.h:408
BYTE PublicDataSize
The size of the data.
Definition: detours.h:271
Holds register state.
Definition: glueiface.h:30
INTSTATUS IntDetGetFunctionAddressByTag(DETOUR_TAG Tag, QWORD *FunctionAddress)
Get a detour function address by its tag.
Definition: detours.c:2144
struct _DETOUR * PDETOUR
DETOUR_TAG
Unique tag used to identify a detour.
Definition: detours.h:119
BOOLEAN Disabled
True if this detour has been disabled.
Definition: detours.h:489
char CHAR
Definition: intro_types.h:56
struct _API_HOOK_PUBLIC_DATA * PAPI_HOOK_PUBLIC_DATA
INTSTATUS IntDetGetByTag(DETOUR_TAG Tag, QWORD *Address, DWORD *Size)
Get a detour handler address and size by its tag.
Definition: detours.c:2110
PCHAR FunctionName
NULL-terminated string of the function name.
Definition: detours.h:337
DETOUR_TAG Tag
Detour tag.
Definition: detours.h:354
BYTE RelocatedCodeOffset
Offset, relative to HandlerAddress, where the prologue that has been replaced by our jump at the begi...
Definition: detours.h:475
struct _API_HOOK_HANDLER API_HOOK_HANDLER
Described a detour handler.
#define DET_ARGS_MAX
The maximum number of arguments passed from the guest to introcore.
Definition: detours.h:69
Describes a function to be hooked.
Definition: detours.h:329
The detour will use a VMCALL instruction in order to notify introcore about an event.
Definition: detours.h:191
DETOUR_TAG Tag
Detour tag.
Definition: detours.h:444
#define PUBLIC_DATA_MAX_NAME_SIZE
The maximum size of the PublicDataName field inside the API_HOOK_PUBLIC_DATA structure.
Definition: detours.h:255
DETOUR_ID
Definition: handlers.h:10
Describes a Linux-function to be hooked.
Definition: detours.h:416
#define PUBLIC_DATA_MAX_DESCRIPTORS
The maximum number of entries in the PublicDataOffsets array inside the API_HOOK_HANDLER structure...
Definition: detours.h:257