#2670·pwntools

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

Author: h4kk4p4kk4Created Jan 27, 2026Updated Sep 8, 2026
Labelsbugbackport-required

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.