Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ac6a617
Bring reason-codes documentation up-to-date:
malx-labs Aug 24, 2026
f31e516
New §2.15 Exception Directory Validator, slotted after §2.14 (Debug) …
malx-labs Aug 24, 2026
6f3f252
Fix formatting issue in RESOURCE ANOMALIES
malx-labs Aug 24, 2026
34e511f
Fix formatting issue
malx-labs Aug 24, 2026
4b95274
Exception directory iteration: initial commit
malx-labs Aug 25, 2026
0d05b6c
Fix fixtures 157 and 160: source size_of_image from optional_header
malx-labs Aug 25, 2026
a2bd593
The heuristics emission layer flattens into alongside its own fiel…
malx-labs Aug 25, 2026
c68cbf2
Of 10 documented export reason codes, only 2 can currently appear
malx-labs Aug 25, 2026
c3a8afe
Take size_of_image from optional_header, not analysis_dict
malx-labs Aug 25, 2026
84ae409
fix(heuristics): stop details payloads clobbering structural reason c…
malx-labs Aug 25, 2026
8477992
(fix) raw_offset is None
malx-labs Aug 26, 2026
7e5beeb
Remove unused analysis object from exception dir validator
malx-labs Aug 26, 2026
e69bd3f
Harden analysis.sections retrieval in version_info validator
malx-labs Aug 26, 2026
7e66ba9
(fix): RESOURCE_DIRECTORY_OUT_OF_BOUNDS code - declared in documentat…
malx-labs Aug 26, 2026
a9f1370
Bring spec documentation up-to-date and raise the unit test count on …
malx-labs Aug 26, 2026
0a8252f
(fix) Failing integration tests
malx-labs Aug 26, 2026
f2c47ae
(fix) Failing unit tests
malx-labs Aug 26, 2026
90fe001
Add unit tests for the exception directory parser and validator. Proj…
malx-labs Aug 26, 2026
0464072
Remove duplicate test file
malx-labs Aug 26, 2026
0539fd3
Rename exception directory test file and reduce headline test count
malx-labs Aug 26, 2026
4cc2303
(fix) Add a default to version info analysis sections retrieval
malx-labs Aug 26, 2026
e5d78fe
Rename rva_graph unit test file
malx-labs Aug 26, 2026
755899b
(fix) size_of_image=None is missing its Optional[int] annotation, and…
malx-labs Aug 26, 2026
fad621c
Restore formatting to resources and rva_graph validators
malx-labs Aug 26, 2026
4c6a099
Finalise v0.7.6.1 release documentation
malx-labs Aug 26, 2026
fbc42dd
Structural validation documentation must fixes applied
malx-labs Aug 26, 2026
9392bd6
Reason code documentation should fixes applied
malx-labs Aug 26, 2026
980d7b6
Reason code documentation minor fixes applied
malx-labs Aug 26, 2026
6b41863
Fix typos
malx-labs Aug 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,81 @@
# **v0.7.6.1 — Exception Directory Validator, and a Silent Output Defect**
**Released: 2026‑08‑27**

## Added
- **Exception directory validator (§2.15)** — deep semantic validation of the
PE exception (`.pdata`) directory: the x64 `RUNTIME_FUNCTION` table and its
`.xdata` `UNWIND_INFO` records, plus the ARM/ARM64 8-byte record walk.
Detects the loader-visible sortedness invariant, function-range validity,
adjacent-range overlap, RVA bounds, unwind version/flag anomalies, and
chained-unwind target faults.
- **`pe_exception` parser** — pure `struct`-level decoder over
`pe.get_data`-acquired bytes, independent of pefile's
`DIRECTORY_ENTRY_EXCEPTION` interpretation. Machine-gated to AMD64 /
ARM64 / ARM64EC / ARMNT; unsupported machines are reported once and the
walk is skipped. UNWIND_INFO V3 (APX preview) is recognised but not
deeply parsed.
- **14 exception reason codes** — `EXCEPTION_DIRECTORY_INVALID_HEADER`,
`_OUT_OF_BOUNDS`, `_UNALIGNED`, `_SIZE_NOT_MULTIPLE`,
`EXCEPTION_TABLE_TRUNCATED`, `EXCEPTION_UNSUPPORTED_MACHINE`,
`EXCEPTION_ENTRY_INVALID`, `EXCEPTION_FUNCTION_RANGE_INVALID`,
`_RVA_OUT_OF_BOUNDS`, `EXCEPTION_ENTRIES_NOT_SORTED`,
`EXCEPTION_FUNCTION_OVERLAP`, `EXCEPTION_UNWIND_INFO_UNALIGNED`,
`_INVALID`, `EXCEPTION_UNWIND_CHAIN_INVALID`.
- `ExceptionStruct` / `ExceptionFunctionEntry` / `ExceptionUnwindInfo` in
the internal schema.
- Reason-code contract regression suite
(`tests/unit/analysis/test_reason_codes.py`) pinning the emission
contract at both the source and output ends.
- Sub-reason taxonomies documented for nine previously undocumented codes.

## Fixed
- **Validator `details` could overwrite the parent reason code.** The
emission layer merged `details` over its own `reason` field, so any
validator using a top-level `reason` key clobbered it. Eleven documented
reason codes had never appeared in output; consumers saw bare sub-reason
strings instead. Validators now use `sub_reason`, the parent code is
written last, and a legacy `reason` payload is re-keyed defensively.
**Output-visible.**
- **`SizeOfImage` was read from the wrong layer**, returning `None` in
production and silently disabling `EXPORT_DIRECTORY_OUT_OF_BOUNDS`,
`DELAY_IMPORT_DIRECTORY_OUT_OF_BOUNDS`, and the SizeOfImage fallback in
`DEBUG_ENTRY_RVA_INVALID` / `RELOCATION_ENTRY_RVA_INVALID`. Now sourced
from `metadata["optional_header"]` and threaded explicitly into
`_directory_invariants`. **Output-visible.**
- **`DATA_DIRECTORY_NOT_MAPPED_TO_SECTION` was suppressed for any file
carrying an overlay.** The `raw_offset is None` guard used a bare
`continue`, skipping the section-mapping checks entirely; it is now
scoped to the overlay check alone. **Output-visible.**
- **`RESOURCE_DIRECTORY_OUT_OF_BOUNDS` was declared and documented but
never emitted** — a directory outside `.rsrc` caused a silent `return`.
Now reported, with `depth` distinguishing the root case from a
subdirectory whose extent overflows the section end. **Output-visible.**
- `version_info` no longer raises on an analysis dict missing `sections`.
- Removed a dead `zero_length_sections` set in `rva_graph`.

## Changed
- `validate_exports` and `validate_delay_imports` are now
`@depends_on("internal", "metadata")`; `validate_debug` and
`validate_relocations` are now
`@depends_on("internal", "metadata", "analysis")`.
- `rva_in_any_section` / `region_in_any_section` take an explicit optional
`size_of_image` argument. Existing two- and three-argument call sites keep
working.
- Tests: 1620 → 2136. Coverage held at 100%.

## Documentation
- `reason-codes.md`: `reason` → `sub_reason` throughout; nine sub-reason
taxonomies added; six descriptions corrected against implementation
(`RESOURCE_ENTRY_OUT_OF_BOUNDS` is subdirectory-only;
`RESOURCE_DATA_OVERLAPS_OTHER_DATA` does not compare blobs to each other;
entropy uniformity and size thresholds stated precisely).
- `structural-validation-deterministic-heuristics.md`: §2.13 and §2.14 no
longer claim placement checks they do not perform, and no longer cite two
reason codes that do not exist. Placement ownership and the `sub_reason`
output contract are now stated explicitly.

---

# **v0.7.6 — Structural validator expansion: debug, relocations directories**
**Released: 2026‑08‑10**

Expand Down
14 changes: 7 additions & 7 deletions README-pypi.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ If you need predictable, automatable IOC extraction — IOCX is built for you.

---

### v0.7.6.1 — Exception Directory Validator

- Adds deep semantic validation of the PE exception (`.pdata`) directory; 14 new reason codes; 15 validators total.
- Fixes a defect that had been suppressing structural findings across the engine.
- **Output-visible:** findings previously suppressed or mislabelled will now appear.
- Tests: 1620 → 2136. Coverage: 100%.

## Version highlights (v0.7.6)

- Added new PE structural validators for relocations and debug directories
- WIN_CERTIFICATE and tls validators now have pefile-independent struct parsers
- Never crashes on malformed input - byte-level parsing with structured error tombstones
- 1620 tests at 100% coverage - deterministic output, snapshot-stable

## Version highlights (v0.7.5)

- Added detection for malformed exports, delay-load tables, resources, VS_VERSIONINFO, and Optional Header fields via 24 structural reason codes
- Surfaces security metadata — DLL characteristics flags, subsystem/machine decoding, per-resource Shannon entropy
- Never crashes on malformed input — byte-level parsing with structured error tombstones
- 1370 tests at 100% coverage — deterministic output, snapshot-stable, cross-verified against `dumpbin`

---

## **Performance**
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<p align="center">
<a href="https://pypi.org/project/iocx/"><img src="https://img.shields.io/pypi/v/iocx?logo=pypi&logoColor=white"></a>
<img src="https://img.shields.io/badge/tests-1620_passed-brightgreen">
<img src="https://img.shields.io/badge/tests-2136_passed-brightgreen">
<img src="https://img.shields.io/badge/coverage-100%25-brightgreen">
<img src="https://img.shields.io/badge/python-3.12-blue">
<a href="https://github.com/iocx-dev/iocx/actions"><img src="https://img.shields.io/github/actions/workflow/status/iocx-dev/iocx/ci.yml?label=build"></a>
Expand Down Expand Up @@ -202,6 +202,16 @@ Fast path — no PE parsing.
<summary><strong>Show Version History</strong></summary>
<br>

### v0.7.6.1 — Exception Directory Validator

- Adds deep semantic validation of the PE exception (`.pdata`) directory; 14 new reason codes; 15 validators total.
- Fixes a defect that had been suppressing structural findings across the engine.
- Four further checks found to be dead in production: two directory placement, a section-mapping, and a resource-directory bounds check.
- **Output-visible:** findings previously suppressed or mislabelled will now appear.
- Tests: 1620 → 2136. Coverage: 100%.

---

### **v0.7.6 — Structural Validator Expansion: Debug and relocations directories**
- Two new PE structural validators - relocations and debug
- WIN_CERTIFICATE and tls validators now source structural truth from dedicated struct parsers, independent of pefile
Expand Down
Loading
Loading