47 for (
DWORD i = 0; i < Patterns->PatternsCount; ++i)
107 DWORD functionRva = 0;
108 QWORD functionRip = 0;
109 QWORD moduleBase = 0;
112 if (NULL == HookDescriptor)
117 if (0 ==
wstrcasecmp(u
"ntoskrnl.exe", HookDescriptor->ModuleName))
126 ERROR(
"[ERROR] IntDriverFindByName failed for %s: 0x%x\n",
131 moduleBase = pDriver->
BaseVa;
134 if (HookDescriptor->Exported)
152 if (NULL == HookDescriptor->Patterns)
154 TRACE(
"[INFO] No patterns given for %s, we won't hook\n", HookDescriptor->FunctionName);
168 WARNING(
"[WARNING] Failed to find '%s', will try again, ignoring section hint\n",
169 HookDescriptor->FunctionName);
179 ERROR(
"[ERROR] Function '%s' not found inside module '%s': 0x%08x\n",
180 HookDescriptor->FunctionName,
utf16_for_log(HookDescriptor->ModuleName), status);
186 HookDescriptor->Arguments.Argc = pArgs->
Argc;
187 memcpy(HookDescriptor->Arguments.Argv, pArgs->
Argv,
sizeof(HookDescriptor->Arguments.Argv[0]) * HookDescriptor->Arguments.Argc);
190 functionRip = functionRva + moduleBase;
192 TRACE(
"[DETOUR] Found function '%s' @ 0x%016llx inside module '%s'\n",
193 HookDescriptor->FunctionName, functionRip,
utf16_for_log(HookDescriptor->ModuleName));
198 for (i = 0; i < HookDescriptor->HandlersCount; i++)
200 pHandler = &HookDescriptor->Handlers[i];
210 if (NULL != pHandler)
212 status =
IntDetSetHook(functionRip, moduleBase, HookDescriptor, pHandler);
215 ERROR(
"[ERROR] IntDetSetHook failed: 0x%08x\n", status);
220 ERROR(
"[DETOUR] Valid handler not found for %s!\n", HookDescriptor->FunctionName);
254 TRACE(
"[DETOUR] Establishing API hooks...\n");
259 for (
size_t i = 0; i < count; i++)
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);
271 if (!pDescrs[i].NotCritical)
273 ERROR(
"[ERROR] Failed to hook Critical API %s, will search the others and abort!\n",
274 pDescrs[i].FunctionName);
280 WARNING(
"[WARNING] Failed to hook non Critical API %s, will ignore\n", pDescrs[i].FunctionName);
284 if (NULL != pDescrs[i].Patterns)
308 TRACE(
"[DETOUR] Done establishing API hooks!\n");
339 for (
size_t i = 0; i < count; i++)
350 TRACE(
"[DETOUR] Disabling detour on function '%s' according to new options: %llx!\n",
357 TRACE(
"[DETOUR] Enabling detour on function '%s' according to new options: %llx!\n",
413 #define MIN_CODE_LEN 24 414 BYTE newcode[64], oldcode[64];
425 ERROR(
"[ERROR] IntIdtGetEntry failed: 0x%08x\n", status);
426 goto cleanup_and_exit;
429 LOG(
"[VECORE] Original #VE handler at %llx...\n", vehnd);
435 ERROR(
"[ERROR] IntDecDecodeInstruction failed: 0x%08x\n", status);
436 goto cleanup_and_exit;
446 if (ix.Instruction == ND_INS_PUSH && ix.Operands[0].Type == ND_OP_IMM && ix.Operands[0].Info.Immediate.Imm == 0x14)
448 for (iidx = 0; iidx < 4; iidx++)
455 ERROR(
"[ERROR] IntDecDecodeInstruction failed: 0x%08x\n", status);
456 goto cleanup_and_exit;
459 if (ix.Instruction == ND_INS_JMPNR)
461 vehnd = vehnd + ix.Length + ix.Operands[0].Info.RelativeOffset.Rel;
462 LOG(
"[VECORE] KiIsrThunkShadow identified, the handler is at 0x%016llx\n", vehnd);
469 ERROR(
"[ERROR] JMP to the main ISR handler not found!\n");
471 goto cleanup_and_exit;
483 LOG(
"[VECORE] KPTI enabled, %llx is the shadow handler, searching for the original handler...\n", vehnd);
491 ERROR(
"[ERROR] IntDecDecodeInstruction failed: 0x%08x\n", status);
492 goto cleanup_and_exit;
495 if ((ix.Instruction == ND_INS_MOV_CR) && ND_IS_OP_REG(&ix.Operands[0], ND_REG_CR, 8, NDR_CR3))
500 if ((ix.Instruction == ND_INS_JMPNR) && (bMovcr3))
502 vehnd = vehnd + i + ix.Length + ix.Operands[0].Info.RelativeOffset.Rel;
510 LOG(
"[VECORE] Found the real #VE handler at %llx...\n", vehnd);
512 LOG(
"[VECORE] The new #VE handler will be at %llx...\n", NewHandler);
518 ERROR(
"[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
519 goto cleanup_and_exit;
528 ndstat = NdDecodeEx(&instrux, oldcode + codelen,
sizeof(oldcode) - codelen, ND_CODE_64, ND_DATA_64);
529 if (!ND_SUCCESS(ndstat))
531 ERROR(
"[ERROR] NdDecodeEx failed: 0x%08x\n", ndstat);
535 codelen += instrux.Length;
546 newcode[iidx++] = 0xE8;
547 newcode[iidx++] = 0x03;
548 newcode[iidx++] = 0x00;
549 newcode[iidx++] = 0x00;
550 newcode[iidx++] = 0x00;
553 newcode[iidx++] = 0x0F;
554 newcode[iidx++] = 0xAE;
555 newcode[iidx++] = 0xE8;
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;
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;
576 newcode[iidx++] = 0xC3;
579 for (
DWORD i = iidx; i < codelen; i++)
587 ERROR(
"[ERROR] IntMemClkCloakRegion failed: 0x%08x\n", status);
588 goto cleanup_and_exit;
591 if (NULL != OldHandler)
596 if (NULL != ReplacedCodeLen)
598 *ReplacedCodeLen = codelen;
601 if (NULL != ReplacedCode)
603 memcpy(ReplacedCode, oldcode, codelen);
634 if (NULL == Function)
650 for (
size_t i = 0; i < count; i++)
653 if ((crc32 == Function->NameHash) &&
657 if (0 != ArgumentsCount)
660 memcpy(pDescrs[i].Arguments.Argv, Arguments,
#define INT_STATUS_PAGE_NOT_PRESENT
Indicates that a virtual address is not present.
#define DETOUR_ENABLE_ALWAYS
Can be used as the API_HOOK_DESCRIPTOR.EnableFlags to always enable the detour.
INTSTATUS IntDetEnableDetour(DETOUR_TAG Tag)
Enables a detour based on its tag.
void IntGuestSetIntroErrorState(INTRO_ERROR_STATE State, INTRO_ERROR_CONTEXT *Context)
Updates the value of the gErrorState and the value of the gErrorStateContext.
static INTSTATUS IntWinApiHook(API_HOOK_DESCRIPTOR *HookDescriptor)
Will hook one function from a module as described by the HookDescriptor.
Windows detour descriptors.
DWORD Argc
The number of valid entries inside the Argv array.
WINDOWS_GUEST * gWinGuest
Global variable holding the state of a Windows guest.
INTSTATUS IntIdtGetEntry(DWORD CpuNumber, DWORD Entry, QWORD *Handler)
Get the handler of an interrupt from the IDT.
INTSTATUS IntPeFindKernelExport(const char *Name, QWORD *ExportGva)
Find an export inside the NT kernel image.
#define INT_STATUS_SUCCESS
DWORD MaxVersion
The maximum version of the OS for which this handler works.
A critical API function was not found inside the guest kernel.
INTSTATUS IntPeFindFunctionByPattern(QWORD ImageBase, WIN_UNEXPORTED_FUNCTION_PATTERN *Pattern, BOOLEAN IgnoreSectionHint, DWORD *Rva)
Find a function using a pattern.
Described a detour handler.
INTSTATUS IntPeFindExportByName(QWORD ImageBase, BYTE *ImageBaseBuffer, CHAR *Name, DWORD *ExportRva)
Find the export name a Rva lies in.
DWORD MinVersion
The minimum version of the OS for which this handler works.
QWORD BaseVa
The guest virtual address of the kernel module that owns this driver object.
INTSTATUS IntWinApiUpdateHookDescriptor(WIN_UNEXPORTED_FUNCTION *Function, DWORD ArgumentsCount, const DWORD *Arguments)
Update a hook descriptor with corresponding function patterns and argument list from CAMI...
#define INT_SUCCESS(Status)
A critical structure was not found inside the guest kernel.
#define INT_STATUS_NOT_NEEDED_HINT
INTSTATUS IntPeFindFunctionByPatternInBuffer(BYTE *Buffer, DWORD BufferSize, WIN_UNEXPORTED_FUNCTION_PATTERN *Pattern, BOOLEAN IgnoreSectionHint, DWORD *Rva)
Find a function using a pattern.
int INTSTATUS
The status data type.
DWORD OSVersion
Os version.
#define INT_STATUS_NOT_FOUND
const size_t gHookableApisX86Size
The number of functions to be hooked for 32-bit Windows guests.
QWORD DisableFlags
Core activation and protection flags that will cause introcore to skip this hook. ...
Will write the contents of the patched data inside the guest.
Describes a pattern for a kernel function that is not exported.
DWORD MaxVersion
The maximum OS version for which this hook should be applied.
Describes a kernel driver.
KERNEL_DRIVER * IntDriverFindByName(const void *Name)
Searches for a driver by its name.
BOOLEAN KptiActive
True if KPTI is enabled on this guest, False if it is not.
DETOUR_ARGS Arguments
Encoding of the arguments needed by introcore from the hooked function.
#define INITIAL_CRC_VALUE
#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...
DWORD Argv[DET_ARGS_MAX]
Argument encoding. See DET_ARG_REGS and DET_ARG_ON_STACK.
#define INT_STATUS_UNSUCCESSFUL
const size_t gHookableApisX64Size
The number of functions to be hooked for 64-bit Windows guests.
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
QWORD Current
The currently used options.
INTSTATUS IntDetSetHook(QWORD FunctionAddress, QWORD ModuleBase, API_HOOK_DESCRIPTOR *Descriptor, API_HOOK_HANDLER *Handler)
Will inject code inside the guest.
#define HpFreeAndNullWithTag(Add, Tag)
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.
QWORD KernelVa
The guest virtual address at which the kernel image.
Describes a function that is not exported.
DWORD MinVersion
The minimum OS version for which this hook should be applied.
INTSTATUS IntDetDisableDetour(DETOUR_TAG Tag)
Disables a detour based on its tag.
DWORD KernelBufferSize
The size of the KernelBuffer.
INTSTATUS IntWinApiHookAll(void)
Iterates through all hookable APIs and sets requested hooks.
Describes the arguments passed by a in-guest detour handler to introcore.
GUEST_STATE gGuest
The current guest state.
WIN_UNEXPORTED_FUNCTION * Patterns
Array of code patterns used to find this function.
INTSTATUS IntWinApiHookVeHandler(QWORD NewHandler, void **Cloak, QWORD *OldHandler, DWORD *ReplacedCodeLen, BYTE *ReplacedCode)
Hooks the #VE handler.
void IntWinApiUpdateHooks(void)
Iterate through all hookable APIs and enable or disable them according to the current Introcore optio...
int wstrcasecmp(const WCHAR *buf1, const WCHAR *buf2)
INTSTATUS IntKernVirtMemRead(QWORD KernelGva, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest kernel virtual memory range.
#define INT_STATUS_NO_MAPPING_STRUCTURES
Indicates that not all mapping structures of a virtual address are present.
BYTE * KernelBuffer
A buffer containing the entire kernel image.
char * utf16_for_log(const WCHAR *WString)
Converts a UTF-16 to a UTF-8 string to be used inside logging macros.
#define INT_STATUS_NOT_SUPPORTED
API_HOOK_DESCRIPTOR gHookableApisX86[]
The functions to be hooked for 32-bit Windows guests.
DWORD Crc32String(const char *String, DWORD InitialCrc)
Computes the CRC for a NULL-terminated utf-8 string.
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.
#define _Out_writes_to_(expr, expr2)
BOOLEAN DisableOnReturn
Set to True if after returning from this event handler, introcore must be unloaded.
#define INT_STATUS_INVALID_PARAMETER
API_HOOK_DESCRIPTOR gHookableApisX64[]
The functions to be hooked for 64-bit Windows guests.
#define INT_STATUS_INVALID_PARAMETER_2
INTRO_PROT_OPTIONS CoreOptions
The activation and protection options for this guest.
INTSTATUS IntDecDecodeInstruction(IG_CS_TYPE CsType, QWORD Gva, void *Instrux)
Decode an instruction from the provided guest linear address.
Describes a function to be hooked.