Files
Domito/src/Domito.cpp
T

376 lines
8.7 KiB
C++
Raw Normal View History

2023-07-02 18:52:22 +02:00
/* ___
* / __|___ _ __ _ __ ___ _ _
* | (__/ _ \ ' \| ' \/ _ \ ' \
* \___\___/_|_|_|_|_|_\___/_||_|
*
*/
#include "Domito.Internal.h"
2023-07-01 06:48:16 +02:00
2023-07-03 00:24:31 +02:00
DOMITO_COMMON G_Common = {};
2023-07-01 06:48:16 +02:00
2023-07-03 00:24:31 +02:00
DECLARE_GLOBAL_CONST_UNICODE_STRING(G_QipRoutineName, L"ZwQueryInformationProcess");
DECLARE_GLOBAL_CONST_UNICODE_STRING(G_IdetdRoutineName, L"RtlImageDirectoryEntryToData");
DECLARE_GLOBAL_CONST_UNICODE_STRING(G_QsiRoutineName, L"ZwQuerySystemInformation");
2023-07-03 00:24:31 +02:00
2023-07-03 18:04:13 +02:00
#ifndef LOG
#define LOG(Format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[Domito][" __FUNCTION__ "] " Format " \n", __VA_ARGS__)
#endif
2023-07-02 19:55:23 +02:00
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
2023-07-02 19:51:44 +02:00
_IRQL_requires_max_(PASSIVE_LEVEL)
2023-07-02 19:55:23 +02:00
NTSTATUS
2023-07-02 19:51:44 +02:00
DomitoInit()
{
2023-07-03 00:55:51 +02:00
//
// Do those first since the follow-up code depends on them
//
G_Common.ZwQueryInformationProcess =
(t_ZwQueryInformationProcess)MmGetSystemRoutineAddress((PUNICODE_STRING)&G_QipRoutineName);
G_Common.RtlImageDirectoryEntryToData =
(t_RtlImageDirectoryEntryToData)MmGetSystemRoutineAddress((PUNICODE_STRING)&G_IdetdRoutineName);
G_Common.ZwQuerySystemInformation =
(t_ZwQuerySystemInformation)MmGetSystemRoutineAddress((PUNICODE_STRING)&G_QsiRoutineName);
2023-07-03 00:55:51 +02:00
2023-07-02 19:55:23 +02:00
return STATUS_SUCCESS; // TODO: unused currently
2023-07-02 19:51:44 +02:00
}
_IRQL_requires_max_(PASSIVE_LEVEL)
void
DomitoShutdown()
{
}
2023-07-01 04:39:52 +02:00
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
2023-07-01 05:33:35 +02:00
DomitoFindModuleBaseAddress(
2023-07-03 01:57:37 +02:00
_In_ PANSI_STRING ModuleName,
2023-07-01 05:24:04 +02:00
_Inout_opt_ PVOID * ModuleBase
)
{
2023-07-01 05:24:04 +02:00
ULONG bufferSize = 0;
PSYSTEM_MODULE_INFORMATION moduleInfo = NULL;
if (!G_Common.ZwQuerySystemInformation)
{
return STATUS_NOT_IMPLEMENTED;
}
2023-07-01 05:24:04 +02:00
const ULONG SystemModuleInformation = 11;
2023-07-01 05:24:04 +02:00
// Query the required buffer size for module information
NTSTATUS status = G_Common.ZwQuerySystemInformation(
2023-07-01 05:24:04 +02:00
SystemModuleInformation,
&bufferSize,
0,
&bufferSize
);
2023-07-01 05:24:04 +02:00
if (status != STATUS_INFO_LENGTH_MISMATCH)
{
return status;
}
2023-07-01 05:24:04 +02:00
// Allocate memory for the module information
moduleInfo = (PSYSTEM_MODULE_INFORMATION)G_Memory.Allocate(
2023-07-01 05:24:04 +02:00
bufferSize
);
2023-07-01 05:24:04 +02:00
if (moduleInfo == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
2023-07-01 05:24:04 +02:00
// Retrieve the module information
status = G_Common.ZwQuerySystemInformation(
2023-07-01 05:24:04 +02:00
SystemModuleInformation,
moduleInfo,
bufferSize,
NULL
);
2023-07-01 05:24:04 +02:00
if (!NT_SUCCESS(status))
{
G_Memory.Free(moduleInfo);
2023-07-01 05:24:04 +02:00
return status;
}
2023-07-01 05:24:04 +02:00
STRING currentImageName;
2023-07-01 05:24:04 +02:00
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);
2023-07-03 01:57:37 +02:00
if (0 == RtlCompareString(ModuleName, &currentImageName, TRUE))
2023-07-01 05:24:04 +02:00
{
status = STATUS_SUCCESS;
2023-07-01 05:24:04 +02:00
// Found the module, store the base address
if (ModuleBase)
2023-07-01 06:12:05 +02:00
{
2023-07-01 05:24:04 +02:00
*ModuleBase = moduleInfo->Module[i].Base;
}
break;
}
}
G_Memory.Free(moduleInfo);
2023-07-01 05:24:04 +02:00
return status;
}
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DomitoFindExportedFunctionAddress(
2023-07-01 05:24:04 +02:00
_In_ PVOID ModuleBase,
2023-07-03 01:57:37 +02:00
_In_ PANSI_STRING FunctionName,
2023-07-01 05:24:04 +02:00
_Inout_opt_ PVOID * FunctionAddress
)
{
2023-07-01 05:24:04 +02:00
NTSTATUS status = STATUS_NOT_FOUND;
ULONG exportSize;
2023-07-03 00:24:31 +02:00
if (G_Common.RtlImageDirectoryEntryToData == NULL)
2023-07-01 05:24:04 +02:00
{
return STATUS_NOT_IMPLEMENTED;
}
2023-07-01 05:24:04 +02:00
// Retrieve the export directory information
2023-07-03 00:24:31 +02:00
const PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)G_Common.RtlImageDirectoryEntryToData(
2023-07-01 05:24:04 +02:00
ModuleBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT,
&exportSize
);
2023-07-01 05:24:04 +02:00
if (exportDirectory == NULL)
{
return STATUS_INVALID_IMAGE_FORMAT;
}
2023-07-01 05:24:04 +02:00
STRING currentFunctionName;
2023-07-01 05:24:04 +02:00
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);
2023-07-01 05:24:04 +02:00
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);
2023-07-01 05:24:04 +02:00
const ULONG functionRva = functionAddresses[i];
const PVOID functionAddress = (PVOID)((ULONG_PTR)ModuleBase + functionRva);
2023-07-01 05:24:04 +02:00
RtlInitAnsiString(&currentFunctionName, functionName);
2023-07-03 01:57:37 +02:00
if (0 == RtlCompareString(FunctionName, &currentFunctionName, TRUE))
2023-07-01 05:24:04 +02:00
{
if (FunctionAddress)
{
status = STATUS_SUCCESS;
*FunctionAddress = functionAddress;
}
break;
}
}
2023-07-01 04:36:59 +02:00
2023-07-01 05:24:04 +02:00
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,
2023-07-01 05:24:25 +02:00
_Outptr_result_maybenull_ PVOID * ppMatch
2023-07-01 05:24:04 +02:00
)
{
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;
}
2023-07-01 06:12:05 +02:00
2023-07-01 06:23:11 +02:00
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
DomitoReadFile(
_In_ HANDLE FileHandle,
_Out_ PVOID Buffer,
_In_ ULONG BufferSize
)
{
NTSTATUS status = STATUS_SUCCESS;
IO_STATUS_BLOCK ioStatusBlock;
// Read the file into memory using ZwReadFile
if (!NT_SUCCESS(status = ZwReadFile(
FileHandle,
NULL,
NULL,
NULL,
&ioStatusBlock,
Buffer,
BufferSize,
NULL,
NULL
)))
{
return status;
}
// Check if the file was read successfully
if (!NT_SUCCESS(ioStatusBlock.Status))
{
return ioStatusBlock.Status;
}
// File read successfully
return status;
}
2023-07-01 06:48:16 +02:00
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
#pragma code_seg("PAGED")
NTSTATUS
DomitoGetProcessImageName(
_In_ ULONG ProcessId,
_Inout_ PUNICODE_STRING * ProcessImageName
)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG returnedLength;
HANDLE hProcess = NULL;
PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process
2023-07-02 18:52:22 +02:00
if (ProcessId == 0 || ProcessId == 4)
2023-07-01 06:48:16 +02:00
{
return STATUS_INVALID_PARAMETER_1;
}
if (ProcessImageName == NULL)
{
return STATUS_INVALID_PARAMETER_2;
2023-07-01 06:48:16 +02:00
}
2023-07-01 06:55:23 +02:00
CLIENT_ID cid;
2023-07-01 06:48:16 +02:00
cid.UniqueProcess = (HANDLE)ProcessId;
cid.UniqueThread = NULL;
OBJECT_ATTRIBUTES objAttr;
InitializeObjectAttributes(
&objAttr,
NULL,
OBJ_KERNEL_HANDLE,
NULL,
NULL
);
if (!NT_SUCCESS(status = ZwOpenProcess(
&hProcess,
PROCESS_ALL_ACCESS,
&objAttr,
&cid
)))
{
return status;
}
2023-07-03 00:24:31 +02:00
if (G_Common.ZwQueryInformationProcess == NULL)
2023-07-01 06:48:16 +02:00
{
2023-07-03 00:24:31 +02:00
status = STATUS_NOT_IMPLEMENTED;
goto cleanUp;
2023-07-01 06:48:16 +02:00
}
/* Query the actual size of the process path */
2023-07-03 00:24:31 +02:00
status = G_Common.ZwQueryInformationProcess(
2023-07-01 06:48:16 +02:00
hProcess,
ProcessImageFileName,
NULL, // buffer
0, // buffer size
&returnedLength
);
if (STATUS_INFO_LENGTH_MISMATCH != status)
{
goto cleanUp;
}
*ProcessImageName = (PUNICODE_STRING)G_Memory.Allocate(returnedLength);
2023-07-01 06:48:16 +02:00
if (*ProcessImageName == NULL)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanUp;
}
/* Retrieve the process path from the handle to the process */
2023-07-03 00:24:31 +02:00
if (!NT_SUCCESS(status = G_Common.ZwQueryInformationProcess(
2023-07-01 06:48:16 +02:00
hProcess,
ProcessImageFileName,
*ProcessImageName,
returnedLength,
&returnedLength
)))
{
G_Memory.Free(*ProcessImageName);
2023-07-01 06:48:16 +02:00
}
cleanUp:
if (hProcess)
{
ZwClose(hProcess);
}
return status;
}
#pragma code_seg()