Exposed custom allocator callback

This commit is contained in:
Benjamin Höglinger-Stelzer 2023-07-01 04:36:59 +02:00
parent 3727b600ce
commit a6b7b455ec
2 changed files with 113 additions and 110 deletions

View File

@ -64,16 +64,19 @@ typedef PVOID(NTAPI* t_RtlImageDirectoryEntryToData)(
typedef
_IRQL_requires_same_
_Function_class_(DOMITO_ALLOCATE_ROUTINE)
_Function_class_(EVT_DOMITO_ALLOCATE_ROUTINE)
__drv_allocatesMem(Mem)
PVOID
NTAPI
DOMITO_ALLOCATE_ROUTINE(
EVT_DOMITO_ALLOCATE_ROUTINE(
_In_ SIZE_T ByteSize
);
typedef DOMITO_ALLOCATE_ROUTINE* PDOMITO_ALLOCATE_ROUTINE;
typedef EVT_DOMITO_ALLOCATE_ROUTINE* PFN_DOMITO_ALLOCATE_ROUTINE;
//
// Finds the base address of a driver module
//
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
@ -81,9 +84,13 @@ EXTERN_C
NTSTATUS
DomitoFindDriverBaseAddress(
_In_ STRING ModuleName,
_In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator,
_Inout_opt_ PVOID * ModuleBase
);
//
// Finds the address of an exported function by name
//
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)

View File

@ -4,87 +4,83 @@
#include "Domito.h"
//
// Finds the base address of a driver module
//
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DomitoFindDriverBaseAddress(
_In_ STRING ModuleName,
_Inout_opt_ PVOID* ModuleBase
_In_ STRING ModuleName,
_In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator,
_Inout_opt_ PVOID * ModuleBase
)
{
ULONG bufferSize = 0;
PSYSTEM_MODULE_INFORMATION moduleInfo = NULL;
ULONG bufferSize = 0;
PSYSTEM_MODULE_INFORMATION moduleInfo = NULL;
const ULONG SystemModuleInformation = 11;
const ULONG SystemModuleInformation = 11;
// Query the required buffer size for module information
NTSTATUS status = ZwQuerySystemInformation(
SystemModuleInformation,
&bufferSize,
0,
&bufferSize
);
// Query the required buffer size for module information
NTSTATUS status = ZwQuerySystemInformation(
SystemModuleInformation,
&bufferSize,
0,
&bufferSize
);
if (status != STATUS_INFO_LENGTH_MISMATCH)
{
return status;
}
if (status != STATUS_INFO_LENGTH_MISMATCH)
{
return status;
}
#pragma warning(disable:4996)
// Allocate memory for the module information
moduleInfo = (PSYSTEM_MODULE_INFORMATION)ExAllocatePoolWithTag(
NonPagedPool,
bufferSize,
'looP'
);
// Allocate memory for the module information
moduleInfo = (PSYSTEM_MODULE_INFORMATION)Allocator(
bufferSize
);
#pragma warning(default:4996)
if (moduleInfo == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
if (moduleInfo == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
// Retrieve the module information
status = ZwQuerySystemInformation(
SystemModuleInformation,
moduleInfo,
bufferSize,
NULL
);
// Retrieve the module information
status = ZwQuerySystemInformation(
SystemModuleInformation,
moduleInfo,
bufferSize,
NULL
);
if (!NT_SUCCESS(status))
{
ExFreePool(moduleInfo);
return status;
}
if (!NT_SUCCESS(status))
{
ExFreePool(moduleInfo);
return status;
}
STRING currentImageName;
STRING currentImageName;
status = STATUS_NOT_FOUND;
// Iterate through the loaded modules and find the desired module
for (ULONG i = 0; i < moduleInfo->Count; i++)
{
RtlInitAnsiString(&currentImageName, moduleInfo->Module[i].ImageName);
status = STATUS_NOT_FOUND;
// Iterate through the loaded modules and find the desired module
for (ULONG i = 0; i < moduleInfo->Count; i++)
{
RtlInitAnsiString(&currentImageName, moduleInfo->Module[i].ImageName);
if (0 == RtlCompareString(&ModuleName, &currentImageName, TRUE))
{
// Found the module, store the base address
if (ModuleBase)
{
status = STATUS_SUCCESS;
*ModuleBase = moduleInfo->Module[i].Base;
}
break;
}
}
if (0 == RtlCompareString(&ModuleName, &currentImageName, TRUE))
{
// Found the module, store the base address
if (ModuleBase)
{
status = STATUS_SUCCESS;
*ModuleBase = moduleInfo->Module[i].Base;
}
break;
}
}
ExFreePool(moduleInfo);
ExFreePool(moduleInfo);
return status;
return status;
}
_Success_(return == STATUS_SUCCESS)
@ -92,64 +88,64 @@ _Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DomitoFindExportedFunctionAddress(
_In_ PVOID ModuleBase,
_In_ STRING FunctionName,
_Inout_opt_ PVOID* FunctionAddress
_In_ PVOID ModuleBase,
_In_ STRING FunctionName,
_Inout_opt_ PVOID * FunctionAddress
)
{
NTSTATUS status = STATUS_NOT_FOUND;
ULONG exportSize;
NTSTATUS status = STATUS_NOT_FOUND;
ULONG exportSize;
DECLARE_CONST_UNICODE_STRING(routineName, L"RtlImageDirectoryEntryToData");
DECLARE_CONST_UNICODE_STRING(routineName, L"RtlImageDirectoryEntryToData");
const t_RtlImageDirectoryEntryToData fp_RtlImageDirectoryEntryToData =
(t_RtlImageDirectoryEntryToData)MmGetSystemRoutineAddress((PUNICODE_STRING)&routineName);
const t_RtlImageDirectoryEntryToData fp_RtlImageDirectoryEntryToData =
(t_RtlImageDirectoryEntryToData)MmGetSystemRoutineAddress((PUNICODE_STRING)&routineName);
if (fp_RtlImageDirectoryEntryToData == NULL)
{
return STATUS_NOT_IMPLEMENTED;
}
if (fp_RtlImageDirectoryEntryToData == NULL)
{
return STATUS_NOT_IMPLEMENTED;
}
// Retrieve the export directory information
const PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)fp_RtlImageDirectoryEntryToData(
ModuleBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT,
&exportSize
);
// Retrieve the export directory information
const PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)fp_RtlImageDirectoryEntryToData(
ModuleBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT,
&exportSize
);
if (exportDirectory == NULL)
{
return STATUS_INVALID_IMAGE_FORMAT;
}
if (exportDirectory == NULL)
{
return STATUS_INVALID_IMAGE_FORMAT;
}
STRING currentFunctionName;
const PULONG functionAddresses = (PULONG)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfFunctions);
const PULONG functionNames = (PULONG)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfNames);
const PUSHORT functionOrdinals = (PUSHORT)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfNameOrdinals);
STRING currentFunctionName;
for (ULONG i = 0; i < exportDirectory->NumberOfNames; i++)
{
const char* functionName = (const char*)((ULONG_PTR)ModuleBase + functionNames[i]);
const USHORT functionOrdinal = functionOrdinals[i];
UNREFERENCED_PARAMETER(functionOrdinal);
const PULONG functionAddresses = (PULONG)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfFunctions);
const PULONG functionNames = (PULONG)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfNames);
const PUSHORT functionOrdinals = (PUSHORT)((ULONG_PTR)ModuleBase + exportDirectory->AddressOfNameOrdinals);
const ULONG functionRva = functionAddresses[i];
const PVOID functionAddress = (PVOID)((ULONG_PTR)ModuleBase + functionRva);
for (ULONG i = 0; i < exportDirectory->NumberOfNames; i++)
{
const char* functionName = (const char*)((ULONG_PTR)ModuleBase + functionNames[i]);
const USHORT functionOrdinal = functionOrdinals[i];
UNREFERENCED_PARAMETER(functionOrdinal);
RtlInitAnsiString(&currentFunctionName, functionName);
const ULONG functionRva = functionAddresses[i];
const PVOID functionAddress = (PVOID)((ULONG_PTR)ModuleBase + functionRva);
if (0 == RtlCompareString(&FunctionName, &currentFunctionName, TRUE))
{
if (FunctionAddress)
{
status = STATUS_SUCCESS;
*FunctionAddress = functionAddress;
}
break;
}
}
RtlInitAnsiString(&currentFunctionName, functionName);
return status;
if (0 == RtlCompareString(&FunctionName, &currentFunctionName, TRUE))
{
if (FunctionAddress)
{
status = STATUS_SUCCESS;
*FunctionAddress = functionAddress;
}
break;
}
}
return status;
}