mirror of
https://github.com/Gallopsled/pwntools.git
synced 2026-11-12 18:27:37 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
493a3e3d92 | ||
|
|
f491bc6a22 | ||
|
|
2198b74df9 | ||
|
|
9d8060496c | ||
|
|
7ea1f1d492 | ||
|
|
da8bf2667d | ||
|
|
a37bce2bdc | ||
|
|
3dd0b24cc3 | ||
|
|
a8c8c28f00 | ||
|
|
315a462603 | ||
|
|
ddeddd455e | ||
|
|
d3140ed983 | ||
|
|
fc250a33a1 | ||
|
|
92911cbabd | ||
|
|
a9715d8c74 | ||
|
|
bd12d1874f | ||
|
|
11b8537d17 | ||
|
|
f7283bf2eb | ||
|
|
d5d7b8385c |
No files matched your search
@@ -60,6 +60,31 @@ jobs:
|
||||
binutils-sparc64-linux-gnu \
|
||||
gcc-multilib \
|
||||
libc6-dbg
|
||||
|
||||
- name: Cache for elfutils
|
||||
uses: actions/cache@v1
|
||||
id: cache-elfutils
|
||||
with:
|
||||
path: ~/.cache/elfutils
|
||||
key: ${{ matrix.os }}-cache-elfutils
|
||||
|
||||
# Install newer elfutils version due to regression in 0.176 available in focal.
|
||||
- name: Install newer elfutils
|
||||
env:
|
||||
ELFUTILS_VERSION: 0.181
|
||||
run: |
|
||||
if [[ ! -d ~/.cache/elfutils/elfutils-${ELFUTILS_VERSION} ]]
|
||||
then
|
||||
wget -O /tmp/elfutils-${ELFUTILS_VERSION}.tar.bz2 https://sourceware.org/elfutils/ftp/${ELFUTILS_VERSION}/elfutils-${ELFUTILS_VERSION}.tar.bz2
|
||||
mkdir -p ~/.cache/elfutils && cd ~/.cache/elfutils
|
||||
tar -xf /tmp/elfutils-${ELFUTILS_VERSION}.tar.bz2
|
||||
cd elfutils-${ELFUTILS_VERSION}
|
||||
LDFLAGS=-Wl,-rpath=/usr/local/lib,--enable-new-dtags ./configure --disable-libdebuginfod --disable-debuginfod && make && sudo make install
|
||||
else
|
||||
cd ~/.cache/elfutils/elfutils-${ELFUTILS_VERSION}
|
||||
sudo make install
|
||||
fi
|
||||
eu-unstrip --version
|
||||
|
||||
- name: Install RPyC for GDB
|
||||
run: |
|
||||
|
||||
@@ -25,6 +25,7 @@ addons:
|
||||
- binutils-sparc64-linux-gnu
|
||||
- bash-static
|
||||
- python3-pip
|
||||
- elfutils
|
||||
cache:
|
||||
- pip
|
||||
- directories:
|
||||
|
||||
+19
-6
@@ -9,9 +9,10 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
|
||||
| Version | Branch | Release Date |
|
||||
| ---------------- | -------- | ---------------------- |
|
||||
| [4.9.0](#490) | `dev` |
|
||||
| [4.8.0](#480) | `beta` |
|
||||
| [4.7.1](#471) | `stable` | Apr 20, 2022
|
||||
| [4.10.0](#4100) | `dev` |
|
||||
| [4.9.0](#490) | `beta` |
|
||||
| [4.8.0](#480) | `stable` | Apr 21, 2022
|
||||
| [4.7.1](#471) | | Apr 20, 2022
|
||||
| [4.7.0](#470) | | Nov 15, 2021
|
||||
| [4.6.0](#460) | | Jul 12, 2021
|
||||
| [4.5.1](#451) | | May 30, 2021
|
||||
@@ -63,19 +64,31 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
| [3.0.0](#300) | | Aug 20, 2016
|
||||
| [2.2.0](#220) | | Jan 5, 2015
|
||||
|
||||
## 4.9.0 (`dev`)
|
||||
## 4.10.0 (`dev`)
|
||||
|
||||
|
||||
|
||||
## 4.9.0 (`beta`)
|
||||
|
||||
- [#1975][1975] Add libcdb commandline tool
|
||||
- [#1979][1979] Add `js_escape()` and `js_unescape()` to `util.fiddling`
|
||||
- [#2011][2011] Fix tube's debug output of same byte compression
|
||||
- [#2023][2023] Support KDE Konsole in run_in_new_terminal function
|
||||
- [#2027][2027] Fix ELF.libc_start_main_return with glibc 2.34
|
||||
- [#2033][2033] Quote file and core path in generated GDB script
|
||||
- [#2035][2035] Change Buffer's parent class to object
|
||||
- [#2037][2037] Allow SSH tunnel to be treated like a TCP socket (with 'raw=True')
|
||||
|
||||
[1975]: https://github.com/Gallopsled/pwntools/pull/1975
|
||||
[1979]: https://github.com/Gallopsled/pwntools/pull/1979
|
||||
[2011]: https://github.com/Gallopsled/pwntools/pull/2011
|
||||
[2023]: https://github.com/Gallopsled/pwntools/pull/2023
|
||||
[2027]: https://github.com/Gallopsled/pwntools/pull/2027
|
||||
[2033]: https://github.com/Gallopsled/pwntools/pull/2033
|
||||
[2035]: https://github.com/Gallopsled/pwntools/pull/2035
|
||||
[2037]: https://github.com/Gallopsled/pwntools/pull/2037
|
||||
|
||||
## 4.8.0 (`beta`)
|
||||
## 4.8.0 (`stable`)
|
||||
|
||||
- [#1922][1922] Fix logic in `wait_for_debugger`
|
||||
- [#1828][1828] libcdb: Load debug info and unstrip libc binary
|
||||
@@ -87,7 +100,7 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
[1939]: https://github.com/Gallopsled/pwntools/pull/1939
|
||||
[1981]: https://github.com/Gallopsled/pwntools/pull/1981
|
||||
|
||||
## 4.7.1 (`stable`)
|
||||
## 4.7.1
|
||||
|
||||
- [#1784][1784] Use temporary cache directory when persistent cache cannot be used
|
||||
- [#1973][1973] ELF symbols can be looked up by bytes values
|
||||
|
||||
@@ -16,6 +16,7 @@ RUN apt-get update \
|
||||
&& locale-gen en_US.UTF-8 \
|
||||
&& apt-get install -y \
|
||||
build-essential \
|
||||
elfutils \
|
||||
git \
|
||||
libssl-dev \
|
||||
libffi-dev \
|
||||
|
||||
+3
-3
@@ -55,8 +55,8 @@ def initialize():
|
||||
from pwnlib.log import getLogger
|
||||
log = getLogger(__name__)
|
||||
|
||||
xdg_config_home = (os.environ.get('XDG_CONFIG_HOME') or
|
||||
os.path.expanduser("~/.config"))
|
||||
xdg_config_home = os.environ.get('XDG_CONFIG_HOME',
|
||||
os.path.expanduser("~/.config"))
|
||||
|
||||
c = configparser.ConfigParser()
|
||||
c.read(['/etc/pwn.conf',
|
||||
@@ -65,7 +65,7 @@ def initialize():
|
||||
|
||||
for section in c.sections():
|
||||
if section not in registered_configs:
|
||||
log.warn("Unknown configuration section %r" % section)
|
||||
log.warn("Unknown configuration section %r", section)
|
||||
continue
|
||||
settings = dict(c.items(section))
|
||||
registered_configs[section](settings)
|
||||
@@ -979,7 +979,10 @@ class ContextType(object):
|
||||
except AttributeError: pass
|
||||
|
||||
# Otherwise, fail
|
||||
level_names = filter(lambda x: isinstance(x,str), logging._levelNames)
|
||||
try:
|
||||
level_names = logging._levelToName.values()
|
||||
except AttributeError:
|
||||
level_names = filter(lambda x: isinstance(x,str), logging._levelNames)
|
||||
permitted = sorted(level_names)
|
||||
raise AttributeError('log_level must be an integer or one of %r' % permitted)
|
||||
|
||||
|
||||
+5
-6
@@ -15,7 +15,7 @@ Example
|
||||
# leaks at least one byte at that address.
|
||||
def leak(address):
|
||||
data = p.read(address, 4)
|
||||
log.debug("%#x => %s" % (address, enhex(data or '')))
|
||||
log.debug("%#x => %s", address, enhex(data or ''))
|
||||
return data
|
||||
|
||||
# For the sake of this example, let's say that we
|
||||
@@ -62,8 +62,7 @@ from pwnlib.elf import constants
|
||||
from pwnlib.log import getLogger
|
||||
from pwnlib.memleak import MemLeak
|
||||
from pwnlib.util.fiddling import enhex
|
||||
from pwnlib.util.packing import unpack, _need_bytes
|
||||
from pwnlib.util.web import wget
|
||||
from pwnlib.util.packing import _need_bytes
|
||||
|
||||
log = getLogger(__name__)
|
||||
sizeof = ctypes.sizeof
|
||||
@@ -562,7 +561,7 @@ class DynELF(object):
|
||||
else: dynlib = self
|
||||
|
||||
if dynlib is None:
|
||||
log.failure("Could not find %r" % lib)
|
||||
log.failure("Could not find %r", lib)
|
||||
return None
|
||||
|
||||
#
|
||||
@@ -573,7 +572,7 @@ class DynELF(object):
|
||||
self.status("Trying lookup based on Build ID")
|
||||
build_id = dynlib._lookup_build_id(lib=lib)
|
||||
if build_id:
|
||||
log.info("Trying lookup based on Build ID: %s" % build_id)
|
||||
log.info("Trying lookup based on Build ID: %s", build_id)
|
||||
path = libcdb.search_by_build_id(build_id)
|
||||
if path:
|
||||
with context.local(log_level='error'):
|
||||
@@ -615,7 +614,7 @@ class DynELF(object):
|
||||
addr = leak.field(cur, LinkMap.l_addr)
|
||||
cur = leak.field(cur, LinkMap.l_next)
|
||||
|
||||
log.debug('Found %r @ %#x' % (name, addr))
|
||||
log.debug('Found %r @ %#x', name, addr)
|
||||
|
||||
self._bases[name] = addr
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (c) 2013 Pratik Kumar Sahu, Nagendra Chowdary, Anish Mathuria
|
||||
# Ported to Python by Gallopsled
|
||||
from __future__ import division
|
||||
|
||||
# +------------------------------------------------------------------------+
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (c) 2013 Pratik Kumar Sahu, Nagendra Chowdary, Anish Mathuria
|
||||
# Ported to Python by Gallopsled
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (c) 2013 Pratik Kumar Sahu, Nagendra Chowdary, Anish Mathuria
|
||||
# Ported to Python by Gallopsled
|
||||
from __future__ import division
|
||||
from __future__ import absolute_import
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (c) 2013 Pratik Kumar Sahu, Nagendra Chowdary, Anish Mathuria
|
||||
# Ported to Python by Gallopsled
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# Copyright (c) 2013 Pratik Kumar Sahu, Nagendra Chowdary, Anish Mathuria
|
||||
# Ported to Python by Gallopsled
|
||||
from __future__ import division
|
||||
|
||||
import os
|
||||
|
||||
+153
-29
@@ -12,9 +12,12 @@ import tempfile
|
||||
from pwnlib.context import context
|
||||
from pwnlib.elf import ELF
|
||||
from pwnlib.log import getLogger
|
||||
from pwnlib.tubes.process import process
|
||||
from pwnlib.util.fiddling import b64d
|
||||
from pwnlib.util.fiddling import enhex
|
||||
from pwnlib.util.fiddling import hexdump
|
||||
from pwnlib.util.misc import read
|
||||
from pwnlib.util.misc import which
|
||||
from pwnlib.util.misc import write
|
||||
from pwnlib.util.safeeval import const
|
||||
from pwnlib.util.web import wget
|
||||
@@ -22,6 +25,7 @@ from pwnlib.util.web import wget
|
||||
log = getLogger(__name__)
|
||||
|
||||
HASHES = ['build_id', 'sha1', 'sha256', 'md5']
|
||||
DEBUGINFOD_SERVERS = ['https://debuginfod.systemtap.org/']
|
||||
|
||||
# https://gitlab.com/libcdb/libcdb wasn't updated after 2019,
|
||||
# but still is a massive database of older libc binaries.
|
||||
@@ -88,29 +92,13 @@ def provider_libc_rip(hex_encoded_id, hash_type):
|
||||
|
||||
PROVIDERS = [provider_libcdb, provider_libc_rip]
|
||||
|
||||
def search_by_hash(hex_encoded_id, hash_type='build_id'):
|
||||
def search_by_hash(hex_encoded_id, hash_type='build_id', unstrip=True):
|
||||
assert hash_type in HASHES, hash_type
|
||||
|
||||
# Ensure that the libcdb cache directory exists
|
||||
cache_dir = os.path.join(context.cache_dir, 'libcdb', hash_type)
|
||||
|
||||
if not os.path.isdir(cache_dir):
|
||||
os.makedirs(cache_dir)
|
||||
|
||||
# If we already downloaded the file, and it looks even passingly like
|
||||
# a valid ELF file, return it.
|
||||
cache = os.path.join(cache_dir, hex_encoded_id)
|
||||
|
||||
if os.path.exists(cache):
|
||||
log.debug("Found existing cached libc at %r", cache)
|
||||
|
||||
data = read(cache)
|
||||
if data.startswith(b'\x7FELF'):
|
||||
log.info_once("Using cached data from %r", cache)
|
||||
return cache
|
||||
else:
|
||||
log.info_once("Skipping unavailable libc %s", hex_encoded_id)
|
||||
return None
|
||||
cache, cache_valid = _check_elf_cache('libcdb', hex_encoded_id, hash_type)
|
||||
if cache_valid:
|
||||
return cache
|
||||
|
||||
# Run through all available libc database providers to see if we have a match.
|
||||
for provider in PROVIDERS:
|
||||
@@ -128,16 +116,146 @@ def search_by_hash(hex_encoded_id, hash_type='build_id'):
|
||||
if not data or not data.startswith(b'\x7FELF'):
|
||||
return None
|
||||
|
||||
# Try to find debug info for this libc.
|
||||
if unstrip:
|
||||
unstrip_libc(cache)
|
||||
|
||||
return cache
|
||||
|
||||
def _search_debuginfo_by_hash(base_url, hex_encoded_id):
|
||||
# Deferred import because it's slow
|
||||
import requests
|
||||
from six.moves import urllib
|
||||
|
||||
def search_by_build_id(hex_encoded_id):
|
||||
# Check if we tried this buildid before.
|
||||
cache, cache_valid = _check_elf_cache('libcdb_dbg', hex_encoded_id, 'build_id')
|
||||
if cache_valid:
|
||||
return cache
|
||||
|
||||
# Try to find separate debuginfo.
|
||||
url = '/buildid/{}/debuginfo'.format(hex_encoded_id)
|
||||
url = urllib.parse.urljoin(base_url, url)
|
||||
data = b""
|
||||
log.debug("Downloading data from debuginfod: %s", url)
|
||||
try:
|
||||
data = wget(url, timeout=20)
|
||||
except requests.RequestException as e:
|
||||
log.warn_once("Failed to fetch libc debuginfo for build_id %s from %s: %s", hex_encoded_id, base_url, e)
|
||||
|
||||
# Save whatever we got to the cache
|
||||
write(cache, data or b'')
|
||||
|
||||
# Return ``None`` if we did not get a valid ELF file
|
||||
if not data or not data.startswith(b'\x7FELF'):
|
||||
log.warn_once("Could not fetch libc debuginfo for build_id %s from %s", hex_encoded_id, base_url)
|
||||
return None
|
||||
|
||||
return cache
|
||||
|
||||
def _check_elf_cache(cache_type, hex_encoded_id, hash_type):
|
||||
"""
|
||||
Check if there already is an ELF file for this hash in the cache.
|
||||
|
||||
>>> cache, _ = _check_elf_cache('libcdb', '2d1c5e0b85cb06ff47fa6fa088ec22cb6e06074e', 'build_id')
|
||||
>>> os.unlink(cache) if os.path.exists(cache)
|
||||
>>> filename = search_by_hash('2d1c5e0b85cb06ff47fa6fa088ec22cb6e06074e', 'build_id', unstrip=False)
|
||||
>>> hex(ELF(filename).symbols.read)
|
||||
'0xe56c0'
|
||||
>>> filename == cache
|
||||
True
|
||||
"""
|
||||
# Ensure that the cache directory exists
|
||||
cache_dir = os.path.join(context.cache_dir, cache_type, hash_type)
|
||||
|
||||
if not os.path.isdir(cache_dir):
|
||||
os.makedirs(cache_dir)
|
||||
|
||||
# If we already downloaded the file, and it looks even passingly like
|
||||
# a valid ELF file, return it.
|
||||
cache = os.path.join(cache_dir, hex_encoded_id)
|
||||
|
||||
if not os.path.exists(cache):
|
||||
return cache, False
|
||||
|
||||
log.debug("Found existing cached ELF at %r", cache)
|
||||
|
||||
data = read(cache)
|
||||
if not data.startswith(b'\x7FELF'):
|
||||
log.info_once("Skipping unavailable ELF %s", hex_encoded_id)
|
||||
return cache, False
|
||||
|
||||
log.info_once("Using cached data from %r", cache)
|
||||
return cache, True
|
||||
|
||||
def unstrip_libc(filename):
|
||||
"""
|
||||
Given a path to a libc binary, attempt to download matching debug info
|
||||
and add them back to the given binary.
|
||||
|
||||
This modifies the given file.
|
||||
|
||||
Arguments:
|
||||
filename(str):
|
||||
Path to the libc binary to unstrip.
|
||||
|
||||
Returns:
|
||||
:const:`True` if binary was unstripped, :const:`False` otherwise.
|
||||
|
||||
Examples:
|
||||
>>> filename = search_by_build_id('2d1c5e0b85cb06ff47fa6fa088ec22cb6e06074e', unstrip=False)
|
||||
>>> libc = ELF(filename)
|
||||
>>> hex(libc.symbols.read)
|
||||
'0xe56c0'
|
||||
>>> 'main_arena' in libc.symbols
|
||||
False
|
||||
>>> unstrip_libc(filename)
|
||||
True
|
||||
>>> libc = ELF(filename)
|
||||
>>> hex(libc.symbols.main_arena)
|
||||
'0x1d57a0'
|
||||
>>> unstrip_libc(which('python'))
|
||||
False
|
||||
>>> filename = search_by_build_id('06a8004be6e10c4aeabbe0db74423ace392a2d6b', unstrip=True)
|
||||
>>> 'main_arena' in ELF(filename).symbols
|
||||
True
|
||||
"""
|
||||
if not which('eu-unstrip'):
|
||||
log.warn_once('Couldn\'t find "eu-unstrip" in PATH. Install elfutils first.')
|
||||
return False
|
||||
|
||||
libc = ELF(filename, checksec=False)
|
||||
if not libc.buildid:
|
||||
log.warn_once('Given libc does not have a buildid. Cannot look for debuginfo to unstrip.')
|
||||
return False
|
||||
|
||||
for server_url in DEBUGINFOD_SERVERS:
|
||||
libc_dbg = _search_debuginfo_by_hash(server_url, enhex(libc.buildid))
|
||||
if libc_dbg:
|
||||
break
|
||||
else:
|
||||
log.warn_once('Couldn\'t find debug info for libc with build_id %s on any debuginfod server.', enhex(libc.buildid))
|
||||
return False
|
||||
|
||||
# Add debug info to given libc binary inplace.
|
||||
p = process(['eu-unstrip', '-o', filename, filename, libc_dbg])
|
||||
output = p.recvall()
|
||||
p.close()
|
||||
|
||||
if output:
|
||||
log.error('Failed to unstrip libc binary: %r', output)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def search_by_build_id(hex_encoded_id, unstrip=True):
|
||||
"""
|
||||
Given a hex-encoded Build ID, attempt to download a matching libc from libcdb.
|
||||
|
||||
Arguments:
|
||||
hex_encoded_id(str):
|
||||
Hex-encoded Build ID (e.g. 'ABCDEF...') of the library
|
||||
unstrip(bool):
|
||||
Try to fetch debug info for the libc and apply it to the downloaded file.
|
||||
|
||||
Returns:
|
||||
Path to the downloaded library on disk, or :const:`None`.
|
||||
@@ -152,15 +270,17 @@ def search_by_build_id(hex_encoded_id):
|
||||
>>> hex(ELF(filename).symbols.read)
|
||||
'0xeef40'
|
||||
"""
|
||||
return search_by_hash(hex_encoded_id, 'build_id')
|
||||
return search_by_hash(hex_encoded_id, 'build_id', unstrip)
|
||||
|
||||
def search_by_md5(hex_encoded_id):
|
||||
def search_by_md5(hex_encoded_id, unstrip=True):
|
||||
"""
|
||||
Given a hex-encoded md5sum, attempt to download a matching libc from libcdb.
|
||||
|
||||
Arguments:
|
||||
hex_encoded_id(str):
|
||||
Hex-encoded md5sum (e.g. 'ABCDEF...') of the library
|
||||
unstrip(bool):
|
||||
Try to fetch debug info for the libc and apply it to the downloaded file.
|
||||
|
||||
Returns:
|
||||
Path to the downloaded library on disk, or :const:`None`.
|
||||
@@ -175,15 +295,17 @@ def search_by_md5(hex_encoded_id):
|
||||
>>> hex(ELF(filename).symbols.read)
|
||||
'0xeef40'
|
||||
"""
|
||||
return search_by_hash(hex_encoded_id, 'md5')
|
||||
return search_by_hash(hex_encoded_id, 'md5', unstrip)
|
||||
|
||||
def search_by_sha1(hex_encoded_id):
|
||||
def search_by_sha1(hex_encoded_id, unstrip=True):
|
||||
"""
|
||||
Given a hex-encoded sha1, attempt to download a matching libc from libcdb.
|
||||
|
||||
Arguments:
|
||||
hex_encoded_id(str):
|
||||
Hex-encoded sha1sum (e.g. 'ABCDEF...') of the library
|
||||
unstrip(bool):
|
||||
Try to fetch debug info for the libc and apply it to the downloaded file.
|
||||
|
||||
Returns:
|
||||
Path to the downloaded library on disk, or :const:`None`.
|
||||
@@ -198,16 +320,18 @@ def search_by_sha1(hex_encoded_id):
|
||||
>>> hex(ELF(filename).symbols.read)
|
||||
'0xeef40'
|
||||
"""
|
||||
return search_by_hash(hex_encoded_id, 'sha1')
|
||||
return search_by_hash(hex_encoded_id, 'sha1', unstrip)
|
||||
|
||||
|
||||
def search_by_sha256(hex_encoded_id):
|
||||
def search_by_sha256(hex_encoded_id, unstrip=True):
|
||||
"""
|
||||
Given a hex-encoded sha256, attempt to download a matching libc from libcdb.
|
||||
|
||||
Arguments:
|
||||
hex_encoded_id(str):
|
||||
Hex-encoded sha256sum (e.g. 'ABCDEF...') of the library
|
||||
unstrip(bool):
|
||||
Try to fetch debug info for the libc and apply it to the downloaded file.
|
||||
|
||||
Returns:
|
||||
Path to the downloaded library on disk, or :const:`None`.
|
||||
@@ -222,7 +346,7 @@ def search_by_sha256(hex_encoded_id):
|
||||
>>> hex(ELF(filename).symbols.read)
|
||||
'0xeef40'
|
||||
"""
|
||||
return search_by_hash(hex_encoded_id, 'sha256')
|
||||
return search_by_hash(hex_encoded_id, 'sha256', unstrip)
|
||||
|
||||
|
||||
|
||||
@@ -279,4 +403,4 @@ def get_build_id_offsets():
|
||||
}.get(context.arch, [])
|
||||
|
||||
|
||||
__all__ = ['get_build_id_offsets', 'search_by_build_id', 'search_by_sha1', 'search_by_sha256', 'search_by_md5']
|
||||
__all__ = ['get_build_id_offsets', 'search_by_build_id', 'search_by_sha1', 'search_by_sha256', 'search_by_md5', 'unstrip_libc']
|
||||
+2
-2
@@ -1477,8 +1477,6 @@ class ROP(object):
|
||||
# Find an appropriate, non-library ELF.
|
||||
# Prioritise non-PIE binaries so we can use _fini
|
||||
exes = (elf for elf in self.elfs if not elf.library and elf.bits == 64)
|
||||
if not exes:
|
||||
log.error('No non-library binaries in [elfs]')
|
||||
|
||||
nonpie = csu = None
|
||||
for elf in exes:
|
||||
@@ -1488,6 +1486,8 @@ class ROP(object):
|
||||
nonpie = elf
|
||||
elif '__libc_csu_init' in elf.symbols:
|
||||
csu = elf
|
||||
else:
|
||||
log.error('No non-library binaries in [elfs]')
|
||||
|
||||
if elf.pie:
|
||||
if nonpie:
|
||||
|
||||
@@ -1820,6 +1820,9 @@ from ctypes import *; libc = CDLL('libc.so.6'); print(libc.getenv(%r))
|
||||
symlink = os.path.join(self.pwd(), b'*')
|
||||
if not hasattr(symlink, 'encode') and hasattr(symlink, 'decode'):
|
||||
symlink = symlink.decode('utf-8')
|
||||
|
||||
if isinstance(wd, six.text_type):
|
||||
wd = packing._need_bytes(wd, 2, 0x80)
|
||||
|
||||
if not wd:
|
||||
wd, status = self.run_to_end('x=$(mktemp -d) && cd $x && chmod +x . && echo $PWD', wd='.')
|
||||
|
||||
+32
-4
@@ -197,6 +197,16 @@ def cyclic_find(subseq, alphabet = None, n = None):
|
||||
>>> cyclic_find(0x61616162, endian='big')
|
||||
1
|
||||
|
||||
Similarly to the case where you can provide a bytes value that is longer
|
||||
than four bytes, you can provided an integer value that is larger than
|
||||
what can be held in four bytes. If such a large value is given, it is
|
||||
automatically truncated.
|
||||
|
||||
>>> cyclic_find(0x6161616361616162)
|
||||
4
|
||||
>>> cyclic_find(0x6261616163616161, endian='big')
|
||||
4
|
||||
|
||||
You can use anything for the cyclic pattern, including non-printable
|
||||
characters.
|
||||
|
||||
@@ -208,14 +218,32 @@ def cyclic_find(subseq, alphabet = None, n = None):
|
||||
n = context.cyclic_size
|
||||
|
||||
if isinstance(subseq, six.integer_types):
|
||||
if subseq >= 2**(8*n):
|
||||
# Assumption: The user has given an integer that is more than 2**(8n) bits, but would otherwise fit within
|
||||
# a register of size 2**(8m) where m is a multiple of four
|
||||
notice = ("cyclic_find() expected an integer argument <= {cap:#x}, you gave {gave:#x}\n"
|
||||
"Unless you specified cyclic(..., n={fits}), you probably just want the first {n} bytes.\n"
|
||||
"Truncating the data at {n} bytes. Specify cyclic_find(..., n={fits}) to override this.").format(
|
||||
cap=2**(8*n)-1,
|
||||
gave=subseq,
|
||||
# The number of bytes needed to represent subseq, rounded to the next 4
|
||||
fits=int(round(float(subseq.bit_length()) / 32 + 0.5) * 32) // 8,
|
||||
n=n,
|
||||
)
|
||||
log.warn_once(notice)
|
||||
if context.endian == 'little':
|
||||
subseq &= 2**(8*n) - 1
|
||||
else:
|
||||
while subseq >= 2**(8*n):
|
||||
subseq >>= 8*n
|
||||
subseq = packing.pack(subseq, bytes=n)
|
||||
subseq = packing._need_bytes(subseq, 2, 0x80)
|
||||
|
||||
if len(subseq) != n:
|
||||
log.warn_once("cyclic_find() expects %i-byte subsequences by default, you gave %r\n"
|
||||
"Unless you specified cyclic(..., n=%i), you probably just want the first 4 bytes.\n"
|
||||
"Truncating the data at 4 bytes. Specify cyclic_find(..., n=%i) to override this.",
|
||||
n, subseq, len(subseq), len(subseq))
|
||||
log.warn_once("cyclic_find() expected a %i-byte subsequence, you gave %r\n"
|
||||
"Unless you specified cyclic(..., n=%i), you probably just want the first %d bytes.\n"
|
||||
"Truncating the data at %d bytes. Specify cyclic_find(..., n=%i) to override this.",
|
||||
n, subseq, len(subseq), n, n, len(subseq))
|
||||
subseq = subseq[:n]
|
||||
|
||||
if alphabet is None:
|
||||
|
||||
+6
-6
@@ -100,13 +100,13 @@ def size(n, abbrev = 'B', si = False):
|
||||
|
||||
return '%.02fP%s' % (n / base, abbrev)
|
||||
|
||||
KB = 1024
|
||||
MB = 1024 * KB
|
||||
GB = 1024 * MB
|
||||
KB = 1000
|
||||
MB = 1000 * KB
|
||||
GB = 1000 * MB
|
||||
|
||||
KiB = 1000
|
||||
MiB = 1000 * KB
|
||||
GiB = 1000 * MB
|
||||
KiB = 1024
|
||||
MiB = 1024 * KiB
|
||||
GiB = 1024 * MiB
|
||||
|
||||
def read(path, count=-1, skip=0):
|
||||
r"""read(path, count=-1, skip=0) -> str
|
||||
|
||||
+4
-5
@@ -333,9 +333,9 @@ def wait_for_debugger(pid, debugger_pid=None):
|
||||
t = Timeout()
|
||||
with t.countdown(timeout=15):
|
||||
with log.waitfor('Waiting for debugger') as l:
|
||||
while debugger_pid:
|
||||
debugger = psutil.Process(debugger_pid)
|
||||
while t.timeout and tracer(pid) is None:
|
||||
while t.timeout and tracer(pid) is None:
|
||||
if debugger_pid:
|
||||
debugger = psutil.Process(debugger_pid)
|
||||
try:
|
||||
debugger.wait(0.01)
|
||||
except psutil.TimeoutExpired:
|
||||
@@ -343,8 +343,7 @@ def wait_for_debugger(pid, debugger_pid=None):
|
||||
else:
|
||||
debugger_pid = 0
|
||||
break
|
||||
else:
|
||||
while t.timeout and tracer(pid) is None:
|
||||
else:
|
||||
time.sleep(0.01)
|
||||
|
||||
if tracer(pid):
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
__version__ = '4.7.1'
|
||||
__version__ = '4.8.0'
|
||||
Reference in new issue
Block a user