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

Add local libc database provider for libcdb #2356

Merged
merged 10 commits into from
Mar 1, 2024
6 changes: 6 additions & 0 deletions pwnlib/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ def STDERR(v):
"""Sends logging to ``stderr`` by default, instead of ``stdout``"""
context.log_console = sys.stderr

def LOCAL_LIBCDB(v):
"""Sets path to local libc-database via ``context.local_libcdb``, e.g.
``LOCAL_LIBCDB='/path/to/libc-databse'``"""
context.defaults['local_libcdb'] = v

hooks = {
'LOG_LEVEL': LOG_LEVEL,
'LOG_FILE': LOG_FILE,
Expand All @@ -170,6 +175,7 @@ def STDERR(v):
'NOASLR': NOASLR,
'NOPTRACE': NOPTRACE,
'STDERR': STDERR,
'LOCAL_LIBCDB': LOCAL_LIBCDB,
}

def initialize():
Expand Down
22 changes: 22 additions & 0 deletions pwnlib/context/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ class ContextType(object):
'endian': 'little',
'gdbinit': "",
'kernel': None,
'local_libcdb': "/var/lib/libc-database",
'log_level': logging.INFO,
'log_file': _devnull(),
'log_console': sys.stdout,
Expand Down Expand Up @@ -1071,6 +1072,27 @@ def log_console(self, stream):
stream = open(stream, 'wt')
return stream

@_validator
def local_libcdb(self, path):
"""
Sets path to local libc-database, get more information for libc-database:
https://github.com/niklasb/libc-database

Works in :attr:`pwnlib.libcdb` when searching by local database provider.

The default value is ``/var/lib/libc-database``.

Sets `context.local_libcdb` to falsely path will turn off local libc-database integration.

When `context.local_libcdb` is default value, no warning will be issued for path check
during `pwnlib.libcdb` searching by local database provider.

Examples:

>>> context.local_libcdb = '/path/to/libc-database'
"""
return path

@property
def mask(self):
return (1 << self.bits) - 1
Expand Down
25 changes: 24 additions & 1 deletion pwnlib/libcdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from pwnlib.context import context
from pwnlib.elf import ELF
from pwnlib.filesystem.path import Path
from pwnlib.log import getLogger
from pwnlib.tubes.process import process
from pwnlib.util.fiddling import enhex
Expand Down Expand Up @@ -39,6 +40,10 @@
# Retry failed lookups after some time
NEGATIVE_CACHE_EXPIRY = 60 * 60 * 24 * 7 # 1 week

# The default value of `context.local_libcdb`, when user doesn't modify `context.local_libcdb`
# suppress the warning output for path check in local database provider.
DEFAULT_LOCAL_LIBCDB = '/var/lib/libc-database'

# https://gitlab.com/libcdb/libcdb wasn't updated after 2019,
# but still is a massive database of older libc binaries.
def provider_libcdb(hex_encoded_id, hash_type):
Expand Down Expand Up @@ -126,7 +131,25 @@ def provider_local_system(hex_encoded_id, hash_type):
return local_libc.data
return None

PROVIDERS = [provider_local_system, provider_libcdb, provider_libc_rip]
# Offline search https://github.com/niklasb/libc-database for hash type
def provider_local_database(hex_encoded_id, hash_type):
if not context.local_libcdb:
return None

localdb = Path(context.local_libcdb)
if not localdb.is_dir():
if context.local_libcdb != DEFAULT_LOCAL_LIBCDB:
log.warn_once("%s does not exist, please download libc-database first.", context.local_libcdb)
return None

log.debug("Searching local libc database, %s: %s", hash_type, hex_encoded_id)
for libc_path in localdb.rglob("*.so"):
if hex_encoded_id == HASHES[hash_type](libc_path):
return read(libc_path)

return None

PROVIDERS = [provider_local_system, provider_local_database, 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
Expand Down
Loading