Bitdefender Hypervisor Memory Introspection
ptfilter.c File Reference

This is the main instrumentation file, which scans, identifies and instruments NT instructions that have the potential to be used as page-table writes. More...

#include "ptfilter.h"
#include "winagent.h"
#include "decoder.h"
#include "hook.h"
#include "icache.h"
#include "kernvm.h"
#include "loader.h"
#include "memcloak.h"
#include "memtables.h"
#include "winagent_ptdriver_x64.h"
#include "winapi.h"
#include "winpe.h"
#include "winpower.h"

Go to the source code of this file.

Data Structures

struct  _PTI_CANDIDATE
 

Macros

#define MAX_ENTRIES_PER_BUCKET   256
 
#define MAX_LUT_PAGES   64
 
#define MAX_HANDLER_SIZE   48ull
 
#define TABLE_BUCKET_MASK   0x3F
 
#define REG(r)   (*(&gVcpu->Regs.Rax + (r)))
 

Typedefs

typedef struct _PTI_CANDIDATE PTI_CANDIDATE
 
typedef struct _PTI_CANDIDATEPPTI_CANDIDATE
 

Functions

static void IntPtiRbTreeNodeFree (RBNODE *Node)
 Called on RB tree node free. More...
 
static int IntPtiRbTreeNodeCompareRip (RBNODE *Left, RBNODE *Right)
 RB tree node compare function. More...
 
static void IntPtiResetState (void)
 Reset the PT filter state (used after removing it from guest memory). More...
 
static void IntPtiDeleteInstruction (PPTI_CANDIDATE Candidate)
 Delete a PT candidate instruction. More...
 
static INTSTATUS IntPtiMonitorAllPtWriteCandidates (void)
 Scan the .text section of the NT image for PT candidates. More...
 
static INTSTATUS IntPtiRestoreAllPtWriteCandidates (void)
 Restore all PT candidates, by removing the INT3/INT 20 hook established on them. More...
 
static INTSTATUS IntPtiInspectInstruction (PPTI_CANDIDATE Candidate)
 Inspect a candidate instruction for page-table modifications. More...
 
INTSTATUS IntPtiRemoveInstruction (QWORD Rip)
 Remove the hook on a monitored instruction. More...
 
INTSTATUS IntPtiHandleInt3 (void)
 This function is the main INT3 handler. More...
 
void IntPtiDumpStats (void)
 Dump PT filtering statistics. More...
 
static INTSTATUS IntPtiHandleWrite (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 This callback handles writes that take place inside the in-guest PT filter. All attempts will be blocked. More...
 
static INTSTATUS IntPtiHandleExecute (void *Context, void *Hook, QWORD Address, INTRO_ACTION *Action)
 This callback handles instruction fetches that take place inside the in-guest PT filter. All attempts will be blocked. More...
 
static INTSTATUS IntPtiHookPtDriver (void)
 Protect the in-guest PT filter against unauthorized access. More...
 
static INTSTATUS IntPtiEnableFiltering (void)
 Enable PT candidate instruction monitoring. More...
 
static INTSTATUS IntPtiDisableFiltering (void)
 Disable PT candidate instructions monitoring. More...
 
static INTSTATUS IntPtiDeployLoader (QWORD GuestVirtualAddress, DWORD AgentTag, void *Context)
 Called on initial loader deployment. More...
 
static QWORD IntPtiDeliverDriverForLoad (QWORD GuestVirtualAddress, DWORD MaxSize, void *Context)
 Called by the driver loader, in order to initialize the in-guest PT-filter. More...
 
static INTSTATUS IntPtiCompleteLoader (QWORD GuestVirtualAddress, DWORD ErrorCode, DWORD AgentTag, void *Context)
 Called once the PT loader finished execution. More...
 
static INTSTATUS IntPtiDeployUnloader (QWORD GuestVirtualAddress, DWORD AgentTag, void *Context)
 Called as soon as the PT filter unloader has been successfully injected. Disables the PT filtering. More...
 
static INTSTATUS IntPtiUnhookPtFilter (void)
 Remove protection from the PT filter. More...
 
static QWORD IntPtiDeliverDriverForUnload (QWORD GuestVirtualAddress, DWORD MaxSize, void *Context)
 This function is called when the boot driver is ready to unload & free the PT filter. More...
 
static INTSTATUS IntPtCompleteUnloader (QWORD GuestVirtualAddress, DWORD ErrorCode, DWORD AgentTag, void *Context)
 Called once the agent unloader has finished executing. More...
 
INTSTATUS IntPtiInjectPtFilter (void)
 Inject the PT filter inside the guest. More...
 
INTSTATUS IntPtiRemovePtFilter (DWORD AgOpts)
 Removes the PT filter. More...
 
BOOLEAN IntPtiIsPtrInAgent (QWORD Ptr, THS_PTR_TYPE Type)
 Check if an address points inside the PT filter. Ignore non-executable sections when doing so. More...
 
INTSTATUS IntPtiCacheRemove (QWORD Gpa)
 Remove a guest physical page from the PT filter cache. More...
 
INTSTATUS IntPtiCacheAdd (QWORD Gpa)
 Add a guest-physical address to the PT filter cache of entries for which an exit is not required. More...
 
QWORD IntPtiGetAgentAddress (void)
 Get the guest virtual address where the PT filter resides. More...
 
QWORD IntPtiAllocMemtableSpace (QWORD Rip, DWORD Size)
 Allocate space for a mem-table. More...
 
void IntPtiHandleGuestResumeFromSleep (void)
 Sets PtFilterWaiting to true if PT filtering was enabled, or to false otherwise. More...
 

Variables

BOOLEAN gPtMonitored
 Indicate the PT filter state. More...
 
BOOLEAN gPtPendingRemove
 
BOOLEAN gPtDeployed
 
BOOLEAN gPtPendingInject
 
BOOLEAN gPtEnableMonitor
 
QWORD gPtDriverAddress
 Guest virtual address where the PT filter was injected. More...
 
DWORD gPtDriverSize
 Size of the PT filter. More...
 
DWORD gPtDriverEntryPoint
 Entry point of the PT filter. More...
 
QWORD gPtDriverCacheAddress
 GVA of the PT filter cache - entries we do not need to generate an exit for. More...
 
QWORD gPtDriverTableAddress
 Table of handlers inside the PT filter. More...
 
QWORD gPtDriverHandlersAddress
 Main handler inside the PT filter. More...
 
QWORD gPtDriverMainAddress
 Main function inside the PT filter. More...
 
QWORD gPtDriverRdataAddress
 Address of the rdata section inside the PT filter. More...
 
QWORD gPtDriverMemtableAddress
 Section used to store mem-tables (checkout memtables.c). More...
 
QWORD gPtDriverCheckFunction
 The check function inside the PT filter. More...
 
PBYTE gPtDriverImage
 Pointer to the PT filter image. More...
 
void * gPtDriverHook
 PT filter hook handle. More...
 
void * gPtDriverCloak
 PT filter cloak handle. More...
 
DWORD gPtHandlerIndex
 Current handler index. More...
 
DWORD gPtTableIndexes [MAX_LUT_PAGES]
 Lookup table of indexes. More...
 
DWORD gPtMemtableSize
 This indicates how much mem-table space we have allocated. More...
 
DWORD gPtMemtableTotalSize
 Total mem-table size. More...
 
DWORD gPtHandlersTotalSize
 Total handlers size. More...
 
LIST_HEAD gPtiCandidatesList = LIST_HEAD_INIT(gPtiCandidatesList)
 We store each candidate in a RB tree, ordered by the location. We also store them in a linked-list, for convenience. More...
 
RBTREE gPtiCandidatesTree = RB_TREE_INIT(gPtiCandidatesTree, IntPtiRbTreeNodeFree, IntPtiRbTreeNodeCompareRip)
 PT candidate instruction RB tree root. More...
 

Detailed Description

This is the main instrumentation file, which scans, identifies and instruments NT instructions that have the potential to be used as page-table writes.

PT filter is an instrumentation mechanism used to intercept all memory write instruction that have the potential of writing to a page-table entry. Initially, we will scan NT image (.text section, more specifically) in order to find candidate instructions. Once candidate instructions are identified, they are replaced with a breakpoint (INT3, encoding 0xCC) instruction. When this breakpoint is hit, a VM exit to Introcore will take place. Introcore will then analyze the instruction operands, and determine whether it is a page-table modification or not. If the instruction is deemed to be e regular memory operation and not a page-table write, then it will simply be restored. Instruction which exhibit page-table write behavior will be replaced with an "INT 20" instruction that will divert code execution inside our filtering agent, which will analyze the instruction and decide whether it does a relevant page-table modification or not. A hyper call (VMCALL) will be issued if such a relevant modification is done. While the PT filter is enabled, the page-tables will not be write-hooked inside the EPT. This mechanism is used mostly for debugging purposes, as writes that do not originate inside the NT will pass through and will not be intercepted at all. For more information regarding the components of the PT filter, take a look at prfilter64.asm.

Definition in file ptfilter.c.

Macro Definition Documentation

◆ MAX_ENTRIES_PER_BUCKET

#define MAX_ENTRIES_PER_BUCKET   256
  1. A table of handler. For each instruction that modifies a page-table entry, we will store its handler address inside this table.
  2. Section of handlers. This contains the actual code handlers for each instrumented instruction.
  3. Cache. This contains all the guest physical pages the PT filter doesn't have to generate a VM exit, since they represent unmonitored pages.
  4. Mem-tables. A section reserved for mem-tables.
  5. The main check function. This function checks if an accessed linear address is a page table or not; if it is, it places the global lock and continues handling, otherwise it resumes execution.
  6. The main handler. This generically handles page-table entry modifications.
  7. Entry point. This is the code that gets executed when an INT 20 is executed; this code simply takes the RIP from the interrupt frame and tries to locate an appropriate handler inside the handler table.

Definition at line 56 of file ptfilter.c.

Referenced by IntPtiAllocMemtableSpace().

◆ MAX_HANDLER_SIZE

#define MAX_HANDLER_SIZE   48ull

Definition at line 58 of file ptfilter.c.

◆ MAX_LUT_PAGES

#define MAX_LUT_PAGES   64

Definition at line 57 of file ptfilter.c.

◆ REG

#define REG (   r)    (*(&gVcpu->Regs.Rax + (r)))

◆ TABLE_BUCKET_MASK

#define TABLE_BUCKET_MASK   0x3F

Definition at line 59 of file ptfilter.c.

Referenced by IntPtiAllocMemtableSpace().

Typedef Documentation

◆ PPTI_CANDIDATE

typedef struct _PTI_CANDIDATE * PPTI_CANDIDATE

◆ PTI_CANDIDATE

typedef struct _PTI_CANDIDATE PTI_CANDIDATE

Describes a PT write candidate instruction.

Function Documentation

◆ IntPtCompleteUnloader()

static INTSTATUS IntPtCompleteUnloader ( QWORD  GuestVirtualAddress,
DWORD  ErrorCode,
DWORD  AgentTag,
void *  Context 
)
static

Called once the agent unloader has finished executing.

This function will reset the PT state and it will disable the power-state spin wait, if it was enabled. Check out winpower.c for more info.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1639 of file ptfilter.c.

Referenced by IntPtiRemovePtFilter().

◆ IntPtiAllocMemtableSpace()

QWORD IntPtiAllocMemtableSpace ( QWORD  Rip,
DWORD  Size 
)

Allocate space for a mem-table.

Instrumenting so many instructions has a great disadvantage: there are high chances that we will hit pages that contain switch-case clauses. Since we monitor all pages that are modified by Introcore against reads, this will lead to a very high number of mem-tables that must be relocated. Since the slack space size is quite small, we cannot relocate all these instructions inside this slack space; instead, we make use of the PT filter itself - we reserved a large section specially for these mem-tables, which will be relocated inside the PT filter space, instead of the NT slack space.

Parameters
[in]RipRip of the instruction to be relocated using mem-tables.
[in]SizeSize required.
Return values
Aguest virtual address pointing inside a section of the PT filter, which can be used by mem-tables.

Definition at line 1988 of file ptfilter.c.

Referenced by IntMtblPatchInstruction().

◆ IntPtiCacheAdd()

INTSTATUS IntPtiCacheAdd ( QWORD  Gpa)

Add a guest-physical address to the PT filter cache of entries for which an exit is not required.

This function updates the PT filter cache by adding the designated value to it. The cache is used by the PT filter to know which guest-physical addresses are not hooked, and, therefore, it needs not to generate a VM exit.

Parameters
[in]GpaThe guest physical address to be added to the cache. Low 12 bits are ignored.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the PT filter is not initialized.

Definition at line 1912 of file ptfilter.c.

Referenced by IntDispatchPtAsEpt().

◆ IntPtiCacheRemove()

INTSTATUS IntPtiCacheRemove ( QWORD  Gpa)

Remove a guest physical page from the PT filter cache.

This function removes a guest physical page from the PT filter cache. Removing an entry is required, for example, when hooking it for the first time.

Parameters
[in]GpaThe guest physical address to be removed from the PT filter cache. Low 12 bits are ignored.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the PT filter is not initialized.

Definition at line 1863 of file ptfilter.c.

Referenced by IntHookGpaSetHook().

◆ IntPtiCompleteLoader()

static INTSTATUS IntPtiCompleteLoader ( QWORD  GuestVirtualAddress,
DWORD  ErrorCode,
DWORD  AgentTag,
void *  Context 
)
static

Called once the PT loader finished execution.

Depending on the injection result, this function will either reset the PT filter state, if injection failed, or it will enable PT filtering, if it succeeded.

Parameters
[in]GuestVirtualAddressUnused.
[in]ErrorCodeInjection error code. 0 for success.
[in]AgentTagUnused.
[in]ContextUnused.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1438 of file ptfilter.c.

Referenced by IntPtiInjectPtFilter().

◆ IntPtiDeleteInstruction()

static void IntPtiDeleteInstruction ( PPTI_CANDIDATE  Candidate)
static

Delete a PT candidate instruction.

Parameters
[in,out]CandidateThe candidate instruction to delete.

Definition at line 186 of file ptfilter.c.

Referenced by IntPtiRemoveInstruction(), and IntPtiRestoreAllPtWriteCandidates().

◆ IntPtiDeliverDriverForLoad()

static QWORD IntPtiDeliverDriverForLoad ( QWORD  GuestVirtualAddress,
DWORD  MaxSize,
void *  Context 
)
static

Called by the driver loader, in order to initialize the in-guest PT-filter.

This function is called by the boot driver agent, and it signals that the PT filter initialization can begin. This function does the following:

  1. Writes the PT filter inside the guest space.
  2. Initialize the cache, mem-tables and the handlers tables; their uses are the following:
    • cache - contains guest-physical pages (page-tables) which are not monitored; of an entry is found by the PT filter inside this cache, it will ignore the write, and it will not trigger an exit;
    • mem-tables - a section dedicated for relocating mem-tables; as this technique places lots of read EPT hooks on the NT image (the instrumented instructions), a high number of switch-case statements will trigger read EPT violations; since the NT slack space is a limited resource, once the PT filter is injected, these switch-case instructions will be relocated inside the PT filter;
    • handlers - a section which contains the handlers for each instrumented instruction.
    • check function - this is the main function which checks if an address looks like a page-table or not;
  3. Patch relevant info inside the PT filter:
    • Self map index inside PML4;
    • Page-table monitored bits - we will exit iff one of these bits is modified;
    • Relevant offsets inside kernel structures.
  4. Protect the PT filter against attacks
    • write-hook non-writable sections
    • execute-hook non-executable sections
  5. Hook the VE handler - place a hook which will divert execution to the PT filter main handler.
Parameters
[in]GuestVirtualAddressThe guest address where the PT filter is deployed.
[in]MaxSizeUnused.
[in]ContextUnused.
Return values
0On success; used internally by the agents.

Definition at line 1222 of file ptfilter.c.

Referenced by IntPtiInjectPtFilter().

◆ IntPtiDeliverDriverForUnload()

static QWORD IntPtiDeliverDriverForUnload ( QWORD  GuestVirtualAddress,
DWORD  MaxSize,
void *  Context 
)
static

This function is called when the boot driver is ready to unload & free the PT filter.

This function is called when the boot driver has been successfully injected, and now it asks Introcore to actually remove the PT filter. This function will call the thread-safeness, in order to make sure to pointers still point inside the PT filter. If we still have pointers, this function will return 1, and the in-guest boot driver will spin for a while before trying again. If everything is OK and all pointers have left the PT filter, it will return 0, and the PT filter will be permanently freed inside the guest by the boot driver.

Parameters
[in]GuestVirtualAddressUnused.
[in]MaxSizeUnused.
[in]ContextUnused.
Return values
0If the PT filter can safely be freed inside the guest.
1If the PT filter cannot be safely freed inside the guest.

Definition at line 1577 of file ptfilter.c.

Referenced by IntPtiRemovePtFilter().

◆ IntPtiDeployLoader()

static INTSTATUS IntPtiDeployLoader ( QWORD  GuestVirtualAddress,
DWORD  AgentTag,
void *  Context 
)
static

Called on initial loader deployment.

Parameters
[in]GuestVirtualAddressUnused.
[in]AgentTagUnused.
[in]ContextUnused.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1196 of file ptfilter.c.

Referenced by IntPtiInjectPtFilter().

◆ IntPtiDeployUnloader()

static INTSTATUS IntPtiDeployUnloader ( QWORD  GuestVirtualAddress,
DWORD  AgentTag,
void *  Context 
)
static

Called as soon as the PT filter unloader has been successfully injected. Disables the PT filtering.

Parameters
[in]GuestVirtualAddressUnused.
[in]AgentTagUnused.
[in]ContextUnused.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1502 of file ptfilter.c.

Referenced by IntPtiRemovePtFilter().

◆ IntPtiDisableFiltering()

static INTSTATUS IntPtiDisableFiltering ( void  )
static

Disable PT candidate instructions monitoring.

This function will disable the filtering by:

  1. Restoring all candidate instructions;
  2. Disabling the PT cache;
  3. Removing all mem-table entries.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1146 of file ptfilter.c.

Referenced by IntPtiDeployUnloader(), and IntPtiRemovePtFilter().

◆ IntPtiDumpStats()

void IntPtiDumpStats ( void  )

Dump PT filtering statistics.

Definition at line 907 of file ptfilter.c.

◆ IntPtiEnableFiltering()

static INTSTATUS IntPtiEnableFiltering ( void  )
static

Enable PT candidate instruction monitoring.

This function will start monitoring all the candidate PT instructions inside the .text section of the NT image.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1094 of file ptfilter.c.

Referenced by IntPtiCompleteLoader().

◆ IntPtiGetAgentAddress()

QWORD IntPtiGetAgentAddress ( void  )

Get the guest virtual address where the PT filter resides.

Return values
Theguest virtual address where the PT filter resides.

Definition at line 1974 of file ptfilter.c.

Referenced by IntMtblCheckAccess(), and IntWinAgentHandleDriverVmcall().

◆ IntPtiHandleExecute()

static INTSTATUS IntPtiHandleExecute ( void *  Context,
void *  Hook,
QWORD  Address,
INTRO_ACTION Action 
)
static

This callback handles instruction fetches that take place inside the in-guest PT filter. All attempts will be blocked.

Parameters
[in]ContextThe context. Unused.
[in]HookHook handle. Unused.
[in]AddressThe written address. Unused.
[out]ActionAction. Will be set to introGuestNotAllowed.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 983 of file ptfilter.c.

Referenced by IntPtiHookPtDriver().

◆ IntPtiHandleGuestResumeFromSleep()

void IntPtiHandleGuestResumeFromSleep ( void  )

Sets PtFilterWaiting to true if PT filtering was enabled, or to false otherwise.

Definition at line 2064 of file ptfilter.c.

Referenced by IntNotifyGuestPowerStateChange().

◆ IntPtiHandleInt3()

INTSTATUS IntPtiHandleInt3 ( void  )

This function is the main INT3 handler.

This function simply searches for the instruction that has been monitored at the current RIP, and calls the inspection function on it, IntPtiInspectInstruction.

Return values
INT_STATUS_NOT_FOUNDIf an instruction has not been monitored at current RIP.
INT_STATUS_NO_DETOUR_EMUIf an instruction was found.

Definition at line 859 of file ptfilter.c.

Referenced by IntHandleBreakpoint(), and IntHandleEptViolation().

◆ IntPtiHandleWrite()

static INTSTATUS IntPtiHandleWrite ( void *  Context,
void *  Hook,
QWORD  Address,
INTRO_ACTION Action 
)
static

This callback handles writes that take place inside the in-guest PT filter. All attempts will be blocked.

Parameters
[in]ContextThe context. Unused.
[in]HookHook handle. Unused.
[in]AddressThe written address. Unused.
[out]ActionAction. Will be set to introGuestNotAllowed.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 949 of file ptfilter.c.

Referenced by IntPtiHookPtDriver().

◆ IntPtiHookPtDriver()

static INTSTATUS IntPtiHookPtDriver ( void  )
static

Protect the in-guest PT filter against unauthorized access.

This function will protect the in-guest pt filter against attacks: non-writable sections will be marked non-writable inside the EPT, while non-executable sections will be marked non-executable.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.

Definition at line 1018 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad().

◆ IntPtiInjectPtFilter()

INTSTATUS IntPtiInjectPtFilter ( void  )

Inject the PT filter inside the guest.

This function will initiate the PT filter injection. NOTE: If this function return success, it does not necessarily means that the PT filter has been successfully injected, it just means that it has been successfully scheduled for injection.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZEDIf Introcore is preparing to unload.
INT_STATUS_NOT_NEEDED_HINTIf the OS is not 64 bit Windows RS4 or newer.
INT_STATUS_ALREADY_INITIALIZED_HINTIf the PT filter ha been already injected.

Definition at line 1676 of file ptfilter.c.

Referenced by IntGuestPreReturnCallback(), IntGuestUpdateCoreOptions(), IntVeCompleteLoader(), and IntWinProcCreateProcessObject().

◆ IntPtiInspectInstruction()

static INTSTATUS IntPtiInspectInstruction ( PPTI_CANDIDATE  Candidate)
static

Inspect a candidate instruction for page-table modifications.

This function is called whenever a breakpoint that was set on a PT candidate instruction is hit. In order to determine if the instruction is page-table modifying, we employ the following checks:

  1. The PML4 index is the same as the self-map index (recursive page-table reference);
  2. It translates to a currently known page-table;
  3. The written value looks like a legit page-table entry If such a relevant modification is identified, the following handling code will be used for the instruction: PUSH 0/1 ; Save the state of the IF flag, as it was when the instruction executed. PUSH disp ; The displacement used by the memory instruction. PUSH gla ; This saves the gla (base register) as used by the memory instruction. CALL check ; Call the main check function, which determines if the gla is PT or not. ; If the above call returns, the instruction can be further processed, as it means it's a PT instruction. PUSH [gla] ; Save old PT entry value. Original instruction PUSH [gla] ; Save new PT entry value. JMP main ; Jumps to the main handler. NOTE: When the check function return, it also places a global lock. This is needed, in order to avoid TOCTOU races with other VCPUs that might modify the same PT entry. NOTE: The lock will be released by the main function, before returning to the NT code. After building this handler, the address of the handler will be installed inside the handlers section of the PT filter, and the handler code will be written inside the PT filter. The old INT3 will now be replaced with an "INT 20": each time an "INT 20" takes place, the PT filter handler will locate the adequate handler inside the handlers table, and call it. Note that this is required, since each instruction will be handled differently.
Parameters
CandidateThe candidate instruction.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 487 of file ptfilter.c.

Referenced by IntPtiHandleInt3().

◆ IntPtiIsPtrInAgent()

BOOLEAN IntPtiIsPtrInAgent ( QWORD  Ptr,
THS_PTR_TYPE  Type 
)

Check if an address points inside the PT filter. Ignore non-executable sections when doing so.

Parameters
[in]PtrThe pointer.
[in]TypeLive RIP or stack value.
Return values
Trueif Ptr points inside the PT filter, false otherwise.

Definition at line 1813 of file ptfilter.c.

Referenced by IntHandleIntroCall(), IntThrSafeIsLiveRIPInIntro(), and IntThrSafeIsStackPtrInIntro().

◆ IntPtiMonitorAllPtWriteCandidates()

static INTSTATUS IntPtiMonitorAllPtWriteCandidates ( void  )
static

Scan the .text section of the NT image for PT candidates.

This function will iterate through the entire .text section of the NT image, and search for viable PT candidates. An instruction is considered a PT candidate if it is one of the following:

  • mov qword [reg{+disp}], 0
  • mov qword [reg{+disp}], reg
  • xchg qword [reg{+disp}], reg
  • lock cmpxchg [reg{+disp}], reg
  • base reg cannot be RSP
  • displacement, if present:
    • must be less than 0x20
    • must be aligned to 8 Once a candidate is identified, it is replaced with an INT3, in order to intercept its first execution following guest re-entry.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 213 of file ptfilter.c.

Referenced by IntPtiEnableFiltering().

◆ IntPtiRbTreeNodeCompareRip()

static int IntPtiRbTreeNodeCompareRip ( RBNODE Left,
RBNODE Right 
)
static

RB tree node compare function.

Parameters
[in]LeftThe left node.
[in]RightThe right node.
Return values
-1If the left node is smaller than the right node.
0If the left node is equal to the right node.
+1If the left node is larger than the right node.

Definition at line 119 of file ptfilter.c.

◆ IntPtiRbTreeNodeFree()

static void IntPtiRbTreeNodeFree ( RBNODE Node)
static

Called on RB tree node free.

Parameters
[in,out]NodeThe node to be freed.

Definition at line 105 of file ptfilter.c.

◆ IntPtiRemoveInstruction()

INTSTATUS IntPtiRemoveInstruction ( QWORD  Rip)

Remove the hook on a monitored instruction.

Parameters
[in]RipThe RIP of the instruction to be removed.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf PT monitoring is not enabled.

Definition at line 792 of file ptfilter.c.

Referenced by IntHandleIntroCall().

◆ IntPtiRemovePtFilter()

INTSTATUS IntPtiRemovePtFilter ( DWORD  AgOpts)

Removes the PT filter.

This function will initiate the PT filter unloading procedure. Once this is done, all monitored instructions will be reverted to their original values. NOTE: If this function return success, it does not necessarily means that the PT filter has been successfully removed, it just means that it has been successfully scheduled for removal.

Parameters
[in]AgOptsAgent options, passed to the IntWinAgentInject function.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the PT filter was not previously injected inside the guest.

Definition at line 1736 of file ptfilter.c.

Referenced by IntGuestUpdateCoreOptions(), and IntWinPowHandleEventCommon().

◆ IntPtiResetState()

static void IntPtiResetState ( void  )
static

Reset the PT filter state (used after removing it from guest memory).

Definition at line 161 of file ptfilter.c.

Referenced by IntPtCompleteUnloader(), IntPtiCompleteLoader(), and IntPtiRemovePtFilter().

◆ IntPtiRestoreAllPtWriteCandidates()

static INTSTATUS IntPtiRestoreAllPtWriteCandidates ( void  )
static

Restore all PT candidates, by removing the INT3/INT 20 hook established on them.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 461 of file ptfilter.c.

Referenced by IntPtiDisableFiltering(), and IntPtiEnableFiltering().

◆ IntPtiUnhookPtFilter()

static INTSTATUS IntPtiUnhookPtFilter ( void  )
static

Remove protection from the PT filter.

This function will remove the protection from the PT filter (write and execute protection). It will also remove the cloak handle established on the INT 20 handler, and it will free the PT driver image inside Introcore space.

Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1530 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForUnload(), and IntPtiRemovePtFilter().

Variable Documentation

◆ gPtDeployed

◆ gPtDriverAddress

QWORD gPtDriverAddress

Guest virtual address where the PT filter was injected.

Definition at line 79 of file ptfilter.c.

Referenced by IntPtiCacheAdd(), IntPtiCacheRemove(), IntPtiDeliverDriverForLoad(), IntPtiGetAgentAddress(), IntPtiHookPtDriver(), IntPtiIsPtrInAgent(), IntPtiRemovePtFilter(), and IntPtiResetState().

◆ gPtDriverCacheAddress

QWORD gPtDriverCacheAddress

GVA of the PT filter cache - entries we do not need to generate an exit for.

Definition at line 82 of file ptfilter.c.

Referenced by IntPtiCacheAdd(), IntPtiCacheRemove(), IntPtiDeliverDriverForLoad(), and IntPtiResetState().

◆ gPtDriverCheckFunction

QWORD gPtDriverCheckFunction

The check function inside the PT filter.

Definition at line 88 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad(), and IntPtiResetState().

◆ gPtDriverCloak

void* gPtDriverCloak

PT filter cloak handle.

Definition at line 92 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad(), and IntPtiUnhookPtFilter().

◆ gPtDriverEntryPoint

DWORD gPtDriverEntryPoint

Entry point of the PT filter.

Definition at line 81 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad(), IntPtiInjectPtFilter(), and IntPtiResetState().

◆ gPtDriverHandlersAddress

QWORD gPtDriverHandlersAddress

Main handler inside the PT filter.

Definition at line 84 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad(), and IntPtiResetState().

◆ gPtDriverHook

void* gPtDriverHook

PT filter hook handle.

Definition at line 91 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad(), IntPtiHookPtDriver(), and IntPtiUnhookPtFilter().

◆ gPtDriverImage

PBYTE gPtDriverImage

Pointer to the PT filter image.

Definition at line 90 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad(), IntPtiHookPtDriver(), and IntPtiUnhookPtFilter().

◆ gPtDriverMainAddress

QWORD gPtDriverMainAddress

Main function inside the PT filter.

Definition at line 85 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad(), and IntPtiResetState().

◆ gPtDriverMemtableAddress

QWORD gPtDriverMemtableAddress

Section used to store mem-tables (checkout memtables.c).

Definition at line 87 of file ptfilter.c.

Referenced by IntPtiAllocMemtableSpace(), IntPtiDeliverDriverForLoad(), and IntPtiResetState().

◆ gPtDriverRdataAddress

QWORD gPtDriverRdataAddress

Address of the rdata section inside the PT filter.

Definition at line 86 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad(), and IntPtiResetState().

◆ gPtDriverSize

DWORD gPtDriverSize

◆ gPtDriverTableAddress

QWORD gPtDriverTableAddress

Table of handlers inside the PT filter.

Definition at line 83 of file ptfilter.c.

Referenced by IntPtiAllocMemtableSpace(), IntPtiDeliverDriverForLoad(), and IntPtiResetState().

◆ gPtEnableMonitor

BOOLEAN gPtEnableMonitor

Definition at line 77 of file ptfilter.c.

Referenced by IntPtiCompleteLoader(), IntPtiDeliverDriverForLoad(), and IntPtiResetState().

◆ gPtHandlerIndex

DWORD gPtHandlerIndex

Current handler index.

Definition at line 94 of file ptfilter.c.

Referenced by IntPtiResetState().

◆ gPtHandlersTotalSize

DWORD gPtHandlersTotalSize

Total handlers size.

Definition at line 100 of file ptfilter.c.

Referenced by IntPtiDeliverDriverForLoad().

◆ gPtiCandidatesList

LIST_HEAD gPtiCandidatesList = LIST_HEAD_INIT(gPtiCandidatesList)

We store each candidate in a RB tree, ordered by the location. We also store them in a linked-list, for convenience.

Definition at line 153 of file ptfilter.c.

◆ gPtiCandidatesTree

RBTREE gPtiCandidatesTree = RB_TREE_INIT(gPtiCandidatesTree, IntPtiRbTreeNodeFree, IntPtiRbTreeNodeCompareRip)

PT candidate instruction RB tree root.

Definition at line 156 of file ptfilter.c.

◆ gPtMemtableSize

DWORD gPtMemtableSize

This indicates how much mem-table space we have allocated.

Definition at line 98 of file ptfilter.c.

Referenced by IntPtiAllocMemtableSpace(), and IntPtiResetState().

◆ gPtMemtableTotalSize

DWORD gPtMemtableTotalSize

Total mem-table size.

Definition at line 99 of file ptfilter.c.

Referenced by IntPtiAllocMemtableSpace(), and IntPtiDeliverDriverForLoad().

◆ gPtMonitored

BOOLEAN gPtMonitored

◆ gPtPendingInject

BOOLEAN gPtPendingInject

◆ gPtPendingRemove

BOOLEAN gPtPendingRemove

◆ gPtTableIndexes

DWORD gPtTableIndexes[MAX_LUT_PAGES]

Lookup table of indexes.

Definition at line 95 of file ptfilter.c.

Referenced by IntPtiAllocMemtableSpace(), and IntPtiResetState().