Add reusable certificate and file validation helpers
Fix process-name ownership and module lookup outputs, add explicit SPKI hashing and bounded chain access, and improve WDM integration. Deprecate superseded entry points with migration guidance and align branch code and tests with the library style. Add CI validation helpers with explicit signature selection and owned results Document runtime-confirmed CI signer selection and crypto reuse Expand CI compatibility matrix to twenty verified samples Extend CI export matrix with Windows 11 x64 and ARM64 samples Document CI API availability and historical mincrypt layouts Add explicit Authenticode workflows and correct CI helper contracts Document CI validation flag 0x20 and add kernel probe Harden CI digest parsing and failure cleanup
This commit is contained in:
1 parent
7985b23be5
commit
3fbfe31d15
38 files changed
+9201
-751
No files matched your search
@@ -0,0 +1,142 @@
|
||||
# Authenticode digests and legacy verification
|
||||
|
||||
Prefer `DomitoCalculatePortableExecutableDigestEx` when computing a PE digest.
|
||||
It takes an explicit SHA-1/256/384/512 algorithm, validates its supported PE layout,
|
||||
and returns a digest independently of whether the file has an embedded signature.
|
||||
This allows SHA-256 catalog lookup for a file without an embedded certificate.
|
||||
Hash calculation is separate from signature verification and signer acceptance.
|
||||
|
||||
The older `DomitoCalculatePortableExecutableDigest` and
|
||||
`DomitoGetPortableExecutableDigestKind` retain their compatibility behavior:
|
||||
linear byte hashing and heuristic pattern discovery with a SHA-1 fallback. They
|
||||
remain bounded, but should not be used to discover a general signature policy.
|
||||
The new API is additive so existing callers do not silently acquire different
|
||||
selection or rejection rules.
|
||||
|
||||
## Supported PE layout
|
||||
|
||||
The explicit API validates DOS/NT/optional-header spans, PE32 and PE32+ magic,
|
||||
declared data-directory count, the complete section table, `SizeOfHeaders`, every
|
||||
nonempty section's raw interval, and the certificate table. It sorts section
|
||||
descriptors by raw file offset before validating their sequence. At most 96
|
||||
sections are accepted, keeping stack storage and sorting work bounded.
|
||||
|
||||
Nonempty sections must form a contiguous sequence starting at `SizeOfHeaders`.
|
||||
Section-header order can differ from raw-file order. Zero-raw-size sections
|
||||
contribute no bytes. An overlay between the raw sections and the certificate
|
||||
table, or EOF for an unsigned file, is included. The checksum and physical
|
||||
certificate-directory slot are excluded. A present certificate table must be
|
||||
8-byte aligned and end at EOF; every entry must have a bounded length, version
|
||||
`0x200`, type PKCS#7 SignedData, and complete 8-byte alignment storage.
|
||||
|
||||
For this subset, sorted section bytes coincide with linear file order, so the
|
||||
implementation can stream validated ranges directly to BCrypt without copying
|
||||
or allocating a whole-file scratch buffer. Digest allocation is the only pool
|
||||
allocation in the hashing path and is released on every failure.
|
||||
|
||||
Gaps, overlapping raw sections, certificates in the middle of a file, and absent
|
||||
certificate-directory slots are unsupported. Some malformed inputs return a
|
||||
format error; ambiguous or excluded layouts return `STATUS_NOT_SUPPORTED`.
|
||||
The missing-slot boundary is deliberate: Windows SIP produced a different hash
|
||||
than the old linear helper on a fixture with zero declared directories. Do not
|
||||
infer Windows parity from the older helper's successful return on that input.
|
||||
|
||||
This is a validated subset, not a claim that every PE accepted by every Windows
|
||||
SIP is supported. Microsoft's [PE format documentation](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format)
|
||||
describes section ordering and exclusions, but unusual overlay behavior requires
|
||||
measurements against the relevant Windows implementation. The local tests use
|
||||
the actual [CryptSIPCreateIndirectData](https://learn.microsoft.com/en-us/windows/win32/api/mssip/nf-mssip-cryptsipcreateindirectdata)
|
||||
provider as a differential oracle, rather than treating a prose summary as the
|
||||
complete algorithm. SIP hash agreement does not establish CI trust-policy parity.
|
||||
|
||||
## Discovering the first embedded content's digest algorithm
|
||||
|
||||
`DomitoGetPortableExecutableDigestKindEx` navigates a bounded DER subset:
|
||||
PKCS#7 ContentInfo / SignedData / encapsulated `SpcIndirectDataContent` /
|
||||
`DigestInfo.AlgorithmIdentifier`. It reads the algorithm associated with the
|
||||
file digest, avoiding unrelated algorithm patterns in certificates, attributes,
|
||||
timestamps, or signer information. SHA-1/256/384/512 are recognized. Algorithm
|
||||
parameters may be absent or ASN.1 NULL; the digest OCTET STRING must have the
|
||||
corresponding length. DER lengths must be bounded, definite, and minimally
|
||||
encoded. Up to seven zero bytes of aligned padding after the outer DER are
|
||||
accepted when included in `WIN_CERTIFICATE.dwLength`, as observed on Microsoft
|
||||
system binaries. Other trailing bytes are rejected.
|
||||
|
||||
An absent certificate table returns `STATUS_NOT_FOUND`, an unsupported algorithm
|
||||
or certificate type returns `STATUS_NOT_SUPPORTED`, and malformed supported
|
||||
structure returns a format error. The output algorithm is zero on failure; no
|
||||
default algorithm is silently manufactured.
|
||||
|
||||
The caller supplies an array containing the security-directory entry and a
|
||||
stable input buffer. The helper inspects the first table entry. It does not
|
||||
enumerate nested/multiple signatures, validate the entire ASN.1 document,
|
||||
validate signerInfos, verify cryptographic signatures, or establish trust.
|
||||
Indefinite-length BER is outside this supported DER subset. Choose explicit
|
||||
algorithms when handling catalog-only files or application-defined lookup order.
|
||||
|
||||
## Explicit legacy catalog policy
|
||||
|
||||
`DomitoValidateFileLegacyModeEx` takes a caller-selected
|
||||
`AcceptedCatalogPolicyBits` mask, a `RequireTrustedCatalog` marker gate, and a
|
||||
`ValidationSource` output. Source is `DOMITO_CI_SOURCE_EMBEDDED` or
|
||||
`DOMITO_CI_SOURCE_CATALOG` on success and zero on failure.
|
||||
|
||||
This helper accepts SHA-1 with exactly 20 bytes or SHA-256 with exactly 32 bytes.
|
||||
Unsupported algorithms return `STATUS_NOT_SUPPORTED`; mismatched lengths return
|
||||
`STATUS_INVALID_PARAMETER`. The underlying observed embedded API supports more
|
||||
algorithms than this helper's catalog workflow, as documented in
|
||||
[the mincrypt contracts](mincrypt-contracts.md).
|
||||
|
||||
Both policy objects must be zero-initialized before first use, or own valid CI
|
||||
results. The helper frees previous contents on entry and before each retry and
|
||||
clears signing time between attempts. The caller owns both final policy results,
|
||||
including any returned on failure, and frees them with `CiFreePolicyInfo`.
|
||||
Embedded-to-catalog fallback and catalog reload occur only for
|
||||
`STATUS_INVALID_IMAGE_HASH`; resource, I/O, and other policy errors propagate.
|
||||
|
||||
Before certificate allocation, the helper references the file object and checks
|
||||
the supplied table interval against the current file size. It then uses the
|
||||
exact-read `DomitoReadFileAt`, which waits on a private completion event. An EOF
|
||||
short read fails before CI sees any uninitialized bytes. The caller must keep
|
||||
file identity/bytes stable between hashing and consumption; a size check cannot
|
||||
prevent concurrent mutation. Handles must be valid in the current process
|
||||
context and satisfy the documented kernel I/O/APC requirements.
|
||||
|
||||
The older `DomitoValidateFileLegacyMode` delegates with the existing
|
||||
`DOMITO_CI_LEGACY_CATALOG_POLICY_BITS` (`0x2007F`) and a false marker gate. That
|
||||
value is a compatibility default with broad categories, not an application trust
|
||||
recommendation. The explicit mask uses **any-overlap** catalog filtering.
|
||||
|
||||
For a catalog-only file, choose an allowed algorithm sequence as application
|
||||
policy (for example SHA-256 followed by SHA-1 when legacy acceptance is intended).
|
||||
For each algorithm, call `DomitoCalculatePortableExecutableDigestEx`, then
|
||||
`DomitoValidateFileLegacyModeEx` with a zero security directory. Free the digest
|
||||
and both policy objects before retrying. Continue to another algorithm only on
|
||||
the specifically intended lookup/signature-mismatch result, not on all failures.
|
||||
Preserve the actual algorithm and validation source in the application's result.
|
||||
This supports an explicit search strategy; it does not reproduce every native
|
||||
CI scenario-selection rule or WinVerifyTrust policy.
|
||||
|
||||
## Validation performed
|
||||
|
||||
On the local Windows 26100 system, host tests compare all four digest algorithms
|
||||
against Windows SIP for PE32/PE32+, unsigned/signed fixtures, overlays, reverse
|
||||
section-header order, multiple certificate entries, and certificate alignment.
|
||||
The installed `ci.dll`, `ntdll.dll`, `kernel32.dll`, and `notepad.exe` form a
|
||||
real-file corpus. Embedded digest algorithms are independently extracted with
|
||||
Crypt32, and computed file digests are compared with the signed
|
||||
`SpcIndirectDataContent` values where an embedded signature exists. This reads
|
||||
files and hashes bytes; it does not load or execute them as code.
|
||||
|
||||
Guard-page truncations, malformed offsets/lengths, unsupported layouts,
|
||||
algorithm selection, injected CNG/allocation failures, retry ownership, exact
|
||||
read failures, and explicit catalog controls are also covered. Actual CI calls
|
||||
are mocked in those host tests. The kernel translation units and layout
|
||||
assertions compile for x64/ARM64 with warnings treated as errors; the opt-in
|
||||
26100 runtime-layout observations remain x64-specific.
|
||||
|
||||
Still pending are historical/ARM64 CI runtime compatibility, Driver Verifier,
|
||||
real catalog-only acceptance across algorithms, nested/multiple-signature
|
||||
selection, weak-crypto/revocation/timestamp policy, and extension of supported PE
|
||||
layouts. Use the [remaining-work ledger](implementation-status.md) and the
|
||||
[flag probe](ci-validate-file-object.md) to plan the VM run.
|
||||
@@ -0,0 +1,651 @@
|
||||
{
|
||||
"schema_version": 2,
|
||||
"scope": "Observed named PE exports in exact architecture-specific ci.dll samples; not runtime or ABI certification",
|
||||
"source_hash_encoding": "Canonical JSON: UTF-8, sorted keys, comma/colon separators, ensure_ascii=false",
|
||||
"generated_from": {
|
||||
"corpus-index.json": "d2c6507794314ca38a2015c74f3b66e81a4bd82d982be0ed1911dcff1d79475a",
|
||||
"iso-corpus-index.json": "ba526a8548f3be100e8d13019aed57de9703a142615c509870720572bc636217",
|
||||
"manifest.json": "bd215ebd3deb480a39b5d71a6ed709dad20368cbe90879a52070b56b023284d4",
|
||||
"ci-26100.8328-evidence.json": "ea0f939df9d8b7abde40e3402c01b2ac398253728f329e8c2b7134de8df6305f"
|
||||
},
|
||||
"apis": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetCertPublisherName",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"samples": [
|
||||
{
|
||||
"label": "Windows 10 1507",
|
||||
"ci_file_version": "10.0.10240.16463",
|
||||
"architecture": "x64",
|
||||
"sha256": "e83d900f4675c6e6ffc3fb7dcd3074610876a1398e495796769988df810fd3bc",
|
||||
"source": "corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": false,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1511",
|
||||
"ci_file_version": "10.0.10586.0",
|
||||
"architecture": "x64",
|
||||
"sha256": "f949bfa614addea6174b28c3818c56b327c9290fd41bd91dfc545414b3df6783",
|
||||
"source": "corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": false,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1607",
|
||||
"ci_file_version": "10.0.14393.2189",
|
||||
"architecture": "x64",
|
||||
"sha256": "ef0c02ecbd0818e84be9f61421f919825f96a3c59199460cab08548eee2881df",
|
||||
"source": "corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": false,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1703",
|
||||
"ci_file_version": "10.0.15063.0",
|
||||
"architecture": "x64",
|
||||
"sha256": "3705aaf408f05326e028621380aa5c96a1f3583a2de8a139b188da4b82577863",
|
||||
"source": "corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1709",
|
||||
"ci_file_version": "10.0.16299.125",
|
||||
"architecture": "x64",
|
||||
"sha256": "1db7ae5a08bd2361fc7fcdd373fb980e8d680035e67b02e5967095db0443effd",
|
||||
"source": "corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1803",
|
||||
"ci_file_version": "10.0.17134.1130",
|
||||
"architecture": "x64",
|
||||
"sha256": "8ce3b8fe38c23b699f30b045383640019a429d3a9d513285c655bffe03a796d9",
|
||||
"source": "corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1809 initial x64 ISO",
|
||||
"ci_file_version": "10.0.17763.1",
|
||||
"architecture": "x64",
|
||||
"sha256": "eb177481f2aea3cae0c2f97f7058e7447c0695e4489428406598f168d4dcc5e8",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1809 October v2 x64 ISO",
|
||||
"ci_file_version": "10.0.17763.348",
|
||||
"architecture": "x64",
|
||||
"sha256": "da8282173cbce7ea38f8fca64db0972c3d9614ddbca98f6b96d11a4cadde92ad",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1903 v1 x64 ISO",
|
||||
"ci_file_version": "10.0.18362.1",
|
||||
"architecture": "x64",
|
||||
"sha256": "5d01bb84fa516e23c25def8ea03fc6b696082ccc67a61575fd00d1fe7c273d72",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1903 v2 x64 ISO",
|
||||
"ci_file_version": "10.0.18362.329",
|
||||
"architecture": "x64",
|
||||
"sha256": "d12131f14f781f8c314a795384e02afc3c2902bf67da9c2e75d8163c891bdd89",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 1909 x64 ISO",
|
||||
"ci_file_version": "10.0.18362.418",
|
||||
"architecture": "x64",
|
||||
"sha256": "c3c5d32da42fa69b0795cd0f8c57252670d673fb036685db5c7d6392ffee0293",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 2004 ISO",
|
||||
"ci_file_version": "10.0.19041.1",
|
||||
"architecture": "x64",
|
||||
"sha256": "2955710d34db26e352e62b20861ba338f0216cc36b378d128057be955e184282",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": false,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 22H2 consumer ISO",
|
||||
"ci_file_version": "10.0.19041.1865",
|
||||
"architecture": "x64",
|
||||
"sha256": "d0408a9f64eafb72e8aa1cf127d07d919f0cab38a6bdf2b406255909c85e3a8d",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetCertPublisherName",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": true,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 11 English x64 v1 ISO",
|
||||
"ci_file_version": "10.0.22000.318",
|
||||
"architecture": "x64",
|
||||
"sha256": "301ae49ac5b87cf1cbe07d9d3c6486a066d045b6bf55fc8eb392d52951ec69ff",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetCertPublisherName",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": true,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 11 23H2 English ISO",
|
||||
"ci_file_version": "10.0.22621.2792",
|
||||
"architecture": "x64",
|
||||
"sha256": "9ed77b8a53946ced8c3540edb26a765060dff908544634e7b069aa49f2b41559",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetCertPublisherName",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": true,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 11 24H2 sample",
|
||||
"ci_file_version": "10.0.26100.9444",
|
||||
"architecture": "x64",
|
||||
"sha256": "c7d23814f3202c51fb23e3ca3d4328855787383cee5d14c4a986a13ec2aeda0b",
|
||||
"source": "ci-26100.8328-evidence.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetCertPublisherName",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": true,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
},
|
||||
"display_file_version": "10.0.26100.8328"
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 21H2 ARM64 ISO (archive Raspberry Pi folder)",
|
||||
"ci_file_version": "10.0.19041.1566",
|
||||
"architecture": "ARM64",
|
||||
"sha256": "a35f651261691cc67acc9c8bfd00bba7a64dd9f16d2c4b6fe1d183e34aeead78",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetCertPublisherName",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": true,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 10 22H2.7 ARM64 ISO",
|
||||
"ci_file_version": "10.0.19041.2965",
|
||||
"architecture": "ARM64",
|
||||
"sha256": "33f2d1256f60392bbb84c4251d6435461dfa852a100e065376f83dc8a4dd2ec6",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetCertPublisherName",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": true,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 11 22H2.9 ARM64 ISO",
|
||||
"ci_file_version": "10.0.22621.1702",
|
||||
"architecture": "ARM64",
|
||||
"sha256": "4164ac08fd19628c5ab6cbca6234265ac2bf7f39d5149f57d3845646d8a8ad60",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetCertPublisherName",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": true,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Windows 11 24H2 ARM64 ISO",
|
||||
"ci_file_version": "10.0.26100.1591",
|
||||
"architecture": "ARM64",
|
||||
"sha256": "a0eba64a9a3f2006d5832079412eca42cc1b9ed66d19b9b0adb7e59ea354415d",
|
||||
"source": "iso-corpus-index.json",
|
||||
"named_exports": [
|
||||
"CiCheckSignedFile",
|
||||
"CiFindPageHashesInCatalog",
|
||||
"CiFindPageHashesInSignedFile",
|
||||
"CiFreePolicyInfo",
|
||||
"CiGetCertPublisherName",
|
||||
"CiGetPEInformation",
|
||||
"CiInitialize",
|
||||
"CiSetTrustedOriginClaimId",
|
||||
"CiValidateFileObject",
|
||||
"CiVerifyHashInCatalog"
|
||||
],
|
||||
"ordinal_only_export_count": 3,
|
||||
"api_presence": {
|
||||
"CiCheckSignedFile": true,
|
||||
"CiFindPageHashesInCatalog": true,
|
||||
"CiFindPageHashesInSignedFile": true,
|
||||
"CiFreePolicyInfo": true,
|
||||
"CiGetCertPublisherName": true,
|
||||
"CiGetPEInformation": true,
|
||||
"CiInitialize": true,
|
||||
"CiSetTrustedOriginClaimId": true,
|
||||
"CiValidateFileObject": true,
|
||||
"CiVerifyHashInCatalog": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
# CI API compatibility matrix
|
||||
|
||||
This matrix records **named export presence in 20 exact `ci.dll` files**,
|
||||
with architecture stated separately for each sample.
|
||||
**Yes** means the complete PE export directory contains the name; **No** means
|
||||
it does not. Neither result is inferred from a header, import library or PDB.
|
||||
Export presence alone does not establish a compatible ABI or successful verification.
|
||||
|
||||
Versions in the tables are **CI file versions**, not necessarily the kernel version.
|
||||
In particular, the Windows 10 22H2 consumer ISO contains CI **19041.1865**.
|
||||
Do not extrapolate a cell to every servicing revision of that Windows release.
|
||||
|
||||
[Machine-readable matrix](ci-api-compatibility.json) includes exact SHA-256 identities,
|
||||
all per-API results and canonical JSON hashes of the retained source inventories.
|
||||
Source hashes ignore whitespace and line-ending differences between checkouts;
|
||||
the binary SHA-256 identities always cover the exact original bytes.
|
||||
|
||||
The tables use numeric `VS_FIXEDFILEINFO` versions. The original modern x64
|
||||
sample has **fixed version 26100.9444** but its string `FileVersion` reports
|
||||
**26100.8328**. Original research/header labels retain that string version;
|
||||
they identify the same SHA-256 file, not two different CI samples.
|
||||
|
||||
## Windows 10 1507–1803 x64 samples
|
||||
|
||||
| API | 10240.16463 | 10586.0 | 14393.2189 | 15063.0 | 16299.125 | 17134.1130 |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| `CiCheckSignedFile` | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiFindPageHashesInCatalog` | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiFindPageHashesInSignedFile` | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiFreePolicyInfo` | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiGetCertPublisherName` | No | No | No | No | No | No |
|
||||
| `CiGetPEInformation` | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiInitialize` | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiSetTrustedOriginClaimId` | No | No | No | Yes | Yes | Yes |
|
||||
| `CiValidateFileObject` | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiVerifyHashInCatalog` | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
|
||||
## Later Windows 10 x64 samples
|
||||
|
||||
| API | 17763.1 | 17763.348 | 18362.1 | 18362.329 | 18362.418 | 19041.1 | 19041.1865 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| `CiCheckSignedFile` | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiFindPageHashesInCatalog` | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiFindPageHashesInSignedFile` | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiFreePolicyInfo` | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiGetCertPublisherName` | No | No | No | No | No | No | Yes |
|
||||
| `CiGetPEInformation` | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiInitialize` | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiSetTrustedOriginClaimId` | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiValidateFileObject` | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| `CiVerifyHashInCatalog` | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
|
||||
## Windows 11 x64 samples
|
||||
|
||||
| API | 22000.318 | 22621.2792 | 26100.9444 |
|
||||
| --- | --- | --- | --- |
|
||||
| `CiCheckSignedFile` | Yes | Yes | Yes |
|
||||
| `CiFindPageHashesInCatalog` | Yes | Yes | Yes |
|
||||
| `CiFindPageHashesInSignedFile` | Yes | Yes | Yes |
|
||||
| `CiFreePolicyInfo` | Yes | Yes | Yes |
|
||||
| `CiGetCertPublisherName` | Yes | Yes | Yes |
|
||||
| `CiGetPEInformation` | Yes | Yes | Yes |
|
||||
| `CiInitialize` | Yes | Yes | Yes |
|
||||
| `CiSetTrustedOriginClaimId` | Yes | Yes | Yes |
|
||||
| `CiValidateFileObject` | Yes | Yes | Yes |
|
||||
| `CiVerifyHashInCatalog` | Yes | Yes | Yes |
|
||||
|
||||
## Windows 10 ARM64 samples
|
||||
|
||||
| API | 19041.1566 | 19041.2965 |
|
||||
| --- | --- | --- |
|
||||
| `CiCheckSignedFile` | Yes | Yes |
|
||||
| `CiFindPageHashesInCatalog` | Yes | Yes |
|
||||
| `CiFindPageHashesInSignedFile` | Yes | Yes |
|
||||
| `CiFreePolicyInfo` | Yes | Yes |
|
||||
| `CiGetCertPublisherName` | Yes | Yes |
|
||||
| `CiGetPEInformation` | Yes | Yes |
|
||||
| `CiInitialize` | Yes | Yes |
|
||||
| `CiSetTrustedOriginClaimId` | Yes | Yes |
|
||||
| `CiValidateFileObject` | Yes | Yes |
|
||||
| `CiVerifyHashInCatalog` | Yes | Yes |
|
||||
|
||||
## Windows 11 ARM64 samples
|
||||
|
||||
| API | 22621.1702 | 26100.1591 |
|
||||
| --- | --- | --- |
|
||||
| `CiCheckSignedFile` | Yes | Yes |
|
||||
| `CiFindPageHashesInCatalog` | Yes | Yes |
|
||||
| `CiFindPageHashesInSignedFile` | Yes | Yes |
|
||||
| `CiFreePolicyInfo` | Yes | Yes |
|
||||
| `CiGetCertPublisherName` | Yes | Yes |
|
||||
| `CiGetPEInformation` | Yes | Yes |
|
||||
| `CiInitialize` | Yes | Yes |
|
||||
| `CiSetTrustedOriginClaimId` | Yes | Yes |
|
||||
| `CiValidateFileObject` | Yes | Yes |
|
||||
| `CiVerifyHashInCatalog` | Yes | Yes |
|
||||
|
||||
## Exact sample identities
|
||||
|
||||
- Windows 10 1507: **10.0.10240.16463 x64**, SHA-256
|
||||
`e83d900f4675c6e6ffc3fb7dcd3074610876a1398e495796769988df810fd3bc`.
|
||||
- Windows 10 1511: **10.0.10586.0 x64**, SHA-256
|
||||
`f949bfa614addea6174b28c3818c56b327c9290fd41bd91dfc545414b3df6783`.
|
||||
- Windows 10 1607: **10.0.14393.2189 x64**, SHA-256
|
||||
`ef0c02ecbd0818e84be9f61421f919825f96a3c59199460cab08548eee2881df`.
|
||||
- Windows 10 1703: **10.0.15063.0 x64**, SHA-256
|
||||
`3705aaf408f05326e028621380aa5c96a1f3583a2de8a139b188da4b82577863`.
|
||||
- Windows 10 1709: **10.0.16299.125 x64**, SHA-256
|
||||
`1db7ae5a08bd2361fc7fcdd373fb980e8d680035e67b02e5967095db0443effd`.
|
||||
- Windows 10 1803: **10.0.17134.1130 x64**, SHA-256
|
||||
`8ce3b8fe38c23b699f30b045383640019a429d3a9d513285c655bffe03a796d9`.
|
||||
- Windows 10 1809 initial x64 ISO: **10.0.17763.1 x64**, SHA-256
|
||||
`eb177481f2aea3cae0c2f97f7058e7447c0695e4489428406598f168d4dcc5e8`.
|
||||
- Windows 10 1809 October v2 x64 ISO: **10.0.17763.348 x64**, SHA-256
|
||||
`da8282173cbce7ea38f8fca64db0972c3d9614ddbca98f6b96d11a4cadde92ad`.
|
||||
- Windows 10 1903 v1 x64 ISO: **10.0.18362.1 x64**, SHA-256
|
||||
`5d01bb84fa516e23c25def8ea03fc6b696082ccc67a61575fd00d1fe7c273d72`.
|
||||
- Windows 10 1903 v2 x64 ISO: **10.0.18362.329 x64**, SHA-256
|
||||
`d12131f14f781f8c314a795384e02afc3c2902bf67da9c2e75d8163c891bdd89`.
|
||||
- Windows 10 1909 x64 ISO: **10.0.18362.418 x64**, SHA-256
|
||||
`c3c5d32da42fa69b0795cd0f8c57252670d673fb036685db5c7d6392ffee0293`.
|
||||
- Windows 10 2004 ISO: **10.0.19041.1 x64**, SHA-256
|
||||
`2955710d34db26e352e62b20861ba338f0216cc36b378d128057be955e184282`.
|
||||
- Windows 10 22H2 consumer ISO: **10.0.19041.1865 x64**, SHA-256
|
||||
`d0408a9f64eafb72e8aa1cf127d07d919f0cab38a6bdf2b406255909c85e3a8d`.
|
||||
- Windows 11 English x64 v1 ISO: **10.0.22000.318 x64**, SHA-256
|
||||
`301ae49ac5b87cf1cbe07d9d3c6486a066d045b6bf55fc8eb392d52951ec69ff`.
|
||||
- Windows 11 23H2 English ISO: **10.0.22621.2792 x64**, SHA-256
|
||||
`9ed77b8a53946ced8c3540edb26a765060dff908544634e7b069aa49f2b41559`.
|
||||
- Windows 11 24H2 sample: **10.0.26100.9444 x64**, SHA-256
|
||||
`c7d23814f3202c51fb23e3ca3d4328855787383cee5d14c4a986a13ec2aeda0b`.
|
||||
String FileVersion: **10.0.26100.8328** (original research label).
|
||||
- Windows 10 21H2 ARM64 ISO (archive Raspberry Pi folder): **10.0.19041.1566 ARM64**, SHA-256
|
||||
`a35f651261691cc67acc9c8bfd00bba7a64dd9f16d2c4b6fe1d183e34aeead78`.
|
||||
- Windows 10 22H2.7 ARM64 ISO: **10.0.19041.2965 ARM64**, SHA-256
|
||||
`33f2d1256f60392bbb84c4251d6435461dfa852a100e065376f83dc8a4dd2ec6`.
|
||||
- Windows 11 22H2.9 ARM64 ISO: **10.0.22621.1702 ARM64**, SHA-256
|
||||
`4164ac08fd19628c5ab6cbca6234265ac2bf7f39d5149f57d3845646d8a8ad60`.
|
||||
- Windows 11 24H2 ARM64 ISO: **10.0.26100.1591 ARM64**, SHA-256
|
||||
`a0eba64a9a3f2006d5832079412eca42cc1b9ed66d19b9b0adb7e59ea354415d`.
|
||||
|
||||
## What callers can rely on
|
||||
|
||||
- `CiValidateFileObject` is already exported in the sampled Windows 10 1507 file.
|
||||
- `CiSetTrustedOriginClaimId` is present in the sampled 1703 file and absent in
|
||||
the three earlier samples. This does not prove its first introduction build.
|
||||
- On sampled x64 files, `CiGetCertPublisherName` is absent in 19041.1
|
||||
and present in 19041.1865.
|
||||
Its first Windows 10 servicing update remains unknown. It is also present
|
||||
in the sampled 22000.318 and 26100.9444 fixed-version files.
|
||||
- The Windows 10 ARM64 21H2 sample already exports the publisher-name API
|
||||
in CI 19041.1566. That does not establish x64 availability at that revision.
|
||||
- CI entry points currently use static imports from `ci.lib`. An unavailable
|
||||
import can prevent driver loading; this matrix does not add an automatic
|
||||
`STATUS_NOT_IMPLEMENTED` fallback. Supporting these older samples requires
|
||||
avoiding unavailable imports or implementing optional resolution.
|
||||
- Choose structures using a verified runtime profile. The sampled x64 chain
|
||||
headers differ: 1507 uses 56 bytes, 1511 uses 72, and 1607–1803 use 104.
|
||||
Export presence, compile-target `NTDDI_VERSION` and total allocation `Size`
|
||||
do not select a compatible layout. See [mincrypt contracts](mincrypt-contracts.md).
|
||||
|
||||
## Coverage gaps and evidence
|
||||
|
||||
**Unknown / not sampled:** x86 export availability; pre-Windows-10;
|
||||
earlier Windows 10 ARM64 releases; and other servicing revisions
|
||||
or architecture/release combinations absent from these tables.
|
||||
These are gaps, not negative export results. No interval between
|
||||
two samples is certified. Runtime verification and cross-version ABI checks
|
||||
remain in the [implementation ledger](implementation-status.md).
|
||||
|
||||
The tables cover every named export found in these samples, including
|
||||
`CiInitialize`; inclusion is not a recommendation to call initialization or
|
||||
global-policy routines. Each sample also has three ordinal-only exports,
|
||||
which are outside this named-API matrix. Private `Mincrypt*` PDB symbols are
|
||||
not automatically callable exports.
|
||||
|
||||
Source inventories are retained in the companion
|
||||
[CodeIntegrity-RE repository](https://git.nefarius.at/nefarius/CodeIntegrity-RE):
|
||||
`corpus-index.json` (VM samples), `iso-corpus-index.json` (ISO samples), and
|
||||
`ci-26100.8328-evidence.json` with `manifest.json` (original 26100 sample).
|
||||
Regenerate with its `generate_compatibility_matrix.py --output <Domito/docs>`.
|
||||
ARM64 cells establish export presence only; the historical x64 layout views
|
||||
must not be selected for ARM64 solely because the same API name is exported.
|
||||
No Windows binary or PDB is distributed with the matrix.
|
||||
@@ -0,0 +1,236 @@
|
||||
# CiValidateFileObject: validation flag 0x00000020
|
||||
|
||||
Issue #3 is **documented; its TESTSIGNING-off runtime experiment is pending**.
|
||||
A related signer-selection experiment has now run successfully on Windows 11
|
||||
22631 with TESTSIGNING enabled (below). That run does not close the requested
|
||||
19041/19045 flag 0 versus 0x20 TESTSIGNING-off comparison.
|
||||
|
||||
## Meaning supported by the evidence
|
||||
|
||||
`DOMITO_CI_VALIDATE_FLAG_BROADEN_ROOT_ACCEPTANCE` is Domito's descriptive name for
|
||||
`0x00000020` in the second argument, `ValidationFlags`. It is not a recovered
|
||||
Microsoft macro name. On the analyzed **ci.dll 10.0.26100.8328 x64**, the flag
|
||||
causes `CipGetAcceptedRootKeys` to OR `0xA4FF` into its accepted-root mask in the
|
||||
branch where the global at RVA `0x45A88` is zero. Other global state, flags, and
|
||||
the requested signing level also affect the result.
|
||||
|
||||
The assembly at preferred image base `0x180000000` establishes the operation:
|
||||
|
||||
```text
|
||||
0x180089e40: MOV EDX, 0xa4ff
|
||||
0x180089e4c: BT ECX, EDI ; ECX = 0x8c in this branch; EDI = signing level
|
||||
0x180089e4f: JC 0x180089e57
|
||||
0x180089e51: TEST SIL, 0x20 ; saved ValidationFlags
|
||||
0x180089e55: JZ 0x180089e59
|
||||
0x180089e57: OR EBX, EDX ; broaden accepted-root mask
|
||||
```
|
||||
|
||||
For requested level 0, flags 0, the branch above, and all other optional global
|
||||
additions disabled, the mask is `0x80AA`; setting only `0x20` makes it `0xA4FF`
|
||||
(additional bits `0x2455`). This is an arithmetic witness, **not a measurement of
|
||||
the running OS's initialized policy**. Levels 2, 3, and 7 already trigger the OR
|
||||
through `0x8C`. When the global at RVA `0x45A88` is nonzero, the helper returns
|
||||
`0xA4FF` directly, so the flag need not change its result.
|
||||
|
||||
Later processing can still remove bit `0x8` when the helper's third argument is
|
||||
nonzero and validation flag `0x00400000` is present. The surrounding
|
||||
`CipDisallowEmbeddedPicrootIfTrusted` path can add that latter flag itself.
|
||||
Thus `0xA4FF` is not a promise about every final policy result.
|
||||
|
||||
The widened mask includes categories associated with test roots and unresolved
|
||||
chains as well as other roots. It must not be named "trust any Authenticode
|
||||
signer", "require Microsoft", or "enable TESTSIGNING". It changes the acceptance
|
||||
policy for this operation; it does not change the system boot setting. Further
|
||||
signature, chain, signing-level, and policy checks still matter. A successful
|
||||
call alone does not establish equivalence with WinVerifyTrust or the caller's
|
||||
intended publisher trust policy.
|
||||
|
||||
`CipGetHashAlgorithmForLegacyScenario` does not test `0x20`: the flag is not a
|
||||
fixed SHA-1/SHA-256 selector. Also distinguish this **input flag** from the
|
||||
unrelated `MINCRYPT_POLICY_INFO.PolicyBits` output bit `0x20`, associated with
|
||||
the built-in DMD root category in this build.
|
||||
|
||||
## Historical generation differences
|
||||
|
||||
The same numeric flag does not imply the same internal root mask across Windows
|
||||
versions. Static analysis of the extracted x64 corpus adds these bounded facts:
|
||||
|
||||
- On sampled `10.0.10240.16463` (1507), `10.0.10586.0` (1511),
|
||||
`10.0.14393.2189` (1607) and `10.0.15063.0` (1703), the recovered
|
||||
`CipGetAcceptedRootKeys` bodies have no direct `flag & 0x20` broadening branch.
|
||||
They still test larger masks containing that bit, so this is not evidence that
|
||||
the flag has no effect anywhere in those verifiers.
|
||||
- On sampled `10.0.16299.125` (1709) and `10.0.17134.1130` (1803), when the
|
||||
helper's main global mode is zero,
|
||||
`flag & 0x20` selects mask `0x224FF` (assignment), rather than the modern
|
||||
`mask |= 0xA4FF` operation. A signing-level predicate can select the same mask.
|
||||
Other global additions occur afterward. The other global mode returns
|
||||
`0x204FF` directly.
|
||||
|
||||
The observed helper masks include branch-specific diagnostics/categories and
|
||||
must not be interpreted as an official stable root enum. The descriptive Domito
|
||||
constant names the intended broadening use without promising a single mask or
|
||||
identical behavior on every build.
|
||||
|
||||
The ISO-derived **10.0.19041.1 x64** helper provides direct static evidence for
|
||||
the reported build family: in its main global mode it uses `mask |= 0x24FF`
|
||||
when flag `0x20` or the signing-level predicate applies; the alternate mode
|
||||
returns `0x24FF`. With requested level zero and optional global additions
|
||||
disabled, `0xAA` becomes `0x24FF` (added bits `0x2455`). This is an arithmetic
|
||||
witness, not a measurement of initialized OS policy. The exact CI SHA-256 is
|
||||
`2955710d34db26e352e62b20861ba338f0216cc36b378d128057be955e184282`.
|
||||
CodeIntegrity-RE retains matched-PDB pseudocode and assembly in
|
||||
`historical/ci-19041.1-contracts.json` and `historical/ci-19041.1-assembly.json`,
|
||||
with batch evidence ID
|
||||
`ev_13f89502777ee38ea98410f7a07f078bb934e78d792b662ab242f7b11d27e747`.
|
||||
Other 19041/19045 servicing revisions and the TESTSIGNING-off runtime workaround
|
||||
still require their own evidence.
|
||||
|
||||
Historical records in CodeIntegrity-RE:
|
||||
`historical/ci-14393-contracts.json`
|
||||
`ev_e63a4c4b7613e231795051b784b9571605b9bf81258b5dcd04d32ddc681abb41`,
|
||||
`historical/ci-15063-contracts.json`
|
||||
`ev_338658fb82559fa6daa8ae5487b90fe84b8e408ea7578feed6d8dff5d590e114`,
|
||||
`historical/ci-16299-contracts.json`
|
||||
`ev_fe5731175f0726f0d46af2f78ca615d284f8598939296815e26b5589db3001cf`,
|
||||
and `historical/ci-17134-contracts.json`
|
||||
`ev_0c3e3359b8b7486318006afa6b95eb2257a18abeec9041a86a32db487bcbe996`.
|
||||
|
||||
## Evidence and compatibility limits
|
||||
|
||||
The [upstream report](https://github.com/Ido-Moshe-Github/CiDllDemo/issues/5#issuecomment-2725851295)
|
||||
describes success with flags `0x20`, signing level 0, and TESTSIGNING off on
|
||||
Windows builds 19041 and 19045. That is third-party runtime evidence, not a
|
||||
reproduction by this project. Its behavior is consistent with broader root
|
||||
acceptance; it does not establish identical internals across those builds.
|
||||
|
||||
Our static evidence uses REA 6.8.0 / Ghidra 12.1.3 and the binary SHA-256
|
||||
`c7d23814f3202c51fb23e3ca3d4328855787383cee5d14c4a986a13ec2aeda0b`.
|
||||
Public-symbol mapping uses ci.pdb GUID `1CAE574B-CF1F-3564-5F74-49567A128629`, age 1.
|
||||
The companion CodeIntegrity-RE repository retains:
|
||||
|
||||
- `ci-flag20-assembly-evidence.json`: assembly evidence
|
||||
`ev_ea763b9be7643a6241b0c805eae5f735a4b4a0a82df1383b1e68da4207f85fb4`.
|
||||
- `evidence/CipGetAcceptedRootKeys.c`: decompilation
|
||||
`ev_c905f03db9470c8b2d89a6295080143f25d5780ca0909de0ca554e40d078a3f3`.
|
||||
- `evidence/CipGetHashAlgorithmForLegacyScenario.c`:
|
||||
`ev_addf8f1bc18da58db80db54eeab0dd78ec5ab88b219ece3e082ebd9a8e50b257`.
|
||||
- `evidence/CipDisallowEmbeddedPicrootIfTrusted.c`:
|
||||
`ev_2475a5804fc87683a54b06acebd3785e5e8eb31f4f542f699fc2ff414c1ab7fe`.
|
||||
- `evidence/CipValidateFileObjectByFileOrPageHash.c`: capacity contract
|
||||
`ev_3897aa76c17cc64a30f60e72b994e695b88c8eda2ae6f246766bdc9314f06cca`.
|
||||
|
||||
No complete enumeration of downstream uses of the flag, historical Microsoft
|
||||
name, or cross-version/architecture guarantee is claimed. The public declaration
|
||||
keeps the existing parameter widths. Names now describe the known inputs; on
|
||||
26100 x64 the third argument is consumed as a byte. Narrowing the ABI everywhere
|
||||
requires separate evidence.
|
||||
|
||||
## Kernel experiment prepared for the VM
|
||||
|
||||
Add `tests/ci-file-object-probe.cpp` to an existing signed test driver and add
|
||||
`include/` to its include path. Link the existing CI imports (`ci.lib`). Include
|
||||
`ntifs.h`, `Domito.MinCrypt.h`, and `tests/ci-file-object-probe.h` at the call site.
|
||||
Invoke `DomitoProbeCiValidateFileObject` at PASSIVE_LEVEL with a referenced
|
||||
file object for the fixture and an array of `DOMITO_CI_PROBE_RESULT_COUNT` results.
|
||||
Keep the file bytes stable and hold the object reference for the entire probe.
|
||||
The surrounding driver owns opening/referencing/closing the file and exporting
|
||||
the result records. The probe has no DriverEntry or installation side effects.
|
||||
|
||||
It makes six calls, always at requested level 0:
|
||||
|
||||
1. Flags `0`, then `0x20`, then `0x20`, then `0`, with 64-byte capacity each time.
|
||||
2. Flags `0`, then `0x20`, with declared capacity 63 (64-byte backing storage).
|
||||
|
||||
Each call uses fresh policies, hash capacity, algorithm, and signing-time storage.
|
||||
Both policy objects are freed after capture, including on failure. The records
|
||||
capture status, both policy statuses/bits, chain presence, signing time, digest
|
||||
algorithm/length/bytes, and a trailing buffer guard. The digest is a **file hash**,
|
||||
not a certificate thumbprint. Failed-call outputs are raw diagnostics, not valid
|
||||
verification results. Chain internals are deliberately not dereferenced.
|
||||
|
||||
The repeated order helps reveal cache/order effects but does not eliminate them.
|
||||
Also run the reversed initial order in a fresh VM snapshot when comparing policy.
|
||||
For the analyzed 26100 helper, both 63-byte-capacity calls should return
|
||||
`STATUS_BUFFER_TOO_SMALL` and set length 64, regardless of the eventual algorithm.
|
||||
Treat older-build differences as observations to investigate, not silently as
|
||||
test success. Every guard must remain intact; successful hash sizes must be at
|
||||
most 64. Inspect non-success statuses rather than treating all failures as
|
||||
invalid signatures (I/O and resource errors are possible).
|
||||
|
||||
Run on Windows 10 19041 and 19045 and a current Windows 11 build. The decisive
|
||||
reproduction uses a driver loadable with TESTSIGNING **off**. Record that setting,
|
||||
Secure Boot, HVCI/WDAC policy, OS build, CI version/hash, driver identity, fixture
|
||||
SHA-256, and each complete result. Keep policy constant between paired calls.
|
||||
Use these fixtures:
|
||||
|
||||
- A known third-party RSA Authenticode executable (ideally the reported fixture).
|
||||
- A Microsoft-signed executable and a catalog-signed file as controls.
|
||||
- An unsigned executable and a copy of the signed file with a byte changed in a
|
||||
hashed section, leaving its certificate table unchanged.
|
||||
- A self-signed/test-root fixture to characterize the broader acceptance policy.
|
||||
- If available, timestamped, expired, revoked, and ECC variants, with expectations
|
||||
recorded in advance and revocation/configuration differences retained.
|
||||
|
||||
Compare with `signtool verify /pa /v` as a separate user-mode policy observation,
|
||||
not an equality oracle. The report is reproduced only when the same valid
|
||||
third-party fixture changes from rejection at 0 to success at `0x20`, under the
|
||||
reported environment, with usable outputs. Unchanged success can mean the
|
||||
existing policy already accepts it. Unchanged failure is a result to investigate.
|
||||
Unsigned and tampered fixtures must not become accepted as valid signatures.
|
||||
Self-signed acceptance must be reported explicitly, not confused with public-CA
|
||||
publisher trust. Do not use this flag as a new production default based only on
|
||||
one positive fixture.
|
||||
|
||||
## Multiple signatures: a separate kernel experiment
|
||||
|
||||
`0x20` is an accepted-root control, not a recovered "PE image" type flag.
|
||||
In the examined 22621.2792 and modern 26100 x64 bodies it leaves the
|
||||
preferred-signing-level search active. `PolicyInfo` can therefore describe a
|
||||
nested Microsoft signature even when the primary company signature also verifies.
|
||||
|
||||
The first-success guard tests aggregate masks `0xE47FFF87` (22621.2792) and
|
||||
`0xE41FFF87` (modern 26100). `0x20` intersects neither; `0x80` intersects both.
|
||||
Compare flags `0x20` versus `0xA0`, requested signing level zero, on the same
|
||||
stable dual-signed file. Record the actual selected leaf/thumbprint, both policy
|
||||
statuses and signing time. Do not interpret status success alone as selection
|
||||
of the company certificate. First successful does not necessarily mean first
|
||||
listed: CI may reject the primary and continue.
|
||||
|
||||
`0x80` has additional policy and fallback effects. Domito exposes it only as
|
||||
`DOMITO_CI_VALIDATE_FLAG_FIRST_SUCCESS_EXPERIMENTAL` and through the opt-in
|
||||
`DomitoCiSignatureSelectionFirstSuccessfulExperimental` mode in
|
||||
`DomitoValidateFileObjectEx`. It is not a production default or a stable signer
|
||||
index. See the [validation helper contracts](ci-validation-helpers.md). The companion research
|
||||
`SIGNATURE-SELECTION.md` provides the full static evidence and an alternative
|
||||
primary-signature path using `CiCheckSignedFile`.
|
||||
|
||||
A user-run kernel probe on Windows 11 **10.0.22631 x64**, CI options **0x00080207**
|
||||
(TESTSIGNING enabled), confirms the selection difference for the exact dual-signed
|
||||
BthPS3 fixture: `0x20` returns Microsoft, while `0xA0` returns the Nefarius leaf
|
||||
`FF0CCF318FD8C14775023A0B52C28FFCCA59D7F7` and signing time
|
||||
**2026-10-02T18:32:01.000Z**. Direct primary SHA-256 `CiCheckSignedFile` returns
|
||||
the same Nefarius leaf, signer/timestamp policies and signing time. All three
|
||||
calls return STATUS_SUCCESS; all policy VerificationStatus fields also succeed.
|
||||
The file digest is identical across calls, before/after file hashes match, and
|
||||
TraceFmt reports 149 events with no losses, format errors or unknown formats.
|
||||
|
||||
The companion `signature-selection/runtime-22631-bthps3.json` records exact
|
||||
trace hashes and the on-disk CI hash. This is one test-signing-enabled run;
|
||||
TESTSIGNING-off, other builds/policies and general signature enumeration remain
|
||||
unverified. `0xA0` does not mean "select any desired publisher".
|
||||
|
||||
## Checks available without the VM
|
||||
|
||||
From an x64 Visual Studio developer shell:
|
||||
|
||||
```powershell
|
||||
python tests\run-ci-probe-tests.py
|
||||
```
|
||||
|
||||
This compiles the actual probe body with mock CI calls and constants extracted
|
||||
from the public header. It verifies call order, input forwarding, fresh capacity
|
||||
and outputs, result capture, and freeing both policies after success and failure.
|
||||
It does **not** emulate the flag's trust semantics. Kernel compilation checks
|
||||
the real headers separately; neither compilation nor mock tests substitute for
|
||||
the VM run above.
|
||||
@@ -0,0 +1,118 @@
|
||||
# CI validation helpers
|
||||
|
||||
These additive APIs are declared in `Domito.h` for Windows 10 compile targets.
|
||||
They reuse CI for cryptographic verification. They do not implement RSA/ECDSA,
|
||||
certificate-chain building or timestamp-signature verification themselves.
|
||||
Raw CI declarations and existing digest/legacy helpers are unchanged.
|
||||
|
||||
## Result lifetime
|
||||
|
||||
Zero-initialize `DOMITO_CI_VALIDATION_RESULT` before first use. Each validation
|
||||
call frees its previous signer/timestamp policies before reuse and resets the
|
||||
result. Do not pass uninitialized storage or copy an owning result as a second
|
||||
owner. On every exit, including a failed call, release it with
|
||||
`DomitoFreeCiValidationResult`. The destructor accepts NULL and empty results.
|
||||
All three APIs require PASSIVE_LEVEL. Referenced input objects/buffers must stay
|
||||
valid and file bytes must stay stable throughout validation and consumption.
|
||||
|
||||
On success, `Hash`/`HashSize`/`HashAlgId` describe a known SHA-1/256/384/512 file
|
||||
digest with a consistent length. Unused digest bytes are zero. This is not a
|
||||
certificate thumbprint. On failure, digest bytes/length/algorithm and signing
|
||||
time are zero; policy objects may retain owned diagnostic allocations. Input
|
||||
flags/level forwarded to the file-object export remain recorded if it was called.
|
||||
Those fields are not CI's final internally normalized policy flags.
|
||||
|
||||
Check the returned NTSTATUS first. Policy verification status, policy bits,
|
||||
certificate identity, timestamps and the application's intended trust policy
|
||||
remain separate observations/checks. Returning STATUS_SUCCESS does not pin a
|
||||
company signer, reproduce WinVerifyTrust policy or prove driver-load acceptance.
|
||||
No helper traverses the private chain layout or matches a certificate for you.
|
||||
|
||||
## File-object path
|
||||
|
||||
`DomitoValidateFileObjectEx` takes a referenced FILE_OBJECT, caller-selected
|
||||
validation flags, a byte-sized requested signing level and a selection mode.
|
||||
It supplies fresh 64-byte hash capacity and initialized policy/time outputs on
|
||||
every call. It does not read, duplicate or acquire ownership of the file object.
|
||||
|
||||
- `DomitoCiSignatureSelectionNative` forwards the caller's flags unchanged.
|
||||
This is native policy, not a guarantee of preferred-level selection: the
|
||||
caller's other flags may already change the search/exit path.
|
||||
- `DomitoCiSignatureSelectionFirstSuccessfulExperimental` additionally sets
|
||||
`DOMITO_CI_VALIDATE_FLAG_FIRST_SUCCESS_EXPERIMENTAL` (0x80). On examined x64
|
||||
builds this changes a successful-candidate early-exit predicate. It also
|
||||
affects other policy/fallback paths. This explicit mode returns
|
||||
STATUS_NOT_SUPPORTED on non-x64 builds. No runtime behavior on ARM64 is implied.
|
||||
|
||||
Neither mode automatically adds `0x20`. Broadening accepted roots is a separate
|
||||
caller decision. Neither mode selects an arbitrary signer index or guarantees
|
||||
that signature zero succeeds. A rejected primary may still lead to another signer.
|
||||
|
||||
```c
|
||||
DOMITO_CI_VALIDATION_RESULT result = {0};
|
||||
NTSTATUS status = DomitoValidateFileObjectEx(
|
||||
fileObject,
|
||||
DOMITO_CI_VALIDATE_FLAG_BROADEN_ROOT_ACCEPTANCE,
|
||||
0,
|
||||
DomitoCiSignatureSelectionFirstSuccessfulExperimental,
|
||||
&result
|
||||
);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
// Apply your expected-certificate/trust policy to result.PolicyInfo.
|
||||
// result.SigningTime belongs to that selected verification result.
|
||||
}
|
||||
DomitoFreeCiValidationResult(&result);
|
||||
```
|
||||
|
||||
The native kernel experiment on the supplied dual-SHA256 BthPS3 fixture returned
|
||||
Microsoft for flags 0x20 and Nefarius for flags 0xA0 on a Windows 11 22631 x64
|
||||
TESTSIGNING-enabled machine. It does not establish all older builds, TESTSIGNING-off
|
||||
behavior or every side effect of 0x80. See [the flag evidence](ci-validate-file-object.md).
|
||||
Do not rename this mode "require our company" or "select primary signature".
|
||||
|
||||
## Embedded PE-buffer path
|
||||
|
||||
`DomitoValidatePortableExecutableEmbeddedSignature` accepts a stable PE buffer
|
||||
and an explicit CALG_SHA1/CALG_SHA_256/CALG_SHA_384/CALG_SHA_512. It calls
|
||||
`DomitoCalculatePortableExecutableDigestEx` and supplies the resulting digest
|
||||
and original first WIN_CERTIFICATE to `CiCheckSignedFile`. The digest allocation
|
||||
is always freed, and only copied digest bytes/owned CI policies remain in the
|
||||
result. Unsupported algorithm/layout and CI errors propagate without trying a
|
||||
different algorithm or a catalog. An absent certificate returns
|
||||
STATUS_INVALID_IMAGE_HASH; the helper cannot turn an unsigned file into a
|
||||
successful catalog verification.
|
||||
|
||||
```c
|
||||
DOMITO_CI_VALIDATION_RESULT result = {0};
|
||||
NTSTATUS status = DomitoValidatePortableExecutableEmbeddedSignature(stablePeBytes, peSize, CALG_SHA_256, &result);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
// Enforce the expected certificate and intended trust policy here.
|
||||
}
|
||||
DomitoFreeCiValidationResult(&result);
|
||||
```
|
||||
|
||||
This uses the explicit digest helper's [supported PE layout subset](authenticode-digests.md):
|
||||
bounded headers, contiguous nonoverlapping raw sections in file order and an EOF
|
||||
certificate table. It is not an arbitrary PE/SIP parser. CI can select nested
|
||||
signatures according to its algorithm rules, so the helper is deliberately named
|
||||
**embedded**, not **force primary**. The matching SHA-256 request selected the
|
||||
company primary in the tested BthPS3 layout; another layout may select another
|
||||
signer or fail. General enumeration remains separate work.
|
||||
|
||||
## Support and validation
|
||||
|
||||
The functions are C-compatible and compile for x64/ARM64. The experimental
|
||||
file-object mode is deliberately gated to x64; native forwarding/embedded code
|
||||
compilation does not certify every architecture/build's CI runtime ABI. CI
|
||||
imports are static and must exist on the target OS, as described in the
|
||||
[availability matrix](ci-api-compatibility.md). Structure/chain interpretation
|
||||
remains subject to the [mincrypt contracts](mincrypt-contracts.md).
|
||||
|
||||
The new host suite checks production code forwarding, hash invariants, failures,
|
||||
partial allocations, cleanup, result reuse and the non-x64 conditional branch.
|
||||
The existing digest suite independently compares Windows SIP and Crypt32 results.
|
||||
Kernel compilation covers the full library, public C clients and layout checks.
|
||||
CodeIntegrity-RE probe v2 now calls the new APIs; a further kernel run is needed
|
||||
to validate these wrappers rather than merely their previously tested raw calls.
|
||||
@@ -0,0 +1,247 @@
|
||||
# Migrating consumer Authenticode helpers
|
||||
|
||||
These helpers centralize file validation, certificate inspection, hashing and
|
||||
allocation cleanup. The contracts keep application identity and trust policy
|
||||
explicit. Host tests and kernel compilation do not establish new CI runtime
|
||||
guarantees.
|
||||
|
||||
## Verified fixes and existing coverage
|
||||
|
||||
- **Implementation defect fixed:** `DomitoGetProcessImageName` freed its allocation
|
||||
on a failed second query but left that freed address in the caller's output.
|
||||
It also left old caller output untouched on earlier failures. It now clears
|
||||
the output first, publishes only a successful bounded result, and frees its
|
||||
local allocation on all other paths. The process handle uses limited-query
|
||||
access (`0x1000`) instead of `PROCESS_ALL_ACCESS`. A PID is resolved once to a
|
||||
process handle; no later query re-resolves that PID.
|
||||
- **Output-contract defect fixed:** `DomitoFindModuleBaseAddress` could preserve
|
||||
an old address when lookup failed. It now clears the optional output first and
|
||||
validates the counted module name. The export-by-module wrapper preserves the
|
||||
underlying status, including missing exports and unsupported forwarders.
|
||||
- **Annotation defect fixed:** the `DomitoReadFileAt` definition's single-object
|
||||
output annotation disagreed with its public byte-count annotation. Both now
|
||||
describe `BufferSize` writable bytes.
|
||||
- **Already addressed before this review:** exact file reads return
|
||||
`STATUS_END_OF_FILE` on short reads and wait for their own pending request.
|
||||
Explicit digest helpers bound PE32/PE32+ headers, sections, certificate spans
|
||||
and DER navigation. Certificate pointers borrow the stable input buffer.
|
||||
[CI validation results](ci-validation-helpers.md) initialize outputs and own
|
||||
both policies, including diagnostic allocations on failure. The current raw
|
||||
CI declaration names the flags and byte-sized signing level; `0x20` broadens
|
||||
root acceptance in examined builds, rather than declaring a file to be PE.
|
||||
|
||||
Applications should avoid truncating file lengths to `EndOfFile.LowPart`,
|
||||
reparsing fixed-kind PE headers, consuming uninitialized CI policies, skipping
|
||||
cleanup on failure, or accepting invalid hexadecimal digits. The helpers below
|
||||
provide reusable primitives without defining application authorization policy.
|
||||
|
||||
## File object, handle and path validation
|
||||
|
||||
`DomitoValidateFileObjectEx`, `DomitoValidateFileHandleEx` and
|
||||
`DomitoValidateFilePathEx` expose the same explicit flags, requested signing
|
||||
level, selection mode and owning `DOMITO_CI_VALIDATION_RESULT`. None adds flags
|
||||
or falls back to a different validation policy. They require PASSIVE_LEVEL and
|
||||
Windows 10 compile targets; the CI imports must exist on the target OS.
|
||||
They do not require `DomitoInit`.
|
||||
|
||||
The handle wrapper requires a trusted **kernel handle** with `FILE_READ_DATA`.
|
||||
It references its FILE_OBJECT, releases that reference on every exit and leaves
|
||||
the caller's handle open. Never pass an unchecked user handle: the reference is
|
||||
made using KernelMode. The caller must keep the handle valid during validation.
|
||||
|
||||
The path wrapper accepts a counted absolute native path, for example
|
||||
`\??\C:\Program Files\Example\app.exe`. It creates a read-only kernel handle,
|
||||
shares only reads, references that same opened file for CI, and closes its own
|
||||
handle. Existing incompatible writers cause an open failure. Special kernel APCs
|
||||
must be enabled for synchronous I/O. Reparse points may redirect the open;
|
||||
validation describes the opened object. It does not establish the identity of
|
||||
a previously looked-up process image or certify in-memory process contents.
|
||||
File-object/handle callers must independently provide stable file bytes.
|
||||
|
||||
```c
|
||||
DOMITO_CI_VALIDATION_RESULT result = {0};
|
||||
NTSTATUS status = DomitoValidateFilePathEx(&nativePath, selectedCiFlags, 0, DomitoCiSignatureSelectionNative, &result);
|
||||
if (NT_SUCCESS(status) && NT_SUCCESS(result.PolicyInfo.VerificationStatus))
|
||||
{
|
||||
// Apply caller-provided certificate/publisher/pin policy here.
|
||||
// A nonzero SigningTime is a separate consumer requirement, if desired.
|
||||
}
|
||||
DomitoFreeCiValidationResult(&result); // Also on CI or application-policy failure.
|
||||
```
|
||||
|
||||
Modern file-object verification can select a preferred Microsoft nested signer
|
||||
where direct embedded verification selected the company signer. Changing paths
|
||||
therefore requires an explicit migration decision. Keep
|
||||
`DomitoValidatePortableExecutableEmbeddedSignature` for the stable PE-buffer,
|
||||
explicit-algorithm route. Its supported PE subset and nested-selection limitations
|
||||
still apply. It verifies the original first WIN_CERTIFICATE through CI, with no
|
||||
algorithm retry or catalog fallback. Existing legacy/catalog APIs remain
|
||||
available with explicit catalog policy; new convenience wrappers do not invoke
|
||||
them implicitly. An absent optional API is not permission to relax trust policy.
|
||||
|
||||
## Certificate fingerprints and SPKI pins
|
||||
|
||||
`DomitoGetCertificateSpki` extracts two borrowed views from stable certificate
|
||||
DER: `Encoded` contains the complete SPKI SEQUENCE TLV; `Content` omits that
|
||||
sequence's tag and length. It handles optional X.509 version fields and bounded,
|
||||
minimal definite DER lengths. It validates navigation/framing and the SPKI field
|
||||
shape, rather than every X.509 field, extension, name, algorithm parameter or
|
||||
signature. It does not verify trust. Failed extraction clears both views.
|
||||
|
||||
`DomitoHashBuffer` hashes exact bytes using SHA-1/256/384/512 and Windows CNG.
|
||||
`HashSize` is capacity on entry, actual length on success, required length on
|
||||
`STATUS_BUFFER_TOO_SMALL`, and zero on other failures. A NULL hash buffer queries
|
||||
the required size. Operational CNG failures erase the selected digest bytes.
|
||||
Input/output buffers must not overlap. Only consume a digest after success.
|
||||
|
||||
`DomitoHashCertificate` takes an explicit `DOMITO_CERTIFICATE_HASH_KIND`:
|
||||
|
||||
- `DomitoCertificateHashDer`: exact complete certificate bytes, suitable for a
|
||||
DER thumbprint. This mode hashes bytes; it does not parse or validate them.
|
||||
- `DomitoCertificateHashSpkiDer`: complete SPKI encoding, including outer TLV.
|
||||
- `DomitoCertificateHashSpkiContentLegacy`: **preserves the consumers' existing
|
||||
content-only convention**. Existing pins must use this mode. Switching to the
|
||||
complete encoding requires recomputing pins from the intended certificates;
|
||||
do not silently treat hashes from the two representations as interchangeable.
|
||||
|
||||
```c
|
||||
UCHAR pin[MINCRYPT_SHA256_LENGTH];
|
||||
ULONG pinSize = sizeof(pin);
|
||||
status =
|
||||
DomitoHashCertificate(cert.Data, cert.Size, DomitoCertificateHashSpkiContentLegacy, CALG_SHA_256, pin, &pinSize);
|
||||
```
|
||||
|
||||
`DomitoDecodeHex` accepts an exact counted Unicode hex string for a caller-selected
|
||||
binary length, rejects invalid digits/odd or mismatched lengths, and zeroes its
|
||||
destination on malformed input. `DomitoEncodeHex` writes uppercase Unicode hex
|
||||
with a NUL terminator; its capacity is in WCHARs including the terminator.
|
||||
Decode configuration pins once into binary and compare like representations.
|
||||
The library embeds no publisher names, root pins, or certificate allowlists.
|
||||
Hashing does not prove that a certificate is a root or trusted issuer.
|
||||
|
||||
## Chain inspection and publisher ownership
|
||||
|
||||
`DomitoGetCiChainView` requires a known, readable, initialized CI-owned policy
|
||||
and an explicit `DomitoCiChainLayoutObservedX64` argument. This asserts the
|
||||
sampled x64 common prefix (+0x28 elements, +0x30 count, +0x34 opaque RootId,
|
||||
minimum 56-byte header, 120-byte elements). It is **not** automatic OS/layout
|
||||
detection. Non-x64 builds return `STATUS_NOT_SUPPORTED`; allocation size and
|
||||
compile-target NTDDI cannot establish runtime layout compatibility.
|
||||
|
||||
The accessor bounds the element array and every exposed certificate/name blob
|
||||
within CI's owned allocation before returning a view. It rejects oversized hash
|
||||
lengths and absent certificate bytes. It exposes neither trailing attributes nor
|
||||
EKU/public-key arrays. It cannot make a forged or freed kernel pointer safe;
|
||||
allocation extent/readability and the asserted layout remain caller preconditions.
|
||||
All returned pointers expire when the policy is freed or its result reused.
|
||||
|
||||
Sampled CI results are leaf-first. Inspect `Elements[0]` for that selected leaf.
|
||||
`Elements[Count-1]` is the last represented certificate; this API does **not**
|
||||
promise it is self-signed, the configured trust anchor, or that the chain includes
|
||||
every certificate through a root. `RootId` is opaque and does not establish those
|
||||
properties. A consumer requiring a specific root must establish its intended CI
|
||||
policy and represented-anchor assumptions instead of inferring trust from position.
|
||||
|
||||
The accessor deliberately imposes no bytewise issuer/next-subject equality.
|
||||
CI name blobs are not an independent chain verifier;
|
||||
their encoding and representation are version-sensitive. Current evidence does
|
||||
not establish universal byte equality as a CI API contract. Preserve such a check
|
||||
as an explicit downstream restriction if compatibility demands it, and assess its
|
||||
false-rejection risk. CI return status, policy verification status and application
|
||||
identity/pin requirements remain separate checks.
|
||||
|
||||
`DomitoGetCertificatePublisherName` dynamically resolves the optional CI export
|
||||
instead of adding a static import. It requires `DomitoInit`; missing modules,
|
||||
exports and unsupported export forwarders propagate their lookup status.
|
||||
The caller passes an empty `UNICODE_STRING`, and uses
|
||||
`DomitoFreeCertificatePublisherName` to release/reset it. Partial allocations on
|
||||
failure are cleaned internally; the destructor is safe again afterward. Its
|
||||
private pool allocator is independent of configurable Domito callbacks. Never
|
||||
free this string through `G_Memory`, RtlFreeUnicodeString or the process-name free
|
||||
API. Display-name comparison remains caller policy, not certificate identity.
|
||||
|
||||
## Process names, allocators and optional exports
|
||||
|
||||
`DomitoGetProcessImageName` returns one Domito allocation containing the
|
||||
`UNICODE_STRING` and its buffer. `DomitoFreeProcessImageName` frees the entire
|
||||
allocation once, without querying callbacks in consumer code. Its output is
|
||||
NULL on failure. The existing ULONG PID interface remains; a PID lookup can race
|
||||
process exit/reuse before the initial open and is not a durable process identity.
|
||||
|
||||
`DomitoGetProcessImageNameEx` instead accepts a caller-referenced PEPROCESS.
|
||||
It uses `SeLocateProcessImageName`, copies the name into the same Domito-owned
|
||||
representation and frees the OS allocation internally. The caller must keep the
|
||||
process referenced for the call. No Domito initialization is needed for this Ex
|
||||
API. The PID API still requires `DomitoInit` for its query routine.
|
||||
Neither name API proves that a subsequent path open addresses the original
|
||||
image file. WDF/requestor-process lifetime and authorization remain downstream.
|
||||
|
||||
**Allocator contract:** the existing callback API does not attach allocator
|
||||
provenance to each result and is not synchronized for concurrent replacement.
|
||||
Configure a compatible allocate/free pair during initialization, before concurrent
|
||||
calls, and keep it unchanged until all callback-backed allocations and in-flight
|
||||
calls are released. A dedicated free name does not make changing callback pairs
|
||||
with outstanding allocations safe. Do not retrofit a hidden prefix onto existing
|
||||
allocations: callers may already free the public base address with their callback.
|
||||
CI policies and the publisher helper use their dedicated free APIs instead.
|
||||
|
||||
`DomitoFindModuleExportedFunctionAddress` combines the existing full-module-path
|
||||
and export-name lookups, clears its output and preserves useful failure status.
|
||||
It requires `DomitoInit`, and does not pin the module. The caller must guarantee
|
||||
that the module remains mapped throughout lookup and use of its returned address.
|
||||
|
||||
## Integration and consumer boundary
|
||||
|
||||
Import `Domito.props` from the Domito package location or override
|
||||
`DomitoRootPath`. The default root is the sheet's own directory. x64/ARM64 and
|
||||
Debug/Release remain selected by the project; `DomitoLibraryPlatform` can override
|
||||
the library platform directory. Both WDM and KMDF final driver projects receive
|
||||
Domito, CI and CNG dependencies. Importing a sheet into a static library does not
|
||||
make link dependencies transitive: import it into the final driver as well.
|
||||
|
||||
WDF caches, PID caches, administrator checks, developer bypasses, request allowlists,
|
||||
build expiry and selected-signing-time requirements stay in consumer code.
|
||||
No default trust evaluator is added: that would silently choose policy absent
|
||||
from the generic SDK. WPP diagnostics can enumerate the bounded chain view without
|
||||
fixed-depth indentation arrays. Report the returned NTSTATUS and local policy
|
||||
failure reason separately rather than mapping all failures inside the SDK.
|
||||
|
||||
The new host suite compiles the production code unchanged apart from its kernel
|
||||
include, uses deterministic kernel doubles for ownership/failure paths, compares
|
||||
SPKI bytes and fingerprints with Crypt32, and uses real CNG for hashing. It tests
|
||||
both architecture conditional branches, which is not ARM64 runtime emulation.
|
||||
Real WDK compilation separately covers x64 and ARM64. These checks do not certify
|
||||
kernel CI behavior, every chain layout, or full X.509 validation.
|
||||
|
||||
References: [SeLocateProcessImageName ownership](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-selocateprocessimagename),
|
||||
[BCryptCreateHash memory management and kernel requirements](https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptcreatehash).
|
||||
|
||||
## Deprecated compatibility entry points
|
||||
|
||||
The public header uses MSVC `__declspec(deprecated("migration guidance"))` for
|
||||
four older functions. Calling or taking their address produces C4996 in C and
|
||||
C++; declarations and binary entry points remain available. Projects treating
|
||||
warnings as errors must migrate, or suppress C4996 locally around a deliberate
|
||||
compatibility call. Do not disable the warning globally to conceal accidental use.
|
||||
|
||||
- `DomitoGetPortableExecutableDigestKind` →
|
||||
`DomitoGetPortableExecutableDigestKindEx`: check NTSTATUS; unrecognized input
|
||||
no longer silently chooses SHA-1. Neither function validates signature trust.
|
||||
- `DomitoCalculatePortableExecutableDigest` →
|
||||
`DomitoCalculatePortableExecutableDigestEx`: select the algorithm explicitly
|
||||
and review the supported layout/rejection rules. This is not a drop-in semantic
|
||||
change for arbitrary files previously accepted by linear hashing.
|
||||
- `DomitoValidateFileLegacyMode` → `DomitoValidateFileLegacyModeEx`: select catalog
|
||||
policy and trusted-catalog requirements explicitly, and consume the validation
|
||||
source. The Ex legacy path remains available where catalog/older-OS behavior
|
||||
is required; migration does not implicitly switch to modern signer selection.
|
||||
- `DomitoGetProcessImageName` → `DomitoGetProcessImageNameEx`: acquire and hold the
|
||||
intended PEPROCESS reference, then use the dedicated name destructor. Looking
|
||||
up a PID immediately before the Ex call cannot eliminate an earlier PID-reuse
|
||||
race; obtain the process reference from the operation's intended identity.
|
||||
This migration does not solve subsequent path-reopen identity races.
|
||||
|
||||
No old type has an unconditional replacement. Raw CI/mincrypt types still
|
||||
describe the native ABI; the owning validation result and borrowed chain view
|
||||
serve different purposes. Raw Windows CI exports, allocator callbacks, module
|
||||
lookup primitives, exact file reads and digest cleanup remain supported.
|
||||
@@ -0,0 +1,127 @@
|
||||
# CI SDK implementation status
|
||||
|
||||
This ledger tracks the source audit S01–S18 and the remaining binary research.
|
||||
The original CodeIntegrity-RE audit remains a snapshot of commit `7985b23`;
|
||||
it should not be read as describing the corrected source unchanged.
|
||||
|
||||
## Implemented with host tests or compilation
|
||||
|
||||
- Additive CI result/selection helpers now package native file-object validation,
|
||||
opt-in x64 first-success selection and explicit embedded verification, with
|
||||
shared policy/digest cleanup. Existing APIs retain their behavior. See the
|
||||
[helper contracts](ci-validation-helpers.md). Host failure/forwarding tests and
|
||||
x64/ARM64 builds cover the wrappers; WPP probe v2 consumes them and awaits a
|
||||
returned kernel trace. The previous v1 trace establishes the raw native routes.
|
||||
|
||||
- **S01–S04:** subtraction-safe PE ranges, no fixed 4 MiB copy, bounded certificate
|
||||
intervals, deterministic failure outputs, and digest cleanup. Compatibility
|
||||
and explicit paths share the bounded hashing core.
|
||||
- **S05:** actual certificate read length checked; allocation bounded against
|
||||
file size; per-operation completion waits through the exact-read helper.
|
||||
- **S06:** `DomitoReadFileAt` uses an explicit offset and private kernel event;
|
||||
`DomitoReadFile` reads exactly from offset zero. Pending completion cannot
|
||||
outlive its stack state or caller buffer. Short reads return EOF.
|
||||
- **S10:** export lookup uses the name ordinal to index the EAT, bounds tables,
|
||||
names and resolved RVAs, and rejects forwarders. A valid loader-mapped module
|
||||
remains a precondition because the API has no externally supplied image size.
|
||||
- **S11–S12:** corrected policy pointer typedef and publisher return/ownership docs.
|
||||
- **S14:** policy cleanup before embedded/catalog/reload retries, with host tests
|
||||
allocating results even on failures. Real CI failure ownership still needs
|
||||
the VM tests below.
|
||||
- **S17:** legacy hash algorithm/length combinations validated and calculation
|
||||
versus verification capabilities documented.
|
||||
- **S18:** byte-count SAL, buffer-capacity rules, scalar input annotations, and
|
||||
kernel read context/APC requirements documented.
|
||||
|
||||
## Implemented within an explicit support boundary
|
||||
|
||||
- **S07:** new bounded DER discovery reads the first outer SPC file-digest
|
||||
AlgorithmIdentifier; new explicit digest API needs no discovery. The old
|
||||
heuristic entry point retains compatibility behavior. Arbitrary BER, nested
|
||||
signatures, and full signature enumeration remain outside this parser.
|
||||
- **S08:** unsigned/catalog-only files can be hashed with a caller-chosen
|
||||
SHA-1 or SHA-256 strategy. The policy-explicit legacy helper forwards catalog
|
||||
controls and reports the successful source. Real catalog lookup comparisons
|
||||
across OS versions are pending; no implicit algorithm retry policy is imposed.
|
||||
- **S09:** the explicit digest path enforces a contiguous raw-section subset and
|
||||
EOF certificate tables, with Windows SIP and real embedded-digest comparisons.
|
||||
Gaps, overlaps, missing directory slots and nonterminal certificates are
|
||||
rejected. The old linear compatibility entry point is not a universal hasher.
|
||||
- **S13/S15/S16:** recovered fields, parameter meanings, policy categories, sizes,
|
||||
name encoding, borrowed lifetimes, and allocator ownership are documented.
|
||||
The opt-in x64 26100 header provides distinct observed layouts and assertions.
|
||||
Default declarations retain source compatibility; later chain fields require
|
||||
a confirmed runtime layout. The sampled 1507 chain header is 56 bytes and has
|
||||
no attributes descriptor at +0x38; 1511 uses 72 bytes; 1607–1803 samples use 104.
|
||||
Distinct views are available in `Domito.MinCrypt.Historical.h`. Neither
|
||||
`NTDDI_VERSION` nor total allocation Size identifies the layout.
|
||||
|
||||
## Requires the test VM or additional matching binaries
|
||||
|
||||
The first user-run kernel trace is available for Windows 11 22631 x64 with
|
||||
TESTSIGNING enabled. It confirms the BthPS3 signer-selection comparison and
|
||||
primary-signature CI path below. That one run, extracted artifacts, host mocks
|
||||
and compilation do not close the remaining work:
|
||||
|
||||
1. Run the paired `CiValidateFileObject` flag `0`/`0x20` probe on 19041/19045
|
||||
with TESTSIGNING off and a loadable signed test driver. Preserve complete
|
||||
statuses, policies and fixture/environment identities (issue #3).
|
||||
2. Complete historical and ARM64 ABI/structure verification and runtime tests.
|
||||
The [published export matrix](ci-api-compatibility.md) now covers all ten
|
||||
named APIs across 20 exact Windows 10/11 x64 and ARM64 CI files.
|
||||
ISO coverage includes Windows 10 1809/1903 revisions, 1909, 21H2/22H2 ARM64,
|
||||
and Windows 11 23H2 x64 plus 22H2/24H2 ARM64.
|
||||
The ARM64 observations establish export presence; their structure layouts
|
||||
and runtime behavior remain unverified. This closes the initial export-presence
|
||||
matrix; additional releases, servicing revisions and architectures remain
|
||||
unsampled. It does not certify ABI or runtime behavior. The six 1507–1803
|
||||
sampled bodies establish the
|
||||
48-byte policy storage and 64-byte hash-capacity gate. Chain constructors
|
||||
establish 56/72/104-byte headers; opt-in views prevent treating 1507 payload
|
||||
as the later attributes descriptor. Unsampled layouts/runtime remain open.
|
||||
3. Test real CI policy ownership on every failure/retry path under Driver
|
||||
Verifier, including allocation failures and initialized outputs.
|
||||
4. Compare real embedded/catalog-only SHA-1/SHA-256 results, catalog cache/reload
|
||||
behavior, trust-mask choices, requested signing levels and flag combinations.
|
||||
5. Measure signing-time propagation, zero/sentinel values, timestamp expiry,
|
||||
revocation freshness/network policy and weak-crypto policy. Record OS policy,
|
||||
Secure Boot/HVCI/WDAC and exact files, not just a boolean result.
|
||||
6. Extend the observed multiple/nested selection result beyond the first run.
|
||||
On Windows 11 22631 x64 with TESTSIGNING enabled, `0x20` returns Microsoft;
|
||||
`0xA0` and direct primary SHA-256 `CiCheckSignedFile` return Nefarius with the
|
||||
same signing time and matching signer/timestamp policy observations. All
|
||||
calls and policy statuses succeed, the file snapshots match, and no trace
|
||||
events are lost. TESTSIGNING-off, general enumeration, full `0x80` semantics
|
||||
and cross-build/policy behavior remain open. Extend supported PE gaps/overlays
|
||||
only after differential evidence.
|
||||
7. Resolve page-hash allocation destruction, normalized-entry/truncation meaning,
|
||||
terminal-entry handling and cross-version layouts before publishing a general
|
||||
page-hash API. `CiFreePolicyInfo` is not an established destructor for it.
|
||||
8. Investigate protected-media/initialization and ordinal-only exports separately
|
||||
if they are needed. Recovered export names alone are insufficient contracts.
|
||||
|
||||
## Checks
|
||||
|
||||
Run the six host runners in `tests/README.md`. Kernel compilation also covers
|
||||
the default modern x64/ARM64 structures, the pre-Windows-10 x64 compile variant,
|
||||
and 14 assertions in the 26100 opt-in header plus 12 historical-view assertions. Those are build checks,
|
||||
not a claim that historical or ARM64 CI runtime ABI has been verified.
|
||||
|
||||
## Consumer-driven helpers
|
||||
|
||||
The [consumer migration review](consumer-helpers.md) separates verified defects,
|
||||
existing corrections, new helpers and downstream policy. Additions include
|
||||
handle/path native CI wrappers, explicit SPKI representation/hash helpers,
|
||||
strict hex conversion, an explicit-layout x64 chain view, optional publisher
|
||||
resolution with matching cleanup, a referenced-process name API and dedicated
|
||||
process-name cleanup. The PID path fixes dangling failure output and excessive
|
||||
process access; module-base lookup clears stale output. WDM/KMDF linking is
|
||||
covered by the package-relative property sheet. No default publisher/root trust
|
||||
policy, automatic legacy fallback, or process authorization/cache is introduced.
|
||||
|
||||
Four compatibility functions carry MSVC deprecation annotations with explicit
|
||||
migration messages: heuristic digest-kind discovery, compatibility PE hashing,
|
||||
implicit-policy legacy validation and PID-based process-name lookup. Native CI
|
||||
types/functions remain available for low-level callers. The compile-only
|
||||
deprecation suite checks actual public headers in C/C++, including modern API
|
||||
controls and expected C4996 diagnostics for each older entry point.
|
||||
@@ -0,0 +1,327 @@
|
||||
# Code Integrity and mincrypt contracts
|
||||
|
||||
The default header retains the existing structure layouts and calling shapes.
|
||||
Parameter names and ownership comments now distinguish the known controls from
|
||||
the verification result. `VerificationStatus` is an `NTSTATUS` with the same
|
||||
32-bit storage. The additional `Domito.MinCrypt.26100.h` header is an **opt-in
|
||||
description of ci.dll 10.0.26100.8328 x64**. It neither adds imports nor extends
|
||||
the default structures on every Windows target.
|
||||
|
||||
The evidence is static REA/Ghidra analysis of SHA-256
|
||||
`c7d23814f3202c51fb23e3ca3d4328855787383cee5d14c4a986a13ec2aeda0b`, with
|
||||
Microsoft ci.pdb GUID `1CAE574B-CF1F-3564-5F74-49567A128629`, age 1 supplying the
|
||||
address/name map. The companion CodeIntegrity-RE repository retains the full
|
||||
records and readable `evidence/` files. The historical corpus below adds
|
||||
sampled x64 Windows 10 observations; ARM64 and unsampled-build compatibility
|
||||
remain open. Compile-target `NTDDI_VERSION` is not runtime layout negotiation.
|
||||
|
||||
The original modern research and `Domito.MinCrypt.26100.h` use the string
|
||||
`FileVersion` label **26100.8328**. That same exact binary has numeric
|
||||
`VS_FIXEDFILEINFO` version **26100.9444**, which the export matrix uses. Its
|
||||
SHA-256 and recovered contracts are unchanged; these labels identify one file.
|
||||
|
||||
## Historical x64 corpus: availability and structure evolution
|
||||
|
||||
The [CI API compatibility matrix](ci-api-compatibility.md) lists observed named
|
||||
exports for 20 exact x64/ARM64 CI files, including the later ISO samples. Consult it
|
||||
for import availability, and the contracts below for layout and ownership limits.
|
||||
|
||||
[NOTES.md](../NOTES.md) lists the exact identities of six sampled Windows 10
|
||||
files: `10.0.10240.16463`, `10.0.10586.0`, `10.0.14393.2189`, `10.0.15063.0`,
|
||||
`10.0.16299.125`, and `10.0.17134.1130`. All export `CiValidateFileObject` and
|
||||
the digest/catalog functions. The global setter is already present in sampled
|
||||
1703, correcting the old 1709 note. The publisher-name export is absent from
|
||||
all six. ISO samples additionally show absence in 19041.1 and presence in
|
||||
19041.1865 and 22000.318 x64; the original 26100 file also exports it. The first
|
||||
Windows 10 servicing update adding it remains unresolved. See CodeIntegrity-RE
|
||||
`iso-corpus-index.json`. Header guards do not negotiate runtime import availability.
|
||||
|
||||
All six sampled x64 file-object exports transfer 48 bytes into each caller
|
||||
policy, with the owned chain pointer at `+0x10`; cleanup zeros `0x30` bytes. Their
|
||||
file-object helpers require hash capacity >=64, return `STATUS_BUFFER_TOO_SMALL`
|
||||
and required length 64 for a smaller buffer, and consume the third input as a
|
||||
byte. This supports the stable policy storage prefix on these exact artifacts;
|
||||
it does not establish all field semantics or every servicing build's behavior.
|
||||
|
||||
**The chain header evolves within Windows 10. The default header's
|
||||
`NTDDI_VERSION >= NTDDI_WIN10` condition cannot safely expose every later field
|
||||
on Windows 10 1507.** Constructor evidence establishes:
|
||||
|
||||
- `10.0.10240.16463` (1507): fixed header 56 bytes (`0x38`), root ID at `+0x34`,
|
||||
variable payload beginning at `+0x38`. There is **no AuthenticodeAttributes
|
||||
header field at `+0x38`**. Accessing the default structure's member on this
|
||||
layout would interpret variable payload bytes as a blob descriptor.
|
||||
- `10.0.10586.0` (1511): fixed header 72 bytes (`0x48`), attributes descriptor at
|
||||
`+0x38`, payload beginning at `+0x48`.
|
||||
- Sampled 1607/1703/1709/1803: fixed header 104 bytes (`0x68`), root ID still at
|
||||
`+0x34`, attributes at `+0x38`, payload beginning at `+0x68`. Constructor evidence
|
||||
establishes space for the 32-byte extension at `+0x48`, not its semantic
|
||||
contents on every build. The historical view leaves this region reserved.
|
||||
|
||||
`Domito.MinCrypt.Historical.h` supplies distinct opt-in x64 views for those
|
||||
observed profiles with 12 compile-time assertions. The common prefix ends after
|
||||
root ID at `+0x34`; chain elements use 120-byte strides in these constructors,
|
||||
but the prefix views expose their storage as opaque. Do not assume every element
|
||||
field is populated on every version. The 26100-specific header separately names
|
||||
its recovered binary-ID field.
|
||||
|
||||
Choose a view only after establishing the runtime artifact/layout. `Size` is
|
||||
**total allocation bytes including payload**: a 1507 allocation can be larger
|
||||
than 72 or 104 bytes, so `Size >= sizeof(later_header)` is not version detection.
|
||||
Once layout identity is established, a size check is an additional field-read
|
||||
bound, not a substitute for identity. The default declarations remain unchanged
|
||||
for source compatibility; their later fields require this explicit runtime scope.
|
||||
|
||||
Successful exported/helper records in CodeIntegrity-RE retain the evidence:
|
||||
|
||||
- `historical/1507-export-contracts.json`:
|
||||
`ev_489c3b57057b0bc5c86950d7bb4ea25108bbc7762abc363e1be7eb5cca034796`.
|
||||
- `historical/ci-10240-helpers.json`:
|
||||
`ev_6d602c57de9614e7c5c28b9532c139f750f0e014b151000ecb41ad36f54bf764`.
|
||||
- `historical/ci-10586-exports.json`:
|
||||
`ev_a09e04976cfd90e9ba69cc6618892f15c3da166c64fa9241efae0db85234fd6e`.
|
||||
- `historical/ci-10586-helpers.json`:
|
||||
`ev_3403d5b8bf7c322fd924880d4cd9b296b98e94238cac2e1c1e9605c4b4d27255`.
|
||||
- `historical/ci-14393-contracts.json`:
|
||||
`ev_e63a4c4b7613e231795051b784b9571605b9bf81258b5dcd04d32ddc681abb41`.
|
||||
- `historical/ci-15063-contracts.json`:
|
||||
`ev_338658fb82559fa6daa8ae5487b90fe84b8e408ea7578feed6d8dff5d590e114`.
|
||||
- `historical/ci-16299-contracts.json`:
|
||||
`ev_fe5731175f0726f0d46af2f78ca615d284f8598939296815e26b5589db3001cf`.
|
||||
- `historical/ci-17134-contracts.json`:
|
||||
`ev_0c3e3359b8b7486318006afa6b95eb2257a18abeec9041a86a32db487bcbe996`.
|
||||
|
||||
## Results and trust policy
|
||||
|
||||
Check the API's returned `NTSTATUS` first. `PolicyInfo.VerificationStatus`,
|
||||
`PolicyBits`, signer details, and timestamps supply additional observations.
|
||||
Successful chain processing does not imply that the caller's file digest matched
|
||||
the signed digest; the comparison can occur afterward. Diagnostic policy data
|
||||
may exist on failure. An extracted publisher name is display information and
|
||||
does not establish publisher identity or signer trust.
|
||||
|
||||
Define the policy the application needs: embedded signature validation,
|
||||
membership in an accepted installed catalog, an expected publisher/key, or a
|
||||
Windows signing scenario. Preserve which path produced a result. A nonzero
|
||||
`PolicyBits` value is not automatically failure, and any one root bit is not a
|
||||
complete trust decision. File bytes and object identity must remain tied to the
|
||||
bytes the application will subsequently use.
|
||||
|
||||
The [file-object flag document](ci-validate-file-object.md) covers `0x20`, hash
|
||||
capacity, signing level, and its pending VM experiment. Other observed flag
|
||||
effects on 26100.8328 x64 are:
|
||||
|
||||
- `0x1` selects hash scenario 5.
|
||||
- Otherwise `0x2` selects scenario 4 for signing levels <=4; higher levels use
|
||||
the level mapping.
|
||||
- Otherwise `0x80000000` selects scenario 5 for levels <=4; higher levels use
|
||||
the level mapping. It takes precedence over `0x4`.
|
||||
- Otherwise `0x4` selects scenario 1; without these choices the signing level
|
||||
maps to a scenario.
|
||||
- `0x00400000` suppresses accepted-root bit `0x8` when the relevant helper mode
|
||||
is enabled; CI can add this flag internally. Bits `0x2` and `0x8` also affect
|
||||
later signing-level/EKU restrictions.
|
||||
|
||||
The scenarios resolve through initialized signing-policy state. Static defaults
|
||||
are not a guarantee of a running system's algorithm, and the flags should not
|
||||
be named as universal fixed SHA selectors. Unknown bits remain unknown. Evidence:
|
||||
`CipGetHashAlgorithmForLegacyScenario`, `CipGetAcceptedRootKeys`, and
|
||||
`CipMinCryptToSigningLevel` in the research bundle.
|
||||
|
||||
## Ownership and initialization
|
||||
|
||||
Zero-initialize both `MINCRYPT_POLICY_INFO` output objects before their first
|
||||
use. Free both with `CiFreePolicyInfo` after use and before reuse, including
|
||||
failure paths. Never call the destructor on arbitrary uninitialized stack data.
|
||||
Do not clear a nonzero `Size` while a chain is still owned: the observed cleanup
|
||||
helper skips an object whose `Size` is zero.
|
||||
|
||||
`ChainInfo` owns one allocation. Public-key blobs, names, encoded certificates,
|
||||
EKUs, attributes, and chain elements are borrowed views into it. Do not free
|
||||
children separately or retain them after releasing the owner. Copying the policy
|
||||
structure with `memcpy` creates two aliases to one allocation, not independent
|
||||
ownership. CI's internal deep-copy helper uses the total allocation size and
|
||||
rebases interior pointers; Domito does not expose that helper.
|
||||
|
||||
The default `CiFreePolicyInfo` declaration retains its legacy `PVOID` return to
|
||||
avoid a broad source compatibility change. **Ignore that value**: observed x64
|
||||
assembly provides no defined pointer result. The opt-in build-specific function
|
||||
pointer type uses `VOID`.
|
||||
|
||||
`CatalogName` is a separate `RtlDuplicateUnicodeString` allocation in the observed
|
||||
catalog export. Initialize it empty, release a returned buffer with
|
||||
`RtlFreeUnicodeString`, and release both policies separately. Publisher-name
|
||||
storage is allocated through the caller's callback and must be released with
|
||||
that allocator's matching free operation, including an allocated buffer on a
|
||||
later conversion failure. It is not owned by either policy object.
|
||||
|
||||
Evidence: `MincryptFreePolicyInfo`, `MincryptCopyPolicyInfo`,
|
||||
`I_MincryptAddChainInfo`, `CiVerifyHashInCatalog`, and `CiGetCertPublisherName`.
|
||||
|
||||
The additive [validation helpers](ci-validation-helpers.md) package safe result
|
||||
ownership, explicit file-object selection and embedded CI verification. They do
|
||||
not change raw CI declarations or existing legacy-helper behavior.
|
||||
|
||||
## Multiple signatures and selected results
|
||||
|
||||
`CiValidateFileObject` returns one selected signature result and its timestamp
|
||||
policy. Those two policy outputs do not enumerate two file signatures. The
|
||||
output file digest and algorithm are not expected-certificate selectors.
|
||||
|
||||
REA tracing of x64 CI 22621.2792 and the original 26100 sample found a
|
||||
flag-dependent distinction: ordinary `0x20` can continue nested-signature
|
||||
verification and retain a policy-preferred signing level. Adding `0x80` enters
|
||||
an early-exit path after the first successful full candidate verification.
|
||||
`0xA0` is therefore a concrete kernel experiment, not a proved stable
|
||||
"select primary signature" flag: `0x80` also affects other policy/fallback paths.
|
||||
An arbitrary signer index, expected-certificate predicate and continuation
|
||||
interface are not exposed by these examined wrappers.
|
||||
|
||||
For the supplied BthPS3 fixture, host SignTool verifies a primary Nefarius
|
||||
SHA-256 signature and a nested Microsoft SHA-256 signature. On both examined CI
|
||||
builds, `CiCheckSignedFile` with the matching SHA-256 digest follows the primary
|
||||
signature directly. This gives a CI-based alternative worth testing without
|
||||
implementing RSA/ECDSA, chain or timestamp verification. A subsequent user-run
|
||||
probe on Windows 11 22631 x64 with TESTSIGNING enabled confirms that `0x20`
|
||||
returns Microsoft while `0xA0` and direct SHA-256 `CiCheckSignedFile` return the
|
||||
Nefarius leaf and its signing time. Every top-level and signer/timestamp policy
|
||||
status succeeds; the two company-signer routes have matching policy observations.
|
||||
The companion `signature-selection/runtime-22631-bthps3.json` retains exact
|
||||
fixture/trace identities. This does not establish TESTSIGNING-off or general
|
||||
cross-build behavior. A different layout may still require bounded signature
|
||||
framing/enumeration.
|
||||
|
||||
The companion CodeIntegrity-RE `SIGNATURE-SELECTION.md` retains fixture hashes,
|
||||
56 procedure bodies, assembly, flag side effects and the kernel test plan.
|
||||
The 23H2 batch is
|
||||
`ev_049bd7d3aa492a9e3e4d8fcbf365ae00a6057751b26f93f3c1663c9436952ff7`;
|
||||
its primary-selection helper is in
|
||||
`ev_c867c73ca7eae7e4fbca2f44c6f6fb5904fb00459d0b84f2da8294b5b05a3866`.
|
||||
|
||||
## Digest-based verification inputs
|
||||
|
||||
`CiCheckSignedFile` consumes a caller-computed file digest. It does not reopen
|
||||
the file or compute its Authenticode hash. On the observed build it accepts
|
||||
SHA-1/256/384/512 with exactly 20/32/48/64 bytes respectively. A wrong algorithm,
|
||||
length, or digest fails the final comparison.
|
||||
|
||||
Its signature input points to a `WIN_CERTIFICATE` header. The observed wrapper
|
||||
requires 4-byte pointer alignment, supplied size >=12, revision `0x200`, type 2,
|
||||
and `8 < dwLength <= supplied size`. The PKCS#7 payload begins at header+8.
|
||||
The wrapper selects the first certificate-table entry. Multiple table entries
|
||||
and nested signatures are separate concepts; this is not a complete signature
|
||||
enumeration interface.
|
||||
|
||||
These exports are present in all six sampled Windows 10 x64 files and the
|
||||
analyzed Windows 11 file. The older header's “Win7–8.1 only” comments described
|
||||
a workflow, not verified export availability. Earlier first-available builds
|
||||
and pre/post-KB3033929 ABI changes still require matching Windows 7/8 artifacts.
|
||||
Import-library names and stdcall stack-byte counts alone do not settle semantics.
|
||||
|
||||
## Catalog controls
|
||||
|
||||
`ReloadCatalogs` controls catalog-store reload and related context setup.
|
||||
`RequireTrustedCatalog` is a nonzero gate requiring an observed catalog extension
|
||||
marker: its matching bytes include `PE`, integer `0x10001`, and `TRUSTED`.
|
||||
The marker is an additional catalog condition, not proof of a Microsoft signer.
|
||||
|
||||
`AcceptedCatalogPolicyBits` accepts a candidate when
|
||||
`(RequestedMask & Catalog.PolicyInfo.PolicyBits) != 0`: **any overlap** is enough.
|
||||
It neither enables policy flags nor requires every requested bit. The existing
|
||||
Domito compatibility value is named `DOMITO_CI_LEGACY_CATALOG_POLICY_BITS`
|
||||
(`0x2007F`). It includes test/DMD categories and diagnostic bit `0x20000`, while
|
||||
omitting other categories. It is retained as an existing behavior, not promoted
|
||||
as a universally safe trust mask. Establish and test the application's accepted
|
||||
signer policy before changing it.
|
||||
|
||||
Observed file-hash lookup supports SHA-1 and SHA-256; the internal path has no
|
||||
SHA-384/512 file-hash case. Embedded-signature algorithm support and catalog
|
||||
lookup support are different capabilities. Catalog-only files need an explicit,
|
||||
tested algorithm strategy rather than assuming SHA-1 from an absent embedded
|
||||
table. Catalog stores, caches, silo/process context, and signing policy affect
|
||||
results. The new `DomitoValidateFileLegacyModeEx` forwards a caller-selected mask and
|
||||
marker gate and reports embedded/catalog origin. Its compatibility wrapper retains
|
||||
the existing mask. See [digest and workflow details](authenticode-digests.md).
|
||||
|
||||
Domito's older-Windows helper keeps its system-process attachment until
|
||||
historical runtime evidence supports changing it.
|
||||
|
||||
Evidence: `I_FindFileOrHeaderHashInLoadedCatalogs` and its assembly
|
||||
`ev_c42e7ee76099d55e7cf7cdd3d9f79e99030ba637680365612afb4906694ae3a8`,
|
||||
`I_ParseCatalog`, and marker matcher
|
||||
`ev_a1d3a5844a2b6be6c16175e307956c9819d0b64a4fe70216f292c12e4ea38d82`.
|
||||
|
||||
## Opt-in x64 26100 structure observations
|
||||
|
||||
The version header has distinct type names and 14 compile-time layout assertions.
|
||||
Use it only after independently establishing the matching runtime build and
|
||||
architecture. A large `ChainInfo->Size` alone does not identify the header: it
|
||||
includes variable trailing data, so an older allocation could also be large.
|
||||
Only after layout identity is established may a size check protect a field read.
|
||||
|
||||
- `DOMITO_CI26100_NAME_BLOB`: pointer at +0, byte length at +8, ASN.1 string tag
|
||||
at +10. Names are not necessarily NUL-terminated. Observed conversion handles
|
||||
UTF8String tag `0x0C` and BMPString `0x1E`; `PCHAR` in the default declaration
|
||||
must not be read as a guarantee of ANSI encoding.
|
||||
- `DOMITO_CI26100_CHAIN_INFO`: `Size` is total allocation bytes; fixed header is
|
||||
104 bytes. Root ID at +0x34 is an opaque integer, not policy bits. The 32 bytes
|
||||
at +0x48 are a platform-manifest binary ID from an authenticated attribute,
|
||||
not a file digest or certificate thumbprint. Zero/nonzero does not by itself
|
||||
prove trust. Require the matching layout and `Size >=104` before reading it.
|
||||
- `DOMITO_CI26100_POLICY_INFO`: 48 bytes; `NotBefore`/`NotAfter` come from the
|
||||
signer certificate validity fields, not an intersection of the whole chain.
|
||||
Interpret `RevocationTime` only with the relevant result. A zero signing time
|
||||
is not a real timestamp to display as a signing date.
|
||||
|
||||
Construction/copy evidence: `ev_d7110cfc711074a4af1874b5c8e701c13bcc3dc58a1596c64dca4ca98966c79e`,
|
||||
`ev_858afecf2170484325379b6a8bc307fb72dad2f9a5a765169192c7363a3386af`,
|
||||
`ev_f82cbee977715399323bb398781c125a9d19b4ea29acd05063ec55b711cfc670`.
|
||||
|
||||
## Partial policy-bit dictionary
|
||||
|
||||
Names in the opt-in header are Domito descriptions of observed 26100 branches,
|
||||
not official Microsoft constants or a universal trusted-root enumeration.
|
||||
|
||||
Root/provenance categories include `0x1` self-issued terminal path, `0x2` selected
|
||||
built-in Microsoft roots, `0x4` test roots, `0x8` the built-in root associated with
|
||||
embedded picroot handling, `0x10` tolerated partial/unresolved chain, `0x20` DMD,
|
||||
`0x40` DMD test, `0x80` another built-in Microsoft root, `0x400` flight root,
|
||||
`0x2000` third-party marketplace, `0x4000` explicit supplied certificate/key
|
||||
acceptance, and `0x8000` Microsoft Identity Root 2020. `0x800` and `0x1000` are
|
||||
additional discriminators on some root entries; their independent meanings
|
||||
remain unresolved. These categories do not establish a full trust result.
|
||||
|
||||
Observed diagnostic branches set `0x20000` chain failure, `0x40000` invalid
|
||||
cryptographic/signature data, `0x80000` unmet EKU, `0x100000` page-hash failure,
|
||||
`0x200000` revocation, `0x400000` certificate validity failure (including
|
||||
not-yet-valid), `0x08000000` path-length constraints, `0x10000000` generic fallback,
|
||||
and `0x20000000` CA/BasicConstraints failure. `0x04000000` marks a no-usable-
|
||||
timestamp branch during revoked-certificate recovery, not universal timestamp
|
||||
absence. `0x50000` and `0x60000` are observed composites; do not infer a unique
|
||||
meaning for every constituent bit. Timestamp-before-revocation processing can
|
||||
clear a revocation bit. Internal checks of high bits are not a replacement for
|
||||
the API status and application policy.
|
||||
|
||||
## Remaining runtime and API coverage
|
||||
|
||||
The missing page-hash exports have recovered argument shapes in the research
|
||||
report. Their normalized allocation uses a 24-byte x64 header and 24-byte entries
|
||||
even for stronger source algorithms. Field meaning, truncation intent, source
|
||||
terminal-entry handling, and a supported destructor remain open. `CiFreePolicyInfo`
|
||||
is not a demonstrated destructor for that allocation. No universal page-hash SDK
|
||||
or static import is added until those ownership and cross-version contracts can
|
||||
be tested.
|
||||
|
||||
`CiGetPEInformation` is a protected-media dispatcher, not a general PE parser.
|
||||
`CiInitialize` is initialization machinery. `CiSetTrustedOriginClaimId` writes a
|
||||
CI global; it is not an ordinary per-file trust selector. Ordinal-only exports
|
||||
and other initialization interfaces require their own evidence and callers.
|
||||
|
||||
Still required: complete sampled-build/ARM64 layout and parameter verification, real CI
|
||||
output lifetimes and retry behavior under failures, timestamp propagation,
|
||||
revocation freshness/network policy, weak-crypto selection, multiple/nested
|
||||
signatures, catalog-only algorithms, and extension of the bounded digest subset to additional PE layouts.
|
||||
The explicit digest helper now has local Windows SIP and real embedded-digest
|
||||
comparisons; this does not close those historical or unusual-layout cases. Run the prepared probes in disposable VMs with exact OS,
|
||||
CI binary, configuration, and fixture identities. Compilation and host mocks do
|
||||
not close those runtime questions.
|
||||
Reference in new issue
Block a user