diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bcdbd48e..5d39a0c09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -85,6 +85,7 @@ The table below shows which release corresponds to each branch, and what date th - [#2189][2189] Explicitly define p64/u64 functions for IDE support - [#2339][2339] Fix: Allow setting attributes on gdb Breakpoints - [#2323][2323] Retry failed lookups after one week in libcdb +- [#2325][2325] Match against local system libc first in libcdb [2242]: https://github.com/Gallopsled/pwntools/pull/2242 [2277]: https://github.com/Gallopsled/pwntools/pull/2277 @@ -101,6 +102,7 @@ The table below shows which release corresponds to each branch, and what date th [2189]: https://github.com/Gallopsled/pwntools/pull/2189 [2339]: https://github.com/Gallopsled/pwntools/pull/2339 [2323]: https://github.com/Gallopsled/pwntools/pull/2323 +[2325]: https://github.com/Gallopsled/pwntools/pull/2325 ## 4.12.0 (`beta`) diff --git a/pwnlib/libcdb.py b/pwnlib/libcdb.py index 142c95d23..4955af3f3 100644 --- a/pwnlib/libcdb.py +++ b/pwnlib/libcdb.py @@ -14,6 +14,7 @@ from pwnlib.log import getLogger from pwnlib.tubes.process import process from pwnlib.util.fiddling import enhex +from pwnlib.util.hashes import sha1filehex, sha256filehex, md5filehex from pwnlib.util.misc import read from pwnlib.util.misc import which from pwnlib.util.misc import write @@ -21,7 +22,12 @@ log = getLogger(__name__) -HASHES = ['build_id', 'sha1', 'sha256', 'md5'] +HASHES = { + 'build_id': lambda path: enhex(ELF(path, checksec=False).buildid or b''), + 'sha1': sha1filehex, + 'sha256': sha256filehex, + 'md5': md5filehex, +} DEBUGINFOD_SERVERS = [ 'https://debuginfod.elfutils.org/', ] @@ -104,7 +110,23 @@ def provider_libc_rip(hex_encoded_id, hash_type): return None return data -PROVIDERS = [provider_libcdb, provider_libc_rip] +# Check if the local system libc matches the requested hash. +def provider_local_system(hex_encoded_id, hash_type): + if hash_type == 'id': + return None + shell_path = os.environ.get('SHELL', None) or '/bin/sh' + if not os.path.exists(shell_path): + log.debug('Shell path %r does not exist. Skipping local system libc matching.', shell_path) + return None + local_libc = ELF(shell_path, checksec=False).libc + if not local_libc: + log.debug('Cannot lookup libc from shell %r. Skipping local system libc matching.', shell_path) + return None + if HASHES[hash_type](local_libc.path) == hex_encoded_id: + return local_libc.data + return None + +PROVIDERS = [provider_local_system, provider_libcdb, provider_libc_rip] def search_by_hash(hex_encoded_id, hash_type='build_id', unstrip=True): assert hash_type in HASHES, hash_type