Skip to content

Commit 3b4b261

Browse files
authored
Add local libc database provider for libcdb (#2356)
* Add local libc database provider for libcdb * Remove unnecessary assert * Add docstring for local_libcdb * Suppress warning output while `context.libdb` sets default * Testing the local system's libc first * Set falsely `context.lcoal_libcdb` to turn off local libc-database integration * Fix docstring * Make path check in validator * Fix doctests * Add CHANGELOG
1 parent 000c31c commit 3b4b261

File tree

4 files changed

+53
-1
lines changed

4 files changed

+53
-1
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ The table below shows which release corresponds to each branch, and what date th
7171

7272
## 4.14.0 (`dev`)
7373

74+
- [#2356][2356] Add local libc database provider for libcdb
7475

76+
[2356]: https://github.com/Gallopsled/pwntools/pull/2356
7577

7678
## 4.13.0 (`beta`)
7779

pwnlib/args.py

+6
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,11 @@ def STDERR(v):
159159
"""Sends logging to ``stderr`` by default, instead of ``stdout``"""
160160
context.log_console = sys.stderr
161161

162+
def LOCAL_LIBCDB(v):
163+
"""Sets path to local libc-database via ``context.local_libcdb``, e.g.
164+
``LOCAL_LIBCDB='/path/to/libc-databse'``"""
165+
context.local_libcdb = v
166+
162167
hooks = {
163168
'LOG_LEVEL': LOG_LEVEL,
164169
'LOG_FILE': LOG_FILE,
@@ -170,6 +175,7 @@ def STDERR(v):
170175
'NOASLR': NOASLR,
171176
'NOPTRACE': NOPTRACE,
172177
'STDERR': STDERR,
178+
'LOCAL_LIBCDB': LOCAL_LIBCDB,
173179
}
174180

175181
def initialize():

pwnlib/context/__init__.py

+27
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ class ContextType(object):
360360
'endian': 'little',
361361
'gdbinit': "",
362362
'kernel': None,
363+
'local_libcdb': "/var/lib/libc-database",
363364
'log_level': logging.INFO,
364365
'log_file': _devnull(),
365366
'log_console': sys.stdout,
@@ -1071,6 +1072,32 @@ def log_console(self, stream):
10711072
stream = open(stream, 'wt')
10721073
return stream
10731074

1075+
@_validator
1076+
def local_libcdb(self, path):
1077+
"""
1078+
Sets path to local libc-database, get more information for libc-database:
1079+
https://github.com/niklasb/libc-database
1080+
1081+
Works in :attr:`pwnlib.libcdb` when searching by local database provider.
1082+
1083+
The default value is ``/var/lib/libc-database``.
1084+
1085+
Sets `context.local_libcdb` to empty string or `None` will turn off local libc-database integration.
1086+
1087+
Examples:
1088+
1089+
>>> context.local_libcdb = pwnlib.data.elf.path
1090+
>>> context.local_libcdb = 'foobar'
1091+
Traceback (most recent call last):
1092+
...
1093+
AttributeError: 'foobar' does not exist, please download libc-database first
1094+
"""
1095+
1096+
if not os.path.isdir(path):
1097+
raise AttributeError("'%s' does not exist, please download libc-database first" % path)
1098+
1099+
return path
1100+
10741101
@property
10751102
def mask(self):
10761103
return (1 << self.bits) - 1

pwnlib/libcdb.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from pwnlib.context import context
1313
from pwnlib.elf import ELF
14+
from pwnlib.filesystem.path import Path
1415
from pwnlib.log import getLogger
1516
from pwnlib.tubes.process import process
1617
from pwnlib.util.fiddling import enhex
@@ -126,7 +127,23 @@ def provider_local_system(hex_encoded_id, hash_type):
126127
return local_libc.data
127128
return None
128129

129-
PROVIDERS = [provider_local_system, provider_libcdb, provider_libc_rip]
130+
# Offline search https://github.com/niklasb/libc-database for hash type
131+
def provider_local_database(hex_encoded_id, hash_type):
132+
if not context.local_libcdb:
133+
return None
134+
135+
localdb = Path(context.local_libcdb)
136+
if not localdb.is_dir():
137+
return None
138+
139+
log.debug("Searching local libc database, %s: %s", hash_type, hex_encoded_id)
140+
for libc_path in localdb.rglob("*.so"):
141+
if hex_encoded_id == HASHES[hash_type](libc_path):
142+
return read(libc_path)
143+
144+
return None
145+
146+
PROVIDERS = [provider_local_system, provider_local_database, provider_libcdb, provider_libc_rip]
130147

131148
def search_by_hash(hex_encoded_id, hash_type='build_id', unstrip=True):
132149
assert hash_type in HASHES, hash_type

0 commit comments

Comments
 (0)