diff --git a/include/Domito.h b/include/Domito.h index 3a1f9b4..68d22f4 100644 --- a/include/Domito.h +++ b/include/Domito.h @@ -178,6 +178,7 @@ EXTERN_C UINT32 DomitoGetPortableExecutableDigestKind( _In_ PUCHAR pPeBytes, + _In_ ULONG PeSize, _In_ PIMAGE_DATA_DIRECTORY pImgDataDirectory ); diff --git a/src/Domito.CodeIntegrity.cpp b/src/Domito.CodeIntegrity.cpp index d181ae7..8a22b33 100644 --- a/src/Domito.CodeIntegrity.cpp +++ b/src/Domito.CodeIntegrity.cpp @@ -20,16 +20,25 @@ _IRQL_requires_max_(DISPATCH_LEVEL) UINT32 DomitoGetPortableExecutableDigestKind( _In_ PUCHAR pPeBytes, + _In_ ULONG PeSize, _In_ PIMAGE_DATA_DIRECTORY pImgDataDirectory ) { - if (!pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress) + const ULONG securityRva = pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; + + if (!securityRva) { return CALG_SHA1; } - const PVOID pBase = pPeBytes + pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; + if (securityRva > PeSize || (PeSize - securityRva) < sizeof(WIN_CERTIFICATE)) + { + return CALG_SHA1; + } + + const PVOID pBase = pPeBytes + securityRva; const LPWIN_CERTIFICATE pCert = (WIN_CERTIFICATE*)pBase; + const ULONG searchLen = min(pCert->dwLength, PeSize - securityRva); PUCHAR pMatch = NULL; if (NT_SUCCESS(DomitoMemorySearchPattern( @@ -37,7 +46,7 @@ DomitoGetPortableExecutableDigestKind( 0x00, 15, pBase, - pCert->dwLength, + searchLen, (PVOID*)&pMatch ))) { @@ -49,7 +58,7 @@ DomitoGetPortableExecutableDigestKind( 0xcc, 19, pBase, - pCert->dwLength, + searchLen, (PVOID*)&pMatch ))) { @@ -99,6 +108,11 @@ DomitoCalculatePortableExecutableDigest( ULONG resultLength; ULONG fileOffset = 0; + if (PeSize < sizeof(IMAGE_DOS_HEADER)) + { + return STATUS_INVALID_IMAGE_NOT_MZ; + } + const PIMAGE_DOS_HEADER phDos = (IMAGE_DOS_HEADER*)pPeBytes; if (phDos->e_magic != IMAGE_DOS_SIGNATURE) { @@ -106,6 +120,11 @@ DomitoCalculatePortableExecutableDigest( return STATUS_INVALID_IMAGE_NOT_MZ; } + if (phDos->e_lfanew > PeSize - sizeof(IMAGE_NT_HEADERS)) + { + return STATUS_INVALID_IMAGE_FORMAT; + } + const PIMAGE_NT_HEADERS phNt = (PIMAGE_NT_HEADERS)(pPeBytes + phDos->e_lfanew); if (phNt->Signature != IMAGE_NT_SIGNATURE) { @@ -167,7 +186,7 @@ DomitoCalculatePortableExecutableDigest( // // Boring bcrypt boilerplate code // - const UINT32 peDigestKind = DomitoGetPortableExecutableDigestKind(pPeBytes, pImgDataDirectory); + const UINT32 peDigestKind = DomitoGetPortableExecutableDigestKind(pPeBytes, PeSize, pImgDataDirectory); if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider( &hbAlg, @@ -275,9 +294,21 @@ DomitoCalculatePortableExecutableDigest( // // Now hash everything else in the file up to the certificate data. // - ULONG remaining = hasEmbeddedSig - ? pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress - fileOffset - : PeSize - fileOffset; + ULONG remaining; + if (hasEmbeddedSig) + { + const ULONG secRva = pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress; + if (secRva < fileOffset) + { + status = STATUS_INVALID_IMAGE_FORMAT; + goto cleanup; + } + remaining = secRva - fileOffset; + } + else + { + remaining = (fileOffset <= PeSize) ? (PeSize - fileOffset) : 0; + } while (remaining > 0) { diff --git a/src/Domito.cpp b/src/Domito.cpp index 73c43d3..41c9dab 100644 --- a/src/Domito.cpp +++ b/src/Domito.cpp @@ -213,7 +213,12 @@ DomitoMemorySearchPattern( *ppMatch = NULL; - for (SIZE_T i = 0; i < puSize - puLen; i++) + if (puLen == 0 || puSize < puLen) + { + return STATUS_NOT_FOUND; + } + + for (SIZE_T i = 0; i + puLen <= puSize; i++) { BOOLEAN found = TRUE; for (SIZE_T j = 0; j < puLen; j++)