Bitdefender Hypervisor Memory Introspection
winapi.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "winapi.h"
6 #include "decoder.h"
7 #include "drivers.h"
8 #include "guests.h"
9 #include "introcpu.h"
10 #include "memcloak.h"
11 #include "winhkhnd.h"
12 #include "winpe.h"
13 #include "crc32.h"
14 
15 
16 static INTSTATUS
18  _In_ WIN_UNEXPORTED_FUNCTION *Patterns,
19  _In_ QWORD ModuleBase,
20  _In_ BOOLEAN IgnoreSectionHint,
21  _Out_ DWORD *FunctionRva,
22  _Out_opt_ DETOUR_ARGS **Arguments
23  )
44 {
46 
47  for (DWORD i = 0; i < Patterns->PatternsCount; ++i)
48  {
49  WIN_UNEXPORTED_FUNCTION_PATTERN *pPattern = &Patterns->Patterns[i];
50 
51  if (ModuleBase == gGuest.KernelVa)
52  {
55  pPattern,
56  IgnoreSectionHint,
57  FunctionRva);
58  }
59  else
60  {
61  status = IntPeFindFunctionByPattern(ModuleBase,
62  pPattern,
63  IgnoreSectionHint,
64  FunctionRva);
65  }
66 
67  if (INT_SUCCESS(status) && Arguments != NULL)
68  {
69  if (pPattern->Arguments.Argc != 0)
70  {
71  *Arguments = &pPattern->Arguments;
72  }
73  else
74  {
75  *Arguments = NULL;
76  }
77 
78  break;
79  }
80  }
81 
82  return status;
83 }
84 
85 
86 static INTSTATUS
88  _In_ API_HOOK_DESCRIPTOR *HookDescriptor
89  )
103 {
105  PAPI_HOOK_HANDLER pHandler = NULL;
106  DETOUR_ARGS *pArgs = NULL;
107  DWORD functionRva = 0;
108  QWORD functionRip = 0;
109  QWORD moduleBase = 0;
110  DWORD i = 0;
111 
112  if (NULL == HookDescriptor)
113  {
115  }
116 
117  if (0 == wstrcasecmp(u"ntoskrnl.exe", HookDescriptor->ModuleName))
118  {
119  moduleBase = gGuest.KernelVa;
120  }
121  else
122  {
123  KERNEL_DRIVER *pDriver = IntDriverFindByName(HookDescriptor->ModuleName);
124  if (NULL == pDriver)
125  {
126  ERROR("[ERROR] IntDriverFindByName failed for %s: 0x%x\n",
127  utf16_for_log(HookDescriptor->ModuleName), status);
128  return status;
129  }
130 
131  moduleBase = pDriver->BaseVa;
132  }
133 
134  if (HookDescriptor->Exported)
135  {
136  // Function exported, parse the exports and get the RVA.
137  if (moduleBase == gGuest.KernelVa)
138  {
139  QWORD functionGva;
140 
141  status = IntPeFindKernelExport(HookDescriptor->FunctionName, &functionGva);
142 
143  functionRva = (DWORD)(functionGva - gGuest.KernelVa);
144  }
145  else
146  {
147  status = IntPeFindExportByName(moduleBase, NULL, HookDescriptor->FunctionName, &functionRva);
148  }
149  }
150  else
151  {
152  if (NULL == HookDescriptor->Patterns)
153  {
154  TRACE("[INFO] No patterns given for %s, we won't hook\n", HookDescriptor->FunctionName);
156  }
157 
158  status = IntWinApiFindFunctionRva(HookDescriptor->Patterns,
159  moduleBase,
160  FALSE,
161  &functionRva,
162  &pArgs);
163 
164  // If we failed to find any pattern for the given routine, retry the search ignoring
165  // OS version or section hint restrictions.
166  if (!INT_SUCCESS(status))
167  {
168  WARNING("[WARNING] Failed to find '%s', will try again, ignoring section hint\n",
169  HookDescriptor->FunctionName);
170  status = IntWinApiFindFunctionRva(HookDescriptor->Patterns,
171  moduleBase,
172  TRUE,
173  &functionRva,
174  &pArgs);
175  }
176  }
177  if (!INT_SUCCESS(status))
178  {
179  ERROR("[ERROR] Function '%s' not found inside module '%s': 0x%08x\n",
180  HookDescriptor->FunctionName, utf16_for_log(HookDescriptor->ModuleName), status);
181  return status;
182  }
183 
184  if (pArgs != NULL)
185  {
186  HookDescriptor->Arguments.Argc = pArgs->Argc;
187  memcpy(HookDescriptor->Arguments.Argv, pArgs->Argv, sizeof(HookDescriptor->Arguments.Argv[0]) * HookDescriptor->Arguments.Argc);
188  }
189 
190  functionRip = functionRva + moduleBase;
191 
192  TRACE("[DETOUR] Found function '%s' @ 0x%016llx inside module '%s'\n",
193  HookDescriptor->FunctionName, functionRip, utf16_for_log(HookDescriptor->ModuleName));
194 
195  // Find a proper handler for this function.
196  pHandler = NULL;
197 
198  for (i = 0; i < HookDescriptor->HandlersCount; i++)
199  {
200  pHandler = &HookDescriptor->Handlers[i];
201 
202  if ((gGuest.OSVersion >= pHandler->MinVersion) && (gGuest.OSVersion <= pHandler->MaxVersion))
203  {
204  break;
205  }
206 
207  pHandler = NULL;
208  }
209 
210  if (NULL != pHandler)
211  {
212  status = IntDetSetHook(functionRip, moduleBase, HookDescriptor, pHandler);
213  if (!INT_SUCCESS(status))
214  {
215  ERROR("[ERROR] IntDetSetHook failed: 0x%08x\n", status);
216  }
217  }
218  else
219  {
220  ERROR("[DETOUR] Valid handler not found for %s!\n", HookDescriptor->FunctionName);
221  status = INT_STATUS_NOT_FOUND;
222  }
223 
224  return status;
225 }
226 
227 
228 INTSTATUS
230  void
231  )
237 {
238  INTSTATUS status = INT_STATUS_SUCCESS, failStatus;
239  API_HOOK_DESCRIPTOR *pDescrs = NULL;
240  size_t count = 0;
241  BOOLEAN shouldFail;
242 
243  if (gGuest.Guest64)
244  {
245  pDescrs = gHookableApisX64;
246  count = gHookableApisX64Size;
247  }
248  else
249  {
250  pDescrs = gHookableApisX86;
251  count = gHookableApisX86Size;
252  }
253 
254  TRACE("[DETOUR] Establishing API hooks...\n");
255 
256  shouldFail = FALSE;
257  failStatus = INT_STATUS_NOT_FOUND;
258 
259  for (size_t i = 0; i < count; i++)
260  {
261  if ((gGuest.OSVersion < pDescrs[i].MinVersion) || (gGuest.OSVersion > pDescrs[i].MaxVersion))
262  {
263  LOG("[DETOUR] API function hook on %s is not enabled for this OS: %d - %d/%d\n",
264  pDescrs[i].FunctionName, pDescrs[i].MinVersion, pDescrs[i].MaxVersion, gGuest.OSVersion);
265  continue;
266  }
267 
268  status = IntWinApiHook(&pDescrs[i]);
269  if (!INT_SUCCESS(status))
270  {
271  if (!pDescrs[i].NotCritical)
272  {
273  ERROR("[ERROR] Failed to hook Critical API %s, will search the others and abort!\n",
274  pDescrs[i].FunctionName);
275  shouldFail = TRUE;
276  failStatus = status;
277  }
278  else
279  {
280  WARNING("[WARNING] Failed to hook non Critical API %s, will ignore\n", pDescrs[i].FunctionName);
281  }
282  }
283 
284  if (NULL != pDescrs[i].Patterns)
285  {
286  HpFreeAndNullWithTag(&pDescrs[i].Patterns, IC_TAG_CAMI);
287  }
288  }
289 
290  if (shouldFail)
291  {
292  if ((failStatus == INT_STATUS_PAGE_NOT_PRESENT) || (failStatus == INT_STATUS_NO_MAPPING_STRUCTURES))
293  {
294  // This allows us to retry initialization.
296  }
297  else
298  {
299  // No way we can init, we didn't find all the functions.
301 
303  }
304 
305  return failStatus;
306  }
307 
308  TRACE("[DETOUR] Done establishing API hooks!\n");
309 
311 
312  return INT_STATUS_SUCCESS;
313 }
314 
315 
316 void
318  void
319  )
324 {
325  const API_HOOK_DESCRIPTOR *pDescrs = NULL;
326  size_t count = 0;
327 
328  if (gGuest.Guest64)
329  {
330  pDescrs = gHookableApisX64;
331  count = gHookableApisX64Size;
332  }
333  else
334  {
335  pDescrs = gHookableApisX86;
336  count = gHookableApisX86Size;
337  }
338 
339  for (size_t i = 0; i < count; i++)
340  {
341  // Most of the detours can't be disabled, ever, because we'd lose quite a bit of the guest's state.
342  if (pDescrs[i].EnableFlags == DETOUR_ENABLE_ALWAYS)
343  {
344  continue;
345  }
346 
347  if ((0 == (pDescrs[i].EnableFlags & gGuest.CoreOptions.Current)) ||
348  (0 != (pDescrs[i].DisableFlags & gGuest.CoreOptions.Current)))
349  {
350  TRACE("[DETOUR] Disabling detour on function '%s' according to new options: %llx!\n",
351  pDescrs[i].FunctionName, gGuest.CoreOptions.Current);
352 
353  IntDetDisableDetour(pDescrs[i].Tag);
354  }
355  else
356  {
357  TRACE("[DETOUR] Enabling detour on function '%s' according to new options: %llx!\n",
358  pDescrs[i].FunctionName, gGuest.CoreOptions.Current);
359 
360  IntDetEnableDetour(pDescrs[i].Tag);
361  }
362  }
363 }
364 
365 
366 INTSTATUS
368  _In_ QWORD NewHandler,
369  _Out_ void **Cloak,
370  _Out_opt_ QWORD *OldHandler,
371  _Out_opt_ DWORD *ReplacedCodeLen,
372  _Out_writes_to_(38, *ReplacedCodeLen) BYTE *ReplacedCode
373  )
406 {
407  INTSTATUS status;
408  QWORD vehnd;
409  DWORD codelen, iidx;
410  INSTRUX ix;
411 
413 #define MIN_CODE_LEN 24
414  BYTE newcode[64], oldcode[64];
415 
416  vehnd = 0;
417 
418  // Note: interrupt 20 should not be called in any way, so it's safe to hook it like this, without employing
419  // thread safeness and without using single instructions.
420 
421  // Get the INT 20 entry.
422  status = IntIdtGetEntry(IG_CURRENT_VCPU, 20, &vehnd);
423  if (!INT_SUCCESS(status))
424  {
425  ERROR("[ERROR] IntIdtGetEntry failed: 0x%08x\n", status);
426  goto cleanup_and_exit;
427  }
428 
429  LOG("[VECORE] Original #VE handler at %llx...\n", vehnd);
430 
431  // Special handling for older Windows versions, where the #VE handler was considered an unexpected exception.
432  status = IntDecDecodeInstruction(IG_CS_TYPE_64B, vehnd, &ix);
433  if (!INT_SUCCESS(status))
434  {
435  ERROR("[ERROR] IntDecDecodeInstruction failed: 0x%08x\n", status);
436  goto cleanup_and_exit;
437  }
438 
439  // If the first instruction of the IDT handler is a "PUSH 0x14", this means we have an older Windows version on
440  // out hand, a version which is not aware of the VirtualizationException.
441  // These versions are: 7, 8, 8.1, TH1, TH2, RS1 and RS2
442  // On these, there are 2 cases:
443  // KPTI on - "PUSH 0x14/JMP KiIsrThunkShadow"
444  // KPTI off - "PUSH 0x14/PUSH rbp/JMP KiUnexpectedInterrupt"
445  // We search the JMP, which directs us to the effective handler.
446  if (ix.Instruction == ND_INS_PUSH && ix.Operands[0].Type == ND_OP_IMM && ix.Operands[0].Info.Immediate.Imm == 0x14)
447  {
448  for (iidx = 0; iidx < 4; iidx++)
449  {
450  vehnd += ix.Length;
451 
452  status = IntDecDecodeInstruction(IG_CS_TYPE_64B, vehnd, &ix);
453  if (!INT_SUCCESS(status))
454  {
455  ERROR("[ERROR] IntDecDecodeInstruction failed: 0x%08x\n", status);
456  goto cleanup_and_exit;
457  }
458 
459  if (ix.Instruction == ND_INS_JMPNR)
460  {
461  vehnd = vehnd + ix.Length + ix.Operands[0].Info.RelativeOffset.Rel;
462  LOG("[VECORE] KiIsrThunkShadow identified, the handler is at 0x%016llx\n", vehnd);
463  break;
464  }
465  }
466 
467  if (iidx == 4)
468  {
469  ERROR("[ERROR] JMP to the main ISR handler not found!\n");
470  status = INT_STATUS_NOT_FOUND;
471  goto cleanup_and_exit;
472  }
473 
474  iidx = 0;
475  }
476 
477  // If this is with KPTI, search for the real handler, as the IDT entry points to the shadow.
478  if (gGuest.KptiActive)
479  {
480  DWORD i = 0;
481  BOOLEAN bMovcr3 = FALSE;
482 
483  LOG("[VECORE] KPTI enabled, %llx is the shadow handler, searching for the original handler...\n", vehnd);
484 
485  while (i < 128)
486  {
487  // We only work on 64 bit.
488  status = IntDecDecodeInstruction(IG_CS_TYPE_64B, vehnd + i, &ix);
489  if (!INT_SUCCESS(status))
490  {
491  ERROR("[ERROR] IntDecDecodeInstruction failed: 0x%08x\n", status);
492  goto cleanup_and_exit;
493  }
494 
495  if ((ix.Instruction == ND_INS_MOV_CR) && ND_IS_OP_REG(&ix.Operands[0], ND_REG_CR, 8, NDR_CR3))
496  {
497  bMovcr3 = TRUE;
498  }
499 
500  if ((ix.Instruction == ND_INS_JMPNR) && (bMovcr3))
501  {
502  vehnd = vehnd + i + ix.Length + ix.Operands[0].Info.RelativeOffset.Rel;
503  break;
504  }
505 
506  i += ix.Length;
507  }
508  }
509 
510  LOG("[VECORE] Found the real #VE handler at %llx...\n", vehnd);
511 
512  LOG("[VECORE] The new #VE handler will be at %llx...\n", NewHandler);
513 
514  // Read the old code.
515  status = IntKernVirtMemRead(vehnd, sizeof(oldcode), oldcode, NULL);
516  if (!INT_SUCCESS(status))
517  {
518  ERROR("[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
519  goto cleanup_and_exit;
520  }
521 
522  codelen = 0;
523  while (codelen < MIN_CODE_LEN)
524  {
525  INSTRUX instrux;
526  NDSTATUS ndstat;
527 
528  ndstat = NdDecodeEx(&instrux, oldcode + codelen, sizeof(oldcode) - codelen, ND_CODE_64, ND_DATA_64);
529  if (!ND_SUCCESS(ndstat))
530  {
531  ERROR("[ERROR] NdDecodeEx failed: 0x%08x\n", ndstat);
533  }
534 
535  codelen += instrux.Length;
536  }
537 
538  // Hook the original #VE handler and make it point to our handler.
539  // The sequence is: PUSH 2 byte chunks from the new VE handler, than ret to it.
540  iidx = 0;
541 
542  // IMPORTANT: In order to mitigate RSB Spectre, we will first do a relative CALL, in order to make sure the RET
543  // misprediction goes to some code controlled by us. This is basically a retpoline of sorts.
544 
545  // CALL $+4
546  newcode[iidx++] = 0xE8;
547  newcode[iidx++] = 0x03;
548  newcode[iidx++] = 0x00;
549  newcode[iidx++] = 0x00;
550  newcode[iidx++] = 0x00;
551 
552  // LFENCE
553  newcode[iidx++] = 0x0F;
554  newcode[iidx++] = 0xAE;
555  newcode[iidx++] = 0xE8;
556 
557  // MOV dword [rsp], NewHandle low
558  newcode[iidx++] = 0xC7;
559  newcode[iidx++] = 0x04;
560  newcode[iidx++] = 0x24;
561  newcode[iidx++] = (NewHandler >> 0) & 0xFF;
562  newcode[iidx++] = (NewHandler >> 8) & 0xFF;
563  newcode[iidx++] = (NewHandler >> 16) & 0xFF;
564  newcode[iidx++] = (NewHandler >> 24) & 0xFF;
565 
566  // MOV dword [rsp + 4], NewHandle high
567  newcode[iidx++] = 0xC7;
568  newcode[iidx++] = 0x44;
569  newcode[iidx++] = 0x24;
570  newcode[iidx++] = 0x04;
571  newcode[iidx++] = (NewHandler >> 32) & 0xFF;
572  newcode[iidx++] = (NewHandler >> 40) & 0xFF;
573  newcode[iidx++] = (NewHandler >> 48) & 0xFF;
574  newcode[iidx++] = (NewHandler >> 56) & 0xFF;
575 
576  newcode[iidx++] = 0xC3;
577 
578  // Fill in the gap with NOPs.
579  for (DWORD i = iidx; i < codelen; i++)
580  {
581  newcode[i] = 0x90;
582  }
583 
584  status = IntMemClkCloakRegion(vehnd, 0, codelen, MEMCLOAK_OPT_APPLY_PATCH, oldcode, newcode, NULL, Cloak);
585  if (!INT_SUCCESS(status))
586  {
587  ERROR("[ERROR] IntMemClkCloakRegion failed: 0x%08x\n", status);
588  goto cleanup_and_exit;
589  }
590 
591  if (NULL != OldHandler)
592  {
593  *OldHandler = vehnd;
594  }
595 
596  if (NULL != ReplacedCodeLen)
597  {
598  *ReplacedCodeLen = codelen;
599  }
600 
601  if (NULL != ReplacedCode)
602  {
603  memcpy(ReplacedCode, oldcode, codelen);
604  }
605 
606  status = INT_STATUS_SUCCESS;
607 
608 cleanup_and_exit:
609 
610  return status;
611 }
612 
613 
614 INTSTATUS
616  _In_ WIN_UNEXPORTED_FUNCTION *Function,
617  _In_ DWORD ArgumentsCount,
618  _In_ const DWORD *Arguments
619  )
630 {
631  API_HOOK_DESCRIPTOR *pDescrs;
632  size_t count;
633 
634  if (NULL == Function)
635  {
637  }
638 
639  if (gGuest.Guest64)
640  {
641  pDescrs = gHookableApisX64;
642  count = gHookableApisX64Size;
643  }
644  else
645  {
646  pDescrs = gHookableApisX86;
647  count = gHookableApisX86Size;
648  }
649 
650  for (size_t i = 0; i < count; i++)
651  {
652  DWORD crc32 = Crc32String(pDescrs[i].FunctionName, INITIAL_CRC_VALUE);
653  if ((crc32 == Function->NameHash) &&
654  (gGuest.OSVersion >= pDescrs[i].MinVersion) && (gGuest.OSVersion <= pDescrs[i].MaxVersion))
655  {
656  pDescrs[i].Patterns = Function;
657  if (0 != ArgumentsCount) // If no arguments are given, leave the default ones.
658  {
659  pDescrs[i].Arguments.Argc = MIN(ArgumentsCount, ARRAYSIZE(pDescrs[i].Arguments.Argv));
660  memcpy(pDescrs[i].Arguments.Argv, Arguments,
661  sizeof(pDescrs[i].Arguments.Argv[0]) * pDescrs[i].Arguments.Argc);
662  }
663 
664  return INT_STATUS_SUCCESS;
665  }
666  }
667 
668  return INT_STATUS_NOT_FOUND;
669 }
670 
#define INT_STATUS_PAGE_NOT_PRESENT
Indicates that a virtual address is not present.
Definition: introstatus.h:438
#define DETOUR_ENABLE_ALWAYS
Can be used as the API_HOOK_DESCRIPTOR.EnableFlags to always enable the detour.
Definition: detours.h:429
#define _Out_
Definition: intro_sal.h:22
_Bool BOOLEAN
Definition: intro_types.h:58
INTSTATUS IntDetEnableDetour(DETOUR_TAG Tag)
Enables a detour based on its tag.
Definition: detours.c:361
void IntGuestSetIntroErrorState(INTRO_ERROR_STATE State, INTRO_ERROR_CONTEXT *Context)
Updates the value of the gErrorState and the value of the gErrorStateContext.
Definition: guests.c:90
#define IC_TAG_CAMI
Live update allocations.
Definition: memtags.h:124
static INTSTATUS IntWinApiHook(API_HOOK_DESCRIPTOR *HookDescriptor)
Will hook one function from a module as described by the HookDescriptor.
Definition: winapi.c:87
Windows detour descriptors.
DWORD Argc
The number of valid entries inside the Argv array.
Definition: detours.h:110
uint8_t BYTE
Definition: intro_types.h:47
WINDOWS_GUEST * gWinGuest
Global variable holding the state of a Windows guest.
Definition: winguest.c:37
INTSTATUS IntIdtGetEntry(DWORD CpuNumber, DWORD Entry, QWORD *Handler)
Get the handler of an interrupt from the IDT.
Definition: introcpu.c:145
#define _In_
Definition: intro_sal.h:21
INTSTATUS IntPeFindKernelExport(const char *Name, QWORD *ExportGva)
Find an export inside the NT kernel image.
Definition: winpe.c:1748
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
DWORD MaxVersion
The maximum version of the OS for which this handler works.
Definition: detours.h:292
A critical API function was not found inside the guest kernel.
Definition: intro_types.h:2439
INTSTATUS IntPeFindFunctionByPattern(QWORD ImageBase, WIN_UNEXPORTED_FUNCTION_PATTERN *Pattern, BOOLEAN IgnoreSectionHint, DWORD *Rva)
Find a function using a pattern.
Definition: winpe.c:3150
Described a detour handler.
Definition: detours.h:283
INTSTATUS IntPeFindExportByName(QWORD ImageBase, BYTE *ImageBaseBuffer, CHAR *Name, DWORD *ExportRva)
Find the export name a Rva lies in.
Definition: winpe.c:1783
DWORD MinVersion
The minimum version of the OS for which this handler works.
Definition: detours.h:288
QWORD BaseVa
The guest virtual address of the kernel module that owns this driver object.
Definition: drivers.h:41
INTSTATUS IntWinApiUpdateHookDescriptor(WIN_UNEXPORTED_FUNCTION *Function, DWORD ArgumentsCount, const DWORD *Arguments)
Update a hook descriptor with corresponding function patterns and argument list from CAMI...
Definition: winapi.c:615
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
A critical structure was not found inside the guest kernel.
Definition: intro_types.h:2441
#define ARRAYSIZE(A)
Definition: introdefs.h:101
#define INT_STATUS_NOT_NEEDED_HINT
Definition: introstatus.h:317
#define ERROR(fmt,...)
Definition: glue.h:62
INTSTATUS IntPeFindFunctionByPatternInBuffer(BYTE *Buffer, DWORD BufferSize, WIN_UNEXPORTED_FUNCTION_PATTERN *Pattern, BOOLEAN IgnoreSectionHint, DWORD *Rva)
Find a function using a pattern.
Definition: winpe.c:3044
int INTSTATUS
The status data type.
Definition: introstatus.h:24
DWORD OSVersion
Os version.
Definition: guests.h:281
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
const size_t gHookableApisX86Size
The number of functions to be hooked for 32-bit Windows guests.
Definition: winhkhnd.c:1809
QWORD DisableFlags
Core activation and protection flags that will cause introcore to skip this hook. ...
Definition: detours.h:367
#define MIN(a, b)
Definition: introdefs.h:146
Will write the contents of the patched data inside the guest.
Definition: memcloak.h:54
Describes a pattern for a kernel function that is not exported.
Definition: winguest.h:85
DWORD MaxVersion
The maximum OS version for which this hook should be applied.
Definition: detours.h:345
#define LOG(fmt,...)
Definition: glue.h:61
Describes a kernel driver.
Definition: drivers.h:30
KERNEL_DRIVER * IntDriverFindByName(const void *Name)
Searches for a driver by its name.
Definition: drivers.c:266
BOOLEAN KptiActive
True if KPTI is enabled on this guest, False if it is not.
Definition: guests.h:291
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
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
#define IG_CURRENT_VCPU
For APIs that take a VCPU number as a parameter, this can be used to specify that the current VCPU sh...
Definition: glueiface.h:324
DWORD Argv[DET_ARGS_MAX]
Argument encoding. See DET_ARG_REGS and DET_ARG_ON_STACK.
Definition: detours.h:111
#define INT_STATUS_UNSUCCESSFUL
Definition: introstatus.h:335
const size_t gHookableApisX64Size
The number of functions to be hooked for 64-bit Windows guests.
Definition: winhkhnd.c:4992
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
Definition: guests.h:290
unsigned long long QWORD
Definition: intro_types.h:53
QWORD Current
The currently used options.
Definition: guests.h:236
#define TRUE
Definition: intro_types.h:30
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 HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
#define TRACE(fmt,...)
Definition: glue.h:58
INTSTATUS IntMemClkCloakRegion(QWORD VirtualAddress, QWORD Cr3, DWORD Size, DWORD Options, PBYTE OriginalData, PBYTE PatchedData, PFUNC_IntMemCloakWriteHandle WriteHandler, void **CloakHandle)
Hides a memory zone from the guest.
Definition: memcloak.c:548
QWORD KernelVa
The guest virtual address at which the kernel image.
Definition: guests.h:283
#define WARNING(fmt,...)
Definition: glue.h:60
Describes a function that is not exported.
Definition: winguest.h:101
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
#define MIN_CODE_LEN
uint32_t DWORD
Definition: intro_types.h:49
DWORD KernelBufferSize
The size of the KernelBuffer.
Definition: winguest.h:852
INTSTATUS IntWinApiHookAll(void)
Iterates through all hookable APIs and sets requested hooks.
Definition: winapi.c:229
Describes the arguments passed by a in-guest detour handler to introcore.
Definition: detours.h:108
GUEST_STATE gGuest
The current guest state.
Definition: guests.c:50
WIN_UNEXPORTED_FUNCTION * Patterns
Array of code patterns used to find this function.
Definition: detours.h:377
INTSTATUS IntWinApiHookVeHandler(QWORD NewHandler, void **Cloak, QWORD *OldHandler, DWORD *ReplacedCodeLen, BYTE *ReplacedCode)
Hooks the #VE handler.
Definition: winapi.c:367
void IntWinApiUpdateHooks(void)
Iterate through all hookable APIs and enable or disable them according to the current Introcore optio...
Definition: winapi.c:317
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
Definition: introcrt.c:98
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
Definition: introcore.c:674
#define INT_STATUS_NO_MAPPING_STRUCTURES
Indicates that not all mapping structures of a virtual address are present.
Definition: introstatus.h:434
BYTE * KernelBuffer
A buffer containing the entire kernel image.
Definition: winguest.h:851
char * utf16_for_log(const WCHAR *WString)
Converts a UTF-16 to a UTF-8 string to be used inside logging macros.
Definition: introcore.c:2845
#define INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
API_HOOK_DESCRIPTOR gHookableApisX86[]
The functions to be hooked for 32-bit Windows guests.
Definition: winhkhnd.c:61
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
static INTSTATUS IntWinApiFindFunctionRva(WIN_UNEXPORTED_FUNCTION *Patterns, QWORD ModuleBase, BOOLEAN IgnoreSectionHint, DWORD *FunctionRva, DETOUR_ARGS **Arguments)
Searches for a function in a module, based on the given patterns.
Definition: winapi.c:17
#define _Out_writes_to_(expr, expr2)
Definition: intro_sal.h:29
BOOLEAN DisableOnReturn
Set to True if after returning from this event handler, introcore must be unloaded.
Definition: guests.h:328
#define INT_STATUS_INVALID_PARAMETER
Definition: introstatus.h:59
API_HOOK_DESCRIPTOR gHookableApisX64[]
The functions to be hooked for 64-bit Windows guests.
Definition: winhkhnd.c:1816
#define INT_STATUS_INVALID_PARAMETER_2
Definition: introstatus.h:65
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
Definition: guests.h:271
INTSTATUS IntDecDecodeInstruction(IG_CS_TYPE CsType, QWORD Gva, void *Instrux)
Decode an instruction from the provided guest linear address.
Definition: decoder.c:180
Describes a function to be hooked.
Definition: detours.h:329
#define FALSE
Definition: intro_types.h:34