Add explicit Authenticode workflows and correct CI helper contracts

This commit is contained in:
nefarius committed 2026-10-26 17:55:58 +01:00
1 parent 1026c48324
commit 7aa23f50be
18 files changed
+1952 -185

No files matched your search

+96 -3
View File
@@ -184,6 +184,43 @@ DomitoGetPortableExecutableDigestKind(
_In_ PIMAGE_DATA_DIRECTORY pImgDataDirectory
);
// Reads the first PKCS#7 entry's SpcIndirectDataContent DigestInfo algorithm
// using bounded DER navigation. Does not validate the signature or select among
// multiple/nested signatures. Absent table => STATUS_NOT_FOUND; unsupported OID
// or certificate type => STATUS_NOT_SUPPORTED; malformed DER => format error.
// Unlike the compatibility helper above, it never silently falls back to SHA-1.
_IRQL_requires_max_(DISPATCH_LEVEL)
EXTERN_C
NTSTATUS
DomitoGetPortableExecutableDigestKindEx(
_In_reads_bytes_(PeSize) const UCHAR* PeBytes,
_In_ ULONG PeSize,
_In_reads_(IMAGE_DIRECTORY_ENTRY_SECURITY + 1) const IMAGE_DATA_DIRECTORY* Directories,
_Out_ PUINT32 DigestCalg
);
// Algorithm-explicit Authenticode digest for the supported layout subset:
// bounded PE32/PE32+ headers, contiguous nonoverlapping raw sections in file
// offset order, optional overlay before a complete EOF certificate table.
// SHA-1/256/384/512 supported. Gaps/overlaps/nonterminal certificates are rejected.
// No signature trust decision is made. Outputs are cleared on failure; the
// certificate borrows stable input memory, and only the digest must be freed.
// See docs/authenticode-digests.md for policy and Windows SIP comparisons.
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
EXTERN_C
NTSTATUS
DomitoCalculatePortableExecutableDigestEx(
_In_reads_bytes_(PeSize) const UCHAR* PeBytes,
_In_ ULONG PeSize,
_In_ UINT32 HashAlgId,
_Out_ PULONG DigestSize,
_Outptr_result_bytebuffer_(*DigestSize) PVOID* Digest,
_Outptr_result_maybenull_ LPWIN_CERTIFICATE* Certificate,
_Out_ PULONG SecuritySize
);
//
// Calculates a PE digest using the existing linear hashing convention.
// Validates accessed header/certificate ranges and clears outputs on failure
@@ -217,8 +254,40 @@ DomitoFreePortableExecutableDigest(
_In_ PVOID pDigestOut
);
#define DOMITO_CI_SOURCE_EMBEDDED 1UL
#define DOMITO_CI_SOURCE_CATALOG 2UL
// Policy-explicit legacy helper. SHA-1/256 only; hash size must match algorithm.
// Policy objects must be zero-initialized or own valid CI results; both are freed
// before each attempt. Caller owns both final policy outputs, including failure.
// Embedded validation is tried first; only INVALID_IMAGE_HASH permits catalog
// fallback/reload. AcceptedCatalogPolicyBits uses ANY-overlap catalog filtering;
// RequireTrustedCatalog gates the observed marker, not publisher identity.
// Source is 0 on failure, EMBEDDED/CATALOG on success. Stable file bytes and a
// handle valid in the caller's current process context are required during I/O.
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
EXTERN_C
NTSTATUS
DomitoValidateFileLegacyModeEx(
_In_ HANDLE FileHandle,
_In_reads_bytes_(HashSize) 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,
_In_ UINT32 AcceptedCatalogPolicyBits,
_In_ BOOLEAN RequireTrustedCatalog,
_Out_ PULONG ValidationSource
);
//
// Verifies if the Authenticode signature of a give PE file matches the provided (e.g. SHA1) file digest.
// Compatibility wrapper around DomitoValidateFileLegacyModeEx, with catalog
// mask DOMITO_CI_LEGACY_CATALOG_POLICY_BITS and RequireTrustedCatalog = FALSE.
// The same initialization, ownership, hash, handle, and stable-file rules apply.
//
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
@@ -258,7 +327,10 @@ DomitoFindModuleBaseAddress(
);
//
// Finds the address of an exported function by name.
// Finds an export by name (case-insensitive) in a valid loader-mapped module.
// ModuleBase must remain mapped; arbitrary file buffers are not supported.
// Export table spans are checked against SizeOfImage. Forwarded exports return
// STATUS_NOT_SUPPORTED; the optional output is cleared before lookup.
//
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
@@ -289,7 +361,28 @@ DomitoMemorySearchPattern(
);
//
// Reads from the beginning of a file until the end or the buffer size is reached.
// Reads exactly BufferSize bytes at a nonnegative absolute file offset.
// Same completion, buffer, handle, APC, and short-read contract as DomitoReadFile.
//
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
EXTERN_C
NTSTATUS
DomitoReadFileAt(
_In_ HANDLE FileHandle,
_Out_writes_bytes_(BufferSize) PVOID Buffer,
_In_ ULONG BufferSize,
_In_ const LARGE_INTEGER* ByteOffset
);
//
// Reads exactly BufferSize bytes from file offset zero. Short reads return
// STATUS_END_OF_FILE; Buffer may then contain a partial read. Zero length succeeds.
// Waits for pending I/O on a private event before returning. Requires PASSIVE_LEVEL
// with special kernel APCs enabled, a readable handle valid in the current process
// (or a kernel handle), and a buffer that remains valid for the entire call.
// For synchronous handles, the explicit read also updates the file position.
//
_Success_(return == STATUS_SUCCESS)
_Must_inspect_result_