mirror of
https://github.com/Gallopsled/pwntools.git
synced 2026-11-09 10:09:36 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df7c1fef9d | ||
|
|
b234b319df | ||
|
|
91768424ba | ||
|
|
af2f8b4bf4 | ||
|
|
ab0ac00c73 | ||
|
|
d87ab3ac65 | ||
|
|
23cd5cb819 | ||
|
|
bb25140807 | ||
|
|
92ad1a4933 | ||
|
|
3e163e9cf2 | ||
|
|
267c6cc15a | ||
|
|
c438893d7e | ||
|
|
1a94acab67 | ||
|
|
a344047348 | ||
|
|
4aa96b48ba | ||
|
|
901f3eddb1 | ||
|
|
5936d0f565 | ||
|
|
08b316098b | ||
|
|
a27cb1c168 | ||
|
|
d923729dfb | ||
|
|
db75ecb897 |
No files matched your search
@@ -4,6 +4,11 @@ Thanks for contributing to Pwntools!
|
||||
|
||||
When reporting an issue, be sure that you are running the latest released version of pwntools (`pip install --upgrade pwntools`).
|
||||
|
||||
Please verify that your issue occurs on 64-bit Ubuntu 14.04. You can use the Dockerfile in `extra/docker/Dockerfile` to save time.
|
||||
Please verify that your issue occurs on 64-bit Ubuntu 14.04. You can use the Dockerfile on `docker.io` for quick testing.
|
||||
|
||||
```
|
||||
$ docker pull pwntools/pwntools:stable
|
||||
$ docker run -it pwntools/pwntools:stable
|
||||
```
|
||||
|
||||
If possible, provide a proof-of-concept which demonstrates the problem. Include any binaries or scripts necessary to reproduce the issue, and please include the full debug output via setting the environment variable `PWNLIB_DEBUG=1`.
|
||||
+3
-4
@@ -1,10 +1,9 @@
|
||||
sudo: false
|
||||
dist: precise
|
||||
language: python
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-multilib
|
||||
- gcc-4.6-arm-linux-gnueabihf
|
||||
- lib32stdc++6
|
||||
- ash
|
||||
- bash
|
||||
@@ -18,8 +17,8 @@ cache:
|
||||
- pip
|
||||
- directories:
|
||||
- usr
|
||||
- /home/travis/virtualenv/python2.7.9/lib/python2.7/site-packages/
|
||||
- /home/travis/virtualenv/python2.7.9/bin/
|
||||
- /home/travis/virtualenv/python2.7.13/lib/python2.7/site-packages/
|
||||
- /home/travis/virtualenv/python2.7.13/bin/
|
||||
python:
|
||||
- "2.7"
|
||||
before_install:
|
||||
|
||||
+34
-5
@@ -9,9 +9,12 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
|
||||
| Version | Branch | Release Date |
|
||||
| ---------------- | -------- | ---------------------- |
|
||||
| [3.10.0](#3100) | `dev` | Oct 21, 2017 (planned)
|
||||
| [3.9.0](#390) | `beta` | Sep 9, 2017 (planned)
|
||||
| [3.8.0](#380) | `stable` | Jul 29, 2017
|
||||
| [3.11.0](#3110) | `dev` | Dec 2, 2017 (planned)
|
||||
| [3.10.0](#3100) | `beta` | Oct 21, 2017 (planned)
|
||||
| [3.9.2](#392) | `stable` | Oct 5, 2017
|
||||
| [3.9.1](#391) | | Sep 28, 2017
|
||||
| [3.9.0](#390) | | Sep 11, 2017
|
||||
| [3.8.0](#380) | | Jul 29, 2017
|
||||
| [3.7.1](#371) | | Jul 14, 2017
|
||||
| [3.7.0](#370) | | Jun 19, 2017
|
||||
| [3.6.1](#361) | | May 12, 2017
|
||||
@@ -36,13 +39,39 @@ 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
|
||||
|
||||
## 3.11.0
|
||||
|
||||
To be released on Dec 2, 2017.
|
||||
|
||||
## 3.10.0
|
||||
|
||||
To be released on Sep 8, 2017.
|
||||
To be released on Oct 21, 2017.
|
||||
|
||||
## 3.9.2
|
||||
|
||||
- [#1043][1043] Do not attempt to populate the libraries used by statically-linked binaries
|
||||
|
||||
[1043]: https://github.com/Gallopsled/pwntools/pull/1043
|
||||
|
||||
## 3.9.1
|
||||
|
||||
- [#1038][1038] Fix an issue with `process()` where glibc would buffer data internally, causing a hang on `select()`
|
||||
- [#1036][1036] Fix Travis CI logging verbosity
|
||||
- [#1029][1029] Fix some `unicode` issues when using the `readline` command history in `tube.interactive()`
|
||||
|
||||
[1038]: https://github.com/Gallopsled/pwntools/pull/1038
|
||||
[1036]: https://github.com/Gallopsled/pwntools/pull/1036
|
||||
[1029]: https://github.com/Gallopsled/pwntools/pull/1029
|
||||
|
||||
## 3.9.0
|
||||
|
||||
To be released on Sep 8, 2017.
|
||||
- [#1003][1003] Make `concat_all` faster while also simplifying it's logic
|
||||
- [#1014][1014] Fix for overwritten env when parsing core file
|
||||
- [#1023][1023] Fixes to Travis CI
|
||||
|
||||
[1003]: https://github.com/Gallopsled/pwntools/pull/1003
|
||||
[1014]: https://github.com/Gallopsled/pwntools/pull/1014
|
||||
[1023]: https://github.com/Gallopsled/pwntools/pull/1023
|
||||
|
||||
## 3.8.0
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||

|
||||
|
||||
[](https://docs.pwntools.com/)
|
||||
[](https://pypi.python.org/pypi/pwntools/)
|
||||
[](https://pypi.python.org/pypi/pwntools/)
|
||||
[](https://travis-ci.org/Gallopsled/pwntools)
|
||||
[](https://coveralls.io/github/Gallopsled/pwntools?branch=dev)
|
||||
[](https://twitter.com/pwntools)
|
||||
|
||||
@@ -44,6 +44,23 @@ extensions = [
|
||||
'sphinxcontrib.napoleon'
|
||||
]
|
||||
|
||||
# Disable "info" logging directly to stdout by Sphinx
|
||||
import logging
|
||||
|
||||
class SphinxPwnlibFilter(logging.Filter):
|
||||
def filter(self, record):
|
||||
if record.name.startswith('pwn'):
|
||||
return False
|
||||
if record.name.startswith('paramiko'):
|
||||
return False
|
||||
return True
|
||||
|
||||
log_filter = SphinxPwnlibFilter()
|
||||
|
||||
for i, handler in enumerate(logging.root.handlers):
|
||||
print("Filtering Sphinx handler", handler)
|
||||
handler.addFilter(log_filter)
|
||||
|
||||
# Napoleon settings
|
||||
napoleon_use_ivar = True
|
||||
napoleon_use_rtype = False
|
||||
|
||||
+18
-16
@@ -417,7 +417,7 @@ class DynELF(object):
|
||||
def _find_linkmap(self, pltgot=None, debug=None):
|
||||
"""
|
||||
The linkmap is a chained structure created by the loader at runtime
|
||||
which contains information on the names and load addresses osf all
|
||||
which contains information on the names and load addresses of all
|
||||
libraries.
|
||||
|
||||
For non-RELRO binaries, a pointer to this is stored in the .got.plt
|
||||
@@ -431,7 +431,7 @@ class DynELF(object):
|
||||
Got = {32: elf.Elf_i386_GOT, 64: elf.Elf_x86_64_GOT}[self.elfclass]
|
||||
r_debug = {32: elf.Elf32_r_debug, 64: elf.Elf64_r_debug}[self.elfclass]
|
||||
|
||||
result = None
|
||||
linkmap = None
|
||||
|
||||
if not pltgot:
|
||||
w.status("Finding linkmap: DT_PLTGOT")
|
||||
@@ -439,24 +439,24 @@ class DynELF(object):
|
||||
|
||||
if pltgot:
|
||||
w.status("GOT.linkmap")
|
||||
result = self.leak.field(pltgot, Got.linkmap)
|
||||
w.status("GOT.linkmap %#x" % result)
|
||||
linkmap = self.leak.field(pltgot, Got.linkmap)
|
||||
w.status("GOT.linkmap %#x" % linkmap)
|
||||
|
||||
if not result:
|
||||
if not linkmap:
|
||||
debug = debug or self._find_dt(constants.DT_DEBUG)
|
||||
if debug:
|
||||
w.status("r_debug.linkmap")
|
||||
result = self.leak.field(debug, r_debug.r_map)
|
||||
linkmap = self.leak.field(debug, r_debug.r_map)
|
||||
w.status("r_debug.linkmap %#x" % result)
|
||||
|
||||
if not (pltgot or debug):
|
||||
if not linkmap:
|
||||
w.failure("Could not find DT_PLTGOT or DT_DEBUG")
|
||||
return None
|
||||
|
||||
result = self._make_absolute_ptr(result)
|
||||
linkmap = self._make_absolute_ptr(linkmap)
|
||||
|
||||
w.success('%#x' % result)
|
||||
return result
|
||||
w.success('%#x' % linkmap)
|
||||
return linkmap
|
||||
|
||||
def waitfor(self, msg):
|
||||
if not self._waitfor:
|
||||
@@ -523,6 +523,7 @@ class DynELF(object):
|
||||
|
||||
Arguments:
|
||||
symb(str): Named routine to look up
|
||||
If omitted, the base address of the library will be returned.
|
||||
lib(str): Substring to match for the library name.
|
||||
If omitted, the current library is searched.
|
||||
If set to ``'libc'``, ``'libc.so'`` is assumed.
|
||||
@@ -566,7 +567,6 @@ class DynELF(object):
|
||||
# Try a quick lookup by build ID
|
||||
self.status("Trying lookup based on Build ID")
|
||||
build_id = dynlib._lookup_build_id(lib=lib)
|
||||
result = None
|
||||
if build_id:
|
||||
log.info("Trying lookup based on Build ID: %s" % build_id)
|
||||
path = libcdb.search_by_build_id(build_id)
|
||||
@@ -575,11 +575,10 @@ class DynELF(object):
|
||||
e = ELF(path)
|
||||
e.address = dynlib.libbase
|
||||
result = e.symbols[symb]
|
||||
|
||||
if not result:
|
||||
self.status("Trying remote lookup")
|
||||
result = dynlib._lookup(symb)
|
||||
else:
|
||||
if symb and not result:
|
||||
self.status("Trying remote lookup")
|
||||
result = dynlib._lookup(symb)
|
||||
if not symb:
|
||||
result = dynlib.libbase
|
||||
|
||||
#
|
||||
@@ -839,6 +838,9 @@ class DynELF(object):
|
||||
def _lookup_build_id(self, lib = None):
|
||||
|
||||
libbase = self.libbase
|
||||
if not self.link_map:
|
||||
self.status("No linkmap found")
|
||||
return None
|
||||
|
||||
if lib is not None:
|
||||
libbase = self.lookup(symb = None, lib = lib)
|
||||
|
||||
@@ -545,7 +545,7 @@ class Corefile(ELF):
|
||||
log.warn('Could not find the stack!')
|
||||
self.stack = None
|
||||
|
||||
with context.local(bytes=self.bytes, log_level='error'):
|
||||
with context.local(bytes=self.bytes, log_level='warn'):
|
||||
try:
|
||||
self._parse_stack()
|
||||
except ValueError:
|
||||
@@ -826,6 +826,10 @@ class Corefile(ELF):
|
||||
# find a pointer to this address, followed by a NULL.
|
||||
last_env_addr = address + 1
|
||||
p_last_env_addr = stack.find(pack(last_env_addr), None, last_env_addr)
|
||||
if p_last_env_addr < 0:
|
||||
# Something weird is happening. Just don't touch it.
|
||||
log.warn_once("Found bad environment at %#x", last_env_addr)
|
||||
return
|
||||
|
||||
# Sanity check that we did correctly find the envp NULL terminator.
|
||||
envp_nullterm = p_last_env_addr+context.bytes
|
||||
|
||||
+12
-1
@@ -55,6 +55,7 @@ from elftools.elf.enums import ENUM_P_TYPE
|
||||
from elftools.elf.gnuversions import GNUVerDefSection
|
||||
from elftools.elf.relocation import RelocationSection
|
||||
from elftools.elf.sections import SymbolTableSection
|
||||
from elftools.elf.segments import InterpSegment
|
||||
|
||||
import intervaltree
|
||||
|
||||
@@ -605,10 +606,20 @@ class ELF(ELFFile):
|
||||
>>> any(map(lambda x: 'libc' in x, bash.libs.keys()))
|
||||
True
|
||||
"""
|
||||
if not self.get_section_by_name('.dynamic'):
|
||||
|
||||
# We need a .dynamic section for dynamically linked libraries
|
||||
if not self.get_section_by_name('.dynamic') or self.statically_linked:
|
||||
self.libs= {}
|
||||
return
|
||||
|
||||
# We must also specify a 'PT_INTERP', otherwise it's a 'statically-linked'
|
||||
# binary which is also position-independent (and as such has a .dynamic).
|
||||
for segment in self.iter_segments_by_type('PT_INTERP'):
|
||||
break
|
||||
else:
|
||||
self.libs = {}
|
||||
return
|
||||
|
||||
try:
|
||||
cmd = 'ulimit -s unlimited; LD_TRACE_LOADED_OBJECTS=1 LD_WARN=1 LD_BIND_NOW=1 %s 2>/dev/null' % sh_string(self.path)
|
||||
|
||||
|
||||
@@ -1,8 +1,2 @@
|
||||
<%docstring>A trap instruction.</%docstring>
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mov r0, 12
|
||||
mov r1, sp
|
||||
BKPT 0xab
|
||||
B .
|
||||
BKPT
|
||||
@@ -24,7 +24,7 @@ Examples:
|
||||
'Hello'
|
||||
|
||||
>>> l = listen(fam='ipv6', timeout=5)
|
||||
>>> assembly = shellcraft.i386.linux.connect('ip6-localhost', l.lport, 'ipv6')
|
||||
>>> assembly = shellcraft.i386.linux.connect('::1', l.lport, 'ipv6')
|
||||
>>> p = run_assembly(assembly)
|
||||
>>> assert l.wait_for_connection()
|
||||
|
||||
|
||||
+20
-10
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python2
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
|
||||
from pwnlib.term import keyconsts as kc
|
||||
@@ -7,7 +9,7 @@ from pwnlib.term import text
|
||||
|
||||
cursor = text.reverse
|
||||
|
||||
buffer_left, buffer_right = u'', u''
|
||||
buffer_left, buffer_right = '', ''
|
||||
saved_buffer = None
|
||||
history = []
|
||||
history_idx = None
|
||||
@@ -29,6 +31,14 @@ suggest_hook = None
|
||||
|
||||
tabs = 0
|
||||
|
||||
def force_to_bytes(data):
|
||||
if isinstance(data, bytes):
|
||||
return data
|
||||
try:
|
||||
return data.encode('utf-8')
|
||||
except Exception:
|
||||
return data.encode('latin-1')
|
||||
|
||||
def set_completer(completer):
|
||||
global complete_hook, suggest_hook
|
||||
if completer is None:
|
||||
@@ -80,7 +90,7 @@ def handle_keypress(trace):
|
||||
|
||||
def clear():
|
||||
global buffer_left, buffer_right, history_idx, search_idx
|
||||
buffer_left, buffer_right = u'', u''
|
||||
buffer_left, buffer_right = '', ''
|
||||
history_idx = None
|
||||
search_idx = None
|
||||
redisplay()
|
||||
@@ -141,7 +151,7 @@ def cancel_search(*_):
|
||||
def commit_search():
|
||||
global search_idx
|
||||
if search_idx is not None and search_results:
|
||||
set_buffer(history[search_results[search_idx][0]], u'')
|
||||
set_buffer(history[search_results[search_idx][0]], '')
|
||||
search_idx = None
|
||||
redisplay()
|
||||
|
||||
@@ -169,7 +179,7 @@ def update_search_results():
|
||||
def search_history(*_):
|
||||
global buffer_left, buffer_right, history_idx, search_idx
|
||||
if search_idx is None:
|
||||
buffer_left, buffer_right = buffer_left + buffer_right, u''
|
||||
buffer_left, buffer_right = buffer_left + buffer_right, ''
|
||||
history_idx = None
|
||||
search_idx = 0
|
||||
update_search_results()
|
||||
@@ -187,7 +197,7 @@ def history_prev(*_):
|
||||
history_idx = -1
|
||||
if history_idx < len(history) - 1:
|
||||
history_idx += 1
|
||||
set_buffer(history[history_idx], u'')
|
||||
set_buffer(history[history_idx], '')
|
||||
|
||||
def history_next(*_):
|
||||
global history_idx, saved_buffer
|
||||
@@ -200,7 +210,7 @@ def history_next(*_):
|
||||
saved_buffer = None
|
||||
else:
|
||||
history_idx -= 1
|
||||
set_buffer(history[history_idx], u'')
|
||||
set_buffer(history[history_idx], '')
|
||||
|
||||
def backward_char(*_):
|
||||
global buffer_left, buffer_right
|
||||
@@ -319,11 +329,11 @@ def forward_word(*_):
|
||||
|
||||
def go_beginning(*_):
|
||||
commit_search()
|
||||
set_buffer(u'', buffer_left + buffer_right)
|
||||
set_buffer('', buffer_left + buffer_right)
|
||||
|
||||
def go_end(*_):
|
||||
commit_search()
|
||||
set_buffer(buffer_left + buffer_right, u'')
|
||||
set_buffer(buffer_left + buffer_right, '')
|
||||
|
||||
keymap = km.Keymap({
|
||||
'<nomatch>' : self_insert,
|
||||
@@ -382,10 +392,10 @@ def readline(_size = None, prompt = '', float = True, priority = 10):
|
||||
if eof:
|
||||
return ''
|
||||
else:
|
||||
buffer = (buffer_left + buffer_right).encode('utf-8')
|
||||
buffer = (buffer_left + buffer_right)
|
||||
if buffer:
|
||||
history.insert(0, buffer)
|
||||
return buffer + '\n'
|
||||
return force_to_bytes(buffer) + '\n'
|
||||
except KeyboardInterrupt:
|
||||
control_c()
|
||||
finally:
|
||||
|
||||
@@ -336,11 +336,11 @@ class process(tube):
|
||||
|
||||
if self.pty is not None:
|
||||
if stdin is slave:
|
||||
self.proc.stdin = os.fdopen(os.dup(master), 'r+')
|
||||
self.proc.stdin = os.fdopen(os.dup(master), 'r+', 0)
|
||||
if stdout is slave:
|
||||
self.proc.stdout = os.fdopen(os.dup(master), 'r+')
|
||||
self.proc.stdout = os.fdopen(os.dup(master), 'r+', 0)
|
||||
if stderr is slave:
|
||||
self.proc.stderr = os.fdopen(os.dup(master), 'r+')
|
||||
self.proc.stderr = os.fdopen(os.dup(master), 'r+', 0)
|
||||
|
||||
os.close(master)
|
||||
os.close(slave)
|
||||
|
||||
+8
-10
@@ -114,17 +114,15 @@ def concat_all(*args):
|
||||
[0, 1, 2, 3, 4, 5, 6]
|
||||
"""
|
||||
|
||||
if len(args) != 1:
|
||||
return concat_all(list(args))
|
||||
def go(arg, output):
|
||||
if isinstance(arg, (tuple, list)):
|
||||
for e in arg:
|
||||
go(e, output)
|
||||
else:
|
||||
output.append(arg)
|
||||
return output
|
||||
|
||||
if not isinstance(args[0], (tuple, list)):
|
||||
return [args[0]]
|
||||
|
||||
res = []
|
||||
for k in args[0]:
|
||||
res.extend(concat_all(k))
|
||||
|
||||
return res
|
||||
return go(args, [])
|
||||
|
||||
def ordlist(s):
|
||||
"""ordlist(s) -> list
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
__version__ = '3.8.0'
|
||||
__version__ = '3.9.2'
|
||||
@@ -86,7 +86,7 @@ except Exception as e:
|
||||
setup(
|
||||
name = 'pwntools',
|
||||
packages = find_packages(),
|
||||
version = '3.8.0',
|
||||
version = '3.9.2',
|
||||
data_files = [('',
|
||||
glob.glob('*.md') + glob.glob('*.txt')),
|
||||
],
|
||||
|
||||
@@ -8,7 +8,10 @@ MAINTAINER Maintainer Gallopsled et al.
|
||||
|
||||
USER root
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
# Use UTF-8
|
||||
RUN apt-get install -y locales
|
||||
RUN locale-gen en_US.UTF-8
|
||||
ENV LANG en_US.UTF-8
|
||||
ENV LANGUAGE en_US:en
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash -e
|
||||
set -e
|
||||
set -ex
|
||||
|
||||
local_deb_extract()
|
||||
{
|
||||
@@ -15,7 +15,7 @@ install_deb()
|
||||
package=$1
|
||||
echo "Installing $package"
|
||||
INDEX="http://packages.ubuntu.com/en/$version/amd64/$package/download"
|
||||
URL=$(curl "$INDEX" | grep -Eo "https?://.*$package.*\.deb" | head -1)
|
||||
URL=$(curl -L "$INDEX" | grep -Eo "https?://.*$package.*\.deb" | head -1)
|
||||
local_deb_extract "$URL"
|
||||
}
|
||||
|
||||
@@ -198,4 +198,4 @@ elif [[ "$(uname)" == "Linux" ]]; then
|
||||
setup_android_emulator
|
||||
fi
|
||||
|
||||
set +e
|
||||
set +ex
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# All of the "conditional sudo" is to do container-based builds on
|
||||
# Travis which are much, much faster.
|
||||
set -e
|
||||
set -ex
|
||||
|
||||
U=travis
|
||||
H=/home/$U
|
||||
@@ -55,4 +55,4 @@ EOF
|
||||
|
||||
ssh -o "StrictHostKeyChecking no" -vvvv [email protected] id
|
||||
|
||||
set +e
|
||||
set +ex
|
||||
Reference in new issue
Block a user