Files
rea/src/application/InvestigationProviders.ts
T
ca4ca65c5e feat(pe): inspect Authenticode certificate tables (#4830)
* feat(pe): inspect Authenticode certificate tables

Add inspect_pe_certificates for IMAGE_DIRECTORY_ENTRY_SECURITY
WIN_CERTIFICATE entries and structurally decoded PKCS#7 signer
and X.509 identity fields. The workflow reads a stable PE image
without executing it or verifying signatures, chains, timestamps,
or Authenticode digest coverage.

* fix(pe): bound and validate certificate DER decoding

- Cap decoded DER values with a shared node budget so sibling fan-out
  cannot exhaust memory before the PKCS#7 check
- Require SignedData version, encapContentInfo and a final signerInfos
  SET in RFC 5652 order, and a signature OCTET STRING in each SignerInfo
- Decode OBJECT IDENTIFIER arcs as unbounded base-128 values, including
  a multi-byte first combined arc
- Decode UniversalString names as UTF-32BE and reject invalid values
- Share PE header admission with the resource layout so a section table
  that does not fit SizeOfHeaders is rejected

* docs: list PE certificates in the translated READMEs

* fix(pe): cap OBJECT IDENTIFIER length and arc size

A crafted type-2 certificate with a 262,144-byte contentType OID stalled
decodeOid for about 20 seconds, because one arc kept growing a BigInt
before the signedData check ran. decodeOid now rejects an OID longer than
256 bytes and an arc longer than 32 bytes before decoding it. Certificate
OIDs, including 2.25 UUID arcs, fit under both caps.

* fix(pe): reject truncated certificate tables and PKCS#7

SignedData now requires one SignerInfo with a non-empty signature and a
complete issuerAndSerialNumber. Certificate names share a 64 KiB decoded-byte
budget and are copied once. A security directory that ends in a short
WIN_CERTIFICATE header fails instead of reporting a complete table. The
certificate CLI forwards the caller abort signal into cleanup.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* chore(ci): keep fork workflow files unchanged

The certificate restack follows current main. Workflow files stay at the
fork tip so this branch update does not rewrite .github/workflows.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(pe): charge serial and validity text to the decoded budget

Certificate and signer serial numbers and validity times now count against
the shared decoded-text budget before they are converted, so a crafted
certificate cannot push megabytes of text into the hashed evidence. The
budget error now names certificate text rather than only names.

Restore the CI workflow to match main: the CI_TIMING_TIER input, the
tier-named timing artifacts and their publication conditions, the Windows
typecheck, and the path and snapshot suites in the curated Windows lane.

* fix(pe): require certificate fields and preserve signer key ids

Reject X.509 records that omit subjectPublicKeyInfo or signatureValue,
return subjectKeyIdentifier bytes as bounded hex, and advertise an absolute
path in the PE certificate input schema.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(pe): reject extra PKCS#7 wrappers and invalid UTF-8 names

ContentInfo and its signedData wrapper no longer ignore trailing values, and
directory strings must round-trip as UTF-8 instead of becoming U+FFFD.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
2026-10-22 17:20:07 +08:00

176 lines
5.7 KiB
TypeScript

import type { AnalysisOperation } from "./AnalysisProvider.js";
import {
createAnalysisProfile,
type AnalysisProfileCommitment,
} from "../domain/analysisProfile.js";
/** Provider identity for deterministic composed analysis workflows. */
export const REA_WORKFLOW_PROVIDER = {
id: "rea-workflow",
name: "REA composed investigation workflow",
version: "1",
} as const;
/** Commit a workflow result to its upstream profile and applicable semantic revision. */
export const workflowAnalysisProfile = (
upstream: AnalysisProfileCommitment,
operation?: AnalysisOperation,
): AnalysisProfileCommitment =>
createAnalysisProfile(REA_WORKFLOW_PROVIDER, {
upstream_analysis_profile: upstream,
source_limitations: "provider-operation-caveats-v1",
...(operation === "binary_overview"
? { workflow_revision: 4 }
: operation === "batch_decompile" ||
operation === "get_call_graph" ||
operation === "trace_feature"
? { workflow_revision: 3 }
: { workflow_revision: 1 }),
});
/** Provider identity for deterministic artifact inventories. */
export const ARTIFACT_GRAPH_PROVIDER = Object.freeze({
id: "rea-artifact-graph",
name: "REA safe artifact graph provider",
version: "1",
} as const);
/** Provider identity for execution-free managed PE/CLI analysis. */
export const MANAGED_STATIC_PROVIDER = Object.freeze({
id: "rea-dotnet-static",
name: "REA managed static analysis provider",
version: "1",
} as const);
/** Provider identity for portable, execution-free PE resource decoding. */
export const PE_RESOURCES_PROVIDER = Object.freeze({
id: "rea-pe-resources",
name: "REA PE resource parser",
version: "1",
} as const);
/** Provider identity for portable, execution-free PE Authenticode table decoding. */
export const PE_CERTIFICATES_PROVIDER = Object.freeze({
id: "rea-pe-certificates",
name: "REA PE certificate parser",
version: "1",
} as const);
/** Provider identity for portable, execution-free ELF note-table decoding. */
export const ELF_NOTES_PROVIDER = Object.freeze({
id: "rea-elf-notes",
name: "REA ELF note parser",
version: "1",
} as const);
/** Provider identity for execution-free Shannon byte-entropy profiling. */
export const BYTE_ENTROPY_PROVIDER = Object.freeze({
id: "byte-entropy",
name: "REA byte entropy",
version: "1",
} as const);
/** Provider identity for portable, execution-free PE and ELF export tables. */
export const NATIVE_EXPORTS_PROVIDER = Object.freeze({
id: "rea-native-exports",
name: "REA PE/ELF export table reader",
version: "1",
} as const);
/** Provider identity for deterministic managed-code comparison workflows. */
export const MANAGED_WORKFLOW_PROVIDER = {
id: "rea-dotnet-workflows",
name: "REA managed-code workflows",
version: "1",
} as const;
/** Provider identity for deterministic Apple application projections. */
export const APPLE_APPLICATION_PROVIDER = {
id: "rea-apple-application",
name: "REA Apple application workflows",
version: "1",
} as const;
/** Provider identity for deterministic Android application projections. */
export const ANDROID_APPLICATION_PROVIDER = {
id: "rea-android-application",
name: "REA Android application workflows",
version: "1",
} as const;
/** Provider identity for deterministic HarmonyOS application projections. */
export const HARMONY_APPLICATION_PROVIDER = {
id: "rea-harmony-application",
name: "REA HarmonyOS application workflows",
version: "1",
} as const;
/** Provider identity for verified publication of retained website scripts. */
export const WEB_SCRIPT_EXPORT_PROVIDER = {
id: "rea-web-script-export",
name: "REA captured script export",
version: "1",
} as const;
/** Provider identity for deterministic static JavaScript application analysis. */
export const JAVASCRIPT_APPLICATION_PROVIDER = {
id: "rea-javascript-application",
name: "REA JavaScript application analyzer",
version: "1",
} as const;
/** Provider identity for static/passive-runtime JavaScript reconciliation. */
export const JAVASCRIPT_RUNTIME_RECONCILIATION_PROVIDER = {
id: "rea-javascript-runtime-reconciliation",
name: "REA JavaScript runtime reconciliation",
version: "1",
} as const;
/** Provider identity for selected views of retained analysis Evidence. */
export const ANALYSIS_VIEW_PROVIDER = {
id: "rea-analysis-view",
name: "REA analysis view projection",
version: "1",
} as const;
/** Provider identity for graph-native feature tracing and version comparison. */
export const JAVASCRIPT_APPLICATION_WORKFLOW_PROVIDER = {
id: "rea-javascript-application-workflows",
name: "REA JavaScript application workflows",
version: "1",
} as const;
/** Provider identity for deterministic Evidence bundle comparisons. */
export const BUNDLE_COMPARISON_PROVIDER = {
id: "rea-bundle-comparison",
name: "REA Evidence bundle comparison",
version: "1",
} as const;
/** Provider identity for comparison-Evidence behavior aggregation. */
export const CHANGED_BEHAVIOR_PROVIDER = {
id: "rea-changed-behavior",
name: "REA changed behavior investigation",
version: "1",
} as const;
/** Provider identity for Evidence-backed call-path reconstruction. */
export const CALL_PATH_PROVIDER = {
id: "rea-call-path",
name: "REA call path reconstruction",
version: "1",
} as const;
/** Provider identity for explicit static/runtime hypothesis correlation. */
export const STATIC_RUNTIME_PROVIDER = {
id: "rea-static-runtime-correlation",
name: "REA static/runtime correlation",
version: "1",
} as const;
/** Provider identity for finite reconstruction specification verification. */
export const RECONSTRUCTION_PROVIDER = {
id: "rea-reconstruction-verifier",
name: "REA reconstruction verifier",
version: "1",
} as const;