[AUTOMATED] fix(analysis): pe-data-directory-count — clamp a PE data-directory count to what its optional header holds - #453
Merged
Conversation
…directory count to what its optional header holds A PE declares how many data directories it has twice: once as `NumberOfRvaAndSizes`, once as the room `SizeOfOptionalHeader` leaves for the array. Windows reads whichever is smaller; `object::File::parse` insists on the declared count, so a packer that overwrites the field rejected the whole image and `functions`, `decompile-all`, `strings`, `xrefs` and `disassemble` all exited 1 with "Invalid PE number of RVA and sizes" before a byte of code was mapped. Clamp the count to `(SizeOfOptionalHeader - 96 or 112) / 8` in a copy of the bytes, at the same canonical read point as the ELF section-table repair and the Mach-O fat-slice peel, so the loader and every analysis pass see one recovered view. Clamping to what fits rather than to a hard 16 is what Windows does, and it means the imports come from the real directory table rather than a fabricated one. The clamp cannot change an image that loads today: it fires only where the declared count already made `object` reject the file (1 of 17 in-repo PE images — the new fixture — and 3 of 163 dataset images, all previously unloadable). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
A PE declares how many data directories it has twice — once as
NumberOfRvaAndSizes, once as the roomSizeOfOptionalHeaderleaves for thearray — and packers overwrite the first. Windows reads whichever is smaller;
kuna rejected the whole image, so
functions,decompile-all,strings,xrefsanddisassembleall exited1before a byte of code was mapped.That image's optional header is 224 bytes — room for exactly the 16 directories
it really carries — and declares 1531532893 of them, verbatim from the reported
Invius-packed binary.
The fix
loader/pe_datadirs.rsclamps the declared count to(SizeOfOptionalHeader - 96 or 112) / 8in a copy of the bytes, at the samecanonical read point as the Mach-O fat-slice peel and the ELF section-table
repair, so the loader and every analysis pass see one recovered view.
means the imports are read from the real directory table instead of a
fabricated one — the recovered binary resolves
GetProcAddress/LoadLibraryA.its own header is wrong however the rest of the file reads, so keeping it lets
the caller report what is actually unreadable. (The ELF repair next door
discards itself instead, because there a cleared section table can genuinely
not have been the problem.)
count already made
objectreject the file. Sweeping every PE in reach, 1 of17 in-repo and 3 of 163 dataset images clamp — the new fixture and three
packed crackmes, all previously unloadable.
The tests
Seven unit tests in
loader/pe_datadirs/tests.rs(PE32 and PE32+, the exactboundary at 16 vs 17, a non-PE and a ROM-magic image left byte-identical, and an
image that stays broken after the clamp), plus the promoted acceptance probe
tests/cli/pe-data-directory-count.jsonagainst a vendored 1024-byte PE32 twin,which fails on the unpatched tree and now reports 2 functions. On the reported
image
kuna functionsgoes from exit 1 to 54 functions, and the entry stub at0x40908edecompiles.Gates:
make testPARITY OK 675/675 ·make test-stagesPARITY OK 640/640 ·make test-cli47/47 ·make check-specOK ·kuna catalog --checkOK ·make rust-testgreen.🤖 Generated with Claude Code