From 1711b5d3174f1a406c540774a1a0efc29cd22777 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Tue, 2 Jan 2024 12:39:26 +0100 Subject: [PATCH 1/4] Match against local system libc first in libcdb Don't do any requests if the libc currently in use on the system running the exploit matches already. This is a small short circuit optimization when the remote target uses the same libc as the local one. This looks at the libc loaded by the local shell binary. This appears more dynamic than hardcoding library paths. Refs #983 --- pwnlib/libcdb.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/pwnlib/libcdb.py b/pwnlib/libcdb.py index 0fb186b7f..f4af0375e 100644 --- a/pwnlib/libcdb.py +++ b/pwnlib/libcdb.py @@ -13,6 +13,7 @@ from pwnlib.log import getLogger from pwnlib.tubes.process import process from pwnlib.util.fiddling import enhex +from pwnlib.util.hashes import sha1sumhex, sha256sumhex, md5sumhex from pwnlib.util.misc import read from pwnlib.util.misc import which from pwnlib.util.misc import write @@ -20,7 +21,12 @@ log = getLogger(__name__) -HASHES = ['build_id', 'sha1', 'sha256', 'md5'] +HASHES = { + 'build_id': lambda path: enhex(ELF(path, checksec=False).buildid or b''), + 'sha1': sha1sumhex, + 'sha256': sha256sumhex, + 'md5': md5sumhex, +} DEBUGINFOD_SERVERS = [ 'https://debuginfod.elfutils.org/', ] @@ -100,7 +106,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['SHELL'] 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 From 5a388b2abd492cef60e80bd654f0b5072e871c56 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Tue, 2 Jan 2024 12:43:33 +0100 Subject: [PATCH 2/4] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d16837c..20bfe1e93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,6 +79,7 @@ The table below shows which release corresponds to each branch, and what date th - [#2309][2309] Detect challenge binary and libc in `pwn template` - [#2308][2308] Fix WinExec shellcraft to make sure it's 16 byte aligned - [#2279][2279] Make `pwn template` always set context.binary +- [#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 @@ -89,6 +90,7 @@ The table below shows which release corresponds to each branch, and what date th [2309]: https://github.com/Gallopsled/pwntools/pull/2309 [2308]: https://github.com/Gallopsled/pwntools/pull/2308 [2279]: https://github.com/Gallopsled/pwntools/pull/2279 +[2325]: https://github.com/Gallopsled/pwntools/pull/2325 ## 4.12.0 (`beta`) From a76fabe6c72d6da0e6202e53b69bbab59303fb59 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Tue, 2 Jan 2024 13:03:10 +0100 Subject: [PATCH 3/4] Handle missing SHELL envvar --- pwnlib/libcdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pwnlib/libcdb.py b/pwnlib/libcdb.py index f4af0375e..1f8394840 100644 --- a/pwnlib/libcdb.py +++ b/pwnlib/libcdb.py @@ -110,7 +110,7 @@ def provider_libc_rip(hex_encoded_id, hash_type): def provider_local_system(hex_encoded_id, hash_type): if hash_type == 'id': return None - shell_path = os.environ['SHELL'] or '/bin/sh' + 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 From 4a19db28faaa5d830c7e58702d35b74e6fc4f865 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Tue, 2 Jan 2024 13:36:26 +0100 Subject: [PATCH 4/4] Fix hash lookup --- pwnlib/libcdb.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pwnlib/libcdb.py b/pwnlib/libcdb.py index 1f8394840..ee10301e7 100644 --- a/pwnlib/libcdb.py +++ b/pwnlib/libcdb.py @@ -13,7 +13,7 @@ from pwnlib.log import getLogger from pwnlib.tubes.process import process from pwnlib.util.fiddling import enhex -from pwnlib.util.hashes import sha1sumhex, sha256sumhex, md5sumhex +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 @@ -23,9 +23,9 @@ HASHES = { 'build_id': lambda path: enhex(ELF(path, checksec=False).buildid or b''), - 'sha1': sha1sumhex, - 'sha256': sha256sumhex, - 'md5': md5sumhex, + 'sha1': sha1filehex, + 'sha256': sha256filehex, + 'md5': md5filehex, } DEBUGINFOD_SERVERS = [ 'https://debuginfod.elfutils.org/',