Added DomitoMemorySearchPattern

This commit is contained in:
Benjamin Höglinger-Stelzer 2023-07-01 05:24:04 +02:00
parent 0d9cc19fbd
commit 1113a23f19
2 changed files with 210 additions and 150 deletions

View File

@ -10,7 +10,7 @@ __drv_allocatesMem(Mem)
PVOID PVOID
NTAPI NTAPI
EVT_DOMITO_ALLOCATE_ROUTINE( EVT_DOMITO_ALLOCATE_ROUTINE(
_In_ SIZE_T ByteSize _In_ SIZE_T ByteSize
); );
typedef EVT_DOMITO_ALLOCATE_ROUTINE* PFN_DOMITO_ALLOCATE_ROUTINE; typedef EVT_DOMITO_ALLOCATE_ROUTINE* PFN_DOMITO_ALLOCATE_ROUTINE;
@ -24,9 +24,9 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
EXTERN_C EXTERN_C
NTSTATUS NTSTATUS
DomitoFindDriverBaseAddress( DomitoFindDriverBaseAddress(
_In_ STRING ModuleName, _In_ STRING ModuleName,
_In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator, _In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator,
_Inout_opt_ PVOID * ModuleBase _Inout_opt_ PVOID * ModuleBase
); );
// //
@ -38,7 +38,23 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
EXTERN_C EXTERN_C
NTSTATUS NTSTATUS
DomitoFindExportedFunctionAddress( DomitoFindExportedFunctionAddress(
_In_ PVOID ModuleBase, _In_ PVOID ModuleBase,
_In_ STRING FunctionName, _In_ STRING FunctionName,
_Inout_opt_ PVOID * FunctionAddress _Inout_opt_ PVOID * FunctionAddress
);
//
// Scans a provided buffer for a memory pattern
//
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS
DomitoMemorySearchPattern(
_In_ PCUCHAR pcPattern,
_In_ UCHAR uWildcard,
_In_ SIZE_T puLen,
_In_ PVOID pcBase,
_In_ SIZE_T puSize,
_Outptr_result_maybenull_ PVOID* ppMatch
); );

View File

@ -7,63 +7,63 @@
// Structure representing a loaded module // Structure representing a loaded module
typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY
{ {
PVOID Unknown1; PVOID Unknown1;
PVOID Unknown2; PVOID Unknown2;
PVOID Base; PVOID Base;
ULONG Size; ULONG Size;
ULONG Flags; ULONG Flags;
USHORT Index; USHORT Index;
USHORT NameLength; USHORT NameLength;
USHORT LoadCount; USHORT LoadCount;
USHORT PathLength; USHORT PathLength;
CHAR ImageName[256]; CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY; } SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY;
// Structure representing the loaded module information // Structure representing the loaded module information
typedef struct _SYSTEM_MODULE_INFORMATION typedef struct _SYSTEM_MODULE_INFORMATION
{ {
ULONG Count; ULONG Count;
SYSTEM_MODULE_INFORMATION_ENTRY Module[ANYSIZE_ARRAY]; SYSTEM_MODULE_INFORMATION_ENTRY Module[ANYSIZE_ARRAY];
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION; } SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
// Function prototype for ZwQuerySystemInformation // Function prototype for ZwQuerySystemInformation
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
ULONG SystemInformationClass, ULONG SystemInformationClass,
PVOID SystemInformation, PVOID SystemInformation,
ULONG SystemInformationLength, ULONG SystemInformationLength,
PULONG ReturnLength PULONG ReturnLength
); );
typedef struct _LDR_DATA_TABLE_ENTRY typedef struct _LDR_DATA_TABLE_ENTRY
{ {
LIST_ENTRY64 InLoadOrderLinks; LIST_ENTRY64 InLoadOrderLinks;
PVOID ExceptionTable; PVOID ExceptionTable;
ULONG ExceptionTableSize; ULONG ExceptionTableSize;
PVOID GpValue; PVOID GpValue;
PVOID NonPagedDebugInfo; PVOID NonPagedDebugInfo;
PVOID ImageBase; PVOID ImageBase;
PVOID EntryPoint; PVOID EntryPoint;
ULONG SizeOfImage; ULONG SizeOfImage;
UNICODE_STRING FullImageName; UNICODE_STRING FullImageName;
UNICODE_STRING BaseImageName; UNICODE_STRING BaseImageName;
ULONG Flags; ULONG Flags;
USHORT LoadCount; USHORT LoadCount;
USHORT TlsIndex; USHORT TlsIndex;
LIST_ENTRY64 HashLinks; LIST_ENTRY64 HashLinks;
PVOID SectionPointer; PVOID SectionPointer;
ULONG CheckSum; ULONG CheckSum;
ULONG TimeDateStamp; ULONG TimeDateStamp;
PVOID LoadedImports; PVOID LoadedImports;
PVOID EntryPointActivationContext; PVOID EntryPointActivationContext;
PVOID PatchInformation; PVOID PatchInformation;
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
typedef PVOID(NTAPI* t_RtlImageDirectoryEntryToData)( typedef PVOID(NTAPI* t_RtlImageDirectoryEntryToData)(
IN PVOID Base, IN PVOID Base,
IN BOOLEAN MappedAsImage, IN BOOLEAN MappedAsImage,
IN USHORT DirectoryEntry, IN USHORT DirectoryEntry,
OUT PULONG Size OUT PULONG Size
); );
_Success_(return == STATUS_SUCCESS) _Success_(return == STATUS_SUCCESS)
@ -71,76 +71,76 @@ _Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS NTSTATUS
DomitoFindDriverBaseAddress( DomitoFindDriverBaseAddress(
_In_ STRING ModuleName, _In_ STRING ModuleName,
_In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator, _In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator,
_Inout_opt_ PVOID * ModuleBase _Inout_opt_ PVOID * ModuleBase
) )
{ {
ULONG bufferSize = 0; ULONG bufferSize = 0;
PSYSTEM_MODULE_INFORMATION moduleInfo = NULL; PSYSTEM_MODULE_INFORMATION moduleInfo = NULL;
const ULONG SystemModuleInformation = 11; const ULONG SystemModuleInformation = 11;
// Query the required buffer size for module information // Query the required buffer size for module information
NTSTATUS status = ZwQuerySystemInformation( NTSTATUS status = ZwQuerySystemInformation(
SystemModuleInformation, SystemModuleInformation,
&bufferSize, &bufferSize,
0, 0,
&bufferSize &bufferSize
); );
if (status != STATUS_INFO_LENGTH_MISMATCH) if (status != STATUS_INFO_LENGTH_MISMATCH)
{ {
return status; return status;
} }
// Allocate memory for the module information // Allocate memory for the module information
moduleInfo = (PSYSTEM_MODULE_INFORMATION)Allocator( moduleInfo = (PSYSTEM_MODULE_INFORMATION)Allocator(
bufferSize bufferSize
); );
if (moduleInfo == NULL) if (moduleInfo == NULL)
{ {
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
// Retrieve the module information // Retrieve the module information
status = ZwQuerySystemInformation( status = ZwQuerySystemInformation(
SystemModuleInformation, SystemModuleInformation,
moduleInfo, moduleInfo,
bufferSize, bufferSize,
NULL NULL
); );
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
{ {
ExFreePool(moduleInfo); ExFreePool(moduleInfo);
return status; return status;
} }
STRING currentImageName; STRING currentImageName;
status = STATUS_NOT_FOUND; status = STATUS_NOT_FOUND;
// Iterate through the loaded modules and find the desired module // Iterate through the loaded modules and find the desired module
for (ULONG i = 0; i < moduleInfo->Count; i++) for (ULONG i = 0; i < moduleInfo->Count; i++)
{ {
RtlInitAnsiString(&currentImageName, moduleInfo->Module[i].ImageName); RtlInitAnsiString(&currentImageName, moduleInfo->Module[i].ImageName);
if (0 == RtlCompareString(&ModuleName, &currentImageName, TRUE)) if (0 == RtlCompareString(&ModuleName, &currentImageName, TRUE))
{ {
// Found the module, store the base address // Found the module, store the base address
if (ModuleBase) if (ModuleBase)
{ {
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
*ModuleBase = moduleInfo->Module[i].Base; *ModuleBase = moduleInfo->Module[i].Base;
} }
break; break;
} }
} }
ExFreePool(moduleInfo); ExFreePool(moduleInfo);
return status; return status;
} }
_Success_(return == STATUS_SUCCESS) _Success_(return == STATUS_SUCCESS)
@ -148,64 +148,108 @@ _Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS NTSTATUS
DomitoFindExportedFunctionAddress( DomitoFindExportedFunctionAddress(
_In_ PVOID ModuleBase, _In_ PVOID ModuleBase,
_In_ STRING FunctionName, _In_ STRING FunctionName,
_Inout_opt_ PVOID * FunctionAddress _Inout_opt_ PVOID * FunctionAddress
) )
{ {
NTSTATUS status = STATUS_NOT_FOUND; NTSTATUS status = STATUS_NOT_FOUND;
ULONG exportSize; ULONG exportSize;
DECLARE_CONST_UNICODE_STRING(routineName, L"RtlImageDirectoryEntryToData"); DECLARE_CONST_UNICODE_STRING(routineName, L"RtlImageDirectoryEntryToData");
const t_RtlImageDirectoryEntryToData fp_RtlImageDirectoryEntryToData = const t_RtlImageDirectoryEntryToData fp_RtlImageDirectoryEntryToData =
(t_RtlImageDirectoryEntryToData)MmGetSystemRoutineAddress((PUNICODE_STRING)&routineName); (t_RtlImageDirectoryEntryToData)MmGetSystemRoutineAddress((PUNICODE_STRING)&routineName);
if (fp_RtlImageDirectoryEntryToData == NULL) if (fp_RtlImageDirectoryEntryToData == NULL)
{ {
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
} }
// Retrieve the export directory information // Retrieve the export directory information
const PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)fp_RtlImageDirectoryEntryToData( const PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)fp_RtlImageDirectoryEntryToData(
ModuleBase, ModuleBase,
TRUE, TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT, IMAGE_DIRECTORY_ENTRY_EXPORT,
&exportSize &exportSize
); );
if (exportDirectory == NULL) if (exportDirectory == NULL)
{ {
return STATUS_INVALID_IMAGE_FORMAT; return STATUS_INVALID_IMAGE_FORMAT;
} }
STRING currentFunctionName; STRING currentFunctionName;
const PULONG functionAddresses = (PULONG)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfFunctions); const PULONG functionAddresses = (PULONG)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfFunctions);
const PULONG functionNames = (PULONG)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfNames); const PULONG functionNames = (PULONG)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfNames);
const PUSHORT functionOrdinals = (PUSHORT)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfNameOrdinals); const PUSHORT functionOrdinals = (PUSHORT)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfNameOrdinals);
for (ULONG i = 0; i < exportDirectory->NumberOfNames; i++) for (ULONG i = 0; i < exportDirectory->NumberOfNames; i++)
{ {
const char* functionName = (const char*)((ULONG_PTR)ModuleBase + functionNames[i]); const char* functionName = (const char*)((ULONG_PTR)ModuleBase + functionNames[i]);
const USHORT functionOrdinal = functionOrdinals[i]; const USHORT functionOrdinal = functionOrdinals[i];
UNREFERENCED_PARAMETER(functionOrdinal); UNREFERENCED_PARAMETER(functionOrdinal);
const ULONG functionRva = functionAddresses[i]; const ULONG functionRva = functionAddresses[i];
const PVOID functionAddress = (PVOID)((ULONG_PTR)ModuleBase + functionRva); const PVOID functionAddress = (PVOID)((ULONG_PTR)ModuleBase + functionRva);
RtlInitAnsiString(&currentFunctionName, functionName); RtlInitAnsiString(&currentFunctionName, functionName);
if (0 == RtlCompareString(&FunctionName, &currentFunctionName, TRUE)) if (0 == RtlCompareString(&FunctionName, &currentFunctionName, TRUE))
{ {
if (FunctionAddress) if (FunctionAddress)
{ {
status = STATUS_SUCCESS; status = STATUS_SUCCESS;
*FunctionAddress = functionAddress; *FunctionAddress = functionAddress;
} }
break; break;
} }
} }
return status; return status;
}
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS
DomitoMemorySearchPattern(
_In_ PCUCHAR pcPattern,
_In_ UCHAR uWildcard,
_In_ SIZE_T puLen,
_In_ PVOID pcBase,
_In_ SIZE_T puSize,
_Outptr_result_maybenull_ PVOID * ppMatch
)
{
ASSERT(ppMatch != NULL && pcPattern != NULL && pcBase != NULL);
if (ppMatch == NULL || pcPattern == NULL || pcBase == NULL)
{
return STATUS_INVALID_PARAMETER;
}
*ppMatch = NULL;
for (SIZE_T i = 0; i < puSize - puLen; i++)
{
BOOLEAN found = TRUE;
for (SIZE_T j = 0; j < puLen; j++)
{
if (pcPattern[j] != uWildcard && pcPattern[j] != ((PCUCHAR)pcBase)[i + j])
{
found = FALSE;
break;
}
}
if (found)
{
*ppMatch = (PUCHAR)pcBase + i;
return STATUS_SUCCESS;
}
}
return STATUS_NOT_FOUND;
} }