Out of bounds read fix

This commit is contained in:
2026-06-23 13:35:04 +02:00
parent f9d35e339f
commit 7985b23be5
3 changed files with 46 additions and 9 deletions
+1
View File
@@ -178,6 +178,7 @@ EXTERN_C
UINT32 UINT32
DomitoGetPortableExecutableDigestKind( DomitoGetPortableExecutableDigestKind(
_In_ PUCHAR pPeBytes, _In_ PUCHAR pPeBytes,
_In_ ULONG PeSize,
_In_ PIMAGE_DATA_DIRECTORY pImgDataDirectory _In_ PIMAGE_DATA_DIRECTORY pImgDataDirectory
); );
+39 -8
View File
@@ -20,16 +20,25 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
UINT32 UINT32
DomitoGetPortableExecutableDigestKind( DomitoGetPortableExecutableDigestKind(
_In_ PUCHAR pPeBytes, _In_ PUCHAR pPeBytes,
_In_ ULONG PeSize,
_In_ PIMAGE_DATA_DIRECTORY pImgDataDirectory _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; 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 LPWIN_CERTIFICATE pCert = (WIN_CERTIFICATE*)pBase;
const ULONG searchLen = min(pCert->dwLength, PeSize - securityRva);
PUCHAR pMatch = NULL; PUCHAR pMatch = NULL;
if (NT_SUCCESS(DomitoMemorySearchPattern( if (NT_SUCCESS(DomitoMemorySearchPattern(
@@ -37,7 +46,7 @@ DomitoGetPortableExecutableDigestKind(
0x00, 0x00,
15, 15,
pBase, pBase,
pCert->dwLength, searchLen,
(PVOID*)&pMatch (PVOID*)&pMatch
))) )))
{ {
@@ -49,7 +58,7 @@ DomitoGetPortableExecutableDigestKind(
0xcc, 0xcc,
19, 19,
pBase, pBase,
pCert->dwLength, searchLen,
(PVOID*)&pMatch (PVOID*)&pMatch
))) )))
{ {
@@ -99,6 +108,11 @@ DomitoCalculatePortableExecutableDigest(
ULONG resultLength; ULONG resultLength;
ULONG fileOffset = 0; ULONG fileOffset = 0;
if (PeSize < sizeof(IMAGE_DOS_HEADER))
{
return STATUS_INVALID_IMAGE_NOT_MZ;
}
const PIMAGE_DOS_HEADER phDos = (IMAGE_DOS_HEADER*)pPeBytes; const PIMAGE_DOS_HEADER phDos = (IMAGE_DOS_HEADER*)pPeBytes;
if (phDos->e_magic != IMAGE_DOS_SIGNATURE) if (phDos->e_magic != IMAGE_DOS_SIGNATURE)
{ {
@@ -106,6 +120,11 @@ DomitoCalculatePortableExecutableDigest(
return STATUS_INVALID_IMAGE_NOT_MZ; 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); const PIMAGE_NT_HEADERS phNt = (PIMAGE_NT_HEADERS)(pPeBytes + phDos->e_lfanew);
if (phNt->Signature != IMAGE_NT_SIGNATURE) if (phNt->Signature != IMAGE_NT_SIGNATURE)
{ {
@@ -167,7 +186,7 @@ DomitoCalculatePortableExecutableDigest(
// //
// Boring bcrypt boilerplate code // Boring bcrypt boilerplate code
// //
const UINT32 peDigestKind = DomitoGetPortableExecutableDigestKind(pPeBytes, pImgDataDirectory); const UINT32 peDigestKind = DomitoGetPortableExecutableDigestKind(pPeBytes, PeSize, pImgDataDirectory);
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider( if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
&hbAlg, &hbAlg,
@@ -275,9 +294,21 @@ DomitoCalculatePortableExecutableDigest(
// //
// Now hash everything else in the file up to the certificate data. // Now hash everything else in the file up to the certificate data.
// //
ULONG remaining = hasEmbeddedSig ULONG remaining;
? pImgDataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress - fileOffset if (hasEmbeddedSig)
: PeSize - fileOffset; {
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) while (remaining > 0)
{ {
+6 -1
View File
@@ -213,7 +213,12 @@ DomitoMemorySearchPattern(
*ppMatch = NULL; *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; BOOLEAN found = TRUE;
for (SIZE_T j = 0; j < puLen; j++) for (SIZE_T j = 0; j < puLen; j++)