30 QWORD entryAddr, entrySize, byteOffs, oldValue, newValue;
45 entryAddr = Address & ~(entrySize - 1);
47 byteOffs = Address & (entrySize - 1);
53 if (instrux->Operands[0].Size > 8)
55 ERROR(
"[ERROR] Unsupported access size: %d at RIP %llx, instruction '%s'!\n",
56 instrux->Operands[0].Size, regs->
Rip, instrux->Mnemonic);
59 goto cleanup_and_exit;
62 writeSize = instrux->Operands[0].Size;
65 if (byteOffs + writeSize > entrySize)
67 ERROR(
"[ERROR] Access at %llx spills in the next entry, size %d, instruction '%s'\n",
68 Address, writeSize, instrux->Mnemonic);
71 goto cleanup_and_exit;
78 ERROR(
"[ERROR] IntGpaCacheFetchAndAdd failed at GPA 0x%016llx: 0x%08x\n", entryAddr, status);
79 goto cleanup_and_exit;
98 ERROR(
"[ERROR] IntDecEmulatePTWrite failed: 0x%08x\n", status);
101 if (instrux->Instruction == ND_INS_MOVNTI && instrux->Operands[0].Info.Memory.Base == NDR_RCX)
105 LOG(
"Dumping memory pointed by RCX:\n");
108 LOG(
"Dumping memory pointed by RDX:\n");
120 ERROR(
"[ERROR] IntDecEmulatePTWrite failed with 0x%08x, " 121 "IntDecGetWrittenValueFromInstruction failed with 0x%08x\n", status, status2);
122 goto cleanup_and_exit;
126 writeSize = writtenValue.
Size;
185 QWORD newValue, oldValue, byteOffs, bitMask, pteAddress;
188 if (NULL == WriteState)
193 if (NULL == OldValue)
198 if (NULL == NewValue)
203 pteAddress = Address & ~((
QWORD)EntrySize - 1);
229 byteOffs = Address & (EntrySize - 1);
233 ERROR(
"[ERROR] Unhandled PT write!\n");
236 goto cleanup_and_exit;
255 CHAR nd[ND_MIN_BUF_SIZE] = {0};
256 NdToText(instrux, regs->
Rip,
sizeof(nd), nd);
258 LOG(
"[PTWH] Possible duplicate write from RIP %llx (last RIP: %x), size %d, (last size: %d), " 259 "entry %llx, cur %llx, int %llx, mask %x, instr: %s\n",
260 regs->
Rip, WriteState->LastWriteRip, size, WriteState->LastWriteSize, Address,
261 WriteState->CurEntry, WriteState->IntEntry, WriteState->WrittenMask, nd);
264 goto cleanup_and_exit;
268 WriteState->LastWriteSize = (size == 8) ? 1 : 0;
271 byteMask = ((1UL << size) - 1) << byteOffs;
276 if (0 == WriteState->WrittenMask)
278 WriteState->CurEntry = oldValue;
282 WriteState->WrittenMask |= byteMask;
285 WriteState->IntEntry = (WriteState->IntEntry & ~bitMask) | ((newValue << (byteOffs * 8)) & bitMask);
287 if (WriteState->WrittenMask != ((1UL << EntrySize) - 1))
290 goto cleanup_and_exit;
296 *NewValue = WriteState->IntEntry;
297 *OldValue = WriteState->CurEntry;
299 WriteState->CurEntry = WriteState->IntEntry;
300 WriteState->IntEntry = 0;
302 WriteState->WrittenMask = 0;
TIMER_FRIENDLY void IntDumpArchRegs(IG_ARCH_REGS const *Registers)
This function dumps the register values in a user friendly format.
INTSTATUS IntHookPtwProcessWrite(PHOOK_PTEWS WriteState, QWORD Address, BYTE EntrySize, QWORD *OldValue, QWORD *NewValue)
Processes a page-table write, returning the old and the new page-table entry value.
IG_ARCH_REGS Regs
The current state of the guest registers.
Measures page table writes emulation.
#define INT_STATUS_SUCCESS
Measures page table writes.
#define IntEnterDebugger()
#define INT_SUCCESS(Status)
#define INT_STATUS_NOT_NEEDED_HINT
int INTSTATUS
The status data type.
BOOLEAN Partial
True if the write is partial and not the entire page table entry is modified.
INSTRUX Instruction
The current instruction, pointed by the guest RIP.
BOOLEAN Emulated
True if the access was already emulated; False if it was not emulated.
INTSTATUS IntHookPtwEmulateWrite(QWORD Address)
Emulate a write that took place on page table entry at Address.
DWORD AccessSize
The size of the memory access. Valid only for EPT exits.
Describes an operand value.
#define INT_STATUS_NOT_INITIALIZED
QWORD QwordValues[ND_MAX_REGISTER_SIZE/8]
BOOLEAN PaeEnabled
True if Physical Address Extension is enabled.
QWORD New
The new, to be written, value of the page table entry.
INTSTATUS IntGpaCacheFetchAndAdd(PGPA_CACHE Cache, QWORD Gpa, DWORD Size, PBYTE Buffer)
Fetch data from a cached entry, or add it to the cache, of not already present.
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
QWORD Old
The old, original, value of the written page table entry.
PTWRITE_CACHE PtWriteCache
The last written PT entry.
const QWORD gByteMaskToBitMask[256]
Converts a byte number to a mask having the bits in those bytes set.
void * GpaCache
The currently used GPA cache.
#define INT_STATUS_INVALID_PARAMETER_4
union _OPERAND_VALUE::@22 Value
The actual operand value.
#define INT_STATUS_INVALID_PARAMETER_5
#define LAST_WRITE_RIP_MASK
We keep only the low 32 bits from the RIP.
#define INT_STATUS_ALREADY_INITIALIZED_HINT
DWORD Size
The operand size.
INTSTATUS IntDecEmulatePTWrite(QWORD *NewValue)
Emulate a page-table write.
GUEST_STATE gGuest
The current guest state.
TIMER_FRIENDLY void IntDumpGva(QWORD Gva, DWORD Length, QWORD Cr3)
This function is a wrapper over IntDumpGvaEx (it uses RowLength = 16, ElementLength = 1...
#define INT_STATUS_PARTIAL_WRITE
#define INT_STATUS_INVALID_PARAMETER_1
#define INT_STATUS_NOT_SUPPORTED
VCPU_STATE * gVcpu
The state of the current VCPU.
INTSTATUS IntDecGetWrittenValueFromInstruction(PINSTRUX Instrux, PIG_ARCH_REGS Registers, PBYTE MemoryValue, OPERAND_VALUE *WrittenValue)
Decode a written value from a memory write instruction.
BOOLEAN Valid
True if the information in this structure is valid; False it it is not.
PTEMU_BUFFER PtEmuBuffer
The page table write emulator buffer.
void IntHookPtsDump(void)
Prints all the page table hooks.