Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for libc databases with offsets using https://libc.rip/api/ #1867

Closed
zglozman opened this issue Apr 19, 2021 · 5 comments · Fixed by #2103
Closed

Support for libc databases with offsets using https://libc.rip/api/ #1867

zglozman opened this issue Apr 19, 2021 · 5 comments · Fixed by #2103
Labels

Comments

@zglozman
Copy link

Thanks for contributing to Pwntools! Ideas from the community help make Pwntools an amazing tool for everybody.

If you've got an idea for a new feature, please provide information about:

  • What the feature does
    takes a leaked offset and find the correct libc binary and downloads it, then returns and ELF object with that file.

  • Why the feature should exist
    To (1) create an abstraction allowing using the same exploit locally with one version of libc and remote with another version of LIBC

  • What tests should be included

If you think you can write the feature yourself, please submit a Pull Request and we can review your changes!
IF nobody is working on that i will be glad to try go build it.

@Arusekk
Copy link
Member

Arusekk commented Apr 19, 2021

I thought #1704 does that already, see https://docs.pwntools.com/en/latest/libcdb.html
(it looks up by build ID, not offsets, but it works for most cases). Please close if it works for you, or submit a PR if you have more ideas.

@zglozman
Copy link
Author

nope, I am talking of a different use case. Let's say I can leak actual addresses of some libc functions and now want to search by offsets and download the correct libs to build my rop chain. I will propose a PR.

@Arusekk
Copy link
Member

Arusekk commented Jul 13, 2021

Any updates on this?

@synap5e
Copy link

synap5e commented Nov 26, 2021

Here's what I used to solve the same scenario if it's any use to anyone finding this issue.

leak is a printf("%<n>$sAAAA<address>") primitive that can be used repeatedly.
This assumes that cost(leak) > cost(libc.rip lookup).

If you were using e.g. a ROP that writes GOT entries you wouldnt need the loop and could dump a bunch of known_symbols at once and make a single request to libc.rip.

log.info('Leaking GOT symbols addresses until libc is known')
libc_db_data = None
known_symbols = {}
prev = None
for f in elf.got:
    if f in ['_ITM_deregisterTMCloneTable', '__gmon_start__', '_ITM_registerTMCloneTable', 'stdout', 'stdin']:
        # ignore - address is likely 0
        continue

    address = u64(leak(elf.got[f]).ljust(8, b'\x00'))
    log.info(f'\t{f.ljust(24)}: 0x{address:016x}')

    if address:
        known_symbols[f] = address
        r = requests.post(
            'https://libc.rip/api/find', 
            json={
                'symbols': {
                    s: hex(a) for s, a in known_symbols.items()
                }
            }
        )
        r.raise_for_status()
        found_libcs = r.json()
        if not found_libcs:
            log.warning('\tCould not find libc in libc.rip database - ignoring symbol')
            del known_symbols[f]
            continue
        elif len(found_libcs) == 1:
            libc_db_data = found_libcs[0]
            break
        else:
            log.info(f'{len(found_libcs)} matching libcs found in libc.rip database')
            if len(found_libcs) == prev:
                # Note: could be more forgiving than failing after the first symbol that fails to refine the list
                log.info('Giving up on resolving and using first')
                libc_db_data = found_libcs[0]
                break
            prev = len(found_libcs)


log.info(f'Found singular matching libc:\n{pformat(libc_db_data)}')
libc_elf_path = libc_db_data['id']
try:
    libc = ELF(libc_elf_path)
except:
    download(libc_db_data['download_url'], libc_elf_path)
    libc = ELF(libc_elf_path)

@Arusekk
Copy link
Member

Arusekk commented Apr 3, 2022

Partially addressed by #1828

peace-maker added a commit to peace-maker/pwntools that referenced this issue Aug 29, 2022
When you're able to leak addresses of the libc library, use `libcdb.search_by_symbol_offsets()` to find and download the matching libc library from https://libc.rip.

If there are multiple matches, the user is prompted to select one interactively. The selection can be saved in the code for future executions of the script.

Fixes Gallopsled#1867
Arusekk added a commit that referenced this issue Mar 22, 2023
* libcdb: Add option to search by function offsets

When you're able to leak addresses of the libc library, use `libcdb.search_by_symbol_offsets()` to find and download the matching libc library from https://libc.rip.

If there are multiple matches, the user is prompted to select one interactively. The selection can be saved in the code for future executions of the script.

Fixes #1867

* libcdb: Handle multiple results when looking up by hash

Sometimes the same library appears to be indexed multiple times (see 0b52d2e713d243f0f65d808fcd3fbe372bb3cd32). Handle that situation by selecting the first in the list, since they should all be identical given the same hash value.

* Update CHANGELOG

* Fix off-by-one when pre-selecting a libc

* Do .json() only once

---------

Co-authored-by: Arusekk <[email protected]>
gogo2464 pushed a commit to gogo2464/pwntools that referenced this issue Sep 10, 2023
)

* libcdb: Add option to search by function offsets

When you're able to leak addresses of the libc library, use `libcdb.search_by_symbol_offsets()` to find and download the matching libc library from https://libc.rip.

If there are multiple matches, the user is prompted to select one interactively. The selection can be saved in the code for future executions of the script.

Fixes Gallopsled#1867

* libcdb: Handle multiple results when looking up by hash

Sometimes the same library appears to be indexed multiple times (see 0b52d2e713d243f0f65d808fcd3fbe372bb3cd32). Handle that situation by selecting the first in the list, since they should all be identical given the same hash value.

* Update CHANGELOG

* Fix off-by-one when pre-selecting a libc

* Do .json() only once

---------

Co-authored-by: Arusekk <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants