27 #define MEMCLOACK_PAGE_MAX_COUNT 2 90 PMEMCLOAK_REGION pCloak;
92 DWORD oldPgOffs, newPgOffs, internalOffset, size;
93 QWORD oldPhysAddr, newPhysAddr;
106 oldValid = (OldEntry & 1);
107 newValid = (NewEntry & 1);
110 if ((!oldValid && !newValid) || ((oldValid && newValid && (oldPhysAddr == newPhysAddr))))
121 oldPgOffs = (
DWORD)(pCloak->
Gva & (OldPageSize - 1));
122 newPgOffs = (
DWORD)(pCloak->
Gva & (NewPageSize - 1));
136 oldPgOffs = (
DWORD)(pCloak->
Gva & (OldPageSize - 1));
137 newPgOffs = (
DWORD)(pCloak->
Gva & (NewPageSize - 1));
158 if ((internalOffset >= pCloak->
Size) || (internalOffset + size > pCloak->
Size) || (size > pCloak->
Size))
160 ERROR(
"[ERROR] Invalid state: internalOffset = %d, size = %d, total size = %d\n",
161 internalOffset, size, pCloak->
Size);
165 TRACE(
"[MEMCLOAK] Translation modification, VA = 0x%016llx, OldEntry = 0x%016llx, NewEntry = 0x%016llx, " 166 "OldSize = 0x%016llx, NewSize = 0x%016llx, OldOffs = %x, NewOffs = %x, size = %d\n",
167 VirtualAddress, OldEntry, NewEntry, OldPageSize, NewPageSize, oldPgOffs, newPgOffs, size);
169 TRACE(
"[MEMCLOAK] Will patch at GPA %llx/%llx offset %x/%x, size %d, int offset %d, [GVA1: %llx GVA2: %llx]\n",
170 oldPhysAddr, newPhysAddr, oldPgOffs, newPgOffs, size,
171 internalOffset, pCloak->
Gva, VirtualAddress);
178 ERROR(
"[ERROR] IntPhysicalMemWrite failed: 0x%08x\n", status);
188 ERROR(
"[ERROR] IntPhysicalMemWrite failed: 0x%08x\n", status);
242 PMEMCLOAK_REGION pClkReg;
243 PMEMCLOAK_PAGE pClkPage;
247 DWORD patchSize, origCodeOffset, retBufOffset, readSize;
250 DWORD startReadOffset, endReadOffset;
251 DWORD glaOffset, gpaOffset;
285 ERROR(
"[ERROR] IntDecDecodeSourceLinearAddressFromInstruction failed: 0x%08x\n", status);
291 ((regs->
Rip >= pClkReg->
Gva) && (regs->
Rip < pClkReg->
Gva + pClkReg->
Size)))
300 if ((0 == readSize) || (readSize > ND_MAX_REGISTER_SIZE))
302 CHAR instrText[ND_MIN_BUF_SIZE] = {0};
304 NdToText(instrux, regs->
Rip, ND_MIN_BUF_SIZE, instrText);
306 ERROR(
"[MEMCLOAK] [ERROR] Couldn't find the source memory operand for instruction at RIP 0x%016llx '%s'!\n",
307 regs->
Rip, instrText);
327 ERROR(
"[ERROR] IntVirtMemRead failed for GPA 0x%016llx with size %d: 0x%08x\n", gla, readSize, status);
335 else if (pb->
Gla != gla)
346 startReadOffset = gpaOffset;
347 endReadOffset = startReadOffset + readSize;
363 if (glaOffset == gpaOffset)
372 readSize = endReadOffset - startReadOffset;
392 patchSize =
MIN(endReadOffset - startReadOffset, pClkPage->
PageEndOffset - startReadOffset);
397 DWORD readInPrevPage;
401 startReadOffset = gpaOffset;
404 endReadOffset = startReadOffset + readSize;
414 retBufOffset = pClkPage->
PageStartOffset - startReadOffset + readInPrevPage;
425 CHAR text[ND_MIN_BUF_SIZE] = { 0 };
427 NdToText(instrux, regs->
Rip, ND_MIN_BUF_SIZE, text);
429 LOG(
"[MEMCLOAK] This should not happen\n");
430 LOG(
"[MEMCLOAK] [CPU %d] From RIP 0x%016llx with instruction '%s', RegSize %d, GPA 0x%016llx, " 431 "MemSize %d, access 0x%016llx/%d [0x%08x, 0x%08x) -> [0x%08x: 0x%08x, 0x%08x)\n",
432 gVcpu->
Index, regs->
Rip, text, instrux->Operands[0].Size, Gpa,
433 instrux->Operands[1].Size, gla, readSize, startReadOffset, endReadOffset,
437 origCodeOffset = retBufOffset = patchSize = 0;
447 memcpy(&pb->
Data[retBufOffset], &pClkReg->
OriginalData[origCodeOffset], patchSize);
452 TRACE(
"[MEMCLOAK] Handled the access on 0x%016llx/0x%016llx with retBufOffset = 0x%08x, " 453 "origCodeOffset = 0x%08x, patchSize = 0x%08x\n",
454 gla, Gpa, retBufOffset, origCodeOffset, patchSize);
468 _In_ PMEMCLOAK_PAGE *Context,
507 status = pClkRegion->
WriteHandler(Hook, Address, pClkRegion->
Gva, pClkRegion, Action);
510 WARNING(
"[WARNING] Memcloak write handler failed for virtual address 0x%llx. Status: 0x%08x\n",
533 if (NULL != Region->OriginalData)
538 if (NULL != Region->PatchedData)
556 _Out_ void **CloakHandle
595 PMEMCLOAK_REGION pClkReg;
599 if (NULL == CloakHandle)
625 pClkReg->
Gva = VirtualAddress;
627 pClkReg->
Size = Size;
635 goto cleanup_and_exit;
642 goto cleanup_and_exit;
646 if (NULL != OriginalData)
652 if (NULL != PatchedData)
657 for (
QWORD va = VirtualAddress; va < VirtualAddress + Size;)
662 leftToHook -= hookLen;
664 pClkPage->
Region = pClkReg;
674 ERROR(
"[ERROR] IntHookGvaSetHook failed for 0x%016llx: 0x%08x\n", va, status);
675 goto cleanup_and_exit;
683 ERROR(
"[ERROR] IntHookGvaSetHook failed for 0x%016llx: 0x%08x\n", va, status);
684 goto cleanup_and_exit;
692 ERROR(
"[ERROR] IntHookGvaSetHook failed for 0x%016llx: 0x%08x\n", va, status);
693 goto cleanup_and_exit;
710 ERROR(
"[ERROR] IntVirtMemWrite failed: 0x%08x\n", status);
711 goto cleanup_and_exit;
715 *CloakHandle = pClkReg;
725 ERROR(
"[ERROR] IntMemClkUncloakRegionInternal failed: 0x%08x\n", status2);
735 _In_ void *CloakHandle,
759 PMEMCLOAK_REGION pClk;
761 if (NULL == CloakHandle)
768 if (Offset >= pClk->
Size)
773 if (Offset + Size > pClk->
Size)
778 if (Size > pClk->
Size)
796 _In_ void *CloakHandle,
830 PMEMCLOAK_REGION pClk;
832 if (NULL == CloakHandle)
839 if (Offset >= pClk->
Size)
844 if (Offset + Size > pClk->
Size)
849 if (Size > pClk->
Size)
874 ERROR(
"[ERROR] IntVirtMemWrite failed: 0x%08x\n", status);
917 memcpy(Region->PatchedData, Region->OriginalData, Region->Size);
927 ERROR(
"[ERROR] IntKernVirtMemWrite failed: 0x%08x\n", status);
931 for (
DWORD i = 0; i < Region->PageCount; i++)
940 ERROR(
"[ERROR] IntHookGvaRemoveHook failed: 0x%08x\n", status);
949 ERROR(
"[ERROR] IntHookGvaRemoveHook failed: 0x%08x\n", status);
958 ERROR(
"[ERROR] IntHookGvaRemoveHook failed: 0x%08x\n", status);
971 _In_ void *CloakHandle,
989 if (NULL == CloakHandle)
997 ERROR(
"[ERROR] IntMemClkUncloakRegionInternal failed: 0x%08x\n", status);
1029 DWORD pageOffset, intOffset, size;
1047 ERROR(
"[ERROR] IntPhysMemRead failed: 0x%08x\n", status);
1051 list = gMemClkRegions.
Flink;
1052 while (list != &gMemClkRegions)
1065 else if ((virtPage >= pReg->
Gva) && (virtPage < pReg->Gva + pReg->
Size))
1069 intOffset = (
DWORD)(virtPage - pReg->
Gva);
1078 memcpy(&pPageContent[pageOffset], &pReg->
OriginalData[intOffset], size);
1081 *Crc32 =
Crc32ComputeFast(&pPageContent[VirtualAddress & PAGE_OFFSET], Size, 0);
1090 _In_ const void *Cloak,
1111 if (Ptr >= pReg->
Gva && Ptr < pReg->Gva + pReg->
Size)
1122 _In_ void *CloakHandle,
1143 if (NULL == CloakHandle)
1148 if (NULL == OriginalData)
1162 *Length = pClk->
Size;
1187 list = gMemClkRegions.
Flink;
1188 while (list != &gMemClkRegions)
1193 ERROR(
"[ERROR] There should be no memcloaks remaining... Got one on %llx, %llx, %d!\n",
1209 ERROR(
"[ERROR] IntMemClkUncloakRegionInternal failed: 0x%08x\n", status);
1227 LOG(
"No cloack regions!\n");
1234 LOG(
"Region @ [0x%016llx, 0x%016llx) with Cr3 = 0x%016llx. Page count: %d. Options: 0x%08x\n",
1237 LOG(
"Original data:\n");
1239 LOG(
"Patched data:\n");
1244 PMEMCLOAK_PAGE pClkPage = &pClkReg->
Pages[i];
1246 NLOG(
"\t\tData offset: 0x%08x Start: 0x%08x End: 0x%08x\n",
DWORD Options
A combination of MEMCLOAK_OPTIONS values.
#define INT_STATUS_PAGE_NOT_PRESENT
Indicates that a virtual address is not present.
#define CONTAINING_RECORD(List, Type, Member)
MEMCLOAK_PAGE Pages[MEMCLOACK_PAGE_MAX_COUNT]
Array of pages contained in this region.
INTSTATUS IntPhysicalMemRead(QWORD PhysicalAddress, DWORD Length, void *Buffer, DWORD *RetLength)
Reads data from a guest physical memory range, but only for a single page.
DWORD PageStartOffset
Offset at which the data starts in this page.
INTSTATUS IntKernVirtMemWrite(QWORD KernelGva, DWORD Length, void *Buffer)
Writes data to a guest kernel virtual memory range.
IG_ARCH_REGS Regs
The current state of the guest registers.
DWORD Index
The VCPU number.
#define CLEAN_PHYS_ADDRESS64(x)
QWORD SystemCr3
The Cr3 used to map the kernel.
#define INT_STATUS_SUCCESS
void * ReadHook
The read hook handle.
#define PAGE_REMAINING(addr)
INTSTATUS(* PFUNC_IntMemCloakWriteHandle)(void *Hook, QWORD Address, QWORD RegionVirtualAddress, void *CloakHandle, INTRO_ACTION *Action)
The type of custom write handlers that can be used by cloak regions.
INTSTATUS IntMemClkModifyPatchedData(void *CloakHandle, DWORD Offset, DWORD Size, const void *Data)
Modifies the patched data inside the guest memory.
#define IntEnterDebugger()
struct _LIST_ENTRY * Flink
#define INT_SUCCESS(Status)
static BOOLEAN IsListEmpty(const LIST_ENTRY *ListHead)
INTSTATUS IntResumeVcpus(void)
Resumes the VCPUs previously paused with IntPauseVcpus.
INTSTATUS IntVirtMemWrite(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer)
Writes data to a guest virtual memory range.
DWORD PageEndOffset
Offset at which the data ends in this page.
struct _MEMCLOAK_REGION * PMEMCLOAK_REGION
BOOLEAN IntMemClkIsPtrInCloak(const void *Cloak, QWORD Ptr)
Checks if a guest virtual address is located inside a cloak region.
#define INT_STATUS_NOT_NEEDED_HINT
static INTSTATUS IntMemClkHandleRead(MEMCLOAK_PAGE *Context, PHOOK_GPA Hook, QWORD Gpa, INTRO_ACTION *Action)
Handles reads from a hidden memory region.
LIST_ENTRY Link
Entry inside the gMemClkRegions linked list.
QWORD Gla
The guest linear address for which the buffer is filled.
#define HpAllocWithTag(Len, Tag)
int INTSTATUS
The status data type.
INTSTATUS IntMemClkUnInit(void)
Uninits the memory cloak subsystem.
void * SwapHook
The swap handle.
INTSTATUS IntPhysicalMemWrite(QWORD PhysicalAddress, DWORD Length, void *Buffer)
Writes data to a guest physical memory range, but only for a single page.
static INTSTATUS IntMemClkHandleWrite(PMEMCLOAK_PAGE *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
Handles writes done inside a hidden memory region.
BOOLEAN Valid
True if Data is valid, False if it is not.
INTSTATUS IntPauseVcpus(void)
Pauses all the guest VCPUs.
INSTRUX Instruction
The current instruction, pointed by the guest RIP.
PBYTE OriginalData
A buffer containing the original data.
Will write the contents of the patched data inside the guest.
INTSTATUS IntHookGvaSetHook(QWORD Cr3, QWORD Gva, DWORD Length, BYTE Type, void *Callback, void *Context, void *ParentHook, DWORD Flags, HOOK_GVA **GvaHook)
Set a read, write, execute or swap hook on a guest virtual address.
DWORD AccessSize
The size of the memory access. Valid only for EPT exits.
#define HOOK_FLG_HIGH_PRIORITY
If flag is set, the callback associated to this hook will have a higher priority than the others...
Allows the code inside the region to modify the region.
BYTE HookType
The type of the hook structure (see _HOOK_TYPE)
struct _MEMCLOAK_PAGE MEMCLOAK_PAGE
A structure that describes a hidden guest memory page.
DWORD Size
The size of the hidden region. OriginalData and PatchedData have this size.
DWORD DataOffset
Offset inside the data buffer.
QWORD Cr3
The Cr3 in which the hidden region is mapped.
static INTSTATUS IntMemClkUncloakRegionInternal(DWORD Options, PMEMCLOAK_REGION Region)
Removes a cloak region, making the original memory contents available again to the guest...
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
INTSTATUS IntMemClkGetOriginalData(void *CloakHandle, BYTE **OriginalData, DWORD *Length)
Returns the original data of a cloaked region.
void * ParentHook
The parent hook. For a GPA hook, for example, a GVA hook or a PagedHook will be the parent hook...
HOOK_HEADER Header
The hook header.
#define INT_STATUS_INVALID_PARAMETER_4
void IntMemClkCleanup(MEMCLOAK_REGION *Region)
Frees any resources held by a MEMCLOAK_REGION.
INTSTATUS IntMemClkModifyOriginalData(void *CloakHandle, DWORD Offset, DWORD Size, void *Data)
Modifies the internal copy of the original data buffer held by a cloak region.
DWORD PageCount
The number of valid entries in the Pages array.
TIMER_FRIENDLY void IntDumpBuffer(const void *Buffer, QWORD Gva, DWORD Length, DWORD RowLength, DWORD ElementLength, BOOLEAN LogHeader, BOOLEAN DumpAscii)
This function dumps a given buffer in a user friendly format.
#define HpFreeAndNullWithTag(Add, Tag)
struct _MEMCLOAK_PAGE * PMEMCLOAK_PAGE
struct _MEMCLOAK_REGION MEMCLOAK_REGION
A structure that describes a hidden guest memory region.
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 Gva
The guest virtual address at which the hidden region starts.
Contains information about the patch buffer.
A structure that describes a hidden guest memory region.
PFUNC_IntMemCloakWriteHandle WriteHandler
The write handler used for this region.
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
#define MEMCLOACK_PAGE_MAX_COUNT
The maximum number of pages that can be contained in a MEMCLOAK_REGION.
INTSTATUS IntHookGvaRemoveHook(HOOK_GVA **Hook, DWORD Flags)
Remove a GVA hook.
static INTSTATUS IntMemClkHandleSwap(MEMCLOAK_PAGE *Context, QWORD VirtualAddress, QWORD OldEntry, QWORD NewEntry, QWORD OldPageSize, QWORD NewPageSize)
Handles swap-in and swap-outs performed on hidden memory regions.
void IntMemClkDump(void)
Dumps all the active cloak regions.
enum _INTRO_ACTION INTRO_ACTION
Event actions.
No access type. This can be used for swap hooks.
#define IntDbgEnterDebugger()
MM Mm
Guest memory information, such as paging mode, system Cr3 value, etc.
INTSTATUS IntDecDecodeSourceLinearAddressFromInstruction(PINSTRUX Instrux, PIG_ARCH_REGS Registers, QWORD *LinearAddress)
Decode the source memory linear address.
PATCH_BUFFER PatchBuffer
The patch buffer used to emulate reads.
GUEST_STATE gGuest
The current guest state.
INTSTATUS IntVirtMemRead(QWORD Gva, DWORD Length, QWORD Cr3, void *Buffer, DWORD *RetLength)
Reads data from a guest virtual memory range.
void * WriteHook
The write hook handle.
DWORD Crc32ComputeFast(const void *Buffer, size_t Size, DWORD InitialCrc)
#define INT_STATUS_NO_MAPPING_STRUCTURES
Indicates that not all mapping structures of a virtual address are present.
#define LIST_HEAD_INIT(Name)
PBYTE PatchedData
A buffer containing the data patched by introcore.
DWORD Size
The valid size of the Data buffer.
#define INT_STATUS_INVALID_PARAMETER_8
#define INT_STATUS_INVALID_PARAMETER_1
#define INT_STATUS_NOT_SUPPORTED
INTSTATUS IntMemClkUncloakRegion(void *CloakHandle, DWORD Options)
Removes a cloak region, making the original memory contents available again to the guest...
VCPU_STATE * gVcpu
The state of the current VCPU.
#define INT_STATUS_FORCE_ACTION_ON_BETA
void * Region
The parent MEMCLOAK_REGION region.
BYTE Data[ND_MAX_REGISTER_SIZE]
The actual contents of the buffer.
#define INT_STATUS_INVALID_PARAMETER_2
A structure that describes a hidden guest memory page.
INTSTATUS IntMemClkHashRegion(QWORD VirtualAddress, QWORD PhysicalAddress, DWORD Size, DWORD *Crc32)
Hashes the contents of a cloaked memory page.
static LIST_HEAD gMemClkRegions
A list containing all the memory regions that are currently hidden from the guest.
#define INT_STATUS_INSUFFICIENT_RESOURCES
#define INT_STATUS_INVALID_PARAMETER_3