Bitdefender Hypervisor Memory Introspection
lixagent.c File Reference
#include "lixagent.h"
#include "alerts.h"
#include "callbacks.h"
#include "glue.h"
#include "guests.h"
#include "hnd_remediation.h"
#include "hnd_loggather.h"
#include "icache.h"
#include "memcloak.h"
#include "slack.h"
#include "lixksym.h"

Go to the source code of this file.

Data Structures

struct  _LIX_AGENT_NAME
 Describes the name of an injected process agent. More...
 
struct  _LIX_AGENT_STATE
 The global agents state. More...
 

Typedefs

typedef struct _LIX_AGENT_NAME LIX_AGENT_NAME
 Describes the name of an injected process agent. More...
 
typedef struct _LIX_AGENT_STATE LIX_AGENT_STATE
 The global agents state. More...
 

Functions

static INTSTATUS IntLixAgentCreateThreadHypercall (LIX_AGENT *Agent)
 Called by the thread-agent to deploy the content of the kthread previously created. More...
 
static INTSTATUS IntLixAgentCreateThreadCompletion (LIX_AGENT *Agent)
 Called by the thread-agent when the kthread started. More...
 
static QWORD IntLixAgentGetToken (void)
 Randomly select a token to be used by the agent code when issuing hyper calls. More...
 
static INTSTATUS IntLixAgentFindInstruction (BYTE MinLen, QWORD *InstructionVa, BYTE *InstructionLen, BYTE *InstructionBytes)
 Searches for a suitable instruction to replace with a INT3 instruction. More...
 
static BOOLEAN IntLixAgentNameIsRunning (const char *Name)
 Iterates through all agent names to check if an agent with the provided name is running. More...
 
static INTSTATUS IntLixAgentNameCreate (const char *Name, DWORD Tag, DWORD Agid, LIX_AGENT_NAME **AgentName)
 Create an agent name and insert the newly create agent-name to linked list. More...
 
static void IntLixAgentNameRemove (LIX_AGENT_NAME *Name)
 Frees and removes from our list the provided LIX_AGENT_NAME. More...
 
void IntLixAgentNameRemoveByAgid (DWORD Agid)
 Iterates through all agent names and removes the entry that contains the provided ID. More...
 
DWORD IntLixAgentNameGetTagByAgid (DWORD Agid)
 Iterates through all agent names and returns the tag of the agent that has the provided agent ID. More...
 
static INTSTATUS IntLixAgentThreadFree (LIX_AGENT_THREAD *Thread)
 Remove the provided agent-thread. More...
 
static void IntLixAgentFree (LIX_AGENT *Agent)
 Remove the provided agent. More...
 
static INTSTATUS IntLixAgentFillDataFromMemory (LIX_AGENT_DATA *Data, LIX_AGENT_TAG Tag)
 Fetch the content of the agent with the provided LIX_AGENT_TAG from memory. More...
 
static INTSTATUS IntLixAgentFillDataFromHandler (LIX_AGENT_DATA *Data, LIX_AGENT_HANDLER *Handler)
 Fetch the content of the agent with the provided LIX_AGENT_TAG from the corresponding LIX_AGENT_HANDLER structure. More...
 
static INTSTATUS IntLixAgentFillData (LIX_AGENT_DATA *Data, LIX_AGENT_HANDLER *Handler)
 Fetch the content of the agent. More...
 
BOOLEAN IntLixAgentMatchVersion (LIX_AGENT_FUNCTIONS *Function)
 Checks if the provided LIX_AGENT_FUNCTIONS match the current guest version. More...
 
static INTSTATUS IntLixAgentResolveOffset (LIX_AGENT_DATA *Data, LIX_AGENT_HANDLER *Handler)
 Search the functions and complete the args/tokens required by the agent. More...
 
static INTSTATUS IntLixAgentAllocate (LIX_AGENT *Agent)
 Allocate a memory zone for the content of the agent. More...
 
static DWORD IntLixAgentGetId (void)
 Generate a new ID. More...
 
static INTSTATUS IntLixAgentCreate (LIX_AGENT_TAG Tag, DWORD TagEx, PFUNC_AgentCallbackHypercall HypercallCallback, PFUNC_AgentCallbackCompletion CompletionCallback, LIX_AGENT **Agent)
 Create an agent entry. More...
 
static INTSTATUS IntLixAgentThreadCreate (LIX_AGENT_TAG Tag, PFUNC_AgentCallbackHypercall HypercallCallback, PFUNC_AgentCallbackCompletion CompletionCallback, BYTE *ContentAddress, DWORD ContentSize, LIX_AGENT_THREAD **Thread)
 Create an agent-thread entry. More...
 
INTSTATUS IntLixAgentInject (LIX_AGENT_TAG Tag, PFUNC_AgentCallbackHypercall HypercallCallback, PFUNC_AgentCallbackCompletion CompletionCallback)
 Schedule an agent injection inside the guest. More...
 
INTSTATUS IntLixAgentThreadInject (LIX_AGENT_TAG Tag, DWORD TagEx, AGENT_TYPE AgentType, PFUNC_AgentCallbackHypercall HypercallCallback, PFUNC_AgentCallbackCompletion CompletionCallback, const char *Name, BYTE *ContentAddress, DWORD ContentSize)
 Schedule an thread-agent injection inside the guest. More...
 
INTSTATUS IntLixAgentActivatePendingAgent (void)
 Activates a pending agent that waits to be injected. More...
 
static INTSTATUS IntLixAgentError (LIX_AGENT *Agent)
 Called when an error occurred while the running the current agent. More...
 
static INTSTATUS IntLixAgentStart (LIX_AGENT *Agent)
 Called when the INT3 instruction from SYSCALL is hit. More...
 
static INTSTATUS IntLixAgentExit (LIX_AGENT *Agent)
 Called when the agent is terminating. More...
 
static INTSTATUS IntLixAgentHandleBreakpoint (LIX_AGENT *Agent, QWORD Rip)
 Called when a INT3 instruction from the current running agent is hit. More...
 
static INTSTATUS IntLixAgentThreadError (LIX_AGENT *Agent)
 Called when an error occurred while the running the current thread-agent. More...
 
static INTSTATUS IntLixAgentThreadExit (LIX_AGENT *Agent)
 Called when the thread-agent is terminating. More...
 
static INTSTATUS IntLixAgentThreadHandleBreakpoint (LIX_AGENT *Agent, QWORD Rip)
 Called when a INT3 instruction from the current running thread-agent is hit. More...
 
INTSTATUS IntLixAgentHandleInt3 (QWORD Rip)
 Called when a INT3 instruction from the current running agent is executed. More...
 
static INTSTATUS IntLixAgentHandleKernelVmcall (void)
 Called when a VMCALL instruction from the current running agent is executed. More...
 
static INTSTATUS IntLixAgentHandleUserVmcall (void)
 Handles a VMCALL issued by a process that has been injected inside the guest. More...
 
INTSTATUS IntLixAgentHandleVmcall (QWORD Rip)
 Handle a VMCALL that was executed inside the guest. More...
 
AG_WAITSTATE IntLixAgentGetState (DWORD *Tag)
 Gets the global agents state. More...
 
void IntLixAgentDisablePendingAgents (void)
 Disables all pending agents. More...
 
LIX_AGENT_TAG IntLixAgentIncProcRef (const char *Name)
 Checks if a process is an agent or not, and increments the ref count of that name. More...
 
LIX_AGENT_TAG IntLixAgentDecProcRef (const char *Name, BOOLEAN *Removed)
 Checks if a process is an agent or not, and decrements the ref count of that name. More...
 
void IntLixAgentEnableInjection (void)
 Enables agent injections. More...
 
void IntLixAgentInit (void)
 Initialize the agents state. More...
 
INTSTATUS IntLixAgentUninit (void)
 Uninit the agents state. More...
 
void IntLixAgentSendEvent (AGENT_EVENT_TYPE Event, DWORD AgentTag, DWORD ErrorCode)
 Send an event to the integrator that contains the AGENT_EVENT_TYPE, tag of the agent and the last error code. More...
 

Variables

static LIX_AGENT_STATE gLixAgentState
 

Typedef Documentation

◆ LIX_AGENT_NAME

Describes the name of an injected process agent.

Whenever a named agent is injected, we allocate such an entry. Whenever a process is created, we check if its name matches the name of an injected agent; if it does, it will be flagged as being an agent. Therefore, it is advisable to use complicated names for the agents, in order to avoid having regular processes marked as agents.

◆ LIX_AGENT_STATE

The global agents state.

Function Documentation

◆ IntLixAgentActivatePendingAgent()

INTSTATUS IntLixAgentActivatePendingAgent ( void  )

Activates a pending agent that waits to be injected.

The steps required to activate a pending agent are:

  • allocate slack space (used by init/uninit agents) if the agent is not already deployed.
  • deploy the agent buffer that contains all the required data resolved (function addresses, args, tokens).
  • find a suitable instruction of length 1
  • replace the instruction with a INT3 instruction
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZEDIf is not safe to inject the agent;
INT_STATUS_NOT_NEEDED_HINTIf no agent waits to be injected; if an agent is already running.
INT_STATUS_ALREADY_INITIALIZEDIf an agent with the same name is already running.
INT_STATUS_INSUFFICIENT_RESOURCESIf the memory alloc fails.

Definition at line 1082 of file lixagent.c.

Referenced by IntAgentActivatePendingAgent(), IntLixAgentEnableInjection(), IntLixAgentExit(), IntLixAgentInject(), IntLixAgentThreadExit(), and IntLixAgentThreadInject().

◆ IntLixAgentAllocate()

static INTSTATUS IntLixAgentAllocate ( LIX_AGENT Agent)
static

Allocate a memory zone for the content of the agent.

This function check if the provided agent has an address assigned; if the agent address is NULL, IntSlackAlloc is called.

This slack memory is used only for the 'init'/'uninit' agents.

Parameters
[in]AgentThe current agent structure.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 681 of file lixagent.c.

Referenced by IntLixAgentActivatePendingAgent().

◆ IntLixAgentCreate()

static INTSTATUS IntLixAgentCreate ( LIX_AGENT_TAG  Tag,
DWORD  TagEx,
PFUNC_AgentCallbackHypercall  HypercallCallback,
PFUNC_AgentCallbackCompletion  CompletionCallback,
LIX_AGENT **  Agent 
)
static

Create an agent entry.

This function allocates a LIX_AGENT entry and fill the required information.

Function IntLixAgentGetToken is called to generate tokens for hypercall/completion/error. Function IntLixAgentFillData is called to gather the agent code/data. Function IntLixAgentResolveOffset is called to fill the agent code/data buffer with the information gathered before.

Parameters
[in]TagThe internal LIX_AGENT_TAG of the agent.
[in]TagExThe tag provided by the integrator.
[in]HypercallCallbackThis callback can be called during the agent execution.
[in]CompletionCallbackThis callback is called when the agent has finished execution.
[out]AgentOn success, contains the handle to the newly created agent.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the LIX_AGENT_HANDLER is not found.
INT_STATUS_INSUFFICIENT_RESOURCESIf the memory alloc fails.

Definition at line 726 of file lixagent.c.

Referenced by IntLixAgentInject(), and IntLixAgentThreadInject().

◆ IntLixAgentCreateThreadCompletion()

static INTSTATUS IntLixAgentCreateThreadCompletion ( LIX_AGENT Agent)
static

Called by the thread-agent when the kthread started.

An event is sent to integrator with the state of the agent.

Parameters
[in]AgentThe current agent.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 2087 of file lixagent.c.

Referenced by IntLixAgentThreadInject().

◆ IntLixAgentCreateThreadHypercall()

static INTSTATUS IntLixAgentCreateThreadHypercall ( LIX_AGENT Agent)
static

Called by the thread-agent to deploy the content of the kthread previously created.

This function writes the content of the kthread at the allocated memory (by the agent) and returns in RAX the entry point of the kthread.

Parameters
[in]AgentThe current agent.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 2028 of file lixagent.c.

Referenced by IntLixAgentThreadInject().

◆ IntLixAgentDecProcRef()

LIX_AGENT_TAG IntLixAgentDecProcRef ( const char *  Name,
BOOLEAN Removed 
)

Checks if a process is an agent or not, and decrements the ref count of that name.

Each time a process terminates, we check if it was an agent, and we decrement the reference count if its name. Once the reference count of an agent name reaches 0, it will be removed.

Parameters
[in]NameThe image name of the process which is checked.
[out]RemovedTrue if the agent was removed.
Return values
Theagent tag, if the process is found to be an agent.

Definition at line 1907 of file lixagent.c.

Referenced by IntLixTaskDestroy(), and IntLixTaskHandleExec().

◆ IntLixAgentDisablePendingAgents()

void IntLixAgentDisablePendingAgents ( void  )

Disables all pending agents.

This function should be called during the uninit phase, as it will disable all the pending agents. These agents will never be injected inside the guest.

Definition at line 1844 of file lixagent.c.

Referenced by IntAgentDisablePendingAgents(), and IntLixGuestNew().

◆ IntLixAgentEnableInjection()

void IntLixAgentEnableInjection ( void  )

Enables agent injections.

Definition at line 1964 of file lixagent.c.

Referenced by IntAgentEnableInjection(), and IntLixGuestNew().

◆ IntLixAgentError()

static INTSTATUS IntLixAgentError ( LIX_AGENT Agent)
static

Called when an error occurred while the running the current agent.

This function dumps the information about the error, send an event that contains the error and remove the name of the agent from the LIX_AGENT_NAME list.

Parameters
[in]AgentThe active agent.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1192 of file lixagent.c.

Referenced by IntLixAgentHandleBreakpoint().

◆ IntLixAgentExit()

static INTSTATUS IntLixAgentExit ( LIX_AGENT Agent)
static

Called when the agent is terminating.

The function set the RIP to the instruction from SYSCALL that was replaced. The current agent is removed and a waiting agent is scheduled.

Parameters
[in]AgentThe active agent.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NO_DETOUR_EMUThe callbacks mechanism should not emulate the current instruction.

Definition at line 1282 of file lixagent.c.

Referenced by IntLixAgentHandleBreakpoint().

◆ IntLixAgentFillData()

static INTSTATUS IntLixAgentFillData ( LIX_AGENT_DATA Data,
LIX_AGENT_HANDLER Handler 
)
static

Fetch the content of the agent.

The function calls the corresponding function (IntLixAgentFillDataFromHandler/IntLixAgentFillDataFromMemory) to fetch the information.

Parameters
[in]DataThe data that contains information about the agent code/data from guest.
[in]HandlerThe LIX_AGENT_HANDLER structure corresponding to the current agent.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf the memory alloc fails.

Definition at line 541 of file lixagent.c.

Referenced by IntLixAgentCreate(), and IntLixAgentThreadCreate().

◆ IntLixAgentFillDataFromHandler()

static INTSTATUS IntLixAgentFillDataFromHandler ( LIX_AGENT_DATA Data,
LIX_AGENT_HANDLER Handler 
)
static

Fetch the content of the agent with the provided LIX_AGENT_TAG from the corresponding LIX_AGENT_HANDLER structure.

The handlers are located in the lixaghnd.c file.

Parameters
[in]DataThe data that contains information about the agent code/data from guest.
[in]HandlerThe LIX_AGENT_HANDLER structure corresponding to the current agent.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf the memory alloc fails.

Definition at line 507 of file lixagent.c.

Referenced by IntLixAgentFillData().

◆ IntLixAgentFillDataFromMemory()

static INTSTATUS IntLixAgentFillDataFromMemory ( LIX_AGENT_DATA Data,
LIX_AGENT_TAG  Tag 
)
static

Fetch the content of the agent with the provided LIX_AGENT_TAG from memory.

Read the LIX_AGENT_HEADER from guest (deployed by the 'init' agent) and checks if the provided Tag is equal with Header->Tag; if true the information required by the agent is gathered (Data->Header, Data->Code, Data->Address, Data->Size), otherwise the next header is read.

Parameters
[in]DataThe data that contains information about the agent code/data from guest.
[in]TagThe LIX_AGENT_TAG identifier of the agent.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the entry with the provided tag is not found.
INT_STATUS_INSUFFICIENT_RESOURCESIf the memory alloc fails.

Definition at line 435 of file lixagent.c.

Referenced by IntLixAgentFillData().

◆ IntLixAgentFindInstruction()

static INTSTATUS IntLixAgentFindInstruction ( BYTE  MinLen,
QWORD InstructionVa,
BYTE InstructionLen,
BYTE InstructionBytes 
)
static

Searches for a suitable instruction to replace with a INT3 instruction.

Will try to find, starting with the SYSCALL/SYSENTER address, the first "STI" instruction and then the first instruction that's at least 5 bytes in length.

Parameters
[in]MinLenUnused.
[in]InstructionVaThe guest virtual address where a suitable instruction was found.
[in]InstructionLenThe length of the identified instruction.
[in]InstructionBytesActual instruction bytes.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.
INT_STATUS_INSUFFICIENT_RESOURCESIf a memory alloc fails.

Definition at line 92 of file lixagent.c.

Referenced by IntLixAgentActivatePendingAgent().

◆ IntLixAgentFree()

static void IntLixAgentFree ( LIX_AGENT Agent)
static

Remove the provided agent.

If the provided agent has a thread-agent assigned, the thread-agent entry is removed. If the agent used slack memory, it is freed and the code of the agent is over-written with 'NOP' instructions. Frees the data allocated by the agent and the agent entry.

Parameters
[in]AgentThe agent entry.

Definition at line 371 of file lixagent.c.

Referenced by IntLixAgentDisablePendingAgents(), IntLixAgentExit(), IntLixAgentInject(), IntLixAgentStart(), IntLixAgentThreadExit(), IntLixAgentThreadInject(), and IntLixAgentUninit().

◆ IntLixAgentGetId()

static DWORD IntLixAgentGetId ( void  )
static

Generate a new ID.

Return values
Thenewly generated ID.

Definition at line 712 of file lixagent.c.

Referenced by IntLixAgentCreate().

◆ IntLixAgentGetState()

AG_WAITSTATE IntLixAgentGetState ( DWORD Tag)

Gets the global agents state.

Parameters
[out]TagOptional agent tag, if an agent is active or pending.
Return values
agActiveIf there's an active agent.
agWaitingIf there's a pending agent.
agNoneIf there are no active or pending agents.

Definition at line 1804 of file lixagent.c.

Referenced by IntAgentGetState().

◆ IntLixAgentGetToken()

static QWORD IntLixAgentGetToken ( void  )
static

Randomly select a token to be used by the agent code when issuing hyper calls.

Return values
Theselected token.

Definition at line 78 of file lixagent.c.

Referenced by IntLixAgentCreate(), and IntLixAgentThreadCreate().

◆ IntLixAgentHandleBreakpoint()

static INTSTATUS IntLixAgentHandleBreakpoint ( LIX_AGENT Agent,
QWORD  Rip 
)
static

Called when a INT3 instruction from the current running agent is hit.

This function calls the proper function to dispatch the breakpoint.

Parameters
[in]AgentThe active agent.
[in]RipThe address of the INT3 instruction.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the breakpoint is generated from an unrecognized RIP.

Definition at line 1335 of file lixagent.c.

Referenced by IntLixAgentHandleInt3().

◆ IntLixAgentHandleInt3()

INTSTATUS IntLixAgentHandleInt3 ( QWORD  Rip)

Called when a INT3 instruction from the current running agent is executed.

This function checks if the INT3 instruction is the previously replaced instruction. If true and the instruction is not restored the IntLixAgentStart is called to start the current agent (the instruction is restored only if another CPU already restored the instruction). Otherwise the function checks if the RIP comes from our agents and handles the breakpoint.

Parameters
[in]RipThe address of the INT3 instruction.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the breakpoint is generated from an unrecognized RIP.

Definition at line 1573 of file lixagent.c.

Referenced by IntAgentHandleInt3().

◆ IntLixAgentHandleKernelVmcall()

static INTSTATUS IntLixAgentHandleKernelVmcall ( void  )
static

Called when a VMCALL instruction from the current running agent is executed.

Return values
INT_STATUS_NOT_SUPPORTEDThis function is not supported.

Definition at line 1658 of file lixagent.c.

Referenced by IntLixAgentHandleVmcall().

◆ IntLixAgentHandleUserVmcall()

static INTSTATUS IntLixAgentHandleUserVmcall ( void  )
static

Handles a VMCALL issued by a process that has been injected inside the guest.

Each injected application should have its own private VMCALL structure, depending on what information it wants to report. Currently, Introcore can digest VMCALLs from two types of applications:

  1. AGENT_HCALL_REM_TOOL - the remediation tool. This is used to send scan statuses (detections, disinfections, etc.) to Introcore and to the integrator.
  2. AGENT_HCALL_GATHER_TOOL - the log gather tool. This tool is used to gather logs from the target virtual machine and this VMCALL is used to send to log chunks to Introcore and the integrator. NOTE: If the current process has not been marked as an agent (if it was not started directly by us or by a process which we injected), all the VMCALLs will be silently discarded.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_PARAMETERIf an invalid parameter is supplied.

Definition at line 1674 of file lixagent.c.

Referenced by IntLixAgentHandleVmcall().

◆ IntLixAgentHandleVmcall()

INTSTATUS IntLixAgentHandleVmcall ( QWORD  Rip)

Handle a VMCALL that was executed inside the guest.

This function handles VMCALLs that took place inside the guest.

Parameters
[in]RipThe address of the VMCALL instruction.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1760 of file lixagent.c.

Referenced by IntAgentHandleVmcall().

◆ IntLixAgentIncProcRef()

LIX_AGENT_TAG IntLixAgentIncProcRef ( const char *  Name)

Checks if a process is an agent or not, and increments the ref count of that name.

Each time a process is created, we check if its name matches the name of a previously injected agent. If it does, we flag that process as an agent, and we increment the reference count of the name.

Parameters
[in]NameThe image name of the process which is checked.
Return values
Theagent tag, if the process is found to be an agent.

Definition at line 1869 of file lixagent.c.

Referenced by IntLixTaskCreate(), and IntLixTaskHandleExec().

◆ IntLixAgentInit()

void IntLixAgentInit ( void  )

Initialize the agents state.

Definition at line 1978 of file lixagent.c.

Referenced by IntLixGuestNew().

◆ IntLixAgentInject()

INTSTATUS IntLixAgentInject ( LIX_AGENT_TAG  Tag,
PFUNC_AgentCallbackHypercall  HypercallCallback,
PFUNC_AgentCallbackCompletion  CompletionCallback 
)

Schedule an agent injection inside the guest.

This function schedule the injection of an agent identified by the LIX_AGENT_TAG inside the guest space. This function is used directly only for internal agents (init/uninit).

Parameters
[in]TagThe internal LIX_AGENT_TAG of the agent.
[in]HypercallCallbackThis callback can be called during the agent execution.
[in]CompletionCallbackThis callback is called when the agent has finished execution.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZEDIf the agent state is not initialized.
INT_STATUS_NOT_FOUNDIf the LIX_AGENT_HANDLER is not found.
INT_STATUS_INSUFFICIENT_RESOURCESIf the memory alloc fails.

Definition at line 896 of file lixagent.c.

Referenced by IntLixGuestAllocate(), and IntLixGuestDeployUninitAgent().

◆ IntLixAgentMatchVersion()

BOOLEAN IntLixAgentMatchVersion ( LIX_AGENT_FUNCTIONS Function)

Checks if the provided LIX_AGENT_FUNCTIONS match the current guest version.

Parameters
[in]FunctionContains a list of function required by the current agent.
Return values
Trueif the LIX_AGENT_FUNCTIONS version matches the current guest version, otherwise false.

Definition at line 570 of file lixagent.c.

Referenced by IntLixAgentResolveOffset().

◆ IntLixAgentNameCreate()

static INTSTATUS IntLixAgentNameCreate ( const char *  Name,
DWORD  Tag,
DWORD  Agid,
LIX_AGENT_NAME **  AgentName 
)
static

Create an agent name and insert the newly create agent-name to linked list.

Parameters
[in]NameThe name of the agent.
[in]TagThe agent tag.
[in]AgidThe agent ID.
[out]AgentNameOn success, contains the newly create agent name object.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INSUFFICIENT_RESOURCESIf a memory alloc fails.

Definition at line 231 of file lixagent.c.

Referenced by IntLixAgentThreadInject().

◆ IntLixAgentNameGetTagByAgid()

DWORD IntLixAgentNameGetTagByAgid ( DWORD  Agid)

Iterates through all agent names and returns the tag of the agent that has the provided agent ID.

Parameters
[in]AgidThe agent ID.
Return values
Thetag of the agent that has the provided agent ID.

Definition at line 312 of file lixagent.c.

Referenced by IntLixAgentHandleUserVmcall().

◆ IntLixAgentNameIsRunning()

static BOOLEAN IntLixAgentNameIsRunning ( const char *  Name)
static

Iterates through all agent names to check if an agent with the provided name is running.

Parameters
[in]NameThe name of the agent.
Return values
Trueif an agent with the provided name is running, otherwise false.

Definition at line 204 of file lixagent.c.

Referenced by IntLixAgentThreadInject().

◆ IntLixAgentNameRemove()

static void IntLixAgentNameRemove ( LIX_AGENT_NAME Name)
static

Frees and removes from our list the provided LIX_AGENT_NAME.

Parameters
[in]NameThe agent-name entry.

Definition at line 270 of file lixagent.c.

Referenced by IntLixAgentDecProcRef(), IntLixAgentNameRemoveByAgid(), and IntLixAgentThreadInject().

◆ IntLixAgentNameRemoveByAgid()

void IntLixAgentNameRemoveByAgid ( DWORD  Agid)

Iterates through all agent names and removes the entry that contains the provided ID.

Parameters
[in]AgidThe agent ID.

Definition at line 285 of file lixagent.c.

Referenced by IntLixAgentError(), IntLixAgentHandleUserVmcall(), and IntLixAgentThreadError().

◆ IntLixAgentResolveOffset()

static INTSTATUS IntLixAgentResolveOffset ( LIX_AGENT_DATA Data,
LIX_AGENT_HANDLER Handler 
)
static

Search the functions and complete the args/tokens required by the agent.

This function fill the external data of the agent:

  1. Copy the hypercall/completion/error tokens to the agent code/data buffer.
  2. Each function name is assigned to a list that contains the number of the functions and the required functions by the agent, because on different kernel versions a function has different signature but the purpose of it is the same. For example on kernel version 2.6.x, to write a file from kernel the 'kernel_write' function is used and on kernel version 4.x.x the '__kernel_write' function is used, and that's why we search the both function. For that example the required field is set to 1 and the count is set to 2 -> only one function must be found.

If the any LIX_AGENT_FUNCTIONS match the current guest version, then for each entry that contains a function name, IntKsymFindByName is called to get the address; if the kallsym is found the address is copied to the agent buffer, otherwise the 'NULL' value is copied.

  1. Copy the provided arguments to the agent code/data buffer.
Parameters
[in]DataThe data that contains information about the agent code/data from guest.
[in]HandlerThe LIX_AGENT_HANDLER structure corresponding to the current agent.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the LIX_AGENT_FUNCTIONS data is not found or if the function address is not found.

Definition at line 593 of file lixagent.c.

Referenced by IntLixAgentCreate(), and IntLixAgentThreadCreate().

◆ IntLixAgentSendEvent()

void IntLixAgentSendEvent ( AGENT_EVENT_TYPE  Event,
DWORD  AgentTag,
DWORD  ErrorCode 
)

Send an event to the integrator that contains the AGENT_EVENT_TYPE, tag of the agent and the last error code.

Parameters
[in]EventThe type of the event.
[in]AgentTagThe tag of the agent
[in]ErrorCodeThe last error-code of the agent.

Definition at line 2119 of file lixagent.c.

Referenced by IntLixAgentCreateThreadCompletion(), IntLixAgentCreateThreadHypercall(), IntLixAgentError(), IntLixAgentStart(), IntLixAgentThreadError(), and IntLixDepComplete().

◆ IntLixAgentStart()

static INTSTATUS IntLixAgentStart ( LIX_AGENT Agent)
static

Called when the INT3 instruction from SYSCALL is hit.

The function unlocks the replaced instruction from SYSCALL and set the RIP to our agent memory zone.

Parameters
[in]AgentThe active agent.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NO_DETOUR_EMUThe callbacks mechanism should not emulate the current instruction.

Definition at line 1231 of file lixagent.c.

Referenced by IntLixAgentHandleInt3().

◆ IntLixAgentThreadCreate()

static INTSTATUS IntLixAgentThreadCreate ( LIX_AGENT_TAG  Tag,
PFUNC_AgentCallbackHypercall  HypercallCallback,
PFUNC_AgentCallbackCompletion  CompletionCallback,
BYTE ContentAddress,
DWORD  ContentSize,
LIX_AGENT_THREAD **  Thread 
)
static

Create an agent-thread entry.

This function allocates a LIX_AGENT_THREAD entry and fill the required information.

Function IntLixAgentGetToken is called to generate tokens for hypercall/completion/error. Function IntLixAgentFillData is called to gather the agent code/data. Function IntLixAgentResolveOffset is called to fill the agent code/data buffer with the information gathered before.

Parameters
[in]TagThe internal LIX_AGENT_TAG of the agent.
[in]HypercallCallbackThis callback can be called during the agent execution.
[in]CompletionCallbackThis callback is called when the agent has finished execution.
[in]ContentAddressPointer to a memory area containing the actual agent.
[in]ContentSizeThe size of the agent, in bytes.
[out]ThreadOn success, contains the handle to the newly created agent.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the LIX_AGENT_HANDLER is not found.
INT_STATUS_INSUFFICIENT_RESOURCESIf the memory alloc fails.

Definition at line 813 of file lixagent.c.

Referenced by IntLixAgentThreadInject().

◆ IntLixAgentThreadError()

static INTSTATUS IntLixAgentThreadError ( LIX_AGENT Agent)
static

Called when an error occurred while the running the current thread-agent.

This function dumps the information about the error, send an event that contains the error and remove the name of the agent from the LIX_AGENT_NAME list.

Parameters
[in]AgentThe active agent.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 1416 of file lixagent.c.

Referenced by IntLixAgentThreadHandleBreakpoint().

◆ IntLixAgentThreadExit()

static INTSTATUS IntLixAgentThreadExit ( LIX_AGENT Agent)
static

Called when the thread-agent is terminating.

The function set the RIP to the instruction from SYSCALL that was replaced. The current agent is removed and a waiting agent is scheduled.

Parameters
[in]AgentThe active agent.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NO_DETOUR_EMUThe callbacks mechanism should not emulate the current instruction.

Definition at line 1456 of file lixagent.c.

Referenced by IntLixAgentThreadHandleBreakpoint().

◆ IntLixAgentThreadFree()

static INTSTATUS IntLixAgentThreadFree ( LIX_AGENT_THREAD Thread)
static

Remove the provided agent-thread.

Frees the data allocated by the thread-agent and the thread-agent entry.

Parameters
[in]ThreadThe agent-thread entry.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 341 of file lixagent.c.

Referenced by IntLixAgentCreateThreadHypercall(), and IntLixAgentFree().

◆ IntLixAgentThreadHandleBreakpoint()

static INTSTATUS IntLixAgentThreadHandleBreakpoint ( LIX_AGENT Agent,
QWORD  Rip 
)
static

Called when a INT3 instruction from the current running thread-agent is hit.

This function calls the proper function to dispatch the breakpoint.

Parameters
[in]AgentThe active agent.
[in]RipThe address of the INT3 instruction.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_FOUNDIf the breakpoint is generated from an unrecognized RIP.

Definition at line 1490 of file lixagent.c.

Referenced by IntLixAgentHandleInt3().

◆ IntLixAgentThreadInject()

INTSTATUS IntLixAgentThreadInject ( LIX_AGENT_TAG  Tag,
DWORD  TagEx,
AGENT_TYPE  AgentType,
PFUNC_AgentCallbackHypercall  HypercallCallback,
PFUNC_AgentCallbackCompletion  CompletionCallback,
const char *  Name,
BYTE ContentAddress,
DWORD  ContentSize 
)

Schedule an thread-agent injection inside the guest.

A thread-agent is a bootstrap that creates a kthread and allocate a zone of memory; the provided content is copied to the allocated memory zone and the kthread will execute the deployed content.

This function schedule the injection of an thread-agent identified by the LIX_AGENT_TAG inside the guest space.

Parameters
[in]TagThe internal LIX_AGENT_TAG of the agent.
[in]TagExThe tag provided by the integrator.
[in]AgentTypeThe type of the injected agent (AGENT_TYPE).
[in]HypercallCallbackThis callback can be called during the agent execution.
[in]CompletionCallbackThis callback is called when the agent has finished execution.
[in]NameThe agent name.
[in]ContentAddressPointer to a memory area containing the actual agent.
[in]ContentSizeThe size of the agent, in bytes.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZEDIf the agent state is not initialized; if is not safe to inject the agent; if the bootstrap agent data/code is not deployed yet.
INT_STATUS_ALREADY_INITIALIZEDIf an agent with the same name is already running.
INT_STATUS_INSUFFICIENT_RESOURCESIf the memory alloc fails.

Definition at line 954 of file lixagent.c.

Referenced by IntLixDepInjectFile(), IntLixDepInjectProcess(), and IntLixDepRunCommand().

◆ IntLixAgentUninit()

INTSTATUS IntLixAgentUninit ( void  )

Uninit the agents state.

Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZED_HINTIf the agents state has not been initialized yet.

Definition at line 1997 of file lixagent.c.

Referenced by IntLixGuestUninit().

Variable Documentation

◆ gLixAgentState

LIX_AGENT_STATE gLixAgentState
static
Initial value:
=
{
}
static LIX_AGENT_STATE gLixAgentState
Definition: lixagent.c:69
LIST_HEAD PendingAgents
List of agents waiting to be injected.
Definition: lixagent.c:56
LIST_HEAD AgentNames
List of agent names.
Definition: lixagent.c:57
#define LIST_HEAD_INIT(Name)
Definition: introlists.h:39

Definition at line 69 of file lixagent.c.