From 791432dcc21f7b9d9d1836c4d9f9851d159060b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 2 Jul 2023 18:51:02 +0200 Subject: [PATCH] More clean-up --- src/Domito.CodeIntegrity.cpp | 498 ++++++++++++++++++++++++++++++++++ src/Domito.Internal.h | 1 - src/Domito.cpp | 501 ----------------------------------- src/Domito.vcxproj | 1 + src/Domito.vcxproj.filters | 3 + 5 files changed, 502 insertions(+), 502 deletions(-) create mode 100644 src/Domito.CodeIntegrity.cpp diff --git a/src/Domito.CodeIntegrity.cpp b/src/Domito.CodeIntegrity.cpp new file mode 100644 index 0000000..5d52523 --- /dev/null +++ b/src/Domito.CodeIntegrity.cpp @@ -0,0 +1,498 @@ +/* ___ _ ___ _ _ _ + * / __|___ __| |___ |_ _|_ _| |_ ___ __ _ _ _(_) |_ _ _ + * | (__/ _ \/ _` / -_) | || ' \ _/ -_) _` | '_| | _| || | + * \___\___/\__,_\___| |___|_||_\__\___\__, |_| |_|\__|\_, | + * |___/ |__/ + */ + +#include "Domito.Internal.h" +#include "Domito.MinCrypt.h" + + +_IRQL_requires_max_(DISPATCH_LEVEL) +UINT32 +DomitoGetPortableExecutableDigestKind( + _In_ PUCHAR pPeBytes, + _In_ PIMAGE_DATA_DIRECTORY pImgDataDirectory +) +{ + if (!pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress) + { + return CALG_SHA1; + } + + const PVOID pBase = pPeBytes + pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; + const LPWIN_CERTIFICATE pCert = (WIN_CERTIFICATE*)pBase; + PUCHAR pMatch = NULL; + + if (NT_SUCCESS(DomitoMemorySearchPattern( + (const PUCHAR)"\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14", + 0x00, + 15, + pBase, + pCert->dwLength, + (PVOID*)&pMatch + ))) + { + return CALG_SHA1; + } + + if (NT_SUCCESS(DomitoMemorySearchPattern( + (const PUCHAR)"\x30\xcc\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\xcc\x05\x00\x04\xcc", + 0xcc, + 19, + pBase, + pCert->dwLength, + (PVOID*)&pMatch + ))) + { + if (pMatch == NULL) + { + return CALG_SHA1; + } + + if (pMatch[1] == 0x31 && pMatch[14] == 0x01 && pMatch[18] == 0x20) + { + return CALG_SHA256; + } + else if (pMatch[1] == 0x41 && pMatch[14] == 0x02 && pMatch[18] == 0x30) + { + return CALG_SHA384; + } + else if (pMatch[1] == 0x51 && pMatch[14] == 0x03 && pMatch[18] == 0x40) + { + return CALG_SHA512; + } + } + + return CALG_SHA1; +} + +_Success_(return == STATUS_SUCCESS) +_Must_inspect_result_ +_IRQL_requires_max_(PASSIVE_LEVEL) +NTSTATUS +DomitoCalculatePortableExecutableDigest( + _In_ PUCHAR pPeBytes, + _In_ ULONG PeSize, + _Out_ PUINT32 pDigestCalgOut, + _Out_ PULONG pDigestSizeOut, + _Out_ PVOID * pDigestOut, + _Outptr_result_maybenull_ LPWIN_CERTIFICATE * pCertOut, + _Out_ PULONG pSizeOfSecurityDirectory +) +{ + PIMAGE_DATA_DIRECTORY pImgDataDirectory; + BOOLEAN is64Bit; + PUCHAR pHash = nullptr; + NTSTATUS status; + BCRYPT_ALG_HANDLE hbAlg = nullptr; + BCRYPT_HASH_HANDLE hbHash = nullptr; + UINT32 hashLength = 0; + ULONG resultLength; + ULONG fileOffset = 0; + + const PIMAGE_DOS_HEADER phDos = (IMAGE_DOS_HEADER*)pPeBytes; + if (phDos->e_magic != IMAGE_DOS_SIGNATURE) + { + // Not an executable + return STATUS_INVALID_IMAGE_NOT_MZ; + } + + const PIMAGE_NT_HEADERS phNt = (PIMAGE_NT_HEADERS)(pPeBytes + phDos->e_lfanew); + if (phNt->Signature != IMAGE_NT_SIGNATURE) + { + // Not a PE image + return STATUS_INVALID_IMAGE_FORMAT; + } + + // + // Check if PE is 32 or 64 bits + // + switch (phNt->OptionalHeader.Magic) + { + case IMAGE_NT_OPTIONAL_HDR32_MAGIC: + is64Bit = FALSE; + break; + case IMAGE_NT_OPTIONAL_HDR64_MAGIC: + is64Bit = TRUE; + break; + default: + return STATUS_INVALID_IMAGE_FORMAT; // Unsupported architecture + } + + // + // TODO: Not sure if 16 * 512 * 512 is right. Do something better! + // + ULONG copySize = phDos->e_lfanew + sizeof(IMAGE_FILE_HEADER) + 4 + 0x40; + const PUCHAR pBuf = (PUCHAR)G_Memory.Allocate(16 * 512 * 512); + if (!pBuf) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Fetch the data directory from the PE. + // Note that we can also use RtlImageDirectoryEntryToData to fetch + // only the security directory entry but why not do it manually + // when we have the full PE image anyway + // + if (is64Bit == TRUE) + { + pImgDataDirectory = ((PIMAGE_NT_HEADERS64)phNt)->OptionalHeader.DataDirectory; + } + else + { + pImgDataDirectory = ((PIMAGE_NT_HEADERS32)phNt)->OptionalHeader.DataDirectory; + } + + // + // Check if the PE file contains a signature + // + const BOOLEAN hasEmbeddedSig = pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress != 0; + + // + // Boring bcrypt boilerplate code + // + const UINT32 peDigestKind = DomitoGetPortableExecutableDigestKind(pPeBytes, pImgDataDirectory); + + if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider( + &hbAlg, + DOMITO_CALG_TO_BCRYPT_ALGORITHM(peDigestKind), // bcrypt doesn't understand standard WinCrypt CALG IDs + MS_PRIMITIVE_PROVIDER, + 0 + ))) + { + goto cleanup; + } + + if (!NT_SUCCESS(status = BCryptGetProperty( + hbAlg, + BCRYPT_HASH_LENGTH, + (PUCHAR)&hashLength, // put the length of the hash into hashLength + sizeof(hashLength), + &resultLength, + 0 + ))) + { + goto cleanup; + } + + // + // Allocate a buffer to store the resulting hash + // + pHash = (PUCHAR)G_Memory.Allocate(hashLength); + if (!pHash) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + RtlZeroMemory(pHash, hashLength); + + // + // Create a handle to the resulting hash + // + if (!NT_SUCCESS(status = BCryptCreateHash( + hbAlg, + &hbHash, + NULL, + 0, + NULL, + 0, + 0 + ))) + { + goto cleanup; + } + + // + // Ok, if we haven't BSODed yet, we're ready to continue + // parsing the PE/COFF and hash the needed values + // + memcpy(pBuf, pPeBytes, copySize); + fileOffset += copySize; + + // + // Hash everything up to the Checksum then skip it + // + status = BCryptHashData( + hbHash, + pBuf, + copySize, + 0 + ); + if (!NT_SUCCESS(status)) + { + goto cleanup; + } + + fileOffset += 4; // Skipping the checksum field here + + // + // Reach the security directory information. + // For x64 PEs it's 10 bytes further + // + copySize = 0x3C; + if (is64Bit == TRUE) + { + copySize += 0x10; + } + + memcpy(pBuf, pPeBytes + fileOffset, copySize); + fileOffset += copySize; + + // + // Again, hash everything up to here then skip the ignored field. + // + status = BCryptHashData( + hbHash, + pBuf, + copySize, + 0 + ); + if (!NT_SUCCESS(status)) + { + goto cleanup; + } + + fileOffset += 8; // Skipping an other ignored field here + + // + // Now hash everything else in the file up to the certificate data. + // + ULONG remaining = hasEmbeddedSig + ? pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress - fileOffset + : PeSize - fileOffset; + + while (remaining > 0) + { + const ULONG chunkSize = min(remaining, 4096); + ULONG readBytes; + memset(pBuf, 0, chunkSize); + + if (fileOffset + chunkSize > PeSize) + { + readBytes = PeSize - chunkSize; + memcpy(pBuf, pPeBytes + fileOffset, readBytes); + fileOffset += readBytes; + break; + } + else + { + memcpy(pBuf, pPeBytes + fileOffset, chunkSize); + readBytes = chunkSize; + fileOffset += readBytes; + } + + if (!NT_SUCCESS(status = BCryptHashData( + hbHash, + pBuf, + readBytes, + 0 + ))) + { + goto cleanup; + } + + remaining -= readBytes; + } + + // + // Finish up the hash here + // + if (!NT_SUCCESS(status = BCryptFinishHash( + hbHash, + pHash, + hashLength, + 0 + ))) + { + goto cleanup; + } + + // + // Supply the results to the caller + // + *pDigestCalgOut = peDigestKind; + *pDigestSizeOut = hashLength; + *pDigestOut = pHash; + if (hasEmbeddedSig == TRUE) + { + *pCertOut = (LPWIN_CERTIFICATE)(pPeBytes + pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress); + *pSizeOfSecurityDirectory = pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size; + } + else + { + *pCertOut = NULL; + *pSizeOfSecurityDirectory = 0; + } + + status = STATUS_SUCCESS; + +cleanup: + if (pBuf) + { + G_Memory.Free(pBuf); + } + + if (hbHash) + { + BCryptDestroyHash(hbHash); + } + + if (hbAlg) + { + BCryptCloseAlgorithmProvider(hbAlg, 0); + } + + return status; +} + +_Success_(return == STATUS_SUCCESS) +_Must_inspect_result_ +_IRQL_requires_max_(PASSIVE_LEVEL) +#pragma code_seg("PAGED") +NTSTATUS +DomitoValidateFileLegacyMode( + _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 = G_Memory.Allocate(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) + { + G_Memory.Free(certDirectory); + } + + return status; +} +#pragma code_seg() diff --git a/src/Domito.Internal.h b/src/Domito.Internal.h index 76d416a..a8a3bfc 100644 --- a/src/Domito.Internal.h +++ b/src/Domito.Internal.h @@ -13,7 +13,6 @@ #include #include "Domito.h" -#include "Domito.MinCrypt.h" /* _ _ _ ___ _ _ _ diff --git a/src/Domito.cpp b/src/Domito.cpp index 1810f9f..07c3453 100644 --- a/src/Domito.cpp +++ b/src/Domito.cpp @@ -4,19 +4,6 @@ static QUERY_INFO_PROCESS ZwQueryInformationProcess; -/******************************************************************************** - * Memory management * - ********************************************************************************/ - - - - - - -/******************************************************************************** - * Library functions * - ********************************************************************************/ - _Success_(return == STATUS_SUCCESS) _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) @@ -205,65 +192,6 @@ DomitoMemorySearchPattern( return STATUS_NOT_FOUND; } -_IRQL_requires_max_(DISPATCH_LEVEL) -UINT32 -DomitoGetPortableExecutableDigestKind( - _In_ PUCHAR pPeBytes, - _In_ PIMAGE_DATA_DIRECTORY pImgDataDirectory -) -{ - if (!pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress) - { - return CALG_SHA1; - } - - const PVOID pBase = pPeBytes + pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; - const LPWIN_CERTIFICATE pCert = (WIN_CERTIFICATE*)pBase; - PUCHAR pMatch = NULL; - - if (NT_SUCCESS(DomitoMemorySearchPattern( - (const PUCHAR)"\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14", - 0x00, - 15, - pBase, - pCert->dwLength, - (PVOID*)&pMatch - ))) - { - return CALG_SHA1; - } - - if (NT_SUCCESS(DomitoMemorySearchPattern( - (const PUCHAR)"\x30\xcc\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\xcc\x05\x00\x04\xcc", - 0xcc, - 19, - pBase, - pCert->dwLength, - (PVOID*)&pMatch - ))) - { - if (pMatch == NULL) - { - return CALG_SHA1; - } - - if (pMatch[1] == 0x31 && pMatch[14] == 0x01 && pMatch[18] == 0x20) - { - return CALG_SHA256; - } - else if (pMatch[1] == 0x41 && pMatch[14] == 0x02 && pMatch[18] == 0x30) - { - return CALG_SHA384; - } - else if (pMatch[1] == 0x51 && pMatch[14] == 0x03 && pMatch[18] == 0x40) - { - return CALG_SHA512; - } - } - - return CALG_SHA1; -} - _Success_(return == STATUS_SUCCESS) _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) @@ -303,286 +231,6 @@ DomitoReadFile( return status; } -_Success_(return == STATUS_SUCCESS) -_Must_inspect_result_ -_IRQL_requires_max_(PASSIVE_LEVEL) -NTSTATUS -DomitoCalculatePortableExecutableDigest( - _In_ PUCHAR pPeBytes, - _In_ ULONG PeSize, - _Out_ PUINT32 pDigestCalgOut, - _Out_ PULONG pDigestSizeOut, - _Out_ PVOID * pDigestOut, - _Outptr_result_maybenull_ LPWIN_CERTIFICATE * pCertOut, - _Out_ PULONG pSizeOfSecurityDirectory -) -{ - PIMAGE_DATA_DIRECTORY pImgDataDirectory; - BOOLEAN is64Bit; - PUCHAR pHash = nullptr; - NTSTATUS status; - BCRYPT_ALG_HANDLE hbAlg = nullptr; - BCRYPT_HASH_HANDLE hbHash = nullptr; - UINT32 hashLength = 0; - ULONG resultLength; - ULONG fileOffset = 0; - - const PIMAGE_DOS_HEADER phDos = (IMAGE_DOS_HEADER*)pPeBytes; - if (phDos->e_magic != IMAGE_DOS_SIGNATURE) - { - // Not an executable - return STATUS_INVALID_IMAGE_NOT_MZ; - } - - const PIMAGE_NT_HEADERS phNt = (PIMAGE_NT_HEADERS)(pPeBytes + phDos->e_lfanew); - if (phNt->Signature != IMAGE_NT_SIGNATURE) - { - // Not a PE image - return STATUS_INVALID_IMAGE_FORMAT; - } - - // - // Check if PE is 32 or 64 bits - // - switch (phNt->OptionalHeader.Magic) - { - case IMAGE_NT_OPTIONAL_HDR32_MAGIC: - is64Bit = FALSE; - break; - case IMAGE_NT_OPTIONAL_HDR64_MAGIC: - is64Bit = TRUE; - break; - default: - return STATUS_INVALID_IMAGE_FORMAT; // Unsupported architecture - } - - // - // TODO: Not sure if 16 * 512 * 512 is right. Do something better! - // - ULONG copySize = phDos->e_lfanew + sizeof(IMAGE_FILE_HEADER) + 4 + 0x40; - const PUCHAR pBuf = (PUCHAR)G_Memory.Allocate(16 * 512 * 512); - if (!pBuf) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Fetch the data directory from the PE. - // Note that we can also use RtlImageDirectoryEntryToData to fetch - // only the security directory entry but why not do it manually - // when we have the full PE image anyway - // - if (is64Bit == TRUE) - { - pImgDataDirectory = ((PIMAGE_NT_HEADERS64)phNt)->OptionalHeader.DataDirectory; - } - else - { - pImgDataDirectory = ((PIMAGE_NT_HEADERS32)phNt)->OptionalHeader.DataDirectory; - } - - // - // Check if the PE file contains a signature - // - const BOOLEAN hasEmbeddedSig = pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress != 0; - - // - // Boring bcrypt boilerplate code - // - const UINT32 peDigestKind = DomitoGetPortableExecutableDigestKind(pPeBytes, pImgDataDirectory); - - if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider( - &hbAlg, - DOMITO_CALG_TO_BCRYPT_ALGORITHM(peDigestKind), // bcrypt doesn't understand standard WinCrypt CALG IDs - MS_PRIMITIVE_PROVIDER, - 0 - ))) - { - goto cleanup; - } - - if (!NT_SUCCESS(status = BCryptGetProperty( - hbAlg, - BCRYPT_HASH_LENGTH, - (PUCHAR)&hashLength, // put the length of the hash into hashLength - sizeof(hashLength), - &resultLength, - 0 - ))) - { - goto cleanup; - } - - // - // Allocate a buffer to store the resulting hash - // - pHash = (PUCHAR)G_Memory.Allocate(hashLength); - if (!pHash) - { - status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup; - } - RtlZeroMemory(pHash, hashLength); - - // - // Create a handle to the resulting hash - // - if (!NT_SUCCESS(status = BCryptCreateHash( - hbAlg, - &hbHash, - NULL, - 0, - NULL, - 0, - 0 - ))) - { - goto cleanup; - } - - // - // Ok, if we haven't BSODed yet, we're ready to continue - // parsing the PE/COFF and hash the needed values - // - memcpy(pBuf, pPeBytes, copySize); - fileOffset += copySize; - - // - // Hash everything up to the Checksum then skip it - // - status = BCryptHashData( - hbHash, - pBuf, - copySize, - 0 - ); - if (!NT_SUCCESS(status)) - { - goto cleanup; - } - - fileOffset += 4; // Skipping the checksum field here - - // - // Reach the security directory information. - // For x64 PEs it's 10 bytes further - // - copySize = 0x3C; - if (is64Bit == TRUE) - { - copySize += 0x10; - } - - memcpy(pBuf, pPeBytes + fileOffset, copySize); - fileOffset += copySize; - - // - // Again, hash everything up to here then skip the ignored field. - // - status = BCryptHashData( - hbHash, - pBuf, - copySize, - 0 - ); - if (!NT_SUCCESS(status)) - { - goto cleanup; - } - - fileOffset += 8; // Skipping an other ignored field here - - // - // Now hash everything else in the file up to the certificate data. - // - ULONG remaining = hasEmbeddedSig - ? pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress - fileOffset - : PeSize - fileOffset; - - while (remaining > 0) - { - const ULONG chunkSize = min(remaining, 4096); - ULONG readBytes; - memset(pBuf, 0, chunkSize); - - if (fileOffset + chunkSize > PeSize) - { - readBytes = PeSize - chunkSize; - memcpy(pBuf, pPeBytes + fileOffset, readBytes); - fileOffset += readBytes; - break; - } - else - { - memcpy(pBuf, pPeBytes + fileOffset, chunkSize); - readBytes = chunkSize; - fileOffset += readBytes; - } - - if (!NT_SUCCESS(status = BCryptHashData( - hbHash, - pBuf, - readBytes, - 0 - ))) - { - goto cleanup; - } - - remaining -= readBytes; - } - - // - // Finish up the hash here - // - if (!NT_SUCCESS(status = BCryptFinishHash( - hbHash, - pHash, - hashLength, - 0 - ))) - { - goto cleanup; - } - - // - // Supply the results to the caller - // - *pDigestCalgOut = peDigestKind; - *pDigestSizeOut = hashLength; - *pDigestOut = pHash; - if (hasEmbeddedSig == TRUE) - { - *pCertOut = (LPWIN_CERTIFICATE)(pPeBytes + pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress); - *pSizeOfSecurityDirectory = pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size; - } - else - { - *pCertOut = NULL; - *pSizeOfSecurityDirectory = 0; - } - - status = STATUS_SUCCESS; - -cleanup: - if (pBuf) - { - G_Memory.Free(pBuf); - } - - if (hbHash) - { - BCryptDestroyHash(hbHash); - } - - if (hbAlg) - { - BCryptCloseAlgorithmProvider(hbAlg, 0); - } - - return status; -} - _Success_(return == STATUS_SUCCESS) _Must_inspect_result_ _IRQL_requires_max_(PASSIVE_LEVEL) @@ -690,152 +338,3 @@ 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_ 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 = G_Memory.Allocate(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) - { - G_Memory.Free(certDirectory); - } - - return status; -} -#pragma code_seg() diff --git a/src/Domito.vcxproj b/src/Domito.vcxproj index d7e7f0f..c11c11c 100644 --- a/src/Domito.vcxproj +++ b/src/Domito.vcxproj @@ -117,6 +117,7 @@ + diff --git a/src/Domito.vcxproj.filters b/src/Domito.vcxproj.filters index e50ca77..a06fff1 100644 --- a/src/Domito.vcxproj.filters +++ b/src/Domito.vcxproj.filters @@ -25,6 +25,9 @@ Source Files + + Source Files +