Bitdefender Hypervisor Memory Introspection
winumpath.c File Reference

This module provides a caching facility for windows user-mode paths, as well as a way of encapsulating the paths in WINUM_PATH objects. More...

#include "winumpath.h"
#include "crc32.h"
#include "introcore.h"

Go to the source code of this file.

Functions

static void IntWinUmPathRbTreeNodeFree (RBNODE *Node)
 Function called whenever a node from the red-black tree is freed. More...
 
static int IntWinUmPathRbTreeNodeCompare (RBNODE *Left, RBNODE *Right)
 Function used for comparison of two red-black tree nodes describing two different paths. More...
 
static WINUM_PATHIntWinUmPathFetchBySubsection (QWORD SubsectionGva)
 Fetches a path object by the given unique identifier, which is the subsection virtual address. More...
 
static void IntWinUmPathFree (WINUM_PATH *Path)
 Releases resources associated to a WINUM_PATH object. More...
 
WINUM_PATHIntWinUmPathCreate (const WCHAR *Path, DWORD PathSize, QWORD SubsectionGva)
 Creates a WINUM_PATH object from the given parameters. More...
 
WINUM_PATHIntWinUmPathReference (WINUM_PATH *Path)
 Increases the reference count of the given WINUM_PATH object. More...
 
WINUM_PATHIntWinUmPathFetchAndReferenceBySubsection (QWORD SubsectionGva)
 Fetches a WINUM_PATH object by the unique identifier and increments the reference counter on it. More...
 
void IntWinUmPathDereference (WINUM_PATH **Path)
 Dereferences a WINUM_PATH object, releasing the resources if the reference count has reached 0. More...
 

Variables

static WCHAR gInvalidModulePath [8] = u"<error>"
 
static WINUM_PATH gInvalidUmPath
 
static RBTREE gPaths = RB_TREE_INIT(gPaths, IntWinUmPathRbTreeNodeFree, IntWinUmPathRbTreeNodeCompare)
 

Detailed Description

This module provides a caching facility for windows user-mode paths, as well as a way of encapsulating the paths in WINUM_PATH objects.

As many user-mode modules are common in Windows, many of them being located in the System32 folder, there is obviously no point in keeping the exactly same path of a module loaded in two different processes twice. For this reason, this module will cache the paths extracted from the guest, identifying them uniquely by the subsection guest virtual address (see IntWinUmPathFetchBySubsection for a more detailed explanation), and instead of duplicating the objects, they will be referenced in other modules where the path objects are used by subsequently calling IntWinUmPathReference/IntWinUmPathFetchAndReferenceBySubsection. This modules also provides an encapsulation of the path objects, keeping the path, the name, the hash, the reference count and the subsection gva, in order to be easily accessed by a caller who uses the path objects provided. Note: failure to dereference a path when it is not used anymore in guest will always result in path mismatch. For example, if a path is not used anymore in the guest then the subsection gva will most likely be re-used for another path. Due to failure to dereference the path, the introcore engine will think that it's the same path as before when fetching it from the cache provided by this module. Thus, there might be false positives (e.g. mismatch ntdll for any other module) or loss of protection (e.g. mismatch process path for unprotected process path), which should be avoided by always dereferencing the path when it is not used anymore.

Definition in file winumpath.c.

Function Documentation

◆ IntWinUmPathCreate()

WINUM_PATH* IntWinUmPathCreate ( const WCHAR Path,
DWORD  PathSize,
QWORD  SubsectionGva 
)

Creates a WINUM_PATH object from the given parameters.

Provided the path string which was read from the guest, the total length of the path and the subsection guest virtual address from which the path string was read, which will serve as a unique identifier for the given path, this function will create a path object based on those. Note that if any error occurs, gInvalidUmPath will be returned by this function. This function may get called on already cached paths, in which case a warning will be issued and the cached path will be fetched from the cache and the reference count will be incremented.

Parameters
[in]PathThe path string which was read from the guest.
[in]PathSizeThe total number of bytes the path contains.
[in]SubsectionGvaThe guest virtual address of the subsection from which the path was fetched.
Returns
The created WINUM_PATH object in case of success or the already cached path if the path exists in the gPaths red-black tree. gInvalidUmPath in case of error.

Definition at line 184 of file winumpath.c.

Referenced by IntWinVadHandleFilePathInMemory().

◆ IntWinUmPathDereference()

void IntWinUmPathDereference ( WINUM_PATH **  Path)

Dereferences a WINUM_PATH object, releasing the resources if the reference count has reached 0.

When all the callers to IntWinUmPathReference/IntWinUmPathFetchAndReferenceBySubsection or after a path creation has been made, decide that the path should no longer be used, this function will get called and the reference count will reach 0. When reaching 0, the resources (that means the Path string where the path is saved, as well as the path object) will be released. This function will also set to NULL the object given as parameter.

Parameters
[in]PathA pointer to the WINUM_PATH object which should be dereferenced or freed if the reference counter reaches 0.

Definition at line 340 of file winumpath.c.

Referenced by IntWinModRemoveModule(), and IntWinVadDestroyObject().

◆ IntWinUmPathFetchAndReferenceBySubsection()

WINUM_PATH* IntWinUmPathFetchAndReferenceBySubsection ( QWORD  SubsectionGva)

Fetches a WINUM_PATH object by the unique identifier and increments the reference counter on it.

Parameters
[in]SubsectionGvaThe guest virtual address of the subsection where the path is found. Serves as a unique identifier.
Returns
The WINUM_PATH object uniquely identified by the given SubsectionGva. If no path exists having the given subsection, the return value will be NULL.

Definition at line 314 of file winumpath.c.

Referenced by IntWinUmPathCreate(), and IntWinVadFetchImageName().

◆ IntWinUmPathFetchBySubsection()

static WINUM_PATH* IntWinUmPathFetchBySubsection ( QWORD  SubsectionGva)
static

Fetches a path object by the given unique identifier, which is the subsection virtual address.

Two subsections, described inside the guest as nt!_SUBSECTION structure will always have the same FILE_OBJECT pointer associated with them if the subsections reside at the same address. Thus, the FILE_OBJECT associated to them will contain the path string. Every VAD which describes a mapped file will have a subsection, therefore, the subsection structure address will always be an unique identifier for paths associated to VADs inside the guest.

Parameters
[in]SubsectionGvaThe guest virtual address of the subsection structure, which is considered an unique identifier for paths.
Returns
The WINUM_PATH object associated with the given Subsection gva, if it exists, otherwise NULL.

Definition at line 125 of file winumpath.c.

Referenced by IntWinUmPathFetchAndReferenceBySubsection().

◆ IntWinUmPathFree()

static void IntWinUmPathFree ( WINUM_PATH Path)
static

Releases resources associated to a WINUM_PATH object.

Parameters
[in]PathThe WINUM_PATH object which is desired to be freed.

Definition at line 165 of file winumpath.c.

Referenced by IntWinUmPathCreate(), and IntWinUmPathDereference().

◆ IntWinUmPathRbTreeNodeCompare()

static int IntWinUmPathRbTreeNodeCompare ( RBNODE Left,
RBNODE Right 
)
static

Function used for comparison of two red-black tree nodes describing two different paths.

The comparison is done based on the guest virtual address of the subsection associated with each path object.

Parameters
[in]LeftThe first node to be compared.
[in]RightThe second node to be compared.
Return values
-1If the first node has a subsection which is less than the second node's subsection. 1 If the second node has a subsection which is less than the first node's subsection. 0 If the subsections are equal. Note that in this case the left and right nodes should describe exactly the same path objects.

Definition at line 78 of file winumpath.c.

◆ IntWinUmPathRbTreeNodeFree()

static void IntWinUmPathRbTreeNodeFree ( RBNODE Node)
static

Function called whenever a node from the red-black tree is freed.

Parameters
[in,out]NodeThe red-black tree which is currently freed.

Definition at line 64 of file winumpath.c.

◆ IntWinUmPathReference()

WINUM_PATH* IntWinUmPathReference ( WINUM_PATH Path)

Increases the reference count of the given WINUM_PATH object.

Calling this function means that one uses a reference to a Path object and desires that the path should not be freed until one calls the IntWinUmPathDereference function on the path.

Parameters
[in]PathThe WINUM_PATH object for which the reference count will be incremented.
Returns
The path after the reference count was incremented.

Definition at line 292 of file winumpath.c.

Referenced by IntWinModHandleModulePathInMemory().

Variable Documentation

◆ gInvalidModulePath

WCHAR gInvalidModulePath[8] = u"<error>"
static

String placeholder for invalid paths.

Definition at line 40 of file winumpath.c.

◆ gInvalidUmPath

WINUM_PATH gInvalidUmPath
static
Initial value:
=
{
.PathSize = CWSTRLEN(gInvalidModulePath) * 2,
.NameSize = CWSTRLEN(gInvalidModulePath) * 2,
.NameHash = INITIAL_CRC_VALUE,
.RefCount = 1,
.SubsectionGva = 0,
}
#define INITIAL_CRC_VALUE
Definition: introdefs.h:221
#define CWSTRLEN(Wstring)
Definition: introdefs.h:104
static WCHAR gInvalidModulePath[8]
Definition: winumpath.c:40

Path object describing an invalid path.

Definition at line 46 of file winumpath.c.

Referenced by IntWinUmPathCreate().

◆ gPaths

Global red-black tree containing all the cached paths.

Definition at line 121 of file winumpath.c.