Skip to content

x86-32 CALL rel16 zeroing out high bytes of EIP missing from instruction specification #7418

@inakilbss

Description

@inakilbss

Describe the bug
In 32-bit x86 code, instruction CALL rel16 (66 e8 cw) zeroes out the high bytes of EIP[1], making it suitable only for calls to code in 0x00000000-0000ffff. However, patching a CALL instruction will suggest it even for destinations outside that range, creating faulty binaries that will most likely crash if executed. The disassembler will also erroneously display the intended destination as the instruction's target, making the bug nontrivial to identify.

To Reproduce

  1. Open an x86 binary
  2. Locate a CALL instruction
  3. Patch the instruction to target an address less than 0x7000 away in either direction and higher than 0xffff
  4. 66 e8 #### will be suggested, which is incorrect

Expected behavior
CALL rel16 is not suggested outside of its real target range, and usages are correctly disassembled to destinations within said range.

Screenshots
Image

Attachments
I was going to include a sample ELF, but not a valid attachment

Environment:

  • OS: Ubuntu 22.04.5 LTS
  • Java Version: 17.0.13
  • Ghidra Version: 11.0
  • Ghidra Origin: Official GitHub distro

Additional context
[1]Intel® 64 and IA-32 Architectures Software Developer’s Manual, volume 2A, chapter 3, page 143:
IF near call THEN IF near relative call THEN [...] IF OperandSize = 16 THEN tempEIP := (EIP + DEST) AND 0000FFFFH; (* DEST is rel16 *) [...]

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions