From b2e69728e3a73e80ee8da285cfc5d28a7c72d2a4 Mon Sep 17 00:00:00 2001 From: Entrpi Date: Wed, 28 Oct 2026 03:10:07 +1100 Subject: [PATCH] feat(artifacts): inventory and extract ESP flash layouts A whole-flash dump of an ESP32-family chip was read as its bootloader image, with the partition table, apps and data left as undescribed bytes, or refused when it began with erased flash. Read it as an esp-flash-image container instead. The partition table is decoded as esp_partition_table_verify accepts it and is found at the caller's partition_table_offset, at the default 0x8000, or by scanning 0x1000-aligned sectors for a table whose MD5 verifies, which the inventory reports as derived. The bootloader is located at its chip's ROM bootloader offset. Each partition is an entry with its declaration in flat format_metadata; the bootloader and app partitions carry ESP image facts from the existing streaming decoder; the otadata records are reported with a selection derived without rollback or anti-rollback, and the running partition stays unknown. One unreadable partition does not hide the others, and extraction writes every partition, nvs_keys included, as ordinary data. Flash layouts are detected before single ESP images. The scan runs only when an ESP image sits at a ROM bootloader offset, and is refused when a bootloader at another chip's offset shows that the dump does not start at flash address 0. open_binary gains flash_offset and partition_table_offset, which require format esp-flash-image and are part of the snapshot target identity; the CLI takes them with --target-format esp-flash-image. Comparison treats a partition's label, type, subtype, range and flags as its declaration. --- .../references/native-and-artifacts.md | 16 + docs/cli.md | 12 + docs/esp-flash-image.md | 166 +++++++ docs/esp-image.md | 8 +- docs/firmware-analysis.md | 11 + docs/index.md | 28 +- src/application/BinaryTargetResolver.ts | 81 +++- src/application/DirectAnalysis.ts | 99 ++-- src/application/binary/BinarySessionOpen.ts | 4 + src/application/binary/BinarySessionPort.ts | 2 + src/application/binary/BinaryTargetSummary.ts | 6 + src/artifacts/ArtifactProvider.ts | 14 + src/artifacts/ArtifactReader.ts | 1 + .../EspFlashImageArtifactReader.test.ts | 371 +++++++++++++++ src/artifacts/EspFlashImageArtifactReader.ts | 436 ++++++++++++++++++ src/artifacts/EspFlashRegionReads.ts | 132 ++++++ src/artifacts/createArtifactReader.ts | 19 + .../extraction/ArtifactExtraction.ts | 12 +- .../inventory/ArtifactGraphConstruction.ts | 7 +- src/artifacts/inventory/classify.ts | 31 +- src/artifacts/inventory/reader.ts | 12 +- src/artifacts/inventory/types.ts | 6 + src/cli/artifactCommands.ts | 57 +++ src/contracts/sessionLifecycleInputs.ts | 38 +- src/domain/analysisSnapshot.ts | 42 +- .../artifactInventorySummaryProjection.ts | 3 +- .../analysisView/artifactInventoryView.ts | 3 +- src/domain/artifactComparison.ts | 14 +- src/domain/artifactFormatMetadata.ts | 150 +++++- src/domain/artifactGraph.ts | 1 + src/domain/binaryTargetTypes.ts | 17 + src/domain/dosCom.ts | 6 +- src/domain/evidenceSubject.ts | 1 + src/domain/firmware/espChips.ts | 22 + src/domain/firmware/espFlash.fixture.ts | 140 ++++++ src/domain/firmware/espFlashBootloader.ts | 74 +++ src/domain/firmware/espFlashLayout.test.ts | 279 +++++++++++ src/domain/firmware/espFlashLayout.ts | 335 ++++++++++++++ src/domain/firmware/espFlashLocation.test.ts | 142 ++++++ src/domain/firmware/espFlashLocation.ts | 181 ++++++++ src/domain/firmware/espFlashPlan.test.ts | 219 +++++++++ src/domain/firmware/espFlashSelection.ts | 32 ++ src/domain/firmware/espOtaData.ts | 165 +++++++ src/domain/firmware/espPartitionTable.ts | 234 ++++++++++ src/domain/liveBinaryTargetSummary.ts | 24 + src/server/registerSessionTools.ts | 20 + tests/acceptance/espFlashImageCli.test.ts | 136 ++++++ .../boundary/filesystem/binaryTarget.test.ts | 100 ++++ tests/boundary/mcp/espFlashImageMcp.test.ts | 98 ++++ 49 files changed, 3918 insertions(+), 89 deletions(-) create mode 100644 docs/esp-flash-image.md create mode 100644 src/artifacts/EspFlashImageArtifactReader.test.ts create mode 100644 src/artifacts/EspFlashImageArtifactReader.ts create mode 100644 src/artifacts/EspFlashRegionReads.ts create mode 100644 src/domain/firmware/espFlash.fixture.ts create mode 100644 src/domain/firmware/espFlashBootloader.ts create mode 100644 src/domain/firmware/espFlashLayout.test.ts create mode 100644 src/domain/firmware/espFlashLayout.ts create mode 100644 src/domain/firmware/espFlashLocation.test.ts create mode 100644 src/domain/firmware/espFlashLocation.ts create mode 100644 src/domain/firmware/espFlashPlan.test.ts create mode 100644 src/domain/firmware/espFlashSelection.ts create mode 100644 src/domain/firmware/espOtaData.ts create mode 100644 src/domain/firmware/espPartitionTable.ts create mode 100644 tests/acceptance/espFlashImageCli.test.ts create mode 100644 tests/boundary/mcp/espFlashImageMcp.test.ts diff --git a/.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md b/.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md index b26c99b3fa..2b67df630d 100644 --- a/.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md +++ b/.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md @@ -673,3 +673,19 @@ refusals. ESP8266 images are refused, and flash-encrypted images are not recognized. Segments are not disassembled, and RISC-V or Xtensa segments cannot be opened as raw-binary. See [ESP images](https://github.com/morluto/rea/blob/main/docs/esp-image.md). + +## ESP flash images + +A whole-flash dump opens as `esp-flash-image`. `root_format_metadata` holds +`partition_table` (its `method`: `default`, `caller` or a derived +`scan`), `bootloader` and `apps` ESP image facts, `otadata` with a derived +`selected` slot and its `assumptions`, and `partitions_outside_dump`; +`running_partition` is always `unknown`. Partition rows +(`partitions/