Compare commits

...
12 Commits
Author SHA1 Message Date
Mathias Svensson 2f7f0de984 Release 3.3.4 2017-01-12 23:40:13 +01:00
Zach Riggle 16b507e197 Change hexdump_iter to not rely on the length of its input file (#850)
We cannot determine the length of the file if passed e.g. a tube or a pipe or PTY or character device (e.g. stdin or /dev/null).

Supercedes: 9c2f0f4e
(cherry picked from commit 14f717b7b4)
2017-01-12 17:20:15 -05:00
Zach Riggle 53f041a4d2 Fix shellcraft.amd64.popad registers (#853)
Fixes Gallopsled/pwntools#848
2017-01-12 16:47:44 -05:00
Zach Riggle b2a5b76cf7 Do not perform temporary register selection if we don't need to (#852)
Fixes Gallopsled/pwntools#847
2017-01-12 16:36:49 -05:00
Zach Riggle 9c2f0f4e89 Fix hexdump_iter for actual file objects, like those used by phd (#846) 2017-01-11 15:06:11 -05:00
Mathias Svensson d1edd275d9 Release 3.3.3 2017-01-10 23:52:50 +01:00
Zach Riggle cb4991c41d Fix regression in amd64.mov with 32-bit values >= 0x80000000 (#843)
Fixes Gallopsled/pwntools#841
Caused by: Gallopsled/pwntools#504 (9ca377c)
2017-01-10 15:56:50 -05:00
Mathias Svensson 323975f343 Release 3.3.2 2017-01-10 18:28:24 +01:00
Zach Riggle f65c258956 Fix hexdump regression in 3.3.1 (#840) 2017-01-10 12:15:34 -05:00
Mathias Svensson d55874a6d3 Release 3.3.1 2017-01-10 16:53:24 +01:00
Zach Riggle 0426d498d9 Resolve feature regression in hexdump(..., cyclic=True)
This code wasnt updated when the code was changed to operate on file descriptors.

Additionally, there was a functional regression, that the first line would be skipped.

Fixes: Gallopsled/pwntools#836
Caused by: Gallopsled/pwntools#695 (d65991d)
2017-01-09 21:59:19 -05:00
Zach Riggle 54e722819b Defer attempts to start ADB server until we actually fail to connect (#833)
* Defer attempts to start ADB server until we actually fail to connect

* Upgrade to a warning message; fix .version() multiple calls with _autoclose

* Add doctest which tests the kill/restart behavior
2017-01-05 12:38:51 -05:00
9 changed files with 142 additions and 46 deletions

No files matched your search

+37 -1
View File
@@ -11,7 +11,11 @@ The table below shows which release corresponds to each branch, and what date th
| ---------------- | -------- | ---------------------- |
| [3.5.0](#350) | `dev` | Mar 18, 2017 (planned)
| [3.4.0](#340) | `beta` | Feb 4, 2017 (planned)
| [3.3.0](#330) | `stable` | Dec 24, 2016
| [3.3.4](#334) | `stable` | Jan 12, 2016
| [3.3.3](#333) | | Jan 10, 2016
| [3.3.2](#332) | | Jan 10, 2016
| [3.3.1](#331) | | Jan 10, 2016
| [3.3.0](#330) | | Dec 24, 2016
| [3.2.1](#321) | | Dec 24, 2016
| [3.2.0](#320) | | Nov 12, 2016
| [3.1.1](#311) | | Oct 23, 2016
@@ -31,6 +35,38 @@ To be released on Mar 18, 2017.
To be released on Feb 4, 2017.
## 3.3.4
- [#850][850] and [#846][846] fix issues with `hexdump` and the `phd` command-line utility, when using pipes (e.g. `echo foo | phd`)
- [#852][852] Fixes register ordering in `regsort`
- [#853][853] Fixes the registers restored in `shellcraft.amd64.popad`
[846]: https://github.com/gallopsled/pwntools/pull/846
[850]: https://github.com/gallopsled/pwntools/pull/850
[852]: https://github.com/gallopsled/pwntools/pull/852
[853]: https://github.com/gallopsled/pwntools/pull/853
## 3.3.3
- [#843][843] fixed a bug in `amd64.mov`.
[843]: https://github.com/gallopsled/pwntools/pull/843
## 3.3.2
- [#840][840] fixed a regression introduced by [#837][837].
[840]: https://github.com/gallopsled/pwntools/pull/840
## 3.3.1
- [#833][833] Fixed a performance-impacting bug in the adb module.
- [#837][837] Fixed a bug([#836][836]) causing `hexdump(cyclic=True)` to throw an exception.
[833]: https://github.com/Gallopsled/pwntools/pull/833
[837]: https://github.com/Gallopsled/pwntools/pull/837
[836]: https://github.com/Gallopsled/pwntools/issues/836
## 3.3.0
- [b198ec8][b198ec8] Added `tube.stream()` function, which is like `tube.interact()` without a prompt or keyboard input.
+1 -1
View File
@@ -2,7 +2,7 @@
![pwntools logo](https://github.com/Gallopsled/pwntools/blob/stable/docs/source/logo.png?raw=true)
[![Docs](https://readthedocs.org/projects/pwntools/badge/?version=stable)](https://docs.pwntools.com/)
[![PyPI](https://img.shields.io/badge/pypi-v3.3.0-green.svg?style=flat)](https://pypi.python.org/pypi/pwntools/)
[![PyPI](https://img.shields.io/badge/pypi-v3.3.4-green.svg?style=flat)](https://pypi.python.org/pypi/pwntools/)
[![Travis](https://travis-ci.org/Gallopsled/pwntools.svg)](https://travis-ci.org/Gallopsled/pwntools)
[![Coveralls](https://img.shields.io/coveralls/Gallopsled/pwntools/dev.svg)](https://coveralls.io/github/Gallopsled/pwntools?branch=dev)
[![Twitter](https://img.shields.io/badge/twitter-pwntools-4099FF.svg?style=flat)](https://twitter.com/pwntools)
+27 -9
View File
@@ -43,14 +43,7 @@ class Message(object):
class Connection(remote):
"""Connection to the ADB server"""
def __init__(self, host, port, level=None, *a, **kw):
# Try to make sure ADB is running if it's on the default host and port.
if host == context.defaults['adb_host'] \
and port == context.defaults['adb_port']:
with context.quiet:
process(context.adb + ['start-server']).recvall()
with context.quiet:
super(Connection, self).__init__(host, port, level=level, *a, **kw)
super(Connection, self).__init__(host, port, level=level, *a, **kw)
self._executable = None
self._argv = None
@@ -91,6 +84,20 @@ class Client(Logger):
@property
def c(self):
"""Client's connection to the ADB server"""
if not self._c:
try:
self._c = Connection(self.host, self.port, level=self.level)
except Exception:
# If the connection fails, try starting a server on that port
# as long as it's the *default* port.
if self.host == context.defaults['adb_host'] \
and self.port == context.defaults['adb_port']:
log.warn("Could not connect to ADB server, trying to start it")
process(context.adb + ['start-server']).recvall()
else:
log.exception('Could not connect to ADB server')
# Final attempt...
if not self._c:
self._c = Connection(self.host, self.port, level=self.level)
return self._c
@@ -135,12 +142,23 @@ class Client(Logger):
@_autoclose
def kill(self):
"""Kills the remote ADB server"""
"""Kills the remote ADB server"
>>> c=adb.protocol.Client()
>>> c.kill()
The server is automatically re-started on the next request,
if the default host/port are used.
>>> c.version() > (4,0)
True
"""
try:
self.send('host:kill')
except EOFError:
pass
@_autoclose
def version(self):
"""
Returns:
+5 -1
View File
@@ -224,6 +224,8 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
('mov', 'b', 'c'),
('mov', 'c', 'x'),
('mov', 'x', '1')]
>>> regsort({'a': 'b', 'b': 'c'}, ['a','b','c'], xchg=0)
[('mov', 'a', 'b'), ('mov', 'b', 'c')]
"""
if randomize is None:
randomize = context.randomize
@@ -333,7 +335,9 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
# If XCHG is expressly disabled, and there is no temporary register,
# try to see if there is any register which can be used as a temp
# register instead.
if not (xchg or tmp):
#
# If there are no cycles, there's no need for a temporary register.
if in_cycle and not (xchg or tmp):
for reg in in_out:
if not depends_on_cycle(reg, in_out, in_cycle):
tmp = reg
+31 -15
View File
@@ -61,17 +61,26 @@ Example:
mov rax, 0x1010110dfac01fe
xor [rsp], rax
pop rax
>>> with context.local(os = 'linux'):
... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip()
xor eax, eax /* (SYS_read) */
>>> with context.local(os = 'freebsd'):
... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip()
push (SYS_read) /* 3 */
pop rax
>>> with context.local(os = 'linux'):
... print shellcraft.amd64.mov('eax', 'PROT_READ | PROT_WRITE | PROT_EXEC').rstrip()
push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */
pop rax
>>> print shellcraft.amd64.mov('rax', 0xffffffff).rstrip()
mov eax, 0xffffffff
>>> print shellcraft.amd64.mov('rax', 0x7fffffff).rstrip()
mov eax, 0x7fffffff
>>> print shellcraft.amd64.mov('rax', 0x80010101).rstrip()
mov eax, 0x80010101
>>> print shellcraft.amd64.mov('rax', 0x80000000).rstrip()
mov eax, 0x1010101 /* 2147483648 == 0x80000000 */
xor eax, 0x81010101
>>> with context.local(os = 'linux'):
... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip()
xor eax, eax /* (SYS_read) */
>>> with context.local(os = 'freebsd'):
... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip()
push (SYS_read) /* 3 */
pop rax
>>> with context.local(os = 'linux'):
... print shellcraft.amd64.mov('eax', 'PROT_READ | PROT_WRITE | PROT_EXEC').rstrip()
push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */
pop rax
Args:
dest (str): The destination register.
@@ -99,7 +108,6 @@ if get_register(src):
if dest.size == 64 and src.size <= 32:
dest = get_register(dest.native32)
src_size = src.size
else:
with ctx.local(arch = 'amd64'):
src = eval(src)
@@ -107,9 +115,9 @@ else:
if not dest.fits(src):
log.error("cannot mov %s, %r: dest is smaller than src" % (dest, src))
src_size = bits_required(src)
orig_dest = dest
if dest.size == 64 and src_size <= 32:
if dest.size == 64 and bits_required(src) <= 32:
dest = get_register(dest.native32)
# Calculate the packed version
@@ -117,7 +125,15 @@ else:
# Calculate the unsigned and signed versions
srcu = packing.unpack(srcp, dest.size, sign=False)
srcs = packing.unpack(srcp, dest.size, sign=True)
# N.B.: We may have downsized the register for e.g. mov('rax', 0xffffffff)
# In this case, srcp is now a 4-byte packed value, which will expand
# to "-1", which isn't correct.
if orig_dest.size != dest.size:
srcs = src
else:
srcs = packing.unpack(srcp, dest.size, sign=True)
%>\
% if is_register(src):
% if src == dest:
+2 -2
View File
@@ -6,8 +6,8 @@ in the same order.
pop rdi
pop rsi
pop rbp
pop rsp
pop rbp
pop rbx /* add rsp, 8 */
pop rbx
pop rdx
pop rcx
pop rax
+37 -15
View File
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import base64
import random
import os
import re
import string
import StringIO
@@ -10,7 +11,7 @@ from . import packing
from ..context import context
from ..log import getLogger
from ..term import text
from .cyclic import cyclic
from .cyclic import de_bruijn
from .cyclic import cyclic_find
log = getLogger(__name__)
@@ -559,13 +560,15 @@ default_style = {
}
cyclic_pregen = ''
de_bruijn_gen = de_bruijn()
def sequential_lines(a,b):
return (a+b) in cyclic_pregen
def update_cyclic_pregenerated(size):
global cyclic_pregen
cyclic_pregen = cyclic(size)
while size > len(cyclic_pregen):
cyclic_pregen += de_bruijn_gen.next()
def hexdump_iter(fd, width=16, skip=True, hexii=False, begin=0, style=None,
highlight=None, cyclic=False):
@@ -627,30 +630,49 @@ def hexdump_iter(fd, width=16, skip=True, hexii=False, begin=0, style=None,
return hbyte, abyte
cache = [style_byte(chr(b)) for b in range(256)]
if cyclic:
update_cyclic_pregenerated(len(s))
numb = 0
while True:
offset = begin + numb
chunk = fd.read(width)
# If a tube is passed in as fd, it will raise EOFError when it runs
# out of data, unlike a file or StringIO object, which return an empty
# string.
try:
chunk = fd.read(width)
except EOFError:
chunk = ''
# We have run out of data, exit the loop
if chunk == '':
break
# Advance the cursor by the number of bytes we actually read
numb += len(chunk)
# Update the cyclic pattern in case
if cyclic:
update_cyclic_pregenerated(numb)
# If this chunk is the same as the last unique chunk,
# use a '*' instead.
if skip and \
(last_unique == chunk or \
(cyclic and sequential_lines(last_unique, chunk))):
if skip and last_unique:
same_as_last_line = (last_unique == chunk)
lines_are_sequential = (cyclic and sequential_lines(last_unique, chunk))
last_unique = chunk
if not skipping:
yield '*'
skipping = True
continue
# Chunk is unique, save for next iteration
last_unique = chunk
if same_as_last_line or lines_are_sequential:
# If we have not already printed a "*", do so
if not skipping:
yield '*'
skipping = True
# Move on to the next chunk
continue
# Chunk is unique, no longer skipping
skipping = False
last_unique = chunk
# Generate contents for line
hexbytes = ''
+1 -1
View File
@@ -1 +1 @@
__version__ = '3.3.0'
__version__ = '3.3.4'
+1 -1
View File
@@ -83,7 +83,7 @@ except ImportError:
setup(
name = 'pwntools',
packages = find_packages(),
version = '3.3.0',
version = '3.3.4',
data_files = [('',
glob.glob('*.md') + glob.glob('*.txt')),
],