89 if (pExport1->
Rva < pExport2->
Rva)
93 else if (pExport1->
Rva > pExport2->
Rva)
124 if (pair[0] >= pExport->
Rva && pair[0] < pExport->
Rva + pair[1])
128 else if (pExport->
Rva < pair[0])
176 if (0 == strcmp(pExport->
Names[i],
"memcpy"))
180 else if (0 == strcmp(pExport->
Names[i],
"memset"))
186 if (0 == strcmp(pExport->
Names[i],
"memmove"))
192 if (0 == strcmp(pExport->
Names[i],
"memcpy_s"))
198 if (0 == strcmp(pExport->
Names[i],
"memmove_s"))
247 for (
QWORD crtGva = Gva; Gva - crtGva < Length; crtGva--)
283 pCache = Module->Cache;
298 DWORD pair[2] = { 0 };
300 pair[1] = ErrorRange;
333 if (pProc->Subsystemx64 != NULL)
337 if (pMod->Cache == Cache && pMod->ExportsSwapHandle != NULL)
342 ERROR(
"[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
343 finalStatus = status;
346 pMod->ExportsSwapHandle = NULL;
351 if (pProc->Subsystemx86 != NULL)
355 if (pMod->Cache == Cache && pMod->ExportsSwapHandle != NULL)
360 ERROR(
"[ERROR] IntSwapMemRemoveTransaction failed: 0x%08x\n", status);
361 finalStatus = status;
364 pMod->ExportsSwapHandle = NULL;
421 pCache = pMod->
Cache;
435 ERROR(
"[ERROR] IntWinModCancelExportTransactions failed: 0x%08x\n", status);
446 WARNING(
"[WARNING] NumberOfNames is %d for module %s\n",
454 WARNING(
"[WARNING] AddressOfNameOrdinals %08x points outside of EAT %08x:%08x, %d names\n",
466 WARNING(
"[WARNING] AddressOfFunctions %08x points outside of Eat %08x:%08x, %d functions\n",
479 WARNING(
"[WARNING] AddressOfNames %08x points outside of Eat %08x:%08x, %d names\n",
497 DWORD offset, exportRva, namePointer, length;
508 ERROR(
"[WARNING] Name ordinal %08x outside of EAT %08x:%08x (AddressOfNameOrdinals at %08x)\n",
515 exportOrdinal = *(
WORD *)(buffer + offset);
519 ERROR(
"[WARNING] We have export ordinal %d, but only %d functions, %d names!\n",
528 ERROR(
"[WARNING] Function offset %08x outside of EAT %08x:%08x (AddressOfFunctions at %08x)\n",
535 exportRva = *(
DWORD *)(buffer + offset);
540 ERROR(
"[WARNING] Name offset %08x outside of EAT %08x:%08x (AddressOfNames at %08x)\n",
550 ERROR(
"[WARNING] Name pointer %08x outside of EAT %08x:%08x\n",
556 name = (
char *)buffer + namePointer;
564 ERROR(
"[WARNING] Name pointer %08x will be outside of EAT %08x:%08x after %d bytes\n",
586 target.
Rva = exportRva;
596 pExport->
Rva = exportRva;
612 ERROR(
"[ERROR] Start of names (%x) it's after (or equal tot he end of names (%x)\n",
693 pCache->
Dirty = Module->Subsystem->Process->StaticDetected != 0 || Module->Subsystem->Process->LateProtection;
695 TRACE(
"[WINUMCACHE] Create cache for module '%s', wow64: %d, dirty: %d.\n",
726 TRACE(
"[INFO] Already filled cache for module %s\n",
utf16_for_log(Module->Path->Path));
742 ERROR(
"[ERROR] EAT %08x:%08x points outside image (%08x) for module %s!\n",
747 goto _cleanup_and_exit;
752 ERROR(
"[WARNING] Module '%s' has EAT bigger than 1 MB: %08x:%08x\n",
756 goto _cleanup_and_exit;
767 &Module->ExportsSwapHandle);
770 ERROR(
"[ERROR] IntSwapMemReadData failed for 0x%016llx, 0x%x: 0x%08x\n",
781 TRACE(
"[WINUMCACHE] Fill export cache for module '%s', wow64 %d.\n",
821 ERROR(
"[ERROR] We have invalid headers for module '%s'!\n",
829 ERROR(
"[ERROR] IntPeGetDirectory failed: 0x%08x\n", status);
836 ERROR(
"[ERROR] IntPeGetDirectory failed: 0x%08x\n", status);
846 memcpy(pCache->
Headers, Headers, 4096);
848 TRACE(
"[WINUMCACHE] Fill header cache for module '%s', wow64: %d\n",
863 if ((Module->Is64BitModule && (Module->Subsystem->SubsystemType !=
winSubsys64Bit)) ||
864 (!Module->Is64BitModule && (Module->Subsystem->SubsystemType ==
winSubsys64Bit)))
866 ERROR(
"[ERROR] %d/%d invalid for module '%s'\n",
867 Module->Is64BitModule, (Module->Subsystem->SubsystemType ==
winSubsys64Bit),
873 WARNING(
"[WARNING] Shady image size for module '%s': 0x%x/0x%x\n",
881 WARNING(
"[WARNING] Shady IAT for module '%s': RVA = %x, size = 0x%x\n",
889 WARNING(
"[WARNING] Shady EAT for module %s: RVA = %x, size = 0x%x, image size = 0x%x\n",
917 while (list != &gWinUmCaches)
923 pCache->
Wow64 == wow64 &&
926 TRACE(
"[WINUMCACHE] Reuse cache for module '%s'\n",
utf16_for_log(Module->Path->Name));
950 if (NULL != Module->Cache)
979 if (Cache->Exports.Array != NULL)
985 if (NULL != Cache->Exports.Names)
990 if (Cache->Headers != NULL)
1048 WARNING(
"[WARNING] Failed to fill header cache with status: 0x%08X.\n", status);
1055 WARNING(
"[WARNING] Failed to fill export cache with status: 0x%08X.\n", status);
1072 if (NULL == Module || NULL == Module->Cache)
1077 return Module->Cache->ExportDirRead;
1090 while (list != &gWinUmCaches)
WINUM_PATH * Path
Module path.
void IntWinUmModCacheRelease(WINUM_MODULE_CACHE *Cache)
Removes a module cache, if it was written (it's dirty).
BOOLEAN ExportDirRead
True if the exports directory has been read.
RBTREE Tree
The RB tree containing all the exports (WINUM_CACHE_EXPORT entries).
int FUNC_RbTreeNodeCustomCompare(RBNODE *Node, void *Key)
static BOOLEAN IntWinModCacheFixNamePointers(RBNODE *Node, void *Module)
Fixes the names, lens and hashes inside the given RB node, provided the info inside the module...
#define CONTAINING_RECORD(List, Type, Member)
static INTSTATUS IntWinUmModCacheFillExports(WIN_PROCESS_MODULE *Module)
Fills the exports cache of the provided module with each exported symbol.
#define NAMEHASH_KERNELBASE
DWORD IatSize
Size of the imports table.
DWORD Crc32Compute(const void *Buffer, size_t Size, DWORD InitialCrc)
Computes the CRC for a byte array.
INTSTATUS IntPeGetDirectory(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD DirectoryEntry, IMAGE_DATA_DIRECTORY *Directory)
Validate & return the indicated image data directory.
#define NAMEHASH_WOW64CPU
BOOLEAN MemoryFuncsRead
True if the memory functions have been identified.
#define INT_STATUS_SUCCESS
INTSTATUS IntSwapMemReadData(QWORD Cr3, QWORD VirtualAddress, DWORD Length, DWORD Options, void *Context, DWORD ContextTag, PFUNC_PagesReadCallback Callback, PFUNC_PreInjectCallback PreInject, void **SwapHandle)
Reads a region of guest virtual memory, and calls the indicated callback when all the data is availab...
struct _LIST_ENTRY * Flink
DWORD StartNames
First RVA pointing to the exported names.
DWORD NumberOfOffsets
Number of symbols pointing to the exported RVA.
static BOOLEAN IntWinUmModMustCacheExports(DWORD NameHash)
Checks of the exports of a module need to be cached.
void FUNC_RbTreeNodeFree(RBNODE *Node)
#define INT_SUCCESS(Status)
DWORD TimeDateStamp
Time/date stamp.
WINUM_CACHE_EXPORT * IntWinUmModCacheExportFind(WIN_PROCESS_MODULE *Module, DWORD Rva, DWORD ErrorRange)
Tries to find an export in the range [Rva, Rva + ErrorRange].
INTSTATUS RbLookupNode(RBTREE *Tree, RBNODE *NodeToSearch, RBNODE **NodeFound)
INTSTATUS RbWalkInorderTree(RBTREE *Tree, PFUNC_RbTreeWalkCallback Callback, void *WalkContext)
#define INT_STATUS_NOT_NEEDED_HINT
INTSTATUS RbLookupNodeCustomCompare(RBTREE *Tree, PFUNC_RbTreeNodeCustomCompare CompareFunc, void *Key, RBNODE **NodeFound)
#define HpAllocWithTag(Len, Tag)
int INTSTATUS
The status data type.
struct _WINUM_MODULE_CACHE::@242 Info
void IntWinUmCacheUninit(void)
Uninit the module cache system. This will remove all cache entries. Use this during Introcore uninit...
INTSTATUS RbInit(RBTREE *Tree, PFUNC_RbTreeNodeFree NodeFree, PFUNC_RbTreeNodeCompare NodeCompare)
int FUNC_RbTreeNodeCompare(RBNODE *Left, RBNODE *Right)
#define INT_STATUS_NOT_FOUND
UINT32 AddressOfNameOrdinals
DWORD EatRva
RVA of the exports table.
DWORD EndNames
Last RVA pointing to the exported names.
static INTSTATUS IntWinModHandleExportsInMemory(void *Context, QWORD Cr3, QWORD VirtualAddress, QWORD PhysicalAddress, void *Data, DWORD DataSize, DWORD Flags)
Called as soon as the exports section of a module is swapped in.
static INTSTATUS IntWinModCancelExportTransactions(WINUM_MODULE_CACHE *Cache)
Cancels all pending swap transactions, in any process, for the provided Cache.
static WINUM_MODULE_CACHE * IntWinUmModCacheFetch(WIN_PROCESS_MODULE *Module)
Returns the cache associated with the provided module.
static void IntWinModCacheExportNodeFree(RBNODE *Node)
RB tree free function.
Process subsystem type 32 bit.
WINUM_CACHE_MEMORY_FUNCS MemFuncs
Memory related functions RVAs.
#define WINUMCACHE_MAX_EXPORTS
We will not cache more than this many exports.
WINUM_CACHE_EXPORT * Array
The array of WINUM_CACHE_EXPORT entries.
INTSTATUS IntSwapMemRemoveTransaction(void *Transaction)
Remove a transaction.
BOOLEAN Wow64
True if this module is Wow64.
#define INITIAL_CRC_VALUE
static BOOLEAN RemoveEntryList(LIST_ENTRY *Entry)
BOOLEAN Guest64
True if this is a 64-bit guest, False if it is a 32-bit guest.
DWORD MemmoveSRva
RVA of the memmoves function.
struct _IMAGE_EXPORT_DIRECTORY * PIMAGE_EXPORT_DIRECTORY
static INTSTATUS IntWinUmModCacheFillHeaders(WIN_PROCESS_MODULE *Module, BYTE *Headers)
Fills MZ/PE headers information for the provided module.
LIST_ENTRY Link
Link inside the global list of module caches.
#define HpFreeAndNullWithTag(Add, Tag)
#define INT_STATUS_KEY_ALREADY_EXISTS
DWORD MemmoveRva
RVA of the memmove function.
DWORD MemcpyRva
RVA of the memcpy function.
DWORD TimeDateStamp
Module time & date stamp.
WINUM_CACHE_EXPORT * IntWinUmCacheGetExportFromRange(WIN_PROCESS_MODULE *Module, QWORD Gva, DWORD Length)
Tries to find an export in the range [Gva - Length, Gva].
static void InsertTailList(LIST_ENTRY *ListHead, LIST_ENTRY *Entry)
void RbUninit(RBTREE *Tree)
#define INT_STATUS_ALREADY_INITIALIZED_HINT
Process subsystem type 64 bit.
LIST_HEAD gWinProcesses
The list of all the processes inside the guest.
DWORD NameOffsets[MAX_OFFSETS_PER_NAME]
Name RVAs pointing to this exported RVA.
void RbPreinit(RBTREE *Tree)
#define UNREFERENCED_PARAMETER(P)
#define IMAGE_DIRECTORY_ENTRY_EXPORT
DWORD NameHash
The CRC32 hash of the name. Used for fast matching.
DWORD Rva
The RVA of this export.
DWORD MemcpySRva
RVA of the memcpys function.
static WINUM_MODULE_CACHE * IntWinModCacheCreate(WIN_PROCESS_MODULE *Module)
Creates an exports cache entry for the provided module.
INTSTATUS IntPeValidateHeader(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD ImageBaseBufferSize, INTRO_PE_INFO *PeInfo, QWORD Cr3)
Validates a PE header.
DWORD EatSize
Size of the exports table.
DWORD NameHashes[MAX_OFFSETS_PER_NAME]
Hashes of the names pointing to this RVA.
#define _In_reads_bytes_(expr)
DWORD SizeOfImage
Size of image.
#define INT_STATUS_INVALID_OBJECT_TYPE
DWORD NameLens[MAX_OFFSETS_PER_NAME]
Length of each name pointing to this RVA.
GUEST_STATE gGuest
The current guest state.
DWORD MemsetRva
RVA of the memset function.
WINUM_MODULE_CACHE * Cache
Module headers cache.
#define _Function_class_(expr)
#define IMAGE_DIRECTORY_ENTRY_IAT
#define MAX_OFFSETS_PER_NAME
We can have up to this many exports pointing to the same RVA.
void IntWinUmModCacheGet(WIN_PROCESS_MODULE *Module)
Initializes the cache for the provided module.
BOOLEAN IntWinUmCacheIsExportDirRead(WIN_PROCESS_MODULE *Module)
Checks if the exports directory of the given module has been read.
BOOLEAN Dirty
True if this caches was created for a module loaded by a statically detected process. Dirty caches are NOT reused by other loaded modules, and they will be destroyed when the module is unloaded.
RBNODE RbNode
RB tree node entry.
#define LIST_HEAD_INIT(Name)
INTSTATUS RbInsertNode(RBTREE *Tree, RBNODE *Node)
PCHAR Names[MAX_OFFSETS_PER_NAME]
The names pointing to this RVA. Each name will point inside the Names structure inside WINUM_CACHE_EX...
char * utf16_for_log(const WCHAR *WString)
Converts a UTF-16 to a UTF-8 string to be used inside logging macros.
#define INT_STATUS_INVALID_PARAMETER_1
BOOLEAN FUNC_RbTreeWalkCallback(RBNODE *Node, void *WalkContext)
#define INT_STATUS_NOT_SUPPORTED
static void IntWinUmCacheRemoveCache(WINUM_MODULE_CACHE *Cache)
Removes a module cache.
INTSTATUS IntWinUmModCacheSetHeaders(WIN_PROCESS_MODULE *Module, BYTE *Headers)
Sets the MZ/PE headers in the cache of a given module.
UINT32 AddressOfFunctions
static int IntWinModCacheExportNodeCompare(RBNODE *Left, RBNODE *Right)
Compares two RB tree nodes, representing cached exports.
DWORD SizeOfImage
Size of the image.
BOOLEAN Image64Bit
True if the image is 64 bit.
void * ExportsSwapHandle
Swap handle for the exports.
const DWORD gExportedDirsToCache[]
#define NAMEHASH_KERNEL32
#define list_for_each(_head, _struct_type, _var)
DWORD IatRva
RVA of the imports table.
BYTE * Headers
A buffer containing the MZ/PE headers of this module.
static int IntWinModCacheExportNodeCompareWithErorr(RBNODE *Node, void *Key)
Checks if the provided key is inside the given RB tree node.
#define NAMEHASH_WOW64WIN
WINUM_CACHE_EXPORTS Exports
The exports cache.
#define SWAPMEM_OPT_UM_FAULT
If set, the PF must be injected only while in user-mode. Use it when reading user-mode memory...
DWORD ModuleNameHash
The hash on the name of the cached module.
PCHAR Names
A pointer to a contiguous memory area containing all the exported names.
This structure describes a running process inside the guest.
#define INT_STATUS_INSUFFICIENT_RESOURCES
WCHAR * Path
The string which represents the user-mode module path.