Gallopsled / pwntools

CTF framework and exploit development library
http://pwntools.com
Other
11.74k stars 1.67k forks source link

[dev] Bad libc mapping detection #2370

Open k4lizen opened 4 months ago

k4lizen commented 4 months ago

For the process.libc property/function, the logic is currently:

def libc():
        # <snip>
        for lib, address in self.libs().items():
            if 'libc.so' in lib or 'libc-' in lib:
                e = ELF(lib)
                e.address = address
                return e

and:

def libs():
        # <snip>
        # Enumerate all of the libraries actually loaded right now.
        maps = {}
        for mapping in maps_raw:
            path = mapping.path
            if os.sep not in path: continue
            path = os.path.realpath(path)
            if path not in maps:
                maps[path]=0
        # <snip>

So if there is a libc- anywhere in the mappings path, it will be counted as libc. I happened to be running the binary in a path which contained that string, and the binary sometimes gets returned incorrectly. This happens especially often if the actual libc didn't yet have time to load into the process, and None should be returned. minimal reproducable script:

from pwn import *
p = process(['./libc-nyanya/junior_formatter'])
print(f'\n\nLIBC: {p.libc}\n\n')
p.close()

Output:

─$ python mvp.py        
[+] Starting local process './libc-nyanya/junior_formatter': pid 84213
[*] '/<snip>/libc-nyanya/junior_formatter'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
    SHSTK:      Enabled
    IBT:        Enabled
    Stripped:   No

LIBC: ELF('/<snip>/libc-nyanya/junior_formatter')

[*] Stopped process './libc-nyanya/junior_formatter' (pid 84213)                                                  

Proposed solution: Still check for '.so' in the second part of the if, and only check for the filename instead of the whole path.