Compare commits

...
19 Commits
Author SHA1 Message Date
Arusekk 493a3e3d92 Release 4.8.0 2022-04-21 01:05:15 +02:00
Arusekk f491bc6a22 Merge branch 'stable' into beta 2022-04-20 15:46:34 +02:00
peace-maker 2198b74df9 Fix CI after Groovy Gorilla went away for libc unstrip test (#2025)
* Fix CI after Groovy Gorilla went away for libc unstrip test

Build elfutils 0.181 from source since we can't use builds
from a newer ubuntu version anymore.

* Install python wheels in CI
2022-02-01 11:07:39 +01:00
Arusekk 9d8060496c Release 4.8.0beta0 2021-11-15 12:44:33 +01:00
Arusekk 7ea1f1d492 Merge branch 'beta' into dev 2021-11-15 12:25:01 +01:00
Arusekk da8bf2667d Fix CI failures (#1997)
Ubuntu, why are you doing this to us?
I seriously mean that Ubuntu is the most silly distro.

Like, they probably updated their docker (or VM) images last week,
then Github got it, and we started getting failures.
They totally changed the behaviour of that 'apport' thing,
and it now drops core files in /var/lib/apport/coredump
instead of the current working directory.

Why is that even... ugh.  Nevermind.  It works now, at least.
But for how long?
2021-11-15 12:14:18 +01:00
Arusekk a37bce2bdc Display nice error message on unavailable ret2csu (#1991)
Fixes #1941
2021-11-14 15:20:59 +01:00
Arusekk 3dd0b24cc3 Add cat2 to shellcraft (#1995)
* Introduce shellcraft.linux.cat2 to avoid sendfile

Fixes #1871

* Switch CAT_PROC_MAPS_EXIT to shellcraft.linux.cat2
2021-11-14 15:20:43 +01:00
Arusekk a8c8c28f00 Fix CI failures (#1994)
* Try to fix build failures by updating sphinx

See sphinx-doc/sphinx#9811

* Does not work with py2, so pin old docutils
2021-11-11 17:53:45 +01:00
Justin Steven 315a462603 Make cyclic_find work with large int values (#1981)
* Make cyclic_find work with large int values

* Add entry for cyclic_find() large int fix

* Tweak cyclic_find() large int warning
2021-11-11 14:59:05 +01:00
ElJeffeandArusekk ddeddd455e Fix: TypeError: can't concat str to bytes (#1953)
* Fix: TypeError: can't concat str to bytes

sh_string returns a string, but two lines try to concat it with bytes, which throws a TypeError.  Either convert them all to bytes or all to string.

* Update to use packing._need_bytes

I just followed the format from surrounding conversions.  Hopefully that works correctly.

* Update pwnlib/tubes/ssh.py

Co-authored-by: Arusekk <[email protected]>

* Conversion to bytes

* Going for higher level conversion

Co-authored-by: Arusekk <[email protected]>
2021-11-01 00:35:10 +01:00
Alan Yee d3140ed983 Using native features of built-in functions over built-in operations config.py (#1980)
Use lazy logging and use second argument of `.get()` instead of relying on `or`
2021-11-01 00:33:32 +01:00
Arusekk fc250a33a1 Add missing copyright notice to ARM alphanumeric (#1955)
Closes #1954
2021-10-07 09:33:34 +02:00
peace-makerandArusekk 92911cbabd libcdb: Load debug info and unstrip libc binary (#1828)
* libcdb: Load debug info and unstrip libc binary

The debug info is obtained from a debuginfod server maintained by systemtap.org. elfutils is used to unstrip the binary and merge the debug info back.

Try to unstrip every libc binary downloaded by the libcdb module by default. #1818

* Install elfutils on CI

* Update CHANGELOG.md

* Add more tests

* Fix negative test

* Raise an exception when eu-unstrip fails

This will hopefully get logged during doctests.

* Install elfutils 0.181 from groovy

Use APT Pinning to select the newer elfutils version from groovy instead of the buggy 0.176 version available in focal.

* Fix missing import of requests

pylint?

Co-authored-by: Arusekk <[email protected]>
2021-10-03 10:51:30 +02:00
Alan Yee a9715d8c74 Use lazy logging instead of native string interpolation (#1972)
https://docs.python.org/3/howto/logging.html#logging-variable-data
2021-10-01 07:48:57 +02:00
Darin Mao bd12d1874f Fix KB, MB, GB globals (#1926) 2021-07-29 19:17:17 +02:00
clubby789 11b8537d17 Fix validation of log level name for Python 3 (#1939)
* Fix validation of log level name for Python 3

* Add changelog

* Reorder changelog and use try/except
2021-07-29 19:16:36 +02:00
Connor NelsonandArusekk f7283bf2eb Fix logic in wait_for_debugger (#1922)
* Fix logic in `wait_for_debugger`

* Update CHANGELOG.md

* Fix CHANGELOG.md

* Fix CHANGELOG.md

Co-authored-by: Arusekk <[email protected]>
2021-07-15 11:42:42 +02:00
Arusekk d5d7b8385c Begin working on 4.8.0 2021-07-12 23:06:17 +02:00
20 changed files with 270 additions and 64 deletions

No files matched your search

+25
View File
@@ -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: |
+1
View File
@@ -25,6 +25,7 @@ addons:
- binutils-sparc64-linux-gnu
- bash-static
- python3-pip
- elfutils
cache:
- pip
- directories:
+19 -6
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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)
+4 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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:
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1 +1 @@
__version__ = '4.7.1'
__version__ = '4.8.0'
+1 -1
View File
@@ -89,7 +89,7 @@ setup(
name = 'pwntools',
python_requires = '>=2.7',
packages = find_packages(),
version = '4.7.1',
version = '4.8.0',
data_files = [('pwntools-doc',
glob.glob('*.md') + glob.glob('*.txt')),
],