diff --git a/include/Domito.h b/include/Domito.h index 922a0bf..fce9dde 100644 --- a/include/Domito.h +++ b/include/Domito.h @@ -30,12 +30,13 @@ typedef EVT_DOMITO_ALLOCATE_ROUTINE* PFN_DOMITO_ALLOCATE_ROUTINE; // This structure encapsulates a signature used in verifying executable files. // #if !defined(WIN_CERTIFICATE) -typedef struct _WIN_CERTIFICATE { +typedef struct _WIN_CERTIFICATE +{ DWORD dwLength; - WORD wRevision; - WORD wCertificateType; - BYTE bCertificate[ANYSIZE_ARRAY]; -} WIN_CERTIFICATE, * LPWIN_CERTIFICATE; + WORD wRevision; + WORD wCertificateType; + BYTE bCertificate[ANYSIZE_ARRAY]; +} WIN_CERTIFICATE, *LPWIN_CERTIFICATE; #endif // @@ -103,9 +104,9 @@ _IRQL_requires_max_(PASSIVE_LEVEL) EXTERN_C NTSTATUS DomitoFindModuleBaseAddress( - _In_ STRING ModuleName, _In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator, - _Inout_opt_ PVOID * ModuleBase + _In_ STRING ModuleName, + _Inout_opt_ PVOID* ModuleBase ); // @@ -119,7 +120,7 @@ NTSTATUS DomitoFindExportedFunctionAddress( _In_ PVOID ModuleBase, _In_ STRING FunctionName, - _Inout_opt_ PVOID * FunctionAddress + _Inout_opt_ PVOID* FunctionAddress ); // @@ -136,7 +137,7 @@ DomitoMemorySearchPattern( _In_ SIZE_T puLen, _In_ PVOID pcBase, _In_ SIZE_T puSize, - _Outptr_result_maybenull_ PVOID * ppMatch + _Outptr_result_maybenull_ PVOID* ppMatch ); // @@ -197,3 +198,20 @@ DomitoGetProcessImageName( _In_ ULONG ProcessId, _Inout_ PUNICODE_STRING* ProcessImageName ); + +_Success_(return == STATUS_SUCCESS) +_Must_inspect_result_ +_IRQL_requires_max_(PASSIVE_LEVEL) +EXTERN_C +NTSTATUS +DomitoValidateFileLegacyMode( + _In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator, + _In_ HANDLE FileHandle, + _In_ PVOID Hash, + _In_ UINT32 HashSize, + _In_ ALG_ID HashAlgId, + _In_ const IMAGE_DATA_DIRECTORY* SecurityDirectory, + _Inout_ MINCRYPT_POLICY_INFO* PolicyInfo, + _Out_ LARGE_INTEGER* SigningTime, + _Inout_ MINCRYPT_POLICY_INFO* TimeStampPolicyInfo +); diff --git a/src/Domito.cpp b/src/Domito.cpp index e75fb73..c5f00ae 100644 --- a/src/Domito.cpp +++ b/src/Domito.cpp @@ -84,8 +84,8 @@ _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS DomitoFindModuleBaseAddress( - _In_ STRING ModuleName, _In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator, + _In_ STRING ModuleName, _Inout_opt_ PVOID * ModuleBase ) { @@ -760,3 +760,153 @@ cleanUp: return status; } #pragma code_seg() + +_Success_(return == STATUS_SUCCESS) +_Must_inspect_result_ +_IRQL_requires_max_(PASSIVE_LEVEL) +#pragma code_seg("PAGED") +NTSTATUS +DomitoValidateFileLegacyMode( + _In_ PFN_DOMITO_ALLOCATE_ROUTINE Allocator, + _In_ HANDLE FileHandle, + _In_ PVOID Hash, + _In_ UINT32 HashSize, + _In_ ALG_ID HashAlgId, + _In_ const IMAGE_DATA_DIRECTORY * SecurityDirectory, + _Inout_ MINCRYPT_POLICY_INFO * PolicyInfo, + _Out_ LARGE_INTEGER * SigningTime, + _Inout_ MINCRYPT_POLICY_INFO * TimeStampPolicyInfo +) +{ + PAGED_CODE(); + + NTSTATUS status = STATUS_SUCCESS; + PVOID certDirectory = nullptr; + KAPC_STATE systemContext = {}; + + do + { + SigningTime->QuadPart = 0; + + CiFreePolicyInfo(PolicyInfo); + CiFreePolicyInfo(TimeStampPolicyInfo); + + if (HashSize != MINCRYPT_SHA1_LENGTH) + { + status = STATUS_INVALID_IMAGE_HASH; + break; + } + + if (SecurityDirectory->Size != 0u && + SecurityDirectory->VirtualAddress != 0u) + { + certDirectory = Allocator(SecurityDirectory->Size); + if (certDirectory == NULL) + { + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + LARGE_INTEGER offset = {}; + IO_STATUS_BLOCK ioStatusBlock = {}; + + offset.LowPart = SecurityDirectory->VirtualAddress; + + status = ZwReadFile( + FileHandle, + NULL, + NULL, + NULL, + &ioStatusBlock, + certDirectory, + SecurityDirectory->Size, + &offset, + NULL + ); + + if (status == STATUS_PENDING) + { + ZwWaitForSingleObject( + FileHandle, + FALSE, + NULL + ); + + MemoryBarrier(); + status = ioStatusBlock.Status; + } + + if (!NT_SUCCESS(status)) + { + break; + } + + KeStackAttachProcess(PsInitialSystemProcess, &systemContext); + { + status = CiCheckSignedFile( + Hash, + HashSize, + HashAlgId, + certDirectory, + SecurityDirectory->Size, + PolicyInfo, + SigningTime, + TimeStampPolicyInfo + ); + } + KeUnstackDetachProcess(&systemContext); + + if (NT_SUCCESS(status)) + { + break; + } + + if (status != STATUS_INVALID_IMAGE_HASH) + { + break; + } + } + + KeStackAttachProcess(PsInitialSystemProcess, &systemContext); + { + status = CiVerifyHashInCatalog( + Hash, + HashSize, + HashAlgId, + FALSE, + 0, + 0x2007F, + PolicyInfo, + NULL, + SigningTime, + TimeStampPolicyInfo + ); + + if (status == STATUS_INVALID_IMAGE_HASH) + { + status = CiVerifyHashInCatalog( + Hash, + HashSize, + HashAlgId, + TRUE, + 0, + 0x2007F, + PolicyInfo, + NULL, + SigningTime, + TimeStampPolicyInfo + ); + } + } + KeUnstackDetachProcess(&systemContext); + + } while (FALSE); + + if (certDirectory) + { + ExFreePool(certDirectory); + } + + return status; +} +#pragma code_seg()