Bitdefender Hypervisor Memory Introspection
winumdoubleagent.c File Reference
#include "winummodule.h"
#include "winummoduleblock.h"
#include "alerts.h"
#include "guests.h"
#include "swapmem.h"

Go to the source code of this file.

Functions

static INTSTATUS IntWinDagentSendDoubleAgentAlert (const WIN_PROCESS_MODULE *Module, const WIN_PROCESS_MODULE *ReturnModule, INTRO_ACTION Action, INTRO_ACTION_REASON Reason, QWORD RetAddr)
 Sends a DoubleAgent alert. More...
 
static INTSTATUS IntWinDagentHandleDoubleAgent (WIN_PROCESS_MODULE *Module, const WIN_PROCESS_MODULE *ReturnModule, INTRO_ACTION *Action, QWORD RetAddr)
 Handles a DoubleAgent module load. More...
 
static INTSTATUS IntWinDagentHandleSlackWritable (void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, const BYTE *Data, DWORD DataSize, DWORD Flags)
 Swapmem callback which is called when the desired area between suspicious module section was swapped-in and made writable. More...
 
static INTSTATUS IntWinDagentHandleSuspModExecution (WIN_PROCESS_MODULE *Module, void *BlockObject, QWORD DllHandle, QWORD Reason, QWORD Reserved, QWORD RetAddress, INTRO_ACTION *Action)
 Callback for module block mechanism, being called whenever executions take place in the possible malicious DLL. More...
 
static INTSTATUS IntWinDagentHandleSuspModHeaders (WIN_PROCESS_MODULE *Module, BYTE *Headers)
 Callback called through module block mechanism when the suspicious module headers are in memory. More...
 
static INTSTATUS IntWinDagentHandleVerifierReason (WIN_PROCESS_MODULE *Module, void *BlockObject, QWORD DllHandle, QWORD Reason, QWORD Reserved, QWORD RetAddress, INTRO_ACTION *Action)
 Called by the module block mechanism when DllMain was called with a specific Reason, DLL_VERIFIER_PROVIDER in this case. More...
 
static INTSTATUS IntWinDagentCheckNativeSubsystem (void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, BYTE *Data, DWORD DataSize, DWORD Flags)
 Swapmem callback for the main module headers of the possible affected process. More...
 
static INTSTATUS IntWinModDagentSuspModCleanup (WIN_PROCESS_MODULE *Module, const void *BlockObject)
 Callback which is called from module block mechanism before the object is destroyed. More...
 
static BOOLEAN IntWinDagentIsInitialDll (WIN_PROCESS_MODULE *Module)
 Check if a module is one of the modules listed in gInitialDlls. More...
 
INTSTATUS IntWinDagentCheckSuspiciousDllLoad (WIN_PROCESS_MODULE *Module)
 Checks if the given module is suspicious of loading through the double agent technique and calls the module block mechanism if it is. More...
 

Variables

const PROTECTED_DLL_INFO gInitialDlls []
 

Function Documentation

◆ IntWinDagentCheckNativeSubsystem()

static INTSTATUS IntWinDagentCheckNativeSubsystem ( void *  Context,
QWORD  Cr3,
QWORD  VirtualAddress,
QWORD  PhysicalAddress,
BYTE Data,
DWORD  DataSize,
DWORD  Flags 
)
static

Swapmem callback for the main module headers of the possible affected process.

The processes which are from the Native Subsystem (IMAGE_SUBSYSTEM_NATIVE) will not load kernel32.dll in the initialization phase, but rather will load if needed afterwards, most of the times, for system processes, not loading it at all. This may cause some false positives and/or performance impact due to checking all the modules, which are considered "before kernel32.dll" since it didn't load at all. For this purpose, we will check that the process is from native subsystem, and will not check anymore modules if it is.

Parameters
[in]ContextThe WIN_PROCESS_MODULE structure.
[in]Cr3The virtual address space.
[in]VirtualAddressThe base virtual address read.
[in]PhysicalAddressThe physical address of the first page (VirtualAddress) read.
[in]DataBuffer containing the read data. This will be freed once the callback returns!
[in]DataSizeSize of the Data buffer.
[in]FlagsSwap flags. Check out SWAPMEM_FLG* for more info.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 657 of file winumdoubleagent.c.

Referenced by IntWinDagentCheckSuspiciousDllLoad().

◆ IntWinDagentCheckSuspiciousDllLoad()

INTSTATUS IntWinDagentCheckSuspiciousDllLoad ( WIN_PROCESS_MODULE Module)

Checks if the given module is suspicious of loading through the double agent technique and calls the module block mechanism if it is.

This is the main function which is called on modules for checking if the double agent technique was used or not. This function will check if verifier.dll is loaded in the current process and if the current module is loaded before kernel32.dll. Take note that there are some cases like the current module is excepted, and loads kernel32.dll, but some module, which is malicious, is also loaded afterwards. For this purpose, we'll check all modules if verifier is loaded, and don't consider a module malicious if it hasn't been called with DLL_VERIFIER_PROVIDER reason. This is also the function where we start checking the native subsystem and we register the module block callbacks for the suspicious modules, which will be called afterwards through the module block mechanism. Note that we can only detect the technique and block it if we are at module load time. For statically detected modules, there is very little to no evidence for such a DLL that it was loaded through double agent, thus the detection cannot take place, and the execution blocking would not be of any use, since the possible malicious part of the DLL was already executed.

Parameters
[in]ModuleThe module which is to be verified whether it is suspicious or not.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_NEEDED_HINTIf the process is not protected, module was static detected or other invalid configurations.

Definition at line 785 of file winumdoubleagent.c.

Referenced by IntWinModHandleModulePathInMemory().

◆ IntWinDagentHandleDoubleAgent()

static INTSTATUS IntWinDagentHandleDoubleAgent ( WIN_PROCESS_MODULE Module,
const WIN_PROCESS_MODULE ReturnModule,
INTRO_ACTION Action,
QWORD  RetAddr 
)
static

Handles a DoubleAgent module load.

This module handles a DoubleAgent-like module being loaded inside a process. If it determines the attempt is malicious, it will block it and it will send an alert.

Parameters
[in]ModuleThe module that was loaded.
[in]ReturnModuleReturn module.
[out]ActionThe desired action.
[in]RetAddrThe return address.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 105 of file winumdoubleagent.c.

Referenced by IntWinDagentHandleSuspModExecution().

◆ IntWinDagentHandleSlackWritable()

static INTSTATUS IntWinDagentHandleSlackWritable ( void *  Context,
QWORD  Cr3,
QWORD  VirtualAddress,
QWORD  PhysicalAddress,
const BYTE Data,
DWORD  DataSize,
DWORD  Flags 
)
static

Swapmem callback which is called when the desired area between suspicious module section was swapped-in and made writable.

We need some space inside the given module so that we initialize the RTL_VERIFIER_PROVIDER_DESCRIPTOR structure needed for verifier.dll. Without this structure initialized, the verifier engine will close the process with STATUS_DLL_INIT_FAILED, which is not desired. Thus, we get some space from within the module, which is writable, and we give it to the verifier engine, which thinks it is given by the possible malicious DLL.

Parameters
[in]ContextThe WIN_PROCESS_MODULE structure.
[in]Cr3The virtual address space.
[in]VirtualAddressThe base virtual address read.
[in]PhysicalAddressThe physical address of the first page (VirtualAddress) read.
[in]DataBuffer containing the read data. This will be freed once the callback returns!
[in]DataSizeSize of the Data buffer.
[in]FlagsSwap flags. Check out SWAPMEM_FLG* for more info.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 192 of file winumdoubleagent.c.

Referenced by IntWinDagentHandleVerifierReason().

◆ IntWinDagentHandleSuspModExecution()

static INTSTATUS IntWinDagentHandleSuspModExecution ( WIN_PROCESS_MODULE Module,
void *  BlockObject,
QWORD  DllHandle,
QWORD  Reason,
QWORD  Reserved,
QWORD  RetAddress,
INTRO_ACTION Action 
)
static

Callback for module block mechanism, being called whenever executions take place in the possible malicious DLL.

This is the main callback which contains the logic whenever an execution takes place in a possible malicious DLL, verifying some heuristics so that the Introcore engine can be sure that we are on a double agent case, such as verifying that the process main module is from native subsystem, in which case it means that the module is not loading kernel32.dll, thus the initial heuristic regarding loading before kernel32.dll would not stand. Other verification like the return module and whether we have a slack space to write the needed verifier structure are made, as well as checking against the exception mechanism through IntWinDagentHandleDoubleAgent. Note: DllHandle, Reason, Reserved will be equal to WINMODBLOCK_INVALID_VALUE if the execution took place on something different than DllMain.

Parameters
[in]ModuleThe module which made an execution and is considered suspicious.
[in]BlockObjectThe WIN_MOD_BLOCK_OBJECT used for operations involving the module block mechanism.
[in]DllHandleThe first parameter of DllMain.
[in]ReasonThe second parameter of DllMain.
[in]ReservedThe third parameter of DllMain.
[in]RetAddressThe RIP address which called the suspicious module.
[in,out]ActionThe INTRO_ACTION returned to module block mechanism.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_NOT_INITIALIZEDIf the slack space between sections was not found during the headers parsing phase.

Definition at line 332 of file winumdoubleagent.c.

Referenced by IntWinDagentCheckSuspiciousDllLoad().

◆ IntWinDagentHandleSuspModHeaders()

static INTSTATUS IntWinDagentHandleSuspModHeaders ( WIN_PROCESS_MODULE Module,
BYTE Headers 
)
static

Callback called through module block mechanism when the suspicious module headers are in memory.

This callback will search, based on the given header, some place inside the suspicious module, between sections, which can be writable and where we can put the RTL_VERIFIER_PROVIDER_DESCRIPTOR structure which is needed for proper verifier engine initialization.

Parameters
[in,out]ModuleThe WIN_PROCESS_MODULE structure for the module which is considered suspicious.
[in]HeadersThe MZPE headers of the given module.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 454 of file winumdoubleagent.c.

Referenced by IntWinDagentCheckSuspiciousDllLoad().

◆ IntWinDagentHandleVerifierReason()

static INTSTATUS IntWinDagentHandleVerifierReason ( WIN_PROCESS_MODULE Module,
void *  BlockObject,
QWORD  DllHandle,
QWORD  Reason,
QWORD  Reserved,
QWORD  RetAddress,
INTRO_ACTION Action 
)
static

Called by the module block mechanism when DllMain was called with a specific Reason, DLL_VERIFIER_PROVIDER in this case.

We want to block all executions and send an alert whenever a suspicious module is called, but in order to not cause a crash to the protected process, e.g. due to improper verifier engine initialization, we need to do some preparatory steps in some cases. When the DLL_VERIFIER_PROVIDER is given as a Reason to DllMain, the module is expected to complete a RTL_VERIFIER_PROVIDER_DESCRIPTOR structure, so that the verifier engine can initialize properly. As we cannot rely on the suspicious module execution, which may do malicious actions after the initialization of the structure, we should initialize it. For this purpose, we have gathered when we have swapped in the headers an address between the module's sections, where we'll put the structure, and at this point we will make it writable (and obviously present in memory), so that the IntWinDagentHandleSlackWritable callback can complete the structure with the data needed by the verifier engine. Note that this callback may issue an introGuestRetry action, which will keep re-executing the DllMain first instruction, causing an EPT violation each time, until the page fault for the structure was injected.

Parameters
[in]ModuleThe module which made an execution and is considered suspicious.
[in]BlockObjectThe WIN_MOD_BLOCK_OBJECT used for operations involving the module block mechanism.
[in]DllHandleThe first parameter of DllMain.
[in]ReasonThe second parameter of DllMain.
[in]ReservedThe third parameter of DllMain.
[in]RetAddressThe RIP address which called the suspicious module.
[in,out]ActionThe INTRO_ACTION returned to module block mechanism.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 552 of file winumdoubleagent.c.

Referenced by IntWinDagentCheckSuspiciousDllLoad().

◆ IntWinDagentIsInitialDll()

static BOOLEAN IntWinDagentIsInitialDll ( WIN_PROCESS_MODULE Module)
static

Check if a module is one of the modules listed in gInitialDlls.

Parameters
[in]ModuleThe module to check.
Returns
True if the indicated module belongs to gInitialDlls, false otherwise.

Definition at line 759 of file winumdoubleagent.c.

Referenced by IntWinDagentCheckSuspiciousDllLoad().

◆ IntWinDagentSendDoubleAgentAlert()

static INTSTATUS IntWinDagentSendDoubleAgentAlert ( const WIN_PROCESS_MODULE Module,
const WIN_PROCESS_MODULE ReturnModule,
INTRO_ACTION  Action,
INTRO_ACTION_REASON  Reason,
QWORD  RetAddr 
)
static

Sends a DoubleAgent alert.

When a DoubleAgent like attack is identified, this function will construct and send a introEventModuleLoadViolation alert to the integrator.

Parameters
[in]ModuleThe module that got maliciously loaded.
[in]ReturnModuleThe return module.
[in]ActionThe taken action.
[in]ReasonThe action reason.
[in]RetAddrThe address the module will return at.
Return values
INT_STATUS_SUCCESSOn success.

Definition at line 25 of file winumdoubleagent.c.

Referenced by IntWinDagentHandleDoubleAgent().

◆ IntWinModDagentSuspModCleanup()

static INTSTATUS IntWinModDagentSuspModCleanup ( WIN_PROCESS_MODULE Module,
const void *  BlockObject 
)
static

Callback which is called from module block mechanism before the object is destroyed.

Before the object is destroyed, the module block will call this function so that one can make sure that there are no more references to that module block object. The destruction of the object can take place either because at some point the decision that the module is not suspicious was made or because the DLL unloaded.

Parameters
[in,out]ModuleThe WIN_PROCESS_MODULE structure for which the module block object is destroyed.
[in]BlockObjectThe module block object which is being destroyed.
Return values
INT_STATUS_SUCCESSOn success.
INT_STATUS_INVALID_INTERNAL_STATEWhen the given module is not associated with the given block object.

Definition at line 728 of file winumdoubleagent.c.

Referenced by IntWinDagentCheckSuspiciousDllLoad().

Variable Documentation

◆ gInitialDlls

const PROTECTED_DLL_INFO gInitialDlls[]
Initial value:
=
{
{ u"ntdll.dll", NAMEHASH_NTDLL },
{ u"kernel32.dll", NAMEHASH_KERNEL32 },
{ u"verifier.dll", NAMEHASH_VERIFIER },
{ u"apisetschema.dll", NAMEHASH_APISETSCHEMA },
}
#define NAMEHASH_NTDLL
Definition: winummodule.h:11
#define NAMEHASH_APISETSCHEMA
Definition: winummodule.h:24
#define NAMEHASH_VERIFIER
Definition: winummodule.h:23
#define NAMEHASH_KERNEL32
Definition: winummodule.h:12

The list of DLLs that can be loaded before kernel32.dll is loaded.

Definition at line 15 of file winumdoubleagent.c.