Gallopsled / Gallopsled/pwntools

Ret2dlresolve should check that VERSYM[ ELF32_R_SYM (reloc->r_info) ] is valid

Open
#2,670 3 comments 0 reactions 0 assignees View on GitHub
backport-required bug
Dominant language
Python
Stars
13.7k
Forks
1.9k
Avg merge
6d 23h
Merged PRs (30d)
3

Description

Currently, Ret2dlresolve chooses a data_addr within the .bss arbitrarily, and errors if the corresponding VERSYM ndx is not mapped.
However, the value at VERSYM[ ELF32_R_SYM (reloc->r_info) ] also must be legal for dl_runtime_resolve() to not segfault. This can cause some nasty hard-to-debug segfaults.
To fix this, Ret2dlresolvePayload._get_recommended_address should search for addresses where the corresponding VERSYM index is set to 0 (or other legal values, although these seem to vary depending on the libc/ld version) in the ELF data.

As an example, here is something I wrote for a CTF chal once (32-bit):

```
def suitable_r_info(elf: pwn.ELF, base: int | None = None) -> int:
dynsym = elf.get_section_by_name(".dynsym").address + (elf.address - elf.load_addr)
gnu_version = elf.get_section_by_name(".gnu.version").address + (elf.address - elf.load_addr)
bss = elf.get_section_by_name(".bss").address + (elf.address - elf.load_addr)
if base is None:
base = bss + 0x100
dynsym_offset = pwn.align(0x10, base - dynsym)
while True:
versym_ptr = gnu_version + (dynsym_offset // 0x10) * 2
if self.binary.u16(versym_ptr) == 0:
return ((dynsym_offset // 0x10) << 8) | 7
dynsym_offset += 0x10
```

Happy to open a PR and try to implement unless there are any issues with doing this.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.