diff --git a/Domito.sln.DotSettings b/Domito.sln.DotSettings index d2af9b1..e3003ea 100644 --- a/Domito.sln.DotSettings +++ b/Domito.sln.DotSettings @@ -6,7 +6,10 @@ True True True + True + True True True True + True True \ No newline at end of file diff --git a/include/Domito.MinCrypt.h b/include/Domito.MinCrypt.h index 6e7e551..924fd8e 100644 --- a/include/Domito.MinCrypt.h +++ b/include/Domito.MinCrypt.h @@ -356,205 +356,12 @@ typedef struct _MINCRYPT_POLICY_INFO #include -/** -* Resets a PolicyInfo struct - frees the dynamically allocated buffer in PolicyInfo (ChainInfo) if not null. -* Zeros the entire PolicyInfo struct. -* -* @param PolicyInfo - the struct to reset. -* -* @return the struct which was reset. -*/ -_IRQL_requires_max_(PASSIVE_LEVEL) -MINCRYPTAPI -PVOID -NTAPI -CiFreePolicyInfo( - _Inout_ MINCRYPT_POLICY_INFO* PolicyInfo -); +/* + * Note: function prototypes moved to + * They'll be made available via run-time dynamic linking instead + */ -/** -* Win7SP1-Win8.1 only (KB3033929 installed). Use CiValidateFileObject on Win10! -* -* Given a file digest and signature of a file, verify the signature and provide information regarding -* the certificates that was used for signing (the entire certificate chain) -* -* @param Hash - buffer containing the digest -* -* @param HashSize - size of the digest, e.g. 0x14(160bit) for SHA1, 0x20(256bit) for SHA256 -* -* @param HashAlgId - digest algorithm identifier, e.g. CALG_SHA1(0x8004), CALG_SHA_256(0x800C) -* -* @param SecurityDirectory - pointer to the start of the security directory -* -* @param SizeOfSecurityDirectory - size the security directory -* -* @param PolicyInfo[out] - PolicyInfo containing information about the signer certificate chain -* -* @param SigningTime[out] - when the file was signed (FILETIME format) -* -* @param TimeStampPolicyInfo[out] - PolicyInfo containing information about the timestamping authority (TSA) certificate chain -* -* @return STATUS_SUCCESS if the file digest in the signature matches the given digest and the signer cetificate is verified. -* Various error values otherwise, for example: -* STATUS_INVALID_IMAGE_HASH - the digest does not match the digest in the signature -* STATUS_IMAGE_CERT_REVOKED - the certificate used for signing the file is revoked -* STATUS_IMAGE_CERT_EXPIRED - the certificate used for signing the file has expired -*/ -_IRQL_requires_max_(PASSIVE_LEVEL) -MINCRYPTAPI -NTSTATUS -NTAPI -CiCheckSignedFile( - _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 -); - - -/** -* Win7SP1-Win8.1 only (KB3033929 installed). Use CiValidateFileObject on Win10! -* -* Checks if the SHA-1 message digest is contained within a verified system catalog -* -* @note must be attached to the PsInitialSystemProcess first! -* -* @param Hash - buffer containing the digest -* -* @param HashSize - size of the digest, e.g. 0x14(160bit) for SHA1, 0x20(256bit) for SHA256 -* -* @param HashAlgId - digest algorithm identifier, e.g. CALG_SHA1(0x8004), CALG_SHA_256(0x800C) -* -* @param IsReloadCatalogs - is reload catalogs cache. -* -* @param Always0 - this is for IsReloadCatalogs, Always0 != 0 ? 16 : 24; -* -* @param Always2007F - unknown, always 0x2007F, maybe a mask. -* -* @param PolicyInfo[out] - PolicyInfo containing information about the signer certificate chain. -* -* @param CatalogName[out option] - catalog file name. -* -* @param SigningTime[out] - when the file was signed (FILETIME format) -* -* @param TimeStampPolicyInfo[out] - PolicyInfo containing information about the timestamping authority (TSA) certificate chain. -* -* @return STATUS_SUCCESS if the file digest in the signature matches the given digest and the signer cetificate is verified. -* Various error values otherwise, for example: -* STATUS_INVALID_IMAGE_HASH - the digest does not match the digest in the signature -* STATUS_IMAGE_CERT_REVOKED - the certificate used for signing the file is revoked -* STATUS_IMAGE_CERT_EXPIRED - the certificate used for signing the file has expired -*/ -_IRQL_requires_max_(PASSIVE_LEVEL) -MINCRYPTAPI -NTSTATUS -NTAPI -CiVerifyHashInCatalog( - _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 (NTDDI_VERSION >= NTDDI_WIN10) - -typedef -_IRQL_requires_same_ -_Function_class_(MINCRYPT_ALLOCATE_ROUTINE) -__drv_allocatesMem(Mem) -PVOID -NTAPI -MINCRYPT_ALLOCATE_ROUTINE( - _In_ SIZE_T ByteSize -); -typedef MINCRYPT_ALLOCATE_ROUTINE* PMINCRYPT_ALLOCATE_ROUTINE; - -/** -* Parse the publisher name from the certificate -* -* @param Certificate - &PolicyInfo.ChainInfo->ChainElements[x].Certificate -* -* @param AllocateRoutine - used to allocate PublisherName buffer. -* -* @param PublisherName[out] - publisher name. -* -* @return buffer length. -*/ -MINCRYPTAPI -NTSTATUS -NTAPI -CiGetCertPublisherName( - _In_ MINCERT_BLOB* Certificate, - _In_ PMINCRYPT_ALLOCATE_ROUTINE AllocateRoutine, - _Out_ PUNICODE_STRING PublisherName -); - - -MINCRYPTAPI -VOID -NTAPI -CiSetTrustedOriginClaimId( - _In_ UINT32 ClaimId -); - -/** -* Given a file object, verify the signature and provide information regarding -* the certificates that was used for signing (the entire certificate chain) -* -* @param FileObject - FileObject of the PE in question -* -* @param Unkonwn1 - unknown, 0 is a valid value. (Unkonwn1 and Unkonwn2 together calculate the minimum support algorithm) -* -* @param Unkonwn2 - unknown, 0 is a valid value. (^ the words above refer to 'CipGetHashAlgorithmForLegacyScenario') -* -* @param PolicyInfo[out] - PolicyInfo containing information about the signer certificate chain. -* -* @param TimeStampPolicyInfo[out] - PolicyInfo containing information about the timestamping authority (TSA) certificate chain. -* -* @param SigningTime[out] - when the file was signed (FILETIME format) -* -* @param Hash - buffer containing the digest -* -* @param HashSize - size of the digest, e.g. 0x14(160bit) for SHA1, 0x20(256bit) for SHA256 -* -* @param HashAlgId - digest algorithm identifier, e.g. CALG_SHA1(0x8004), CALG_SHA_256(0x800C) -* -* @return STATUS_SUCCESS if the file digest in the signature matches the given digest and the signer cetificate is verified. -* Various error values otherwise, for example: -* STATUS_INVALID_IMAGE_HASH - the digest does not match the digest in the signature -* STATUS_IMAGE_CERT_REVOKED - the certificate used for signing the file is revoked -* STATUS_IMAGE_CERT_EXPIRED - the certificate used for signing the file has expired -*/ -_IRQL_requires_max_(PASSIVE_LEVEL) -MINCRYPTAPI -NTSTATUS -NTAPI -CiValidateFileObject( - _In_ FILE_OBJECT* FileObject, - _In_opt_ UINT32 Unkonwn1, - _In_opt_ UINT32 Unkonwn2, - _Out_ MINCRYPT_POLICY_INFO* PolicyInfo, - _Out_ MINCRYPT_POLICY_INFO* TimeStampPolicyInfo, - _Out_ LARGE_INTEGER* SigningTime, - _Out_ UINT8* Hash, - _Inout_ UINT32* HashSize, - _Out_ ALG_ID* HashAlgId -); - -#endif // NTDDI_VERSION >= NTDDI_WIN10 - EXTERN_C_END #if _MSC_VER >= 1200 diff --git a/include/Domito.h b/include/Domito.h index cd44ba2..1fc757b 100644 --- a/include/Domito.h +++ b/include/Domito.h @@ -139,6 +139,92 @@ DOMITO_CALG_TO_BCRYPT_ALGORITHM( } +/* ___ _ ___ _ _ _ + * / __|___ __| |___ |_ _|_ _| |_ ___ __ _ _ _(_) |_ _ _ + * | (__/ _ \/ _` / -_) | || ' \ _/ -_) _` | '_| | _| || | + * \___\___/\__,_\___| |___|_||_\__\___\__, |_| |_|\__|\_, | + * |___/ |__/ + */ + +_IRQL_requires_max_(PASSIVE_LEVEL) +EXTERN_C +PVOID +DomitoCiFreePolicyInfo( + _Inout_ MINCRYPT_POLICY_INFO* PolicyInfo +); + +_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 +); + +_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 +); + +typedef +_IRQL_requires_same_ +_Function_class_(MINCRYPT_ALLOCATE_ROUTINE) +__drv_allocatesMem(Mem) +PVOID +NTAPI +MINCRYPT_ALLOCATE_ROUTINE( + _In_ SIZE_T ByteSize +); +typedef MINCRYPT_ALLOCATE_ROUTINE* PMINCRYPT_ALLOCATE_ROUTINE; + +NTSTATUS +DomitoCiGetCertPublisherName( + _In_ MINCERT_BLOB* Certificate, + _In_ PMINCRYPT_ALLOCATE_ROUTINE AllocateRoutine, + _Out_ PUNICODE_STRING PublisherName +); + +VOID +DomitoCiSetTrustedOriginClaimId( + _In_ UINT32 ClaimId +); + +_Success_(return == STATUS_SUCCESS) +_Must_inspect_result_ +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +DomitoCiValidateFileObject( + _In_ FILE_OBJECT* FileObject, + _In_opt_ UINT32 Unkonwn1, + _In_opt_ UINT32 Unkonwn2, + _Out_ MINCRYPT_POLICY_INFO* PolicyInfo, + _Out_ MINCRYPT_POLICY_INFO* TimeStampPolicyInfo, + _Out_ LARGE_INTEGER* SigningTime, + _Out_ UINT8* Hash, + _Inout_ UINT32* HashSize, + _Out_ ALG_ID* HashAlgId +); + + /******************************************************************************** * Library functions * ********************************************************************************/ diff --git a/src/Domito.CodeIntegrity.cpp b/src/Domito.CodeIntegrity.cpp index 5d52523..7dda77d 100644 --- a/src/Domito.CodeIntegrity.cpp +++ b/src/Domito.CodeIntegrity.cpp @@ -1,13 +1,15 @@ -/* ___ _ ___ _ _ _ - * / __|___ __| |___ |_ _|_ _| |_ ___ __ _ _ _(_) |_ _ _ +/* ___ _ ___ _ _ _ + * / __|___ __| |___ |_ _|_ _| |_ ___ __ _ _ _(_) |_ _ _ * | (__/ _ \/ _` / -_) | || ' \ _/ -_) _` | '_| | _| || | * \___\___/\__,_\___| |___|_||_\__\___\__, |_| |_|\__|\_, | - * |___/ |__/ + * |___/ |__/ */ #include "Domito.Internal.h" #include "Domito.MinCrypt.h" +DOMITO_CODE_INTEGRITY G_CI = {}; + _IRQL_requires_max_(DISPATCH_LEVEL) UINT32 @@ -372,12 +374,18 @@ DomitoValidateFileLegacyMode( do { + if (!G_CI.CiFreePolicyInfo || !G_CI.CiCheckSignedFile || !G_CI.CiVerifyHashInCatalog) + { + status = STATUS_NOT_IMPLEMENTED; + break; + } + SigningTime->QuadPart = 0; - CiFreePolicyInfo(PolicyInfo); - CiFreePolicyInfo(TimeStampPolicyInfo); + G_CI.CiFreePolicyInfo(PolicyInfo); + G_CI.CiFreePolicyInfo(TimeStampPolicyInfo); - if (HashSize != MINCRYPT_SHA1_LENGTH) + if (HashSize != MINCRYPT_SHA1_LENGTH && HashSize != MINCRYPT_SHA256_LENGTH) { status = STATUS_INVALID_IMAGE_HASH; break; @@ -429,7 +437,7 @@ DomitoValidateFileLegacyMode( KeStackAttachProcess(PsInitialSystemProcess, &systemContext); { - status = CiCheckSignedFile( + status = G_CI.CiCheckSignedFile( Hash, HashSize, HashAlgId, @@ -455,7 +463,7 @@ DomitoValidateFileLegacyMode( KeStackAttachProcess(PsInitialSystemProcess, &systemContext); { - status = CiVerifyHashInCatalog( + status = G_CI.CiVerifyHashInCatalog( Hash, HashSize, HashAlgId, @@ -470,7 +478,7 @@ DomitoValidateFileLegacyMode( if (status == STATUS_INVALID_IMAGE_HASH) { - status = CiVerifyHashInCatalog( + status = G_CI.CiVerifyHashInCatalog( Hash, HashSize, HashAlgId, diff --git a/src/Domito.Internal.h b/src/Domito.Internal.h index 0c9e634..9df8dd0 100644 --- a/src/Domito.Internal.h +++ b/src/Domito.Internal.h @@ -123,3 +123,223 @@ typedef struct // Global instance, individual field can be adjusted by the caller // extern DOMITO_MEMORY G_Memory; + + +/* ___ _ ___ _ _ _ + * / __|___ __| |___ |_ _|_ _| |_ ___ __ _ _ _(_) |_ _ _ + * | (__/ _ \/ _` / -_) | || ' \ _/ -_) _` | '_| | _| || | + * \___\___/\__,_\___| |___|_||_\__\___\__, |_| |_|\__|\_, | + * |___/ |__/ + */ + +/** +* Resets a PolicyInfo struct - frees the dynamically allocated buffer in PolicyInfo (ChainInfo) if not null. +* Zeros the entire PolicyInfo struct. +* +* @param PolicyInfo - the struct to reset. +* +* @return the struct which was reset. +*/ +_IRQL_requires_max_(PASSIVE_LEVEL) +typedef +PVOID +(NTAPI* +t_CiFreePolicyInfo)( + _Inout_ MINCRYPT_POLICY_INFO* PolicyInfo +); + + +/** +* Win7SP1-Win8.1 only (KB3033929 installed). Use CiValidateFileObject on Win10! +* +* Given a file digest and signature of a file, verify the signature and provide information regarding +* the certificates that was used for signing (the entire certificate chain) +* +* @param Hash - buffer containing the digest +* +* @param HashSize - size of the digest, e.g. 0x14(160bit) for SHA1, 0x20(256bit) for SHA256 +* +* @param HashAlgId - digest algorithm identifier, e.g. CALG_SHA1(0x8004), CALG_SHA_256(0x800C) +* +* @param SecurityDirectory - pointer to the start of the security directory +* +* @param SizeOfSecurityDirectory - size the security directory +* +* @param PolicyInfo[out] - PolicyInfo containing information about the signer certificate chain +* +* @param SigningTime[out] - when the file was signed (FILETIME format) +* +* @param TimeStampPolicyInfo[out] - PolicyInfo containing information about the timestamping authority (TSA) certificate chain +* +* @return STATUS_SUCCESS if the file digest in the signature matches the given digest and the signer cetificate is verified. +* Various error values otherwise, for example: +* STATUS_INVALID_IMAGE_HASH - the digest does not match the digest in the signature +* STATUS_IMAGE_CERT_REVOKED - the certificate used for signing the file is revoked +* STATUS_IMAGE_CERT_EXPIRED - the certificate used for signing the file has expired +*/ +_IRQL_requires_max_(PASSIVE_LEVEL) +typedef +NTSTATUS +(NTAPI* +t_CiCheckSignedFile)( + _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 +); + + +/** +* Win7SP1-Win8.1 only (KB3033929 installed). Use CiValidateFileObject on Win10! +* +* Checks if the SHA-1 message digest is contained within a verified system catalog +* +* @note must be attached to the PsInitialSystemProcess first! +* +* @param Hash - buffer containing the digest +* +* @param HashSize - size of the digest, e.g. 0x14(160bit) for SHA1, 0x20(256bit) for SHA256 +* +* @param HashAlgId - digest algorithm identifier, e.g. CALG_SHA1(0x8004), CALG_SHA_256(0x800C) +* +* @param IsReloadCatalogs - is reload catalogs cache. +* +* @param Always0 - this is for IsReloadCatalogs, Always0 != 0 ? 16 : 24; +* +* @param Always2007F - unknown, always 0x2007F, maybe a mask. +* +* @param PolicyInfo[out] - PolicyInfo containing information about the signer certificate chain. +* +* @param CatalogName[out option] - catalog file name. +* +* @param SigningTime[out] - when the file was signed (FILETIME format) +* +* @param TimeStampPolicyInfo[out] - PolicyInfo containing information about the timestamping authority (TSA) certificate chain. +* +* @return STATUS_SUCCESS if the file digest in the signature matches the given digest and the signer cetificate is verified. +* Various error values otherwise, for example: +* STATUS_INVALID_IMAGE_HASH - the digest does not match the digest in the signature +* STATUS_IMAGE_CERT_REVOKED - the certificate used for signing the file is revoked +* STATUS_IMAGE_CERT_EXPIRED - the certificate used for signing the file has expired +*/ +_IRQL_requires_max_(PASSIVE_LEVEL) +typedef +NTSTATUS +(NTAPI* +t_CiVerifyHashInCatalog)( + _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 (NTDDI_VERSION >= NTDDI_WIN10) + +/** +* Parse the publisher name from the certificate +* +* @param Certificate - &PolicyInfo.ChainInfo->ChainElements[x].Certificate +* +* @param AllocateRoutine - used to allocate PublisherName buffer. +* +* @param PublisherName[out] - publisher name. +* +* @return buffer length. +*/ +typedef +NTSTATUS +(NTAPI* +t_CiGetCertPublisherName)( + _In_ MINCERT_BLOB* Certificate, + _In_ PMINCRYPT_ALLOCATE_ROUTINE AllocateRoutine, + _Out_ PUNICODE_STRING PublisherName +); + + +typedef +VOID +(NTAPI* +t_CiSetTrustedOriginClaimId)( + _In_ UINT32 ClaimId +); + +/** +* Given a file object, verify the signature and provide information regarding +* the certificates that was used for signing (the entire certificate chain) +* +* @param FileObject - FileObject of the PE in question +* +* @param Unkonwn1 - unknown, 0 is a valid value. (Unkonwn1 and Unkonwn2 together calculate the minimum support algorithm) +* +* @param Unkonwn2 - unknown, 0 is a valid value. (^ the words above refer to 'CipGetHashAlgorithmForLegacyScenario') +* +* @param PolicyInfo[out] - PolicyInfo containing information about the signer certificate chain. +* +* @param TimeStampPolicyInfo[out] - PolicyInfo containing information about the timestamping authority (TSA) certificate chain. +* +* @param SigningTime[out] - when the file was signed (FILETIME format) +* +* @param Hash - buffer containing the digest +* +* @param HashSize - size of the digest, e.g. 0x14(160bit) for SHA1, 0x20(256bit) for SHA256 +* +* @param HashAlgId - digest algorithm identifier, e.g. CALG_SHA1(0x8004), CALG_SHA_256(0x800C) +* +* @return STATUS_SUCCESS if the file digest in the signature matches the given digest and the signer cetificate is verified. +* Various error values otherwise, for example: +* STATUS_INVALID_IMAGE_HASH - the digest does not match the digest in the signature +* STATUS_IMAGE_CERT_REVOKED - the certificate used for signing the file is revoked +* STATUS_IMAGE_CERT_EXPIRED - the certificate used for signing the file has expired +*/ +_IRQL_requires_max_(PASSIVE_LEVEL) +typedef +NTSTATUS +(NTAPI* +t_CiValidateFileObject)( + _In_ FILE_OBJECT* FileObject, + _In_opt_ UINT32 Unkonwn1, + _In_opt_ UINT32 Unkonwn2, + _Out_ MINCRYPT_POLICY_INFO* PolicyInfo, + _Out_ MINCRYPT_POLICY_INFO* TimeStampPolicyInfo, + _Out_ LARGE_INTEGER* SigningTime, + _Out_ UINT8* Hash, + _Inout_ UINT32* HashSize, + _Out_ ALG_ID* HashAlgId +); + +#endif // NTDDI_VERSION >= NTDDI_WIN10 + +// +// Function pointers to CI.dll exports +// +typedef struct +{ + t_CiFreePolicyInfo CiFreePolicyInfo; + + t_CiCheckSignedFile CiCheckSignedFile; + + t_CiVerifyHashInCatalog CiVerifyHashInCatalog; + + t_CiGetCertPublisherName CiGetCertPublisherName; + + t_CiSetTrustedOriginClaimId CiSetTrustedOriginClaimId; + + t_CiValidateFileObject CiValidateFileObject; + +} DOMITO_CODE_INTEGRITY; + +// +// Global instance +// +extern DOMITO_CODE_INTEGRITY G_CI;