diff --git a/README.md b/README.md index f049b63..d28471c 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,13 @@ Built for and tested on **Windows 10 version 1507 (or newer) x64/ARM64**. 32-Bit ## How to use - Add the `include` directory to your project's headers search path. -- `#include ` wherever required. +- Add includes (preferably in the provided order): + ```c + #include + #include + #include + #include + ``` - Call `DomitoInit()` in your `DriverEntry` once to bootstrap internals. - Link against the resulting `Domito.lib` file for your desired architecture. - Link against `cng.lib` for the CNG BCrypt APIs. diff --git a/include/Domito.h b/include/Domito.h index 3d30df2..bfa97a9 100644 --- a/include/Domito.h +++ b/include/Domito.h @@ -179,6 +179,7 @@ DomitoCiFreePolicyInfo( _Success_(return == STATUS_SUCCESS) _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) +EXTERN_C NTSTATUS DomitoCiCheckSignedFile( _In_ PVOID Hash, @@ -194,6 +195,7 @@ DomitoCiCheckSignedFile( _Success_(return == STATUS_SUCCESS) _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) +EXTERN_C NTSTATUS DomitoCiVerifyHashInCatalog( _In_ PVOID Hash, @@ -219,6 +221,7 @@ MINCRYPT_ALLOCATE_ROUTINE( ); typedef MINCRYPT_ALLOCATE_ROUTINE* PMINCRYPT_ALLOCATE_ROUTINE; +EXTERN_C NTSTATUS DomitoCiGetCertPublisherName( _In_ MINCERT_BLOB* Certificate, @@ -226,6 +229,7 @@ DomitoCiGetCertPublisherName( _Out_ PUNICODE_STRING PublisherName ); +EXTERN_C VOID DomitoCiSetTrustedOriginClaimId( _In_ UINT32 ClaimId @@ -234,6 +238,7 @@ DomitoCiSetTrustedOriginClaimId( _Success_(return == STATUS_SUCCESS) _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) +EXTERN_C NTSTATUS DomitoCiValidateFileObject( _In_ FILE_OBJECT* FileObject, diff --git a/src/Domito.CodeIntegrity.cpp b/src/Domito.CodeIntegrity.cpp index 7dda77d..49df98d 100644 --- a/src/Domito.CodeIntegrity.cpp +++ b/src/Domito.CodeIntegrity.cpp @@ -11,6 +11,167 @@ DOMITO_CODE_INTEGRITY G_CI = {}; +/* ___ ___ __ __ + * / __|_ _| \ \ / / _ __ _ _ __ _ __ ___ _ _ ___ + * | (__ | | \ \/\/ / '_/ _` | '_ \ '_ \/ -_) '_(_-< + * \___|___| \_/\_/|_| \__,_| .__/ .__/\___|_| /__/ + * |_| |_| + */ + +_IRQL_requires_max_(PASSIVE_LEVEL) +PVOID +DomitoCiFreePolicyInfo( + _Inout_ MINCRYPT_POLICY_INFO* PolicyInfo +) +{ + if (G_CI.CiFreePolicyInfo) + { + return G_CI.CiFreePolicyInfo(PolicyInfo); + } + + return NULL; +} + +_Success_(return == STATUS_SUCCESS) +_Must_inspect_result_ +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +DomitoCiCheckSignedFile( + _In_ PVOID Hash, + _In_ UINT32 HashSize, + _In_ ALG_ID HashAlgId, + _In_ PVOID SecurityDirectory, + _In_ UINT32 SizeOfSecurityDirectory, + _Out_ MINCRYPT_POLICY_INFO * PolicyInfo, + _Out_ LARGE_INTEGER * SigningTime, + _Out_ MINCRYPT_POLICY_INFO * TimeStampPolicyInfo +) +{ + if (G_CI.CiCheckSignedFile) + { + return G_CI.CiCheckSignedFile( + Hash, + HashSize, + HashAlgId, + SecurityDirectory, + SizeOfSecurityDirectory, + PolicyInfo, + SigningTime, + TimeStampPolicyInfo + ); + } + + return STATUS_NOT_IMPLEMENTED; +} + +_Success_(return == STATUS_SUCCESS) +_Must_inspect_result_ +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +DomitoCiVerifyHashInCatalog( + _In_ PVOID Hash, + _In_ UINT32 HashSize, + _In_ ALG_ID HashAlgId, + _In_ BOOLEAN IsReloadCatalogs, + _In_ UINT32 Always0, + _In_ UINT32 Always2007F, + _Out_ MINCRYPT_POLICY_INFO * PolicyInfo, + _Out_opt_ UNICODE_STRING * CatalogName, + _Out_ LARGE_INTEGER * SigningTime, + _Out_ MINCRYPT_POLICY_INFO * TimeStampPolicyInfo +) +{ + if (G_CI.CiVerifyHashInCatalog) + { + return G_CI.CiVerifyHashInCatalog( + Hash, + HashSize, + HashAlgId, + IsReloadCatalogs, + Always0, + Always2007F, + PolicyInfo, + CatalogName, + SigningTime, + TimeStampPolicyInfo + ); + } + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +DomitoCiGetCertPublisherName( + _In_ MINCERT_BLOB * Certificate, + _In_ PMINCRYPT_ALLOCATE_ROUTINE AllocateRoutine, + _Out_ PUNICODE_STRING PublisherName +) +{ + if (G_CI.CiGetCertPublisherName) + { + G_CI.CiGetCertPublisherName( + Certificate, + AllocateRoutine, + PublisherName + ); + } + + return STATUS_NOT_IMPLEMENTED; +} + +VOID +DomitoCiSetTrustedOriginClaimId( + _In_ UINT32 ClaimId +) +{ + if (G_CI.CiSetTrustedOriginClaimId) + { + G_CI.CiSetTrustedOriginClaimId(ClaimId); + } +} + +_Success_(return == STATUS_SUCCESS) +_Must_inspect_result_ +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +DomitoCiValidateFileObject( + _In_ FILE_OBJECT * FileObject, + _In_opt_ UINT32 Unknown1, + _In_opt_ UINT32 Unknown2, + _Out_ MINCRYPT_POLICY_INFO * PolicyInfo, + _Out_ MINCRYPT_POLICY_INFO * TimeStampPolicyInfo, + _Out_ LARGE_INTEGER * SigningTime, + _Out_ UINT8 * Hash, + _Inout_ UINT32 * HashSize, + _Out_ ALG_ID * HashAlgId +) +{ + if (G_CI.CiValidateFileObject) + { + G_CI.CiValidateFileObject( + FileObject, + Unknown1, + Unknown2, + PolicyInfo, + TimeStampPolicyInfo, + SigningTime, + Hash, + HashSize, + HashAlgId + ); + } + + return STATUS_NOT_IMPLEMENTED; +} + + +/* _ _ _ _ _ _ _ ___ _ _ + * | | | | |_(_) (_) |_ _ _ | __| _ _ _ __| |_(_)___ _ _ ___ + * | |_| | _| | | | _| || | | _| || | ' \/ _| _| / _ \ ' \(_-< + * \___/ \__|_|_|_|\__|\_, | |_| \_,_|_||_\__|\__|_\___/_||_/__/ + * |__/ + */ + _IRQL_requires_max_(DISPATCH_LEVEL) UINT32 DomitoGetPortableExecutableDigestKind( diff --git a/src/Domito.Internal.h b/src/Domito.Internal.h index 867ece9..42335a8 100644 --- a/src/Domito.Internal.h +++ b/src/Domito.Internal.h @@ -51,11 +51,11 @@ typedef struct _SYSTEM_MODULE_INFORMATION } SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION; // Function prototype for ZwQuerySystemInformation -NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( - ULONG SystemInformationClass, - PVOID SystemInformation, - ULONG SystemInformationLength, - PULONG ReturnLength +EXTERN_C NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( + _In_ ULONG SystemInformationClass, + _Inout_ PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength ); typedef struct _LDR_DATA_TABLE_ENTRY @@ -89,7 +89,7 @@ typedef PVOID(NTAPI* t_RtlImageDirectoryEntryToData)( OUT PULONG Size ); -typedef NTSTATUS(*QUERY_INFO_PROCESS) ( +typedef NTSTATUS(NTAPI* t_ZwQueryInformationProcess) ( __in HANDLE ProcessHandle, __in PROCESSINFOCLASS ProcessInformationClass, __out_bcount(ProcessInformationLength) PVOID ProcessInformation, @@ -97,6 +97,24 @@ typedef NTSTATUS(*QUERY_INFO_PROCESS) ( __out_opt PULONG ReturnLength ); +/* ___ + * / __|___ _ __ _ __ ___ _ _ + * | (__/ _ \ ' \| ' \/ _ \ ' \ + * \___\___/_|_|_|_|_|_\___/_||_| + * + */ + +typedef struct +{ + t_RtlImageDirectoryEntryToData RtlImageDirectoryEntryToData; + + t_ZwQueryInformationProcess ZwQueryInformationProcess; + +} DOMITO_COMMON; + +extern DOMITO_COMMON G_Common; + + /* __ __ __ __ _ * | \/ |___ _ __ ___ _ _ _ _ | \/ |__ _ _ _ __ _ __ _ ___ _ __ ___ _ _| |_ * | |\/| / -_) ' \/ _ \ '_| || | | |\/| / _` | ' \/ _` / _` / -_) ' \/ -_) ' \ _| diff --git a/src/Domito.cpp b/src/Domito.cpp index 80e4a9b..72939df 100644 --- a/src/Domito.cpp +++ b/src/Domito.cpp @@ -8,7 +8,7 @@ #include "Domito.Internal.h" -static QUERY_INFO_PROCESS ZwQueryInformationProcess; +DOMITO_COMMON G_Common = {}; static STRING G_FN_CiFreePolicyInfo = RTL_CONSTANT_STRING("CiFreePolicyInfo"); static STRING G_FN_CiCheckSignedFile = RTL_CONSTANT_STRING("CiCheckSignedFile"); @@ -17,6 +17,9 @@ static STRING G_FN_CiGetCertPublisherName = RTL_CONSTANT_STRING("CiGetCertPublis static STRING G_FN_CiSetTrustedOriginClaimId = RTL_CONSTANT_STRING("CiSetTrustedOriginClaimId"); static STRING G_FN_CiValidateFileObject = RTL_CONSTANT_STRING("CiValidateFileObject"); +DECLARE_GLOBAL_CONST_UNICODE_STRING(G_QipRoutineName, L"ZwQueryInformationProcess"); +DECLARE_GLOBAL_CONST_UNICODE_STRING(G_IdetdRoutineName, L"RtlImageDirectoryEntryToData"); + _Success_(return == STATUS_SUCCESS) _Must_inspect_result_ @@ -60,6 +63,11 @@ DomitoInit() } } + G_Common.ZwQueryInformationProcess = + (t_ZwQueryInformationProcess)MmGetSystemRoutineAddress((PUNICODE_STRING)&G_QipRoutineName); + G_Common.RtlImageDirectoryEntryToData = + (t_RtlImageDirectoryEntryToData)MmGetSystemRoutineAddress((PUNICODE_STRING)&G_IdetdRoutineName); + return STATUS_SUCCESS; // TODO: unused currently } @@ -160,19 +168,14 @@ DomitoFindExportedFunctionAddress( { NTSTATUS status = STATUS_NOT_FOUND; ULONG exportSize; - - DECLARE_CONST_UNICODE_STRING(routineName, L"RtlImageDirectoryEntryToData"); - - const t_RtlImageDirectoryEntryToData fp_RtlImageDirectoryEntryToData = - (t_RtlImageDirectoryEntryToData)MmGetSystemRoutineAddress((PUNICODE_STRING)&routineName); - - if (fp_RtlImageDirectoryEntryToData == NULL) + + if (G_Common.RtlImageDirectoryEntryToData == NULL) { return STATUS_NOT_IMPLEMENTED; } // Retrieve the export directory information - const PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)fp_RtlImageDirectoryEntryToData( + const PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)G_Common.RtlImageDirectoryEntryToData( ModuleBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, @@ -347,22 +350,14 @@ DomitoGetProcessImageName( return status; } - if (ZwQueryInformationProcess == NULL) + if (G_Common.ZwQueryInformationProcess == NULL) { - UNICODE_STRING routineName = RTL_CONSTANT_STRING(L"ZwQueryInformationProcess"); - - ZwQueryInformationProcess = - (QUERY_INFO_PROCESS)MmGetSystemRoutineAddress(&routineName); - - if (ZwQueryInformationProcess == NULL) - { - status = STATUS_NOT_IMPLEMENTED; - goto cleanUp; - } + status = STATUS_NOT_IMPLEMENTED; + goto cleanUp; } /* Query the actual size of the process path */ - status = ZwQueryInformationProcess( + status = G_Common.ZwQueryInformationProcess( hProcess, ProcessImageFileName, NULL, // buffer @@ -384,7 +379,7 @@ DomitoGetProcessImageName( } /* Retrieve the process path from the handle to the process */ - if (!NT_SUCCESS(status = ZwQueryInformationProcess( + if (!NT_SUCCESS(status = G_Common.ZwQueryInformationProcess( hProcess, ProcessImageFileName, *ProcessImageName,