45 for (
DWORD i = 0; i < Patterns->PatternsCount; ++i)
95 DWORD functionRva = 0;
96 QWORD functionRip = 0;
100 if (NULL == HookDescriptor)
105 if (0 ==
wstrcasecmp(u
"ntoskrnl.exe", HookDescriptor->ModuleName))
114 ERROR(
"[ERROR] IntDriverFindByName failed for %s: 0x%x\n",
119 moduleBase = pDriver->
BaseVa;
122 if (HookDescriptor->Exported)
140 if (NULL == HookDescriptor->Patterns)
142 TRACE(
"[INFO] No patterns given for %s, we won't hook\n", HookDescriptor->FunctionName);
155 WARNING(
"[WARNING] Failed to find '%s', will try again, ignoring section hint\n",
156 HookDescriptor->FunctionName);
165 ERROR(
"[ERROR] Function '%s' not found inside module '%s': 0x%08x\n",
166 HookDescriptor->FunctionName,
utf16_for_log(HookDescriptor->ModuleName), status);
170 functionRip = functionRva + moduleBase;
172 TRACE(
"[DETOUR] Found function '%s' @ 0x%016llx inside module '%s'\n",
173 HookDescriptor->FunctionName, functionRip,
utf16_for_log(HookDescriptor->ModuleName));
178 for (i = 0; i < HookDescriptor->HandlersCount; i++)
180 pHandler = &HookDescriptor->Handlers[i];
190 if (NULL != pHandler)
192 status =
IntDetSetHook(functionRip, moduleBase, HookDescriptor, pHandler);
195 ERROR(
"[ERROR] IntDetSetHook failed: 0x%08x\n", status);
200 ERROR(
"[DETOUR] Valid handler not found for %s!\n", HookDescriptor->FunctionName);
234 TRACE(
"[DETOUR] Establishing API hooks...\n");
239 for (
size_t i = 0; i < count; i++)
243 LOG(
"[DETOUR] API function hook on %s is not enabled for this OS: %d - %d/%d\n",
244 pDescrs[i].FunctionName, pDescrs[i].MinVersion, pDescrs[i].MaxVersion,
gGuest.
OSVersion);
251 if (!pDescrs[i].NotCritical)
253 ERROR(
"[ERROR] Failed to hook Critical API %s, will search the others and abort!\n",
254 pDescrs[i].FunctionName);
260 WARNING(
"[WARNING] Failed to hook non Critical API %s, will ignore\n", pDescrs[i].FunctionName);
264 if (NULL != pDescrs[i].Patterns)
288 TRACE(
"[DETOUR] Done establishing API hooks!\n");
319 for (
size_t i = 0; i < count; i++)
330 TRACE(
"[DETOUR] Disabling detour on function '%s' according to new options: %llx!\n",
337 TRACE(
"[DETOUR] Enabling detour on function '%s' according to new options: %llx!\n",
393 #define MIN_CODE_LEN 24 394 BYTE newcode[64], oldcode[64];
405 ERROR(
"[ERROR] IntIdtGetEntry failed: 0x%08x\n", status);
406 goto cleanup_and_exit;
409 LOG(
"[VECORE] Original #VE handler at %llx...\n", vehnd);
415 ERROR(
"[ERROR] IntDecDecodeInstruction failed: 0x%08x\n", status);
416 goto cleanup_and_exit;
426 if (ix.Instruction == ND_INS_PUSH && ix.Operands[0].Type == ND_OP_IMM && ix.Operands[0].Info.Immediate.Imm == 0x14)
428 for (iidx = 0; iidx < 4; iidx++)
435 ERROR(
"[ERROR] IntDecDecodeInstruction failed: 0x%08x\n", status);
436 goto cleanup_and_exit;
439 if (ix.Instruction == ND_INS_JMPNR)
441 vehnd = vehnd + ix.Length + ix.Operands[0].Info.RelativeOffset.Rel;
442 LOG(
"[VECORE] KiIsrThunkShadow identified, the handler is at 0x%016llx\n", vehnd);
449 ERROR(
"[ERROR] JMP to the main ISR handler not found!\n");
451 goto cleanup_and_exit;
463 LOG(
"[VECORE] KPTI enabled, %llx is the shadow handler, searching for the original handler...\n", vehnd);
471 ERROR(
"[ERROR] IntDecDecodeInstruction failed: 0x%08x\n", status);
472 goto cleanup_and_exit;
475 if ((ix.Instruction == ND_INS_MOV_CR) && ND_IS_OP_REG(&ix.Operands[0], ND_REG_CR, 8, NDR_CR3))
480 if ((ix.Instruction == ND_INS_JMPNR) && (bMovcr3))
482 vehnd = vehnd + i + ix.Length + ix.Operands[0].Info.RelativeOffset.Rel;
490 LOG(
"[VECORE] Found the real #VE handler at %llx...\n", vehnd);
492 LOG(
"[VECORE] The new #VE handler will be at %llx...\n", NewHandler);
498 ERROR(
"[ERROR] IntKernVirtMemRead failed: 0x%08x\n", status);
499 goto cleanup_and_exit;
508 ndstat = NdDecodeEx(&instrux, oldcode + codelen,
sizeof(oldcode) - codelen, ND_CODE_64, ND_DATA_64);
509 if (!ND_SUCCESS(ndstat))
511 ERROR(
"[ERROR] NdDecodeEx failed: 0x%08x\n", ndstat);
515 codelen += instrux.Length;
526 newcode[iidx++] = 0xE8;
527 newcode[iidx++] = 0x03;
528 newcode[iidx++] = 0x00;
529 newcode[iidx++] = 0x00;
530 newcode[iidx++] = 0x00;
533 newcode[iidx++] = 0x0F;
534 newcode[iidx++] = 0xAE;
535 newcode[iidx++] = 0xE8;
538 newcode[iidx++] = 0xC7;
539 newcode[iidx++] = 0x04;
540 newcode[iidx++] = 0x24;
541 newcode[iidx++] = (NewHandler >> 0) & 0xFF;
542 newcode[iidx++] = (NewHandler >> 8) & 0xFF;
543 newcode[iidx++] = (NewHandler >> 16) & 0xFF;
544 newcode[iidx++] = (NewHandler >> 24) & 0xFF;
547 newcode[iidx++] = 0xC7;
548 newcode[iidx++] = 0x44;
549 newcode[iidx++] = 0x24;
550 newcode[iidx++] = 0x04;
551 newcode[iidx++] = (NewHandler >> 32) & 0xFF;
552 newcode[iidx++] = (NewHandler >> 40) & 0xFF;
553 newcode[iidx++] = (NewHandler >> 48) & 0xFF;
554 newcode[iidx++] = (NewHandler >> 56) & 0xFF;
556 newcode[iidx++] = 0xC3;
559 for (
DWORD i = iidx; i < codelen; i++)
567 ERROR(
"[ERROR] IntMemClkCloakRegion failed: 0x%08x\n", status);
568 goto cleanup_and_exit;
571 if (NULL != OldHandler)
576 if (NULL != ReplacedCodeLen)
578 *ReplacedCodeLen = codelen;
581 if (NULL != ReplacedCode)
583 memcpy(ReplacedCode, oldcode, codelen);
614 if (NULL == Function)
630 for (
size_t i = 0; i < count; i++)
633 if ((crc32 == Function->NameHash) &&
637 if (0 != ArgumentsCount)
640 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.
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.
#define _Out_writes_to_(expr, expr2)
BOOLEAN DisableOnReturn
Set to True if after returning from this event handler, introcore must be unloaded.
static INTSTATUS IntWinApiFindFunctionRva(WIN_UNEXPORTED_FUNCTION *Patterns, QWORD ModuleBase, BOOLEAN IgnoreSectionHint, DWORD *FunctionRva)
Searches for a function in a module, based on the given patterns.
#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.