Hello,

I am reporting a security vulnerability in GNU Binutils affecting the BFD
library's DLX relocation backend.

*Summary*

The PCREL26 relocation handler elf32_dlx_relocate26() in bfd/elf32-dlx.c
performs a 4-byte read/write at (data + reloc_entry->address) without
validating the offset against the section size. Because the function
returns bfd_reloc_ok unconditionally, the generic bounds check in
bfd/reloc.c is bypassed entirely.

A crafted ELF32 DLX object with an out-of-bounds relocation offset
triggers an arbitrary write into adjacent mmap'd memory when processed
by objdump -g (or any BFD consumer). This has been demonstrated to
achieve arbitrary code execution via FSOP corruption of _IO_2_1_stderr_,
including full ASLR bypass.


*Affected Component*
  File:      bfd/elf32-dlx.c
  Function:  elf32_dlx_relocate26()
  Versions:  All versions through current HEAD (confirmed on git HEAD,
             Debian 13, glibc 2.41, x86_64)
  CWE:       CWE-787 (Out-of-bounds Write)

*Vulnerable Code*

  // bfd/elf32-dlx.c — elf32_dlx_relocate26()
  insn = bfd_get_32(abfd, data + reloc_entry->address);  // OOB read
  // ... relocation math ...
  bfd_put_32(abfd, insn, data + reloc_entry->address);   // OOB write
  return bfd_reloc_ok;                                    // bypasses
bounds check

The offset reloc_entry->address is read directly from the untrusted ELF
file and is never checked against input_section->size.

*Exploitation*

When the .debug_info section is >= 128 KB, malloc() uses mmap() to
allocate the section buffer. On x86_64 Linux, this places the buffer
in the same virtual memory region as libc's data segment. The distance
between the buffer and _IO_2_1_stderr_ is deterministic even with ASLR
enabled (measured at 0x21A4D0 across all test runs).

Four OOB PCREL26 relocations are used to corrupt _IO_2_1_stderr_ fields
(FSOP — File Stream Oriented Programming):

  1. _flags[0:3]     ← command string ("ps\0") → becomes system() argument
  2. _IO_write_ptr   ← non-zero              → triggers _IO_wfile_overflow
  3. _wide_data      ← pointer to fake struct → redirects vtable dispatch
  4. vtable          ← _IO_wfile_jumps        → enters wide file code path

Execution path when objdump writes to stderr:

  _IO_wfile_overflow(stderr)
    → _IO_wdoallocbuf(stderr)
      → stderr->_wide_data->_wide_vtable->__doallocate(stderr)
      = system(stderr)
      = system("ps")

A standalone proof-of-concept (no GDB, no root) using Linux ptrace to
resolve ASLR at runtime is attached. It has been confirmed to achieve
arbitrary code execution on an unmodified Debian 13 installation.

*Attachements*

poc_generate.py  — generates the malicious ELF payload
poc_ptrace.py    — standalone exploit with ASLR bypass (no GDB)

Public repository:
https://github.com/4D4J/objdump-Out-Of-Bounds-write

I am happy to provide additional technical details, test cases, or to
coordinate the disclosure timeline with your team.

Regards,
<https://github.com/4D4J/objdump-Out-Of-Bounds-write>Rapido (=

Reply via email to