[GH-ISSUE #5715] [Bug] inspect-binary-layout fails on a valid ELF containing IKCFG_ST #3463

Closed
opened 2026-10-31 00:40:45 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 20, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5715

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Native analysis or decompilation

Observed behavior

inspect-binary-layout exits 1 with execution_failure and no layout Evidence for a valid gcc-linked ELF64 x86-64 PIE containing the ordinary read-only string IKCFG_ST. The independent verifier reproduced the failure twice. A control differing only in the same-length string CONTROL_ succeeds. Both executables run successfully, and readelf, objdump, and nm accept both.

Reproduction

From a built source checkout on Linux x64, with REA_PWNTOOLS_PYTHON set to an absolute Python executable containing pwntools 4.15.0, pyelftools 0.33 and Unicorn 2.1.2:

: "${REA_PWNTOOLS_PYTHON:?Set this to the configured absolute Python executable}"
work_dir="$(mktemp -d)"
mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data"   "$work_dir/cache" "$work_dir/state" "$work_dir/tmp"
cat > "$work_dir/marker.c" <<'C'
#include <stdio.h>
__attribute__((used)) static const char marker[] = "IKCFG_ST";
int main(void) { puts(marker); return 0; }
C
sed s/IKCFG_ST/CONTROL_/ "$work_dir/marker.c" > "$work_dir/control.c"
gcc -O1 "$work_dir/marker.c" -o "$work_dir/marker"
gcc -O1 "$work_dir/control.c" -o "$work_dir/control"

for name in marker control; do
  "$work_dir/$name"
  readelf -aW "$work_dir/$name" > "$work_dir/$name.readelf.txt"
  objdump -h -x "$work_dir/$name" > "$work_dir/$name.objdump.txt"
  nm "$work_dir/$name" > "$work_dir/$name.nm.txt"
  env -i PATH="$PATH" HOME="$work_dir/home"     XDG_CONFIG_HOME="$work_dir/cfg" XDG_DATA_HOME="$work_dir/data"     XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state"     TMPDIR="$work_dir/tmp" REA_LOG_LEVEL=silent     REA_PWNTOOLS_PYTHON="$REA_PWNTOOLS_PYTHON"     node scripts/rea.mjs inspect-binary-layout "$work_dir/$name" --json     > "$work_dir/$name.rea.json"
  result=$?
  printf '%s REA exit: %s\n' "$name" "$result"
done

The verifier executed equivalent isolated commands in a Linux amd64 container: marker REA exit 1 twice; control REA exit 0. Both fixture executions and all independent ELF reader invocations exit 0. These are retained baseline observations; this submission rechecked main source only.

Expected behavior

Return layout Evidence for the unchanged marker-bearing executable. docs/binary-diagnostics.md:3-12 and src/contracts/native/binaryDiagnosticsToolContracts.ts:48 at the baseline advertise offline layout and static mitigation inspection for Linux x64 ELF64 x86-64 little-endian EXEC/DYN/REL inputs. This freshly linked ET_DYN fixture is in that profile; an ordinary data string does not invalidate its ELF structures.

Impact and scope

P1 for the reproduced supported-input case: the advertised layout workflow fails completely, with no identified REA option that returns its Evidence for the original bytes. Rewriting the string changes artifact identity; external ELF readers do not return REA Evidence. No data corruption or security-boundary crossing was observed. Other marker placements, architectures, and MCP transport were not tested.

REA version

rea-agents 6.7.0, source commit 9d8e7803326a382cbbb3ffdb900f5e93e5442d68. Verified at baseline; main source-checked only at 84c89d1107cda017509bc3cd851573d073f9906d: no changes since baseline to the cited contract, provider/decoder files or package-lock.json. Latest published release checked: 6.7.0.

Runtime and platform

Reproducing runtime: Linux amd64 container; Node.js v24.22.0; gcc 12.2.0; pwntools 4.15.0, pyelftools 0.33, Unicorn 2.1.2. Submission host: Node.js v26.12.0; macOS 27.0.1 arm64, used for source and tracker checks, not the Linux-only reproduction.

Target and artifact context

Self-built ELF64 little-endian x86-64 ET_DYN executable with a used constant string in read-only data and no IKCFG_ED closing marker. The control changes only that same-length string. No private target or disassembler configuration is required.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

The marker fixture's CLI JSON contains:

{
  "code": "execution_failure",
  "details": {
    "provider_id": "pwntools-elf",
    "operation": "inspect_binary_layout",
    "diagnostics": {
      "phase": "decoder",
      "failure_kind": "decoder",
      "reason": "StopIteration: ",
      "stdout": "",
      "stderr": "",
      "captured_output": {"stdout": "", "stderr": "", "truncated": false}
    }
  }
}

It recommends rea doctor and marks the failure non-retryable. The control returns 31 sections, 13 segments, 44 symbols, 9 relocations and mitigation inferences. Direct construction with unchanged upstream ELF(path, checksec=False) raises StopIteration for the marker fixture at pwnlib/elf/elf.py:304, stop = next(self.search(b'IKCFG_ED')); the control parses successfully. Evidence provenance: independently observed and retained by the verifier, not a new main runtime replay.

Typed outcome or recovery expected

Exit 0 with layout Evidence for the original marker-bearing bytes, preserving artifact identity, original sections/segments, symbols/relocations and uncertainty in mitigation inferences. The marker-free control must continue to succeed. Reclassifying this valid input as invalid format would not restore the contract.

Analysis or suspected cause

Source-derived reasoning, supported by the direct upstream traceback: pwntools 4.15.0 (Gallopsled/pwntools) treats IKCFG_ST as a possible embedded kernel configuration and calls next while searching for IKCFG_ED. Its absence raises StopIteration even though the ELF is structurally valid. This originates in the bundled provider dependency's kernel-config heuristic. REA constructs LayoutELF at bridge/pwntools/layout_impl.py:170; its exception list at line 305 omits this exception. bridge/pwntools/decoder_runtime.py:47-52 and src/native/pwntools/PwntoolsDecoder.ts:441-452 project a generic decoder execution failure. The missing closing config marker is not an invalid ELF structure.

Additional context

Prepared with AI assistance from an independently reproduced and semantically reviewed draft. No successful restoration or earlier known-good version has been established. Related #5401 concerns missing-file/directory acquisition errors in inspect-with-objdump; it has a different trigger and restoration contract.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5715 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Native analysis or decompilation ### Observed behavior `inspect-binary-layout` exits 1 with `execution_failure` and no layout Evidence for a valid gcc-linked ELF64 x86-64 PIE containing the ordinary read-only string `IKCFG_ST`. The independent verifier reproduced the failure twice. A control differing only in the same-length string `CONTROL_` succeeds. Both executables run successfully, and `readelf`, `objdump`, and `nm` accept both. ### Reproduction From a built source checkout on Linux x64, with `REA_PWNTOOLS_PYTHON` set to an absolute Python executable containing pwntools 4.15.0, pyelftools 0.33 and Unicorn 2.1.2: ```sh : "${REA_PWNTOOLS_PYTHON:?Set this to the configured absolute Python executable}" work_dir="$(mktemp -d)" mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" "$work_dir/cache" "$work_dir/state" "$work_dir/tmp" cat > "$work_dir/marker.c" <<'C' #include <stdio.h> __attribute__((used)) static const char marker[] = "IKCFG_ST"; int main(void) { puts(marker); return 0; } C sed s/IKCFG_ST/CONTROL_/ "$work_dir/marker.c" > "$work_dir/control.c" gcc -O1 "$work_dir/marker.c" -o "$work_dir/marker" gcc -O1 "$work_dir/control.c" -o "$work_dir/control" for name in marker control; do "$work_dir/$name" readelf -aW "$work_dir/$name" > "$work_dir/$name.readelf.txt" objdump -h -x "$work_dir/$name" > "$work_dir/$name.objdump.txt" nm "$work_dir/$name" > "$work_dir/$name.nm.txt" env -i PATH="$PATH" HOME="$work_dir/home" XDG_CONFIG_HOME="$work_dir/cfg" XDG_DATA_HOME="$work_dir/data" XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state" TMPDIR="$work_dir/tmp" REA_LOG_LEVEL=silent REA_PWNTOOLS_PYTHON="$REA_PWNTOOLS_PYTHON" node scripts/rea.mjs inspect-binary-layout "$work_dir/$name" --json > "$work_dir/$name.rea.json" result=$? printf '%s REA exit: %s\n' "$name" "$result" done ``` The verifier executed equivalent isolated commands in a Linux amd64 container: marker REA exit 1 twice; control REA exit 0. Both fixture executions and all independent ELF reader invocations exit 0. These are retained baseline observations; this submission rechecked main source only. ### Expected behavior Return layout Evidence for the unchanged marker-bearing executable. `docs/binary-diagnostics.md:3-12` and `src/contracts/native/binaryDiagnosticsToolContracts.ts:48` at the baseline advertise offline layout and static mitigation inspection for Linux x64 ELF64 x86-64 little-endian EXEC/DYN/REL inputs. This freshly linked ET_DYN fixture is in that profile; an ordinary data string does not invalidate its ELF structures. ### Impact and scope P1 for the reproduced supported-input case: the advertised layout workflow fails completely, with no identified REA option that returns its Evidence for the original bytes. Rewriting the string changes artifact identity; external ELF readers do not return REA Evidence. No data corruption or security-boundary crossing was observed. Other marker placements, architectures, and MCP transport were not tested. ### REA version `rea-agents` 6.7.0, source commit `9d8e7803326a382cbbb3ffdb900f5e93e5442d68`. Verified at baseline; main source-checked only at `84c89d1107cda017509bc3cd851573d073f9906d`: no changes since baseline to the cited contract, provider/decoder files or package-lock.json. Latest published release checked: 6.7.0. ### Runtime and platform Reproducing runtime: Linux amd64 container; Node.js v24.22.0; gcc 12.2.0; pwntools 4.15.0, pyelftools 0.33, Unicorn 2.1.2. Submission host: Node.js v26.12.0; macOS 27.0.1 arm64, used for source and tracker checks, not the Linux-only reproduction. ### Target and artifact context Self-built ELF64 little-endian x86-64 ET_DYN executable with a used constant string in read-only data and no `IKCFG_ED` closing marker. The control changes only that same-length string. No private target or disassembler configuration is required. ### Interface CLI ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence The marker fixture's CLI JSON contains: ```json { "code": "execution_failure", "details": { "provider_id": "pwntools-elf", "operation": "inspect_binary_layout", "diagnostics": { "phase": "decoder", "failure_kind": "decoder", "reason": "StopIteration: ", "stdout": "", "stderr": "", "captured_output": {"stdout": "", "stderr": "", "truncated": false} } } } ``` It recommends `rea doctor` and marks the failure non-retryable. The control returns 31 sections, 13 segments, 44 symbols, 9 relocations and mitigation inferences. Direct construction with unchanged upstream `ELF(path, checksec=False)` raises `StopIteration` for the marker fixture at `pwnlib/elf/elf.py:304`, `stop = next(self.search(b'IKCFG_ED'))`; the control parses successfully. Evidence provenance: independently observed and retained by the verifier, not a new main runtime replay. ### Typed outcome or recovery expected Exit 0 with layout Evidence for the original marker-bearing bytes, preserving artifact identity, original sections/segments, symbols/relocations and uncertainty in mitigation inferences. The marker-free control must continue to succeed. Reclassifying this valid input as invalid format would not restore the contract. ### Analysis or suspected cause Source-derived reasoning, supported by the direct upstream traceback: pwntools 4.15.0 ([Gallopsled/pwntools](https://github.com/Gallopsled/pwntools)) treats `IKCFG_ST` as a possible embedded kernel configuration and calls `next` while searching for `IKCFG_ED`. Its absence raises `StopIteration` even though the ELF is structurally valid. This originates in the bundled provider dependency's kernel-config heuristic. REA constructs `LayoutELF` at `bridge/pwntools/layout_impl.py:170`; its exception list at line 305 omits this exception. `bridge/pwntools/decoder_runtime.py:47-52` and `src/native/pwntools/PwntoolsDecoder.ts:441-452` project a generic decoder execution failure. The missing closing config marker is not an invalid ELF structure. ### Additional context Prepared with AI assistance from an independently reproduced and semantically reviewed draft. No successful restoration or earlier known-good version has been established. Related #5401 concerns missing-file/directory acquisition errors in `inspect-with-objdump`; it has a different trigger and restoration contract.
Author
Owner

@coygeek commented on GitHub (Oct 24, 2026):

Checked resolved on main at d87e73f2db.

The original IKCFG_ST fixture and its CONTROL_ counterpart both succeeded through the production Python decoder and public CLI on Linux x64 with pwntools 4.15.0. The existing verifier's marker-patched ELF also matched its original in sections, segments, symbols, relocations, linkage and mitigations. Input digests matched the returned artifact identities, and file bytes remained unchanged. The structural adapter now disables unrelated kernel configuration/version searches. No fixture was executed, and this run did not use MCP.

Relevant implementation: layout_impl.py, verify-binary-layout.mjs.

Closing as completed on main.

<!-- gh-comment-id:6380752366 --> @coygeek commented on GitHub (Oct 24, 2026): Checked resolved on `main` at d87e73f2db50be72d33a4b3c7199af35518b441c. The original `IKCFG_ST` fixture and its `CONTROL_` counterpart both succeeded through the production Python decoder and public CLI on Linux x64 with pwntools 4.15.0. The existing verifier's marker-patched ELF also matched its original in sections, segments, symbols, relocations, linkage and mitigations. Input digests matched the returned artifact identities, and file bytes remained unchanged. The structural adapter now disables unrelated kernel configuration/version searches. No fixture was executed, and this run did not use MCP. Relevant implementation: [layout_impl.py](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/bridge/pwntools/layout_impl.py#L157), [verify-binary-layout.mjs](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/scripts/verify-binary-layout.mjs#L336). Closing as completed on main.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3463
No description provided.