Bitdefender Hypervisor Memory Introspection
lixapi.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "lixapi.h"
6 #include "decoder.h"
7 #include "drivers.h"
8 #include "lixcrash.h"
9 #include "lixcred.h"
10 #include "lixmm.h"
11 #include "guests.h"
12 #include "crc32.h"
13 #include "lixksym.h"
14 
15 
22 #define __init_detour_entry(fn_name, callback, flags) \
23  { \
24  .FunctionName = #fn_name, \
25  .HijackFunctionName = NULL, \
26  .Callback = (callback), \
27  .Id = det_ ## fn_name, \
28  .EnableFlags = (flags), \
29  }
30 
31 
38 #define __init_detour_entry_regex(fn_name, regex, callback, flags) \
39  { \
40  .FunctionName = #fn_name regex, \
41  .HijackFunctionName = NULL, \
42  .Callback = callback, \
43  .Id = det_ ## fn_name, \
44  .EnableFlags = flags, \
45  }
46 
47 
48 
55 #define __init_detour_entry_hijack(fn_name, hijack_fn_name, callback, flags) \
56  { \
57  .FunctionName = #fn_name, \
58  .HijackFunctionName = #hijack_fn_name, \
59  .Callback = callback, \
60  .Id = det_ ## fn_name ## _ ## hijack_fn_name, \
61  .EnableFlags = flags, \
62  }
63 
64 
65 
70 {
80 
82 
97 
101 };
102 
103 
104 
105 static INTSTATUS
107  _In_ const LIX_FN_DETOUR *FnDetour,
108  _Out_ QWORD *Address
109  )
123 {
124  INTSTATUS status = INT_STATUS_SUCCESS;
125  INSTRUX instrux;
126  QWORD ksymStart = 0;
127  QWORD ksymEnd = 0;
128  QWORD ksymHijack = 0;
129 
130  *Address = 0;
131 
132  ksymHijack = IntKsymFindByName(FnDetour->HijackFunctionName, NULL);
133  if (!ksymHijack)
134  {
135  ERROR("[ERROR] IntLixGuestFindKsymByName failed with status: 0x%08x. (%s)\n",
136  status, FnDetour->HijackFunctionName);
137  return status;
138  }
139 
140  ksymStart = IntKsymFindByName(FnDetour->FunctionName, &ksymEnd);
141  if (!ksymStart)
142  {
143  ERROR("[ERROR] IntLixGuestFindKsymByName failed with status: 0x%08x. (%s)\n", status, FnDetour->FunctionName);
144  return status;
145  }
146 
147  while (ksymStart < ksymEnd)
148  {
149  status = IntDecDecodeInstruction(IG_CS_TYPE_64B, ksymStart, &instrux);
150  if (!INT_SUCCESS(status))
151  {
152  ERROR("[ERROR] IntDecDecodeInstruction failed with status: 0x%08x.\n", status);
153  return status;
154  }
155 
156  if (instrux.Instruction == ND_INS_CALLNR)
157  {
158  QWORD hijackRelativeAddr = ksymHijack - (ksymStart + 5);
159 
160  if (hijackRelativeAddr == instrux.Operands[0].Info.RelativeOffset.Rel)
161  {
162  *Address = ksymStart;
163 
164  return INT_STATUS_SUCCESS;
165  }
166  }
167 
168  ksymStart += instrux.Length;
169  }
170 
171  return INT_STATUS_NOT_FOUND;
172 }
173 
174 
175 static INTSTATUS
177  _In_ const LIX_FN_DETOUR *FnDetour,
178  _Out_ BOOLEAN *MustValidateThreads
179  )
194 {
195  INTSTATUS status = INT_STATUS_SUCCESS;
196  QWORD functionAddress = 0;
197 
198  if (FnDetour->HijackFunctionName == NULL)
199  {
200  functionAddress = IntKsymFindByName(FnDetour->FunctionName, NULL);
201  if (!functionAddress)
202  {
203  ERROR("[ERROR] Critical API '%s' not found! Aborting!\n", FnDetour->FunctionName);
204  return INT_STATUS_NOT_FOUND;
205  }
206 
207  TRACE("[DETOUR] Found function '%s' @ 0x%016llx\n", FnDetour->FunctionName, functionAddress);
208  }
209  else
210  {
211  status = IntLixApiHijackHook(FnDetour, &functionAddress);
212  if (!INT_SUCCESS(status))
213  {
214  ERROR("[ERROR] Critical API '%s' not found! Aborting!\n", FnDetour->FunctionName);
215  return INT_STATUS_NOT_FOUND;
216  }
217  TRACE("[DETOUR] Found hijack function '%s' inside function '%s' @ 0x%016llx\n",
218  FnDetour->HijackFunctionName, FnDetour->FunctionName, functionAddress);
219  }
220 
221  *MustValidateThreads = TRUE;
222 
223  status = IntDetSetLixHook(functionAddress, FnDetour, MustValidateThreads);
224  if (!INT_SUCCESS(status))
225  {
226  ERROR("[ERROR] Failed to detour %s: 0x%08x\n", FnDetour->FunctionName, status);
227 
228  IntDisasmGva(functionAddress, 0x20);
229 
230  return status;
231  }
232 
233  return INT_STATUS_SUCCESS;
234 }
235 
236 
237 static __forceinline BOOLEAN
239  _In_ const char *Name,
240  _In_ DWORD NameHash
241  )
250 {
251  return NameHash == Crc32String(Name, INITIAL_CRC_VALUE);
252 }
253 
254 
255 INTSTATUS
257  void
258  )
269 {
270  INTSTATUS status = INT_STATUS_SUCCESS;
271  BOOLEAN validateThreads = FALSE;
272 
273  for (DWORD i = 0; i < gLixGuest->OsSpecificFields.FunctionsCount; i++)
274  {
275  DWORD descriptorCount = 0;
276  DWORD descriptorNumber = gLixGuest->OsSpecificFields.Functions[i].HookHandler;
277 
278  for (DWORD j = 0; j < ARRAYSIZE(gLixHookHandlersx64); j++)
279  {
280  if (IntLixApiCmpFunctionNameWithHash(gLixHookHandlersx64[j].FunctionName,
282  {
283  if (descriptorCount != descriptorNumber)
284  {
285  descriptorCount++;
286  continue;
287  }
288 
289  descriptorCount++;
290 
291  BOOLEAN mustValidate = FALSE;
292  status = IntLixApiHook(&gLixHookHandlersx64[j], &mustValidate);
293  if (!INT_SUCCESS(status))
294  {
295  ERROR("[ERROR] Failed to set hook, status: 0x%x\n", status);
296  return status;
297  }
298 
299  if (mustValidate)
300  {
301  validateThreads = TRUE;
302  }
303 
304  break;
305  }
306  }
307  }
308 
309  status = IntKernVirtMemWrite(gLixGuest->MmAlloc.Detour.Data.Address, sizeof(QWORD), &gGuest.CoreOptions.Current);
310  if (!INT_SUCCESS(status))
311  {
312  ERROR("[ERROR] IntKernVirtMemWrite failed for 0x%llx with status: 0x%08x\n",
313  gLixGuest->MmAlloc.Detour.Data.Address, status);
314  return status;
315 
316  }
317 
318  TRACE("[DETOUR] Linux detours activated... \n");
319 
320  if (!validateThreads)
321  {
322  LOG("[LIXAPI] No need for validating threads!\n");
323  return INT_STATUS_SUCCESS;
324  }
325 
326  LOG("[LIXAPI] Ensuring no thread will return into our hooks!\n");
327 
329  if (!INT_SUCCESS(status))
330  {
331  ERROR("[ERROR] IntThrSafeCheckThreads failed: 0x%08x\n", status);
332  return status;
333  }
334 
335  return INT_STATUS_SUCCESS;
336 }
337 
338 
339 void
341  void
342  )
348 {
349  IntPauseVcpus();
350 
351  INTSTATUS status = INT_STATUS_SUCCESS;
352 
353  // The memory zone that contains the #LIX_HYPERCALL_PAGE is protected against write/execute
355  ProtectionOptions),
357  if (!INT_SUCCESS(status))
358  {
359  ERROR("[ERROR] IntKernVirtMemPatchQword failed with status: 0x%08x\n", status);
360  }
361 
362  IntResumeVcpus();
363 }
INTSTATUS IntLixTaskHandleDoExit(void *Detour)
Handles the exit() system call.
Definition: lixprocess.c:3444
#define DETOUR_ENABLE_ALWAYS
Can be used as the API_HOOK_DESCRIPTOR.EnableFlags to always enable the detour.
Definition: detours.h:425
LIX_OPAQUE_FIELDS OsSpecificFields
OS-dependent and specific information.
Definition: lixguest.h:576
INTSTATUS IntLixTaskHandleFork(void *Detour)
Handles the fork() system call performed by a linux process.
Definition: lixprocess.c:3142
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
INTSTATUS IntLixVmaAdjust(void *Detour)
Detour handler for in-guest functions adjusting VMA ranges.
Definition: lixmm.c:2052
#define OFFSET_OF(Type, Member)
Definition: introlists.h:33
INTSTATUS IntKernVirtMemWrite(QWORD KernelGva, DWORD Length, void *Buffer)
Writes data to a guest kernel virtual memory range.
Definition: introcore.c:699
DWORD HookHandler
Used to identify the index of the LIX_FN_DETOUR the in the gLixHookHandlersx64.
Definition: lixguest.h:52
#define _In_
Definition: intro_sal.h:21
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
#define __init_detour_entry_hijack(fn_name, hijack_fn_name, callback, flags)
Create a new LIX_FN_DETOUR entry that is used for middle-function detours.
Definition: lixapi.c:55
INTSTATUS IntLixFtraceHandler(void *Detour)
Handles the incoming &#39;text_poke&#39; patches from the guest.
Definition: lixguest.c:1480
void IntLixApiUpdateHooks(void)
Update the hookable APIs according to the current Introcore options.
Definition: lixapi.c:340
__default_fn_attr void module_param_sysfs_setup(void *module)
Definition: handlers.c:161
INTSTATUS IntLixCrashPanicHandler(void *Detour)
Called if the &#39;panic&#39; or &#39;kcrash_exec&#39; handler is hit.
Definition: lixcrash.c:490
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
DWORD FunctionsCount
The number of function to be hooked.
Definition: lixguest.h:387
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
Definition: introcore.c:2355
#define ARRAYSIZE(A)
Definition: introdefs.h:101
#define INTRO_OPT_PROT_KM_LX_TEXT_READS
Enable kernel &#39;_text&#39; section read protection (Linux only).
Definition: intro_types.h:483
INTSTATUS IntLixTaskHandleVmRw(void *Detour)
Handles the process_vm_writev() system call.
Definition: lixprocess.c:3344
__default_fn_attr void text_poke(void *addr, const void *opcode, size_t len)
Definition: handlers.c:374
__default_fn_attr void change_protection(long vma, unsigned long start, unsigned long end, unsigned long newprot, int dirty_accountable, int prot_numa)
Definition: handlers.c:265
#define ERROR(fmt,...)
Definition: glue.h:62
__default_fn_attr long arch_ptrace(long child, long request)
Definition: handlers.c:211
INTSTATUS IntDriverUnloadHandler(void const *Detour)
The detour handler that will be invoked when a guest driver is unloaded.This handles driver unloading...
Definition: drivers.c:110
INTSTATUS IntLixApiHookAll(void)
Iterates through all APIs that can be hooked and sets requested hooks.
Definition: lixapi.c:256
int INTSTATUS
The status data type.
Definition: introstatus.h:24
INTSTATUS IntLixVmaRemove(void *Detour)
Detour handler for functions that unmap memory for processes.
Definition: lixmm.c:2111
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
const LIX_FN_DETOUR gLixHookHandlersx64[]
An array of the LIX_FN_DETOUR that contains all detours used by the introspection engine...
Definition: lixapi.c:69
__default_fn_attr void vma_adjust(long _vma, unsigned long _start, unsigned long _end, unsigned long _pgoff, void *_insert, void *_expand, long *_skip_call, long saved_vma, long next, long prev)
Definition: handlers.c:314
__default_fn_attr int complete_signal(int sig, void *task, enum pid_type type)
Definition: handlers.c:355
INTSTATUS IntLixJumpLabelHandler(void *Detour)
Handles the incoming read (arch_jmp_label_transform) from the guest.
Definition: lixguest.c:1496
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
Definition: introcore.c:2320
INTSTATUS IntThrSafeCheckThreads(QWORD Options)
Checks if any of the guest threads have their RIP or have any stack pointers pointing to regions of c...
__default_fn_attr void module_param_sysfs_remove(void *module)
Definition: handlers.c:169
INTSTATUS IntLixVmaInsert(void *Detour)
Detour handler for "__vma_link_rb" function.
Definition: lixmm.c:1692
__default_fn_attr void wake_up_new_task(long task)
Definition: handlers.c:177
#define LOG(fmt,...)
Definition: glue.h:61
INTSTATUS IntDriverLoadHandler(void const *Detour)
The detour handler that will be invoked when a guest loads a new driver.This handles driver loading i...
Definition: drivers.c:45
static INTSTATUS IntLixApiHook(const LIX_FN_DETOUR *FnDetour, BOOLEAN *MustValidateThreads)
Will hook one function as described by the FnDetour.
Definition: lixapi.c:176
INTSTATUS IntLixVmaChangeProtection(void *Detour)
Detour handler for "change_protection" function.
Definition: lixmm.c:1753
__default_fn_attr void expand_downwards(long vma, unsigned long address)
Definition: handlers.c:342
__default_fn_attr size_t process_vm_rw_core(int pid, void *iter, void *rvec, unsigned long riovcnt, unsigned long flags, int vm_write)
Definition: handlers.c:228
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
INTSTATUS IntLixCommitCredsHandle(void *Detour)
Detour handler for "commit_creds" function.
Definition: lixcred.c:694
INTSTATUS IntLixTaskHandleExec(void *Detour)
Handles the exec() system call of a linux process.
Definition: lixprocess.c:2927
unsigned long long QWORD
Definition: intro_types.h:53
QWORD Current
The currently used options.
Definition: guests.h:232
__default_fn_attr void __access_remote_vm(void *task, void *mm, unsigned long addr, void *buf, int len, unsigned int gup_flags)
Definition: handlers.c:407
static BOOLEAN IntLixApiCmpFunctionNameWithHash(const char *Name, DWORD NameHash)
Check if the crc32 of the Name is equal to the provided NameHash.
Definition: lixapi.c:238
#define TRUE
Definition: intro_types.h:30
__default_fn_attr void panic(const char *fmt)
Definition: handlers.c:391
INTSTATUS IntLixAccessRemoteVmHandler(void *Detour)
Detour handler for __access_remote_vm.
Definition: lixprocess.c:4967
__default_fn_attr void do_exit(long code)
Definition: handlers.c:203
#define TRACE(fmt,...)
Definition: glue.h:58
INTSTATUS IntDetSetLixHook(QWORD FunctionAddress, const LIX_FN_DETOUR *FnDetour, BOOLEAN *MultipleInstructions)
Detours a function from guest.
Definition: detours.c:874
__default_fn_attr void ftrace_write(unsigned long ip, const char *val, int size)
Definition: handlers.c:383
LIX_FUNCTION * Functions
An array of LIX_FUNCTION to be hooked.
Definition: lixguest.h:388
#define INTRO_OPT_ENABLE_UM_PROTECTION
Aggregates all the user mode protection flags.
Definition: intro_types.h:527
#define __forceinline
Definition: introtypes.h:61
uint32_t DWORD
Definition: intro_types.h:49
#define THS_CHECK_DETOURS
Will check if any RIP is inside detours.
__default_fn_attr void arch_jump_label_transform(void *entry, enum jump_label_type type)
Definition: handlers.c:399
INTSTATUS IntLixTextPokeHandler(void *Detour)
Handles the incoming &#39;text_poke&#39; patches from the guest.
Definition: lixguest.c:1462
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:48
#define INTRO_OPT_PANIC_CLEANUP
Enable memory cleanup after an OS crash (Linux).
Definition: intro_types.h:454
struct _LINUX_GUEST::@125::@128 Detour
#define INTRO_OPT_EVENT_OS_CRASH
Enable OS crash events (generates introEventCrashEvent events).
Definition: intro_types.h:431
__default_fn_attr void commit_creds(long *creds)
Definition: handlers.c:146
DWORD NameHash
Crc32 of the function name.
Definition: lixguest.h:51
INTSTATUS IntLixTaskHandlePtrace(void *Detour)
Handles the ptrace() system call.
Definition: lixprocess.c:3386
INTSTATUS IntKernVirtMemPatchQword(QWORD GuestVirtualAddress, QWORD Data)
Writes 8 bytes in the guest kernel memory.
Definition: introcore.c:932
#define __init_detour_entry_regex(fn_name, regex, callback, flags)
Create a new LIX_FN_DETOUR entry that appends the provided &#39;regex&#39; to the end of the &#39;FunctioName&#39;...
Definition: lixapi.c:38
INTSTATUS IntLixCrashHandle(void *Detour)
Sends an event that contains the information about signal received by the current task...
Definition: lixcrash.c:298
DWORD Crc32String(const char *String, DWORD InitialCrc)
Computes the CRC for a NULL-terminated utf-8 string.
Definition: crc32.c:200
64-bit selector.
Definition: glueiface.h:188
__default_fn_attr void vma_rb_erase(long vma, void *root)
Definition: handlers.c:328
__default_fn_attr void __vma_link_rb(void *mm, void *vma, void **rb_link, void *rb_parent)
Definition: handlers.c:241
void IntDisasmGva(QWORD Gva, DWORD Length)
This function disassembles a code buffer (given its GVA) and then dumps the instructions (textual dis...
Definition: dumper.c:385
__default_fn_attr int flush_old_exec(long binprm)
Definition: handlers.c:185
QWORD IntKsymFindByName(const char *Name, QWORD *SymEnd)
Searches the given Name in kallsyms and returns the Start & End offset.
Definition: lixksym.c:1361
INTSTATUS IntLixVmaExpandDownwards(void *Detour)
Detour handler for "expand_downwards" function.
Definition: lixmm.c:1906
#define __init_detour_entry(fn_name, callback, flags)
Create a new LIX_FN_DETOUR entry.
Definition: lixapi.c:22
static INTSTATUS IntLixApiHijackHook(const LIX_FN_DETOUR *FnDetour, QWORD *Address)
Fetch the address of the hijack function name provided by the LIX_FN_DETOUR.
Definition: lixapi.c:106
struct _LINUX_GUEST::@125 MmAlloc
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
Definition: guests.h:267
INTSTATUS IntDecDecodeInstruction(IG_CS_TYPE CsType, QWORD Gva, void *Instrux)
Decode an instruction from the provided guest linear address.
Definition: decoder.c:180
LINUX_GUEST * gLixGuest
Global variable holding the state of a Linux guest.
Definition: lixguest.c:29
#define FALSE
Definition: intro_types.h:34
Describes a Linux-function to be hooked.
Definition: detours.h:412