Skip to content

fix: honor partition boundaries when a finding overruns them - #33

Merged
nmatt0 merged 1 commit into
nmatt0:masterfrom
wilco375:fix/partition-boundary-overlap
Sep 17, 2026
Merged

nmatt0 merged 1 commit into
nmatt0:masterfrom
wilco375:fix/partition-boundary-overlap

Conversation

@wilco375

@wilco375 wilco375 commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Updates the scanning logic to treat a discovered partition table as the authoritative source for partition boundaries, so a finding's own recorded size can no longer hide a real partition behind it.

In a dumped firmware image, I had the issue that various stale or false positive findings overlapping with real partitions caused those real partitions not to be extracted. A stale ext superblock at 0x200000 records an 80 MB size, so its extent runs to 0x5200000 — well past the start of the 1.4 GB partition at 0x1800000. The scanner skipped that entire extent, so the real partition was never validated and simply went missing.

Moria before the fix:

$ moria firmware.bin
OFFSET            SIZE     TYPE              TIER        NOTES
0x200             16.5 KB  gpt               verified    little 6 members
├─ 0x400000 p1    20.0 MB  Linux filesystem
├─ 0x1800000 p2   1.4 GB   Linux filesystem
├─ 0x59800000 p3  1.4 GB   Linux filesystem
├─ 0xb1800000 p4  128 MB   Linux filesystem
├─ 0xb9800000 p5  128 MB   Linux filesystem
└─ 0xc1800000 p6  2.1 GB   Linux filesystem
0x60000           691 KB   fit               consistent  big
0x200000          80.0 MB  ext               consistent  little
0x5241000         1.7 KB   private_key       consistent  little
0x52416a8         241 KB   certificate       consistent  little
… +263 more certificate (12.2 MB, -A to list)
0x5281000         1.0 MB   private_key       consistent  little
0x53ad6de         466 B    bzip2             structural  little
0x54d9000         138 KB   elf               consistent  little/arm64 64-bit  "shared object"
0x54fc000         6.0 KB   elf               consistent  little/arm64 64-bit  "shared object"
[...]

$ moria --depth 1 -e firmware.bin 
OFFSET      SIZE     TYPE            TIER        NOTES
0x200       16.5 KB  gpt             verified    little 6 members
0x60000     691 KB   fit             consistent  big
0x200000    80.0 MB  ext             consistent  little
0x5241000   1.7 KB   private_key     consistent  little
0x52416a8   241 KB   certificate     consistent  little
0x527dc83   8.0 KB   certificate     consistent  little
0x527fc78   4.9 KB   certificate     consistent  little
0x5281000   1.0 MB   private_key     consistent  little
0x5389000   2.7 KB   certificate     consistent  little
0x5389ad4   1.9 KB   certificate     consistent  little
0x538a288   904 B    certificate     consistent  little
[...]

Moria after the fix:

$ moria firmware.bin
OFFSET            SIZE     TYPE              TIER        NOTES
0x200             16.5 KB  gpt               verified    little 6 members
├─ 0x400000 p1    20.0 MB  Linux filesystem
├─ 0x1800000 p2   1.4 GB   Linux filesystem
├─ 0x59800000 p3  1.4 GB   Linux filesystem
├─ 0xb1800000 p4  128 MB   Linux filesystem
├─ 0xb9800000 p5  128 MB   Linux filesystem
└─ 0xc1800000 p6  2.1 GB   Linux filesystem
0x60000           691 KB   fit               consistent  big
0x200000          80.0 MB  ext               consistent  little
0x1800000         1.4 GB   ext               consistent  little
0x59800000        1.4 GB   ext               consistent  little
0xb1800000        128 MB   ext               consistent  little
0xb9800000        128 MB   ext               consistent  little
0xc1800000        2.1 GB   ext               consistent  little

Files analyzed:  1
Bytes analyzed:  5.2 GB
Findings:        8
Elapsed:         0.273 s

$ moria -e --depth 1 firmware.bin 
OFFSET      SIZE     TYPE  TIER        NOTES
0x200       16.5 KB  gpt   verified    little 6 members
0x60000     691 KB   fit   consistent  big
0x200000    80.0 MB  ext   consistent  little
0x1800000   1.4 GB   ext   consistent  little
0x59800000  1.4 GB   ext   consistent  little
0xb1800000  128 MB   ext   consistent  little
0xb9800000  128 MB   ext   consistent  little
0xc1800000  2.1 GB   ext   consistent  little

-> extracted to firmware.bin.extracted/
Files analyzed:  1
Bytes analyzed:  5.2 GB
Findings:        8
Elapsed:         3.583 s

Note how after the fix, moria cleanly detects and extracts the actual partitions. Most of the previously listed findings are just files inside those partitions, and are now extracted properly by the ext extractor under their real names and paths. Nothing is lost by them disappearing from the listing: certificate, elf and private_key are identify-only types with no extractor, so they never produced a single file.

The stale ext partition at 0x200000 is still reported and extracted itself, but its recorded size no longer lets the scanner skip past 0x1800000. In this firmware image, a similar issue cause p4 to be skipped as well, which this also resolves. Any findings cleanly fitting between the partitions in the partition table are unaffected and still extracted as before, and an image without a partition table behaves exactly as it did.

The partition table is used for boundaries only, not as a list of things to extract. For example, as p1 holds no recognisable filesystem, it is not extracted like before.

All present tests pass.

Note: the code was written by Claude Code. This PR description was largely written by me with validation from Claude, and code and functionality was all manually verified.

A finding's size comes from its own header, so a stale superblock left in
unpartitioned space can claim an extent covering partitions written long
after it. The scanner skipped that whole extent, so the superblocks of the
partitions inside it were never validated: they went missing entirely
rather than being demoted to also_matched.

Clamp the skip-ahead at the next partition start, and stop resolve() from
demoting a finding that begins exactly on a partition boundary.
@nmatt0
nmatt0 merged commit f7f983d into nmatt0:master Sep 17, 2026
4 checks passed
nmatt0 added a commit that referenced this pull request Sep 17, 2026
test: regression for the partition-boundary overrun fix (#33)
jacobocasado pushed a commit to starredjaco/moria that referenced this pull request Sep 21, 2026
A stale/oversized finding must not hide a real partition behind it: the
scanner clamps its skip-ahead at partition boundaries, and resolve() no
longer demotes a finding that starts exactly on a partition boundary.

Adds tests/test_partition_overlap.py — fully self-contained (a hand-built
GPT plus synthetic ext superblocks, no mkfs tools). It is a differential:
a stale ext at 0x8000 overruns a real partition at 0x40000; with the GPT
present the real partition is recovered, and with the GPT zeroed the same
stale finding hides it. That both asserts the fix and confirms the
partition table is what makes the difference (it fails on pre-fix master).
Wired into run.sh and CTest.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants