Compare commits

..
11 Commits
Author SHA1 Message Date
Arusekk f1624dc8ac Release 4.2.2 2020-10-20 15:21:59 +02:00
Arusekk a824e83bcb Only require changelog if major changes present 2020-10-20 14:57:36 +02:00
Arusekk dff2e807cd Fix udp socket server AttributeError (#1706)
Closes #1690
2020-10-20 14:29:54 +02:00
Arusekk b8ca473a39 Use descriptive workflow names 2020-10-20 12:17:58 +02:00
lucasgandArusekk 09541e042b [elf.py] convert linux string banner into an actual str (#1700)
* [elf.py] convert linux string banner into an actual str 

``self.string(address)`` actually return a bytes object containing the raw bytes, not a string in a pythonesque sense !
Since quite some time on Python3, ``re.search`` only works on proper str so we need to convert it before feeding it to ``re.search``

``.decode()`` works both on Python2 and Python3

* Update kernel ELF handling

Co-authored-by: Arusekk <[email protected]>
2020-10-17 16:10:22 +02:00
James O'NealandJames O'Neal dd92ca6c61 Fix broken shellcraft linux templates (#1699)
* fixing broken linux templates

* adding change to changelog

Co-authored-by: James O'Neal <[email protected]>
2020-10-13 14:13:21 +02:00
Teddy Heinen 5e279e7993 fix #1684 (ROP gadget loading fails when it matches "add esp, esi") (#1686)
* fix ROP gadget loading when binary contains a gadget with add rsp, <register>

* add documentation regarding the fact that loading gadget "add $sp, <reg>" will fail
2020-09-27 11:55:39 +02:00
Jonas 846f98294f Change lookup algorithm of adb.which (#1663)
* Change lookup algorithm of `adb.which`.

This is done because the current algorithm does not work when the binary (e.g. `su`) is installed in the last element of $PATH.

Example:

```shell
$ echo $PATH
/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
$ echo $PATH | while read -r -d: directory; do
>     echo  "$directory/su";
> done
/sbin/su
/vendor/bin/su
/system/sbin/su
/system/bin/su
$ (IFS=:
>   for directory in $PATH; do
>       echo "$directory/su";
>   done
> )
/sbin/su
/vendor/bin/su
/system/sbin/su
/system/bin/su
/system/xbin/su
```

* Update CHANGELOG
2020-08-24 17:19:09 +02:00
ArusekkandHeap Crash 78df70c986 Inform GDB of file when using QEMU (#1630)
* Inform GDB of file when using QEMU

Fixes #1625

* Sync CHANGELOG from dev + version bump

Co-authored-by: Heap Crash <[email protected]>
2020-07-11 15:58:16 +02:00
Arusekk b5de88e118 [ci] Look for merge conflict markers commited (#1623)
Inspired by #1606
Fixes #1622
2020-07-09 23:08:08 -05:00
heapcrash 2e61a6be7f [release] 4.2.0 is now "stable" 2020-07-03 19:10:40 -05:00
107 changed files with 491 additions and 792 deletions

No files matched your search

+10 -1
View File
@@ -17,4 +17,13 @@ jobs:
- name: Check changelog for updates
run: |
git log --stat ${GITHUB_BASE}..HEAD | grep CHANGELOG.md
if git log --stat ${GITHUB_BASE}..HEAD | grep CHANGELOG.md; then
echo 'Changelog updated :D'
else
if git log --stat ${GITHUB_BASE}..HEAD | grep '++\|--'; then
echo 'Major changes detected, changelog required!'
false
else
echo 'Minor changes detected, no changelog required!'
fi
fi
+8 -17
View File
@@ -2,7 +2,7 @@ name: Continuous Integration
on: [push, pull_request]
jobs:
build:
test:
strategy:
matrix:
python-version: [2.7, 3.8]
@@ -74,20 +74,11 @@ jobs:
binutils-arm-linux-gnueabihf \
binutils-mips-linux-gnu \
binutils-powerpc-linux-gnu \
binutils-sparc64-linux-gnu \
gcc-multilib \
libc6-dbg \
$ANDROID_JRE
- name: Testing Corefiles
run: |
ulimit -a
ulimit -c unlimited
cat /proc/sys/kernel/core_pattern
cat /proc/sys/kernel/core_uses_pid
( cd $(mktemp -d); sh -c 'kill -11 $$' || true; ls -la ./*core* /var/crash/*.crash;) || true
- name: Install Android AVD
- name: Install android avd
if: steps.java-needed.outputs.need
run: |
USER=travis source travis/install.sh
@@ -110,12 +101,13 @@ jobs:
- name: Install documentation dependencies
run: pip install -r docs/requirements.txt
- name: Disable broken tests
run: |
rm -f docs/source/elf/corefile.rst
- name: Manually install non-broken Unicorn
run: pip install unicorn==1.0.2rc3
- name: Version Check
run: PWNLIB_NOTERM=1 pwn version
- name: Coverage doctests
run: |
source .android.env || :
@@ -194,7 +186,7 @@ jobs:
staging-merge:
runs-on: ubuntu-latest
if: github.repository_owner == 'Gallopsled' && github.event_name == 'push' && startsWith(github.event.ref, 'refs/heads/') && endsWith(github.event.ref, '-staging')
needs: build
needs: test
steps:
- uses: actions/checkout@v2
with:
@@ -207,12 +199,11 @@ jobs:
TARGET=${BRANCH%-staging}
git branch -f "$TARGET"
git push origin "$TARGET"
git push origin --delete "$BRANCH"
pypi:
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
needs: build
needs: test
steps:
- name: Download artifacts
uses: actions/download-artifact@v2
+7 -9
View File
@@ -2,7 +2,7 @@ name: Lint
on: [push, pull_request]
jobs:
build:
lint:
strategy:
matrix:
python-version: [3.8]
@@ -11,6 +11,9 @@ jobs:
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Cache for pip
uses: actions/cache@v1
id: cache-pip
@@ -23,13 +26,8 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Critical lint
- name: Lint
run: |
pip install flake8
flake8 . --count --select=E9,F63,F7,E71 --show-source --statistics --exclude=android-?dk # TODO: Add F82
- name: Style lint
run: |
flake8 pwnlib setup.py docs travis --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
flake8 examples --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --ignore='F403,F405'
flake8 pwn --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --ignore='F401,F403,F405'
flake8 . --count --select=E9,F63,F7 --show-source --statistics --exclude=android-?dk # TODO: Add F82
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude=pwnlib/constants,android-?dk,.git,__pycache__
+28
View File
@@ -0,0 +1,28 @@
name: Check for merge markers
on: [pull_request]
env:
GITHUB_BASE: origin/${{ github.event.pull_request.base.ref }}
jobs:
mergecheck:
strategy:
matrix:
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 5
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Check for merge conflict markers commited
run: |
if git show ${GITHUB_BASE}..HEAD | grep -EB15 --color=always '^\+\+(>>>>>|=====|<<<<<)'; then
echo 'WARNING: Merge marker commits found in history.'
if git diff ${GITHUB_BASE}..HEAD | grep -EB15 --color=always '^\+(>>>>>|=====|<<<<<)'; then
echo 'ERROR: Merge markers still present! Do something!'
exit 1
fi
else
echo 'Congrats! All the merges you did were clean or resolved correctly :)'
fi
-1
View File
@@ -20,7 +20,6 @@ addons:
- binutils-arm-linux-gnueabihf
- binutils-mips-linux-gnu
- binutils-powerpc-linux-gnu
- binutils-sparc64-linux-gnu
- bash-static
cache:
- pip
+20 -7
View File
@@ -9,9 +9,11 @@ The table below shows which release corresponds to each branch, and what date th
| Version | Branch | Release Date |
| ---------------- | -------- | ---------------------- |
| [4.3.0](#430) | `dev` | Aug 1, 2020 (planned)
| [4.2.0](#420) | `beta` | Jul 1, 2020 (planned)
| [4.1.5](#415) | `stable` | Jun 27, 2020
| [4.4.0](#440) | `dev` | Sep 1, 2020 (planned)
| [4.3.0](#430) | `beta` | Aug 1, 2020 (planned)
| [4.2.0](#420) | `stable` | Jul 3, 2020 (planned)
| [4.1.7](#417) | | Jun 30, 2020
| [4.1.5](#415) | | Jun 27, 2020
| [4.1.4](#414) | | Jun 26, 2020
| [4.1.3](#413) | | Jun 23, 2020
| [4.1.2](#412) | | Jun 5, 2020
@@ -53,9 +55,13 @@ 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.3.0 (`dev`)
## 4.4.0 (`dev`)
To be released on Jun 30, 2020.
- [#1616][1616] Fix `cyclic` cli for 64 bit integers
[1616]: https://github.com/Gallopsled/pwntools/pull/1616
## 4.3.0 (`beta`)
- [#1576][1576] Add `executable=` argument to `ELF.search`
- [#1584][1584] Add `jmp_esp`/`jmp_rsp` attribute to `ROP`
@@ -77,9 +83,16 @@ To be released on Jun 30, 2020.
[1564]: https://github.com/Gallopsled/pwntools/pull/1564
[1621]: https://github.com/Gallopsled/pwntools/pull/1621
## 4.2.0 (`beta`)
## 4.2.1 (`stable`)
To be released on Jun 5, 2020.
- [#1625][1625] GDB now properly loads executables with QEMU
- [#1663][1663] Change lookup algorithm of `adb.which`
- [#1699][1699] Fix broken linux shellcraft templates
[1625]: https://github.com/Gallopsled/pwntools/pull/1625
[1699]: https://github.com/Gallopsled/pwntools/pull/1699
## 4.2.0
- [#1436][1436] Add ret2dlresolve automation
- [fecf9f] tubes.ssh.process() no longer requires python 2 installed on remote (still requires python, though)
+10 -7
View File
@@ -1,13 +1,12 @@
# pwntools - CTF toolkit
![pwntools logo](https://github.com/Gallopsled/pwntools/blob/stable/docs/source/logo.png?raw=true)
[![PyPI](https://img.shields.io/pypi/v/pwntools?style=flat)](https://pypi.python.org/pypi/pwntools/)
[![Docs](https://readthedocs.org/projects/pwntools/badge/?version=stable)](https://docs.pwntools.com/)
[![Travis](https://img.shields.io/travis/Gallopsled/pwntools/dev?logo=Travis)](https://travis-ci.org/Gallopsled/pwntools)
![GitHub Workflow Status (branch)](https://img.shields.io/github/workflow/status/Gallopsled/pwntools/Continuous%20Integration/dev?logo=GitHub)
[![Coveralls](https://img.shields.io/coveralls/github/Gallopsled/pwntools/dev?logo=coveralls)](https://coveralls.io/github/Gallopsled/pwntools?branch=dev)
[![PyPI](https://img.shields.io/pypi/v/pwntools?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)
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://choosealicense.com/licenses/mit/)
[![Twitter](https://img.shields.io/twitter/follow/Pwntools)](https://twitter.com/pwntools)
Pwntools is a CTF framework and exploit development library. Written in Python, it is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.
@@ -21,6 +20,10 @@ r.send(asm(shellcraft.sh()))
r.interactive()
```
# Try It Now!
You can now do a live demo of Pwntools, [right in your browser](https://demo.pwntools.com).
# Documentation
Our documentation is available at [docs.pwntools.com](https://docs.pwntools.com/)
@@ -29,7 +32,7 @@ To get you started, we've provided some example solutions for past CTF challenge
# Installation
Pwntools is best supported on 64-bit Ubuntu LTE releases (14.04, 16.04, 18.04, and 20.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.). Python >= 2.7 is required (Python 3 suggested as best).
Pwntools is best supported on 64-bit Ubuntu LTE releases (12.04, 14.04, 16.04 and 18.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.). Python >= 2.7 is required (Python 3 suggested as best).
Most of the functionality of pwntools is self-contained and Python-only. You should be able to get running quickly with
@@ -37,7 +40,7 @@ Most of the functionality of pwntools is self-contained and Python-only. You sh
apt-get update
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade pwntools
python3 -m pip install --upgrade git+https://github.com/Gallopsled/pwntools.git@dev
```
However, some of the features (assembling/disassembling foreign architectures) require non-Python dependencies. For more information, see the [complete installation instructions here](https://docs.pwntools.com/en/stable/install.html).
+8 -1
View File
@@ -340,7 +340,7 @@ def linkcode_resolve(domain, info):
val = mod
for k in info['fullname'].split('.'):
val = getattr(val, k, None)
if val is None:
if val == None:
break
# Special case for shellcraft
@@ -410,6 +410,13 @@ def py2_doctest_init(self, checker=None, verbose=None, optionflags=0):
checker = Py2OutputChecker()
doctest.DocTestRunner.__init__(self, checker, verbose, optionflags)
class EndlessLoop(Exception): pass
def alrm_handler(sig, frame):
signal.alarm(180) # three minutes
raise EndlessLoop()
signal.signal(signal.SIGALRM, alrm_handler)
signal.alarm(600) # ten minutes
if 'doctest' in sys.argv:
def setup(app):
app.connect('autodoc-skip-member', dont_skip_any_doctests)
+16 -16
View File
@@ -17,19 +17,19 @@
count ,
cycle ,
dropwhile ,
filter ,
filterfalse ,
groupby ,
ifilter ,
ifilterfalse ,
imap ,
islice ,
map ,
izip ,
izip_longest ,
permutations ,
product ,
repeat ,
starmap ,
takewhile ,
tee ,
zip ,
zip_longest
tee
.. function:: chain
@@ -63,29 +63,29 @@
Alias for :func:`itertools.groupby`
.. function:: filter
.. function:: ifilter
Alias for python3-style :func:`filter`
Alias for :func:`itertools.ifilter`
.. function:: filterfalse
.. function:: ifilterfalse
Alias for :func:`itertools.filterfalse`
Alias for :func:`itertools.ifilterfalse`
.. function:: map
.. function:: imap
Alias for python3-style :func:`map`
Alias for :func:`itertools.imap`
.. function:: islice
Alias for :func:`itertools.islice`
.. function:: zip
.. function:: izip
Alias for python3-style :func:`zip`
Alias for :func:`itertools.izip`
.. function:: zip_longest
.. function:: izip_longest
Alias for :func:`itertools.zip_longest`
Alias for :func:`itertools.izip_longest`
.. function:: permutations
-9
View File
@@ -36,14 +36,5 @@ print(shell.echo("single string"))
print(shell.echo(["list","of","strings"]))
print(shell["echo single statement"])
# ssh.process() is the most flexible way to run a command)
io = shell.process(['/bin/bash', '-c', 'echo Hello $FOO'],
env={'FOO': 'World'}, # Set environment
stderr='/dev/null', # Override file descriptors
aslr=False, # Disable ASLR on processes
setuid=False, # Disable setuid bit so processes can be debugged
shell=False) # Enable or disable shell evaluation
print(io.recvall())
# Show off the interactive shell
shell.interactive()
+1 -1
View File
@@ -1 +1 @@
bionic
xenial
-26
View File
@@ -1,26 +0,0 @@
############################################################
# Dockerfile to build Pwntools container
# Based on Ubuntu
############################################################
FROM ubuntu:bionic
MAINTAINER Maintainer Gallopsled et al.
RUN apt-get update \
&& apt-get install -y \
build-essential \
git \
libssl-dev \
libffi-dev \
python2.7 \
python-pip \
python-dev \
&& pip install --upgrade pip \
&& python -m pip install --upgrade pwntools \
&& PWNLIB_NOTERM=1 pwn update \
&& apt-get install -y sudo \
&& useradd -m pwntools \
&& passwd --delete --unlock pwntools \
&& echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
USER pwntools
WORKDIR /home/pwntools
+1 -1
View File
@@ -80,4 +80,4 @@ info = log.info
debug = log.debug
success = log.success
__all__ = [x for x in tuple(globals()) if x != '__name__']
__all__ = [x for x in globals().keys() if x != '__name__']
+6 -4
View File
@@ -827,10 +827,12 @@ def which(name, all = False, *a, **kw):
"""
# Unfortunately, there is no native 'which' on many phones.
which_cmd = '''
echo $PATH | while read -d: directory; do
[ -x "$directory/{name}" ] || continue;
echo -n "$directory/{name}\\x00";
done
(IFS=:
for directory in $PATH; do
[ -x "$directory/{name}" ] || continue;
echo -n "$directory/{name}\\x00";
done
)
[ -x "{name}" ] && echo -n "$PWD/{name}\\x00"
'''.format(name=name)
+1 -1
View File
@@ -64,7 +64,7 @@ class BootloaderImage(object):
Returns:
Contents of the image.
"""
if isinstance(index_or_name, six.integer_types):
if isinstance(index_or_name, int):
index = index_or_name
else:
for i in range(len(self.img_info)):
+14 -29
View File
@@ -167,9 +167,6 @@ def which_binutils(util):
'i386': ['x86_64', 'amd64'],
'i686': ['x86_64', 'amd64'],
'amd64': ['x86_64', 'i386'],
'mips64': ['mips'],
'powerpc64': ['powerpc'],
'sparc64': ['sparc'],
}.get(arch, [])
# If one of the candidate architectures matches the native
@@ -193,18 +190,16 @@ def which_binutils(util):
for gutil in utils:
# e.g. objdump
if arch is None:
patterns = [gutil]
pattern = gutil
# e.g. aarch64-linux-gnu-objdump, avr-objdump
# e.g. aarch64-linux-gnu-objdump
else:
patterns = ['%s*linux*-%s' % (arch, gutil),
'%s-%s' % (arch, gutil)]
pattern = '%s*linux*-%s' % (arch,gutil)
for pattern in patterns:
for dir in environ['PATH'].split(':'):
res = sorted(glob(path.join(dir, pattern)))
if res:
return res[0]
for dir in environ['PATH'].split(':'):
res = sorted(glob(path.join(dir, pattern)))
if res:
return res[0]
# No dice!
print_binutils_instructions(util, context)
@@ -250,9 +245,9 @@ def _assembler():
stderr=subprocess.STDOUT, universal_newlines=True)
version = re.search(r' (\d\.\d+)', result).group(1)
if version < '2.19':
log.warn_once('Your binutils version is too old and may not work!\n'
'Try updating with: https://docs.pwntools.com/en/stable/install/binutils.html\n'
'Reported Version: %r', result.strip())
log.warn_once('Your binutils version is too old and may not work!\n' + \
'Try updating with: https://docs.pwntools.com/en/stable/install/binutils.html\n' + \
'Reported Version: %r' % result.strip())
return assembler
@@ -327,7 +322,6 @@ def _bfdname():
'amd64' : 'elf64-x86-64',
'arm' : 'elf32-%sarm' % E,
'thumb' : 'elf32-%sarm' % E,
'avr' : 'elf32-avr',
'mips' : 'elf32-trad%smips' % E,
'mips64' : 'elf64-trad%smips' % E,
'alpha' : 'elf64-alpha',
@@ -350,13 +344,10 @@ def _bfdname():
def _bfdarch():
arch = context.arch
convert = {
'amd64': 'i386:x86-64',
'i386': 'i386',
'ia64': 'ia64-elf64',
'mips64': 'mips',
'powerpc64': 'powerpc',
'sparc64': 'sparc',
'thumb': 'arm',
'i386': 'i386',
'amd64': 'i386:x86-64',
'thumb': 'arm',
'ia64': 'ia64-elf64'
}
if arch in convert:
@@ -758,12 +749,6 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
>>> print(disasm(unhex('656664676665400F18A4000000000051'), byte=0, arch='amd64'))
0: gs data16 fs data16 rex nop/reserved BYTE PTR gs:[eax+eax*1+0x0]
f: push rcx
>>> print(disasm(unhex('01000000'), arch='sparc64'))
0: 01 00 00 00 nop
>>> print(disasm(unhex('60000000'), arch='powerpc64'))
0: 60 00 00 00 nop
>>> print(disasm(unhex('00000000'), arch='mips64'))
0: 00000000 nop
"""
result = ''
+1 -2
View File
@@ -18,6 +18,5 @@ __all__ = [
'scramble',
'shellcraft',
'unhex',
'update',
'version'
'update'
]
Executable → Regular
+24 -12
View File
@@ -4,6 +4,7 @@ from __future__ import division
import argparse
import functools
import os
import re
import pwnlib
@@ -18,22 +19,25 @@ p = common.parser_commands.add_parser(
formatter_class = argparse.RawDescriptionHelpFormatter,
)
p.add_argument(
group = p.add_mutually_exclusive_group()
group.add_argument(
'-e', '--exact',
action='store_true',
help='Do an exact match for a constant instead of searching for a regex',
metavar = 'constant',
# nargs = 1,
default = None,
help = 'Do an exact match for a constant instead of searching for a regex',
)
p.add_argument(
group.add_argument(
'regex',
help='The regex matching constant you want to find',
nargs = '?',
default = '',
help = 'The regex matching constant you want to find',
)
p.add_argument(
'constant',
nargs = '?',
default = None,
type = safeeval.expr,
help = 'The constant to find',
)
@@ -61,7 +65,7 @@ p.add_argument(
def main(args):
if args.exact:
# This is the simple case
print(cpp(args.regex).strip())
print(cpp(args.exact).strip())
else:
# New we search in the right module.
# But first: We find the right module
@@ -76,12 +80,20 @@ def main(args):
else:
matcher = re.compile(args.regex)
# Evaluate the given constant
if args.constant:
try:
constant = safeeval.expr(args.constant)
except:
log.error("Could not evaluate constant %r" % args.constant)
else:
constant = None
# The found matching constants and the length of the longest string
out = []
maxlen = 0
constant = args.constant
for k in dir(mod):
# No python stuff
if k.endswith('__') and k.startswith('__'):
@@ -92,7 +104,7 @@ def main(args):
continue
# Check the constant
if constant is not None:
if constant != None:
val = getattr(mod, k)
if args.mask_mode:
if constant & val != val:
@@ -112,7 +124,7 @@ def main(args):
# If we are in match_mode, then try to find a combination of
# constants that yield the exact given value
# We do not want to find combinations using the value 0.
if constant and args.mask_mode:
if not (constant == None or constant == 0) and args.mask_mode:
mask = constant
good = []
out = [(v, k) for v, k in out if v != 0]
-2
View File
@@ -21,7 +21,6 @@ from pwnlib.commandline import shellcraft
from pwnlib.commandline import template
from pwnlib.commandline import unhex
from pwnlib.commandline import update
from pwnlib.commandline import version
from pwnlib.commandline.common import parser
from pwnlib.context import context
@@ -44,7 +43,6 @@ commands = {
'template': template.main,
'unhex': unhex.main,
'update': update.main,
'version': version.main,
}
def main():
+1 -10
View File
@@ -18,10 +18,9 @@ parser.add_argument('exe', nargs='?', help='Target binary')
parser.add_argument('--host', help='Remote host / SSH server')
parser.add_argument('--port', help='Remote port / SSH port', type=int)
parser.add_argument('--user', help='SSH Username')
parser.add_argument('--pass', '--password', help='SSH Password', dest='password')
parser.add_argument('--pass', help='SSH Password', dest='password')
parser.add_argument('--path', help='Remote path of file on SSH server')
parser.add_argument('--quiet', help='Less verbose template comments', action='store_true')
parser.add_argument('--color', help='Print the output in color', choices=['never', 'always', 'auto'], default='auto')
def main(args):
cache = None
@@ -58,16 +57,8 @@ def main(args):
# Fix Mako formatting bs
output = re.sub('\n\n\n', '\n\n', output)
# Colorize the output if it's a TTY
if args.color == 'always' or (args.color == 'auto' and sys.stdout.isatty()):
from pygments import highlight
from pygments.formatters import TerminalFormatter
from pygments.lexers.python import PythonLexer
output = highlight(output, PythonLexer(), TerminalFormatter())
print(output)
# If redirected to a file, make the resulting script executable
if not sys.stdout.isatty():
try: os.fchmod(sys.stdout.fileno(), 0o700)
except OSError: pass
-31
View File
@@ -1,31 +0,0 @@
#!/usr/bin/env python
from __future__ import absolute_import
from __future__ import division
import os
import subprocess
import pwnlib
pwnlib.args.free_form = False
from pwn import *
from pwnlib.commandline import common
parser = common.parser_commands.add_parser(
'version',
help = 'Pwntools version'
)
def main(a):
version = pwnlib.version
git_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
if os.path.exists(os.path.join(git_root, '.git')):
gitver = subprocess.check_output(['git', '-C', git_root, 'log', '-1', '--format=%h (%cr)'])
branch = subprocess.check_output(['git', '-C', git_root, 'rev-parse', '--abbrev-ref', 'HEAD'])
version = '%s-%s-%s' % (version, branch.decode().strip(), gitver.decode())
log.info("Pwntools v%s" % version)
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
+1 -1
View File
@@ -92,7 +92,7 @@ class ConstantsModule(ModuleType):
# Special case for __all__, we want to return the contextually
# relevant module.
if key == '__all__':
return list(self.guess().__dict__.keys())
return self.guess().__dict__.keys()
# Special case for all other special properties which aren't defined
if key.endswith('__'):
-1
View File
@@ -1,7 +1,6 @@
from __future__ import absolute_import
from pwnlib.data.elf import fmtstr
from pwnlib.data.elf import relro
from pwnlib.data.elf import ret2dlresolve
import os
path = os.path.dirname(__file__)
-8
View File
@@ -1,8 +0,0 @@
all: i386 amd64
i386: vuln.c
gcc "$^" -fno-stack-protector -no-pie -m32 -o $@
amd64: vuln.c
gcc "$^" -fno-stack-protector -no-pie -o $@
@@ -1,5 +0,0 @@
import os
path = os.path.dirname(__file__)
def get(x):
return os.path.join(path, x)
Binary file not shown.
Binary file not shown.
-8
View File
@@ -1,8 +0,0 @@
#include <unistd.h>
void vuln(void){
char buf[64];
read(STDIN_FILENO, buf, 200);
}
int main(int argc, char** argv){
vuln();
}
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -21,8 +21,8 @@ class KernelConfig(object):
self.excludes = set(excludes)
#: Kernel version that this check should be enforced on
self.minver = map(int, str(minver).split('.'))
self.maxver = map(int, str(maxver).split('.'))
self.minver = list(map(int, str(minver).split('.')))
self.maxver = list(map(int, str(maxver).split('.')))
def relevant(self, config):
+10 -10
View File
@@ -219,8 +219,8 @@ class Mapping(object):
stop += self.stop
if not (self.start <= start <= stop <= self.stop):
log.error("Byte range [%#x:%#x] not within range [%#x:%#x]",
start, stop, self.start, self.stop)
log.error("Byte range [%#x:%#x] not within range [%#x:%#x]" \
% (start, stop, self.start, self.stop))
data = self._core.read(start, stop-start)
@@ -431,7 +431,7 @@ class Corefile(ELF):
Corefiles can also be pulled from remote machines via SSH!
>>> s = ssh(user='travis', host='example.pwnme', password='demopass')
>>> s = ssh(host='example.pwnme')
>>> _ = s.set_working_directory()
>>> elf = ELF.from_assembly(shellcraft.trap())
>>> path = s.upload(elf.path)
@@ -551,15 +551,15 @@ class Corefile(ELF):
self.load_addr = 0
self._address = 0
if self.elftype != 'CORE':
if not self.elftype == 'CORE':
log.error("%s is not a valid corefile" % self.file.name)
if self.arch not in prstatus_types:
if not self.arch in prstatus_types.keys():
log.warn_once("%s does not use a supported corefile architecture, registers are unavailable" % self.file.name)
prstatus_type = prstatus_types.get(self.arch)
prpsinfo_type = prpsinfo_types.get(self.bits)
siginfo_type = siginfo_types.get(self.bits)
prstatus_type = prstatus_types.get(self.arch, None)
prpsinfo_type = prpsinfo_types.get(self.bits, None)
siginfo_type = siginfo_types.get(self.bits, None)
with log.waitfor("Parsing corefile...") as w:
self._load_mappings()
@@ -669,8 +669,8 @@ class Corefile(ELF):
continue
if mapping.start == self.at_sysinfo_ehdr \
or (not vdso and mapping.size in [0x1000, 0x2000]
and mapping.flags == 5
or (not vdso and mapping.size in [0x1000, 0x2000] \
and mapping.flags == 5 \
and self.read(mapping.start, 4) == b'\x7fELF'):
mapping.name = '[vdso]'
vdso = True
+17 -45
View File
@@ -90,12 +90,6 @@ log = getLogger(__name__)
__all__ = ['load', 'ELF']
def _iter_symbols(sec):
# Cache result of iter_symbols.
if not hasattr(sec, '_symbols'):
sec._symbols = list(sec.iter_symbols())
return iter(sec._symbols)
class Function(object):
"""Encapsulates information about a function in an :class:`.ELF` binary.
@@ -275,9 +269,6 @@ class ELF(ELFFile):
self.arch = 'mips64'
self.bits = 64
self._sections = None
self._segments = None
#: IntervalTree which maps all of the loaded memory segments
self.memory = intervaltree.IntervalTree()
self._populate_memory()
@@ -319,7 +310,7 @@ class ELF(ELFFile):
config = gz.read()
if config:
self.config = parse_kconfig(config)
self.config = parse_kconfig(config.decode())
#: ``True`` if the ELF is a statically linked executable
self.statically_linked = bool(self.elftype == 'EXEC' and self.load_addr)
@@ -464,6 +455,9 @@ class ELF(ELFFile):
self.checksec(*a, **kw)
)
def __repr__(self):
return "ELF(%r)" % self.path
def get_machine_arch(self):
return {
'EM_X86_64': 'amd64',
@@ -491,13 +485,6 @@ class ELF(ELFFile):
""":class:`str`: ELF type (``EXEC``, ``DYN``, etc)"""
return describe_e_type(self.header.e_type).split()[0]
def iter_segments(self):
# Yield and cache all the segments in the file
if self._segments is None:
self._segments = [self.get_segment(i) for i in range(self.num_segments())]
return iter(self._segments)
@property
def segments(self):
"""
@@ -550,13 +537,6 @@ class ELF(ELFFile):
return None
def iter_sections(self):
# Yield and cache all the sections in the file
if self._sections is None:
self._sections = [self.get_section(i) for i in range(self.num_sections())]
return iter(self._sections)
@property
def sections(self):
"""
@@ -862,7 +842,7 @@ class ELF(ELFFile):
if not isinstance(sec, SymbolTableSection):
continue
for sym in _iter_symbols(sec):
for sym in sec.iter_symbols():
# Avoid duplicates
if sym.name in self.functions:
continue
@@ -886,7 +866,7 @@ class ELF(ELFFile):
if not isinstance(section, SymbolTableSection):
continue
for symbol in _iter_symbols(section):
for symbol in section.iter_symbols():
value = symbol.entry.st_value
if not value:
continue
@@ -927,7 +907,7 @@ class ELF(ELFFile):
if self.statically_linked:
return
for section in self.sections:
for section in self.iter_sections():
# We are only interested in relocations
if not isinstance(section, RelocationSection):
continue
@@ -981,7 +961,7 @@ class ELF(ELFFile):
# Iterate over the dynamic symbol table
dynsym = self.get_section_by_name('.dynsym')
symbol_iter = _iter_symbols(dynsym)
symbol_iter = dynsym.iter_symbols()
# 'gotsym' is the index of the first GOT symbol
gotsym = self.dynamic_value_by_tag('DT_MIPS_GOTSYM')
@@ -1023,10 +1003,9 @@ class ELF(ELFFile):
# In particular, this is where EBX points when it points into the GOT.
dt_pltgot = self.dynamic_value_by_tag('DT_PLTGOT') or 0
# There are three PLTs we may need to search
# There are two PLTs we may need to search
plt = self.get_section_by_name('.plt') # <-- Functions only
plt_got = self.get_section_by_name('.plt.got') # <-- Functions used as data
plt_sec = self.get_section_by_name('.plt.sec')
plt_mips = self.get_section_by_name('.MIPS.stubs')
# Invert the GOT symbols we already have, so we can look up by address
@@ -1034,7 +1013,7 @@ class ELF(ELFFile):
inv_symbols.update({v:k for k,v in self.symbols.items()})
with context.local(arch=self.arch, bits=self.bits, endian=self.endian):
for section in (plt, plt_got, plt_sec, plt_mips):
for section in (plt, plt_got, plt_mips):
if not section:
continue
@@ -1055,7 +1034,10 @@ class ELF(ELFFile):
return
banner = self.string(self.symbols.linux_banner)
# convert banner into a utf-8 string since re.search does not accept bytes anymore
banner = banner.decode('utf-8')
# 'Linux version 3.18.31-gd0846ecc
regex = r'Linux version (\S+)'
match = re.search(regex, banner)
@@ -1113,8 +1095,8 @@ class ELF(ELFFile):
return_from_main = int(return_from_main[ : return_from_main.index(':') ], 16)
return return_from_main
def search(self, needle, writable = False, executable = False):
"""search(needle, writable = False, executable = False) -> generator
def search(self, needle, writable = False):
"""search(needle, writable = False) -> generator
Search the ELF's virtual address space for the specified string.
@@ -1127,7 +1109,6 @@ class ELF(ELFFile):
Arguments:
needle(str): String to search for.
writable(bool): Search only writable sections.
executable(bool): Search only executable sections.
Yields:
An iterator for each virtual address that matches.
@@ -1145,20 +1126,11 @@ class ELF(ELFFile):
>>> len(list(bash.search(b'GNU bash'))) > 0
True
It is also possible to search for instructions in executable sections.
>>> binary = ELF.from_assembly('nop; mov eax, 0; jmp esp; ret')
>>> jmp_addr = next(binary.search(asm('jmp esp'), executable = True))
>>> binary.read(jmp_addr, 2) == asm('jmp esp')
True
"""
load_address_fixup = (self.address - self.load_addr)
if writable:
segments = self.writable_segments
elif executable:
segments = self.executable_segments
else:
segments = self.segments
@@ -1853,7 +1825,7 @@ class ELF(ELFFile):
# Check for Linux configuration, it must contain more than
# just the version.
if len(self.config) > 1:
config_opts = collections.defaultdict(list)
config_opts = collections.defaultdict(lambda: [])
for checker in kernel_configuration:
result, message = checker(self.config)
+9 -25
View File
@@ -36,17 +36,13 @@ def emulate_plt_instructions(elf, got, address, data, targets):
data = packing.unpack_many(data, bits=32, endian='little')
data = packing.flat(data, bits=32, endian='big')
uc, ctx = prepare_unicorn_and_context(elf, got, address, data)
# Brute force addresses, assume that PLT entry points are at 4-byte aligned
# Do not emulate more than a handful of instructions.
for i, pc in enumerate(range(address, address + len(data), 4)):
if log.isEnabledFor(logging.DEBUG):
log.debug('%s %#x', fiddling.enhex(data[i*4:(i+1) * 4]), pc)
log.debug(elf.disasm(pc, 4))
uc.context_restore(ctx)
target = emulate_plt_instructions_inner(uc, elf, got, pc, data[i*4:], targets)
target = emulate_plt_instructions_inner(elf, got, pc, data[i*4:], targets)
if target in targets:
log.debug("%#x -> %#x", pc, target)
@@ -54,7 +50,8 @@ def emulate_plt_instructions(elf, got, address, data, targets):
return rv
def prepare_unicorn_and_context(elf, got, address, data):
def emulate_plt_instructions_inner(elf, got, pc, data, targets):
# Deferred import to not affect load time
import unicorn as U
# Instantiate the emulator with the correct arguments for the current
@@ -91,15 +88,15 @@ def prepare_unicorn_and_context(elf, got, address, data):
uc = U.Uc(arch, mode)
# Map the page of memory, and fill it with the contents
start = address & (~0xfff)
stop = (address + len(data) + 0xfff) & (~0xfff)
start = pc & (~0xfff)
stop = (pc + len(data) + 0xfff) & (~0xfff)
if not (0 <= start <= stop <= (1 << elf.bits)):
return None
uc.mem_map(start, stop-start)
uc.mem_write(address, data)
assert uc.mem_read(address, len(data)) == data
uc.mem_write(pc, data)
assert uc.mem_read(pc, len(data)) == data
# MIPS is unique in that it relies entirely on _DYNAMIC, at the beginning
# of the GOT. Each PLT stub loads an address stored here.
@@ -132,17 +129,9 @@ def prepare_unicorn_and_context(elf, got, address, data):
trap = packing.p32(0x34000000, endian=elf.endian)
uc.mem_write(magic_addr, trap)
return uc, uc.context_save()
def emulate_plt_instructions_inner(uc, elf, got, pc, data, targets):
import unicorn as U
# Hook invalid addresses and any accesses out of the specified address range
stopped_addr = []
# For MIPS. Explanation at prepare_unicorn_and_context.
magic_addr = 0xdbdbdbdb
def hook_mem(uc, access, address, size, value, user_data):
# Special case to allow MIPS to dereference the _DYNAMIC pointer
# in the GOT.
@@ -153,10 +142,8 @@ def emulate_plt_instructions_inner(uc, elf, got, pc, data, targets):
uc.emu_stop()
return False
hooks = [
uc.hook_add(U.UC_HOOK_MEM_READ, hook_mem, stopped_addr),
uc.hook_add(U.UC_HOOK_MEM_UNMAPPED, hook_mem, stopped_addr)
]
uc.hook_add(U.UC_HOOK_MEM_READ, hook_mem, stopped_addr)
uc.hook_add(U.UC_HOOK_MEM_UNMAPPED, hook_mem, stopped_addr)
# callback for tracing instructions
# def hook_code(uc, address, size, user_data):
@@ -191,7 +178,4 @@ def emulate_plt_instructions_inner(uc, elf, got, pc, data, targets):
if stopped_addr:
retval = stopped_addr.pop()
for hook in hooks:
uc.hook_del(hook)
return retval
+1 -1
View File
@@ -44,4 +44,4 @@ data:
blacklist = set(raw)
encode = amd64DeltaEncoder()
__all__ = ['encode']
__all__ = [encode]
+1 -1
View File
@@ -32,7 +32,7 @@ class ArmEncoder(Encoder):
enc_dec_loop = b.encDecoderLoopBuilder(dec_loop)
dec = b.DecoderBuilder(dec_loop, self.icache_flush)
output, dec = b.buildInit(dec)
output,dec = b.buildInit(dec);
output += dec
output += enc_dec_loop
@@ -42,10 +42,10 @@ def off_gen(c):
return x
return 0
# return an alphanumeric value ret such that c XOR ret is also alphanumeric
# =========================================================================
# return an alphanumeric value ret such that c XOR ret is also alphanumeric
# =========================================================================
def alphanumeric_get_complement(c):
c &= 0xff
c &= 0xff;
while True:
ret = alphanumeric_get_byte()
if alphanumeric_check(c ^ ret):
+3 -10
View File
@@ -3,12 +3,9 @@
r"""
File Structure Exploitation
struct FILE (_IO_FILE) is the structure for File Streams.
This offers various targets for exploitation on an existing bug in the code.
Examples - ``_IO_buf_base`` and ``_IO_buf_end`` for reading data to arbitrary location.
struct FILE (_IO_FILE) is the structure for File Streams. This offers various targets for exploitation on an existing bug in the code. Examples - _IO_buf_base and _IO_buf_end for reading data to arbitrary location.
Remembering the offsets of various structure members while faking a FILE structure can be difficult,
so this python class helps you with that. Example-
Remembering the offsets of various structure members while faking a FILE structure can be difficult, so this python class helps you with that. Example-
>>> context.clear(arch='amd64')
>>> fileStr = FileStructure(null=0xdeadbeef)
@@ -27,7 +24,6 @@ from __future__ import division
from pwnlib.context import context
from pwnlib.log import getLogger
from pwnlib.util.misc import python_2_bytes_compatible
from pwnlib.util.packing import pack
log = getLogger(__name__)
@@ -66,8 +62,6 @@ variables={
26:{name:'vtable',size:length}
}
del name, size, length
def update_var(l):
r"""
@@ -97,8 +91,6 @@ def update_var(l):
var['unknown2']=48
return var
@python_2_bytes_compatible
class FileStructure(object):
r"""
Crafts a FILE structure, with default values for some fields, like _lock which should point to null ideally, set.
@@ -195,6 +187,7 @@ class FileStructure(object):
else:
structure += pack(self.__getattr__(val), self.length[val]*8)
return structure
__str__ = __bytes__
def struntil(self,v):
r"""
+3 -1
View File
@@ -11,6 +11,7 @@ from pwnlib.tubes.remote import remote
env_server = args.get('FLAG_HOST', 'flag-submission-server').strip()
env_port = args.get('FLAG_PORT', '31337').strip()
env_proto = args.get('FLAG_PROTO', 'tcp').strip()
env_file = args.get('FLAG_FILE', '/does/not/exist').strip()
env_exploit_name = args.get('EXPLOIT_NAME', 'unnamed-exploit').strip()
env_target_host = args.get('TARGET_HOST', 'unknown-target').strip()
@@ -23,6 +24,7 @@ def submit_flag(flag,
target=env_target_host,
server=env_server,
port=env_port,
proto=env_proto,
team=env_team_name):
"""
Submits a flag to the game server
@@ -33,7 +35,7 @@ def submit_flag(flag,
target(str): Target identifier, optional
server(str): Flag server host name, optional
port(int): Flag server port, optional
team(str): Team identifier, optional
proto(str), Flag server protocol, optional
Optional arguments are inferred from the environment,
or omitted if none is set.
+4 -3
View File
@@ -834,13 +834,14 @@ class FmtStr(object):
"""
def __init__(self, execute_fmt, offset=None, padlen=0, numbwritten=0):
def __init__(self, execute_fmt, offset = None, padlen = 0, numbwritten = 0):
self.execute_fmt = execute_fmt
self.offset = offset
self.padlen = padlen
self.numbwritten = numbwritten
if self.offset is None:
if self.offset == None:
self.offset, self.padlen = self.find_offset()
log.info("Found format string offset: %d", self.offset)
@@ -902,7 +903,7 @@ class FmtStr(object):
"""
fmtstr = randoms(self.padlen).encode()
fmtstr += fmtstr_payload(self.offset, self.writes, numbwritten=self.padlen + self.numbwritten, write_size='byte')
fmtstr += fmtstr_payload(self.offset, self.writes, numbwritten=self.padlen, write_size='byte')
self.execute_fmt(fmtstr)
self.writes = {}
+10 -15
View File
@@ -237,14 +237,13 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None):
if pid:
gdbserver_args += ['--once', '--attach']
if env is not None:
if env:
env_args = []
for key in tuple(env):
if key.startswith('LD_'): # LD_PRELOAD / LD_LIBRARY_PATH etc.
env_args.append('{}={}'.format(key, env.pop(key)))
else:
env_args.append('{}={}'.format(key, env[key]))
gdbserver_args += ['--wrapper', 'env', '-i'] + env_args + ['--']
if env_args:
gdbserver_args += ['--wrapper', 'env'] + env_args + ['--']
gdbserver_args += ['localhost:0']
gdbserver_args += args
@@ -400,7 +399,7 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, **kw
>>> io.interactive() # doctest: +SKIP
>>> io.close()
"""
if isinstance(args, six.integer_types + (tubes.process.process, tubes.ssh.ssh_channel)):
if isinstance(args, (int, tubes.process.process, tubes.ssh.ssh_channel)):
log.error("Use gdb.attach() to debug a running process")
if isinstance(args, (bytes, six.text_type)):
@@ -497,7 +496,7 @@ def binary():
if multiarch:
return multiarch
log.warn_once('Cross-architecture debugging usually requires gdb-multiarch\n'
log.warn_once('Cross-architecture debugging usually requires gdb-multiarch\n' \
'$ apt-get install gdb-multiarch')
if not gdb:
@@ -632,6 +631,9 @@ def attach(target, gdbscript = '', exe = None, gdb_args = None, ssh = None, sysr
if context.os == 'android':
pre += 'set gnutarget ' + _bfdname() + '\n'
if exe:
pre += 'file %s\n' % exe
# let's see if we can find a pid to attach to
pid = None
if isinstance(target, six.integer_types):
@@ -981,7 +983,7 @@ def corefile(process):
# This is effectively the same as what the 'gcore' binary does
gdb_args = ['-batch',
'-q',
'-nx',
'--nx',
'-ex', '"set pagination off"',
'-ex', '"set height 0"',
'-ex', '"set width 0"',
@@ -992,14 +994,7 @@ def corefile(process):
with context.local(terminal = ['sh', '-c']):
with context.quiet:
pid = attach(process, gdb_args=gdb_args)
log.debug("Got GDB pid %d", pid)
try:
os.waitpid(pid, 0)
except Exception:
pass
if not os.path.exists(corefile_path):
log.error("Could not generate a corefile for process %d", process.pid)
os.waitpid(pid, 0)
return elf.corefile.Core(corefile_path)
+1 -8
View File
@@ -98,7 +98,6 @@ import logging
import os
import random
import re
import six
import sys
import threading
import time
@@ -184,9 +183,6 @@ class Progress(object):
self.last_status = 0
def _log(self, status, args, kwargs, msgtype):
# Logs are strings, not bytes. Handle Python3 bytes() objects.
status = six.ensure_text(status)
# this progress logger is stopped, so don't generate any more records
if self._stopped:
return
@@ -283,14 +279,11 @@ class Logger(object):
self._logger = logger
def _getlevel(self, levelString):
if isinstance(levelString, six.integer_types):
if isinstance(levelString, int):
return levelString
return logging._levelNames[levelString.upper()]
def _log(self, level, msg, args, kwargs, msgtype, progress = None):
# Logs are strings, not bytes. Handle Python3 bytes() objects.
msg = six.ensure_text(msg)
extra = kwargs.get('extra', {})
extra.setdefault('pwnlib_msgtype', msgtype)
extra.setdefault('pwnlib_progress', progress)
+6 -6
View File
@@ -63,7 +63,7 @@ class MemLeak(object):
... if addr & 0xff == 0:
... return None
... return binsh[addr:addr+4]
>>> leaker_nonulls.d(0) is None
>>> leaker_nonulls.d(0) == None
leaking 0x0
True
>>> leaker_nonulls[0x100:0x104] == binsh[0x100:0x104]
@@ -155,18 +155,18 @@ class MemLeak(object):
Arguments:
address(int): Base address to calculate offsets from
field(obj): Instance of a ctypes field
expected(int,bytes): Expected value
expected(int,str): Expected value
Return Value:
The type of the return value will be dictated by
the type of ``field``.
"""
if isinstance(expected, six.integer_types):
expected = pack(expected, bytes=obj.size)
elif not isinstance(expected, bytes):
if not isinstance(expected, (int, bytes)):
raise TypeError("Expected value must be an int or bytes")
if isinstance(expected, int):
expected = pack(expected, bytes=obj.size)
assert obj.size == len(expected)
return self.compare(address + obj.offset, expected)
+3 -3
View File
@@ -109,8 +109,8 @@ class AdbClient(Logger):
process(context.adb + ['start-server']).recvall()
time.sleep(0.3)
else:
log.exception('Could not connect to ADB server (%s:%s)',
self.host, self.port)
log.exception('Could not connect to ADB server (%s:%s)' % \
(self.host, self.port))
# Final attempt...
if not self._c:
@@ -462,7 +462,7 @@ class AdbClient(Logger):
>>> expected = {'mode': 16749, 'size': 0, 'time': 0}
>>> pwnlib.protocols.adb.AdbClient().stat('/proc') == expected
True
>>> pwnlib.protocols.adb.AdbClient().stat('/does/not/exist') is None
>>> pwnlib.protocols.adb.AdbClient().stat('/does/not/exist') == None
True
"""
if isinstance(path, six.text_type):
+1 -1
View File
@@ -243,7 +243,7 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
# Collapse constant values
#
# For eaxmple, {'eax': 0, 'ebx': 0} => {'eax': 0, 'ebx': 'eax'}
v_k = defaultdict(list)
v_k = defaultdict(lambda: [])
for k,v in sorted(in_out.items()):
if v not in all_regs and v != 0:
v_k[v].append(k)
+2 -4
View File
@@ -9,8 +9,6 @@ from pwnlib.util import packing
import six
from pwnlib.util.misc import python_2_bytes_compatible
class Unresolved(object):
"""
@@ -57,8 +55,6 @@ class StackAdjustment(Unresolved):
"""
pass
@python_2_bytes_compatible
class AppendedArgument(Unresolved):
"""
Encapsulates information about a pointer argument, and the data
@@ -190,6 +186,8 @@ class AppendedArgument(Unresolved):
def __bytes__(self):
return packing.flat(self.resolve())
if six.PY2:
__str__ = __bytes__
def __repr__(self):
if isinstance(self.address, six.integer_types):
+2 -2
View File
@@ -54,12 +54,12 @@ class Gadget(object):
def __getitem__(self, key):
# Backward compatibility
if isinstance(key, six.integer_types):
if isinstance(key, int):
key = self.__indices[key]
return getattr(self, key)
def __setitem__(self, key, value):
# Backward compatibility
if isinstance(key, six.integer_types):
if isinstance(key, int):
key = self.__indices[key]
return setattr(self, key, value)
+51 -64
View File
@@ -2,61 +2,65 @@ r"""
Provides automatic payload generation for exploiting buffer overflows
using ret2dlresolve.
We use the following example program:
Example:
::
>>> program = tempfile.mktemp()
>>> source = program + ".c"
>>> write(source, '''
... #include <unistd.h>
... void vuln(void){
... char buf[64];
... read(STDIN_FILENO, buf, 200);
... }
... int main(int argc, char** argv){
... vuln();
... }''')
>>> cmdline = ["gcc", source, "-fno-stack-protector", "-no-pie", "-m32", "-o", program]
>>> process(cmdline).wait_for_close()
#include <unistd.h>
void vuln(void){
char buf[64];
read(STDIN_FILENO, buf, 200);
}
int main(int argc, char** argv){
vuln();
}
We can automate the process of exploitation with these some example binaries.
>>> context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('i386'))
>>> rop = ROP(context.binary)
>>> dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["echo pwned"])
>>> rop.read(0, dlresolve.data_addr) # do not forget this step, but use whatever function you like
>>> rop.ret2dlresolve(dlresolve)
>>> raw_rop = rop.chain()
>>> print(rop.dump())
0x0000: 0x80482e0 read(0, 0x804ae00)
0x0004: 0x80484ea <adjust @0x10> pop edi; pop ebp; ret
0x0008: 0x0 arg0
0x000c: 0x804ae00 arg1
0x0010: 0x80482d0 [plt_init] system(0x804ae24)
0x0014: 0x2b84 [dlresolve index]
0x0018: b'gaaa' <return address>
0x001c: 0x804ae24 arg0
>>> p = elf.process()
>>> p.sendline(fit({64+context.bytes*3: raw_rop, 200: dlresolve.payload}))
>>> p.recvline()
b'pwned\n'
You can also use ``Ret2dlresolve`` on AMD64:
>>> context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
>>> context.binary = program
>>> elf = ELF(program)
>>> rop = ROP(elf)
>>> dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["echo pwned"])
>>> rop.read(0, dlresolve.data_addr) # do not forget this step, but use whatever function you like
>>> rop.ret2dlresolve(dlresolve)
>>> raw_rop = rop.chain()
>>> print(rop.dump())
0x0000: 0x400593 pop rdi; ret
>>> print(rop.dump()) # doctest: +SKIP
0x0000: 0x8049030 read(0, 0x804ce00)
0x0004: 0x8049208 <adjust @0x10> pop edi; pop ebp; ret
0x0008: 0x0 arg0
0x000c: 0x804ce00 arg1
0x0010: 0x8049020 [plt_init] system(0x804ce30)
0x0014: 0x4b74 [dlresolve index]
0x0018: b'gaaa' <return address>
0x001c: 0x804ce30 arg0
>>> p = process(program)
>>> p.sendline(fit({64+context.bytes*3: raw_rop, 200: dlresolve.payload}))
>>> p.recvline()
b'pwned\n'
>>> # and now for 64 bits
>>> cmdline = ["gcc", source, "-fno-stack-protector", "-no-pie", "-o", program]
>>> process(cmdline).wait_for_close()
>>> context.binary = program
>>> elf = ELF(program)
>>> rop = ROP(elf)
>>> dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["echo pwned"])
>>> rop.read(0, dlresolve.data_addr) # do not forget this step, but use whatever function you like
>>> rop.ret2dlresolve(dlresolve)
>>> raw_rop = rop.chain()
>>> print(rop.dump()) # doctest: +SKIP
0x0000: 0x4011aa pop rdi; ret
0x0008: 0x0 [arg0] rdi = 0
0x0010: 0x400591 pop rsi; pop r15; ret
0x0018: 0x601e00 [arg1] rsi = 6299136
0x0010: 0x4011a8 pop rsi; pop r15; ret
0x0018: 0x404e00 [arg1] rsi = 4214272
0x0020: b'iaaajaaa' <pad r15>
0x0028: 0x4003f0 read
0x0030: 0x400593 pop rdi; ret
0x0038: 0x601e48 [arg0] rdi = 6299208
0x0040: 0x4003e0 [plt_init] system
0x0048: 0x15670 [dlresolve index]
>>> p = elf.process()
0x0028: 0x401030 read
0x0030: 0x4011aa pop rdi; ret
0x0038: 0x404e58 [arg0] rdi = 4214360
0x0040: 0x401020 [plt_init] system
0x0048: 0x318 [dlresolve index]
>>> p = process(program)
>>> p.sendline(fit({64+context.bytes: raw_rop, 200: dlresolve.payload}))
>>> if dlresolve.unreliable:
... p.poll(True) == -signal.SIGSEGV
@@ -65,7 +69,6 @@ You can also use ``Ret2dlresolve`` on AMD64:
True
"""
import six
from copy import deepcopy
from pwnlib.context import context
@@ -79,7 +82,6 @@ ELF32_R_SYM_SHIFT = 8
ELF64_R_SYM_SHIFT = 32
class Elf32_Rel(object):
''
"""
.. code-block:: c
@@ -101,7 +103,6 @@ class Elf32_Rel(object):
class Elf64_Rel(object):
''
"""
.. code-block:: c
@@ -123,7 +124,6 @@ class Elf64_Rel(object):
class Elf32_Sym(object):
''
"""
.. code-block:: c
@@ -158,7 +158,6 @@ class Elf32_Sym(object):
class Elf64_Sym(object):
''
"""
.. code-block:: c
@@ -193,7 +192,6 @@ class Elf64_Sym(object):
class Queue(list):
''
def size(self):
size = 0
for v in self:
@@ -207,21 +205,10 @@ class Queue(list):
class MarkedBytes(bytes):
''
pass
class Ret2dlresolvePayload(object):
"""Create a ret2dlresolve payload
Arguments:
elf (ELF): Binary to search
symbol (str): Function to search for
args (list): List of arguments to pass to the function
Returns:
A ``Ret2dlresolvePayload`` object which can be passed to ``rop.ret2dlresolve``
"""
def __init__(self, elf, symbol, args, data_addr=None):
self.elf = elf
self.elf_load_address_fixup = self.elf.address - self.elf.load_addr
@@ -357,7 +344,7 @@ class Ret2dlresolvePayload(object):
elif isinstance(top, bytes):
top = pack(self.data_addr + len(self.payload) + queue.size())
queue.append(MarkedBytes(queue[0]))
elif isinstance(top, six.integer_types):
elif isinstance(top, int):
top = pack(top)
self.payload += top
+11 -56
View File
@@ -88,36 +88,6 @@ You can also append complex arguments onto stack when the stack pointer is known
0x7fffe038: b'-c\x00$'
0x7fffe03c: b'ls\x00$'
ROP also detects 'jmp $sp' gadget to help exploit binaries with NX disabled.
You can get this gadget on 'i386':
>>> context.clear(arch='i386')
>>> elf = ELF.from_assembly('nop; jmp esp; ret')
>>> rop = ROP(elf)
>>> jmp_gadget = rop.jmp_esp
>>> elf.read(jmp_gadget.address, 2) == asm('jmp esp')
True
You can also get this gadget on 'amd64':
>>> context.clear(arch='amd64')
>>> elf = ELF.from_assembly('nop; jmp rsp; ret')
>>> rop = ROP(elf)
>>> jmp_gadget = rop.jmp_rsp
>>> elf.read(jmp_gadget.address, 2) == asm('jmp rsp')
True
Gadgets whose address has badchar are filtered out:
>>> context.clear(arch='i386')
>>> elf = ELF.from_assembly('nop; pop eax; jmp esp; int 0x80; jmp esp; ret')
>>> rop = ROP(elf, badchars=b'\x02')
>>> jmp_gadget = rop.jmp_esp # It returns the second gadget
>>> elf.read(jmp_gadget.address, 2) == asm('jmp esp')
True
>>> rop = ROP(elf, badchars=b'\x02\x06')
>>> rop.jmp_esp == None # The address of both gadgets has badchar
True
ROP Example
-------------------
@@ -332,7 +302,6 @@ from pwnlib.util import lists
from pwnlib.util import packing
from pwnlib.util.cyclic import cyclic
from pwnlib.util.packing import pack
from pwnlib.util.misc import python_2_bytes_compatible
log = getLogger(__name__)
__all__ = ['ROP']
@@ -371,7 +340,7 @@ class DescriptiveStack(list):
descriptions = {}
def __init__(self, address):
self.descriptions = collections.defaultdict(list)
self.descriptions = collections.defaultdict(lambda: [])
self.address = address or 0
self._next_next = 0
self._next_last = 0
@@ -413,7 +382,6 @@ class DescriptiveStack(list):
return '\n'.join(rv)
@python_2_bytes_compatible
class ROP(object):
r"""Class which simplifies the generation of ROP-chains.
@@ -783,6 +751,7 @@ class ROP(object):
stack.describe(self.describe(slot))
if not isinstance(slot, bytes):
slot = slot.encode()
slot += self.generatePadding(stack.next, len(slot) % context.bytes)
for chunk in lists.group(context.bytes, slot):
stack.append(chunk)
@@ -1088,6 +1057,9 @@ class ROP(object):
"""Returns: Raw bytes of the ROP chain"""
return self.chain()
def __str__(self):
return str(self.chain())
def __get_cachefile_name(self, files):
"""Given an ELF or list of ELF objects, return a cache file for the set of files"""
cachedir = os.path.join(tempfile.gettempdir(), 'pwntools-rop-cache-%d.%d' % sys.version_info[:2])
@@ -1129,7 +1101,7 @@ class ROP(object):
#
# - leave
# - pop reg
# - add $sp, value
# - add $sp, <hexadecimal value>
# - ret
#
# Currently, ROPgadget does not detect multi-byte "C2" ret.
@@ -1137,7 +1109,7 @@ class ROP(object):
#
pop = re.compile(r'^pop (.{3})')
add = re.compile(r'^add [er]sp, (\S+)$')
add = re.compile(r'^add [er]sp, ((?:0[xX])?[0-9a-fA-F]+)$')
ret = re.compile(r'^ret$')
leave = re.compile(r'^leave$')
int80 = re.compile(r'int +0x80')
@@ -1153,6 +1125,8 @@ class ROP(object):
# False
# >>> valid('add esp, 0x24')
# True
# >>> valid('add esp, esi')
# False
#
valid = lambda insn: any(map(lambda pattern: pattern.match(insn), [pop,add,ret,leave,int80,syscall,sysenter]))
@@ -1334,7 +1308,7 @@ class ROP(object):
self.raw(call)
def __getattr__(self, attr):
"""Helper to make finding ROP gadgets easier.
"""Helper to make finding ROP gadets easier.
Also provides a shorthand for ``.call()``:
``rop.function(args)`` is equivalent to ``rop.call(function, args)``
@@ -1347,7 +1321,7 @@ class ROP(object):
True
>>> rop.ret_8 == rop.search(move=8)
True
>>> rop.ret is not None
>>> rop.ret != None
True
"""
gadget = collections.namedtuple('gadget', ['address', 'details'])
@@ -1371,25 +1345,6 @@ class ROP(object):
count = int(attr.split('_')[1])
return self.search(move=count)
#
# Check for 'jmp_esp'('i386') or 'jmp_rsp'('amd64')
#
if attr == 'jmp_esp' and context.arch == 'i386' \
or attr == 'jmp_rsp' and context.arch == 'amd64':
jmp_sp = {'i386': 'jmp esp',
'amd64': 'jmp rsp'
}[context.arch]
insn_asm = b'\xff\xe4'
for elf in self.elfs:
for addr in elf.search(insn_asm, executable = True):
if set(pack(addr)) & self._badchars:
continue
return Gadget(addr, [jmp_sp], [], context.bytes)
return None
if attr in ('int80', 'syscall', 'sysenter'):
mapping = {'int80': 'int 0x80',
'syscall': 'syscall',
+1 -1
View File
@@ -155,7 +155,7 @@ class module(ModuleType):
return hex(n)
def okay(self, s, *a, **kw):
if isinstance(s, six.integer_types):
if isinstance(s, int):
s = packing.pack(s, *a, **kw)
return b'\0' not in s and b'\n' not in s
+1 -1
View File
@@ -16,7 +16,7 @@ def init_mako():
from mako import ast
import threading
if lookup is not None:
if lookup != None:
return
class IsInsideManager(object):
@@ -33,13 +33,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(pretty(arg, False))
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft.aarch64 import mov
from pwnlib.shellcraft.aarch64.linux import read, readn, mmap
from pwnlib import constants as C
@@ -29,7 +28,7 @@ Example:
protection = C.PROT_READ | C.PROT_WRITE | C.PROT_EXEC
flags = C.MAP_ANONYMOUS | C.MAP_PRIVATE
assert isinstance(fd, six.integer_types)
assert isinstance(fd, int)
%>
%if length is None:
/* How many bytes should we receive? */
@@ -56,13 +56,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(repr(arg))
+1 -2
View File
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft import pretty, common, aarch64, registers
from pwnlib.shellcraft.registers import aarch64 as regs
from pwnlib.util.packing import pack, unpack
@@ -40,7 +39,7 @@ if not key in regs:
key_str = key
key_int = key
if isinstance(key, six.integer_types):
if isinstance(key, int):
key_str = pack(key, bytes=4)
else:
key_int = unpack(key, 'all')
@@ -76,13 +76,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(pretty(arg, False))
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft import amd64, pretty, common
from pwnlib.util.packing import pack, unpack
from pwnlib.util.lists import group
@@ -25,7 +24,7 @@ done = common.label('egghunter_done')
next_page = common.label('egghunter_nextpage')
egg_str = egg
if isinstance(egg, six.integer_types):
if isinstance(egg, int):
egg_str = pack(egg, bytes=4)
if len(egg_str) % 4:
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft.amd64 import push
from pwnlib.shellcraft.amd64.linux import read, readn, mmap
from pwnlib import constants as C
@@ -29,7 +28,7 @@ Example:
protection = C.PROT_READ | C.PROT_WRITE | C.PROT_EXEC
flags = C.MAP_ANONYMOUS | C.MAP_PRIVATE
assert isinstance(fd, six.integer_types)
assert isinstance(fd, int)
%>
%if length is None:
/* How many bytes should we receive? */
@@ -92,13 +92,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(repr(arg))
+1 -1
View File
@@ -6,7 +6,7 @@ Args:
</%docstring>
<%page args="return_value = None"/>
% if return_value is not None:
% if return_value != None:
${amd64.mov('rax', return_value)}
% endif
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.regsort import regsort
from pwnlib.shellcraft import registers, eval
from pwnlib.shellcraft.amd64 import mov
@@ -51,7 +50,7 @@ if isinstance(edx, str):
except NameError:
pass
if isinstance(eax, six.integer_types) and isinstance(edx, six.integer_types) and eax >> 63 == edx:
if isinstance(eax, int) and isinstance(edx, int) and eax >> 63 == edx:
cdq = True
reg_context.pop('rdx')
+1 -2
View File
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft import pretty, common, amd64, registers
from pwnlib.util.packing import pack, unpack
from pwnlib.context import context as ctx
@@ -46,7 +45,7 @@ else:
key_str = key
key_int = key
if isinstance(key, six.integer_types):
if isinstance(key, int):
key_str = pack(key, bytes=4)
else:
key_int = unpack(key, 'all')
@@ -33,13 +33,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(pretty(arg, False))
@@ -54,13 +54,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(repr(arg))
+1 -1
View File
@@ -15,7 +15,7 @@ Examples:
</%docstring>
<%page args="return_value = None"/>
% if return_value is not None:
% if return_value != None:
${arm.mov('r0', return_value)}
% endif
+1 -2
View File
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft import pretty, common, arm, registers
from pwnlib.shellcraft.registers import arm as regs
from pwnlib.util.packing import pack, unpack
@@ -40,7 +39,7 @@ if not key in regs:
key_str = key
key_int = key
if isinstance(key, six.integer_types):
if isinstance(key, int):
key_str = pack(key, bytes=4)
else:
key_int = unpack(key, 'all')
@@ -18,13 +18,13 @@ Any of the arguments can be expressions to be evaluated by :func:`pwnlib.constan
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(repr(arg))
@@ -65,13 +65,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(pretty(arg, False))
@@ -20,22 +20,22 @@ ${acceptloop}:
/* Socket file descriptor is placed in EBP */
/* sock = socket(AF_INET, SOCK_STREAM, 0) */
${i386.linux.push(0)}
${i386.linux.push('SOCK_STREAM')}
${i386.linux.push('AF_INET')}
${i386.push(0)}
${i386.push('SOCK_STREAM')}
${i386.push('AF_INET')}
${i386.linux.syscall('SYS_socketcall', 'SYS_socketcall_socket', 'esp')}
${i386.linux.mov('esi', 'eax')} /* keep socket fd */
${i386.mov('esi', 'eax')} /* keep socket fd */
/* bind(sock, &addr, sizeof addr); // sizeof addr == 0x10 */
${i386.linux.push(0)}
${i386.push(0)}
/* ${htons(port)} == htons(${port}) */
${i386.linux.push('AF_INET | (%d << 16)' % htons(port))}
${i386.linux.mov('ecx', 'esp')}
${i386.push('AF_INET | (%d << 16)' % htons(port))}
${i386.mov('ecx', 'esp')}
${i386.linux.push(0x10)} /* sizeof addr */
${i386.linux.push('ecx')} /* &addr */
${i386.linux.push('eax')} /* sock */
${i386.push(0x10)} /* sizeof addr */
${i386.push('ecx')} /* &addr */
${i386.push('eax')} /* sock */
${i386.linux.syscall('SYS_socketcall', 'SYS_socketcall_bind', 'esp')}
/* listen(sock, whatever) */
@@ -44,17 +44,17 @@ ${acceptloop}:
${looplabel}:
/* accept(sock, NULL, NULL) */
${i386.linux.push(0x0)}
${i386.linux.push('esi')} /* sock */
${i386.push(0x0)}
${i386.push('esi')} /* sock */
${i386.linux.syscall('SYS_socketcall', 'SYS_socketcall_accept', 'esp')}
${i386.linux.mov('ebp', 'eax')} /* keep in-coming socket fd */
${i386.mov('ebp', 'eax')} /* keep in-coming socket fd */
${i386.linux.syscall('SYS_fork')}
xchg eax, edi
test edi, edi
${i386.linux.mov('ebx', 'ebp')}
${i386.mov('ebx', 'ebp')}
cmovz ebx, esi /* on child we close the server sock instead */
/* close(sock) */
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft import i386, pretty, common
from pwnlib.util.packing import pack, unpack
from pwnlib.util.lists import group
@@ -25,7 +24,7 @@ done = common.label('egghunter_done')
next_page = common.label('egghunter_nextpage')
egg_str = egg
if isinstance(egg, six.integer_types):
if isinstance(egg, int):
egg_str = pack(egg)
if len(egg_str) % 4:
@@ -28,7 +28,7 @@ ${looplabel}:
pushad
int 0x80
% if port is None:
% if port == None:
test eax, eax
popad
pop edx
@@ -22,6 +22,6 @@
%endif
${label}:
${i386.linux.syscall('SYS_mprotect', 'ebx', 'ecx', 'PROT_READ | PROT_WRITE | PROT_EXEC')}
${i386.linux.mov('ecx', 0x1000)}
${i386.mov('ecx', 0x1000)}
add ebx, ecx
jnz ${label}
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft.i386 import push
from pwnlib.shellcraft.i386.linux import read, readn, mmap
from pwnlib import constants as C
@@ -30,7 +29,7 @@ Example:
protection = C.PROT_READ | C.PROT_WRITE | C.PROT_EXEC
flags = C.MAP_ANONYMOUS | C.MAP_PRIVATE
assert isinstance(fd, six.integer_types)
assert isinstance(fd, int)
%>
%if length is None:
/* How many bytes should we receive? */
@@ -90,13 +90,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(pretty(arg, False))
+1 -1
View File
@@ -6,7 +6,7 @@ Args:
</%docstring>
<%page args="return_value = None"/>
% if return_value is not None:
% if return_value != None:
${i386.mov('eax', return_value)}
% endif
+1 -2
View File
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.regsort import regsort
from pwnlib.constants import Constant, eval
from pwnlib.shellcraft import registers
@@ -45,7 +44,7 @@ if isinstance(edx, str):
except NameError:
pass
if isinstance(eax, six.integer_types) and isinstance(edx, six.integer_types) and eax >> 31 == edx:
if isinstance(eax, int) and isinstance(edx, int) and eax >> 31 == edx:
cdq = True
reg_context.pop('edx')
+1 -2
View File
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft import pretty, common, i386, registers
from pwnlib.util.packing import pack, unpack
from pwnlib.context import context as ctx
@@ -45,7 +44,7 @@ else:
key_str = key
key_int = key
if isinstance(key, six.integer_types):
if isinstance(key, int):
key_str = pack(key, bytes=4)
else:
key_int = unpack(key, 'all')
@@ -58,13 +58,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(pretty(arg, False))
@@ -88,13 +88,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(pretty(arg, False))
@@ -33,13 +33,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(pretty(arg, False))
@@ -1,5 +1,4 @@
<%
import six
from pwnlib.shellcraft.thumb import push
from pwnlib.shellcraft.thumb.linux import read, readn, mmap
from pwnlib import constants as C
@@ -29,7 +28,7 @@ Example:
protection = C.PROT_READ | C.PROT_WRITE | C.PROT_EXEC
flags = C.MAP_ANONYMOUS | C.MAP_PRIVATE
assert isinstance(fd, six.integer_types)
assert isinstance(fd, int)
%>
%if length is None:
/* How many bytes should we receive? */
@@ -62,13 +62,13 @@ Example:
args = []
else:
syscall_repr = 'syscall(%s)'
if syscall is None:
if syscall == None:
args = ['?']
else:
args = [repr(syscall)]
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
if arg is None:
if arg == None:
args.append('?')
else:
args.append(repr(arg))
+1 -1
View File
@@ -6,7 +6,7 @@ Args:
</%docstring>
<%page args="return_value = None"/>
% if return_value is not None:
% if return_value != None:
${thumb.mov('r0', return_value)}
% endif
+3 -3
View File
@@ -116,9 +116,9 @@ class PathCompleter(Completer):
if self.only_dirs:
cs = [c for c in cs if os.path.isdir(c)]
if self.mask:
cs = [c for c in cs
if self.mask.match(os.path.basename(c))
or os.path.isdir(c)]
cs = [c for c in cs if \
self.mask.match(os.path.basename(c)) or \
os.path.isdir(c)]
self._completions = cs
def complete(self, buffer_left, buffer_right):
+3 -3
View File
@@ -38,9 +38,9 @@ def getraw(timeout = None):
'''Get list of raw key codes corresponding to zero or more key presses'''
cs = []
c = getch(timeout)
while c is not None: # timeout
while c != None: # timeout
cs.append(c)
if c is None: # EOF
if c == None: # EOF
break
c = getch()
return cs
@@ -196,7 +196,7 @@ _ti_table = None
def _peek_ti():
global _cbuf
if _ti_table is None:
if _ti_table == None:
_init_ti_table()
# XXX: Faster lookup, plox
for seq, key in _ti_table:
+1 -1
View File
@@ -183,7 +183,7 @@ class Buffer(Exception):
size (int): (Optional) If set and not None, returns the size variable back.
Returns:
Fill size as integer if size is None, else size.
Fill size as integer if size == None, else size.
"""
if size is None:
size = self.buffer_fill_size
+5 -18
View File
@@ -35,20 +35,12 @@ class listen(sock):
>>> r.recvline()
b'Hello\n'
>>> # It works with ipv4 by default
>>> l = listen()
>>> l.spawn_process('/bin/sh')
>>> r = remote('127.0.0.1', l.lport)
>>> r = remote('localhost', l.lport)
>>> r.sendline(b'echo Goodbye')
>>> r.recvline()
b'Goodbye\n'
>>> # and it works with ipv6 by defaut, too!
>>> l = listen()
>>> r = remote('::1', l.lport)
>>> r.sendline(b'Bye-bye')
>>> l.recvline()
b'Bye-bye\n'
"""
#: Local port
@@ -74,8 +66,8 @@ class listen(sock):
_accepter = None
def __init__(self, port=0, bindaddr='::',
fam='any', typ='tcp', *args, **kwargs):
def __init__(self, port=0, bindaddr = "0.0.0.0",
fam = "any", typ = "tcp", *args, **kwargs):
super(listen, self).__init__(*args, **kwargs)
port = int(port)
@@ -85,8 +77,8 @@ class listen(sock):
fam = self._get_family(fam)
typ = self._get_type(typ)
if fam == socket.AF_INET and bindaddr == '::':
bindaddr = '0.0.0.0'
if fam == socket.AF_INET6 and bindaddr == '0.0.0.0':
bindaddr = '::'
h = self.waitfor('Trying to bind to %s on port %d' % (bindaddr, port))
@@ -99,11 +91,6 @@ class listen(sock):
h.status("Trying %s" % self.sockaddr[0])
listen_sock = socket.socket(self.family, self.type, self.proto)
listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if self.family == socket.AF_INET6:
try:
listen_sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, fam == socket.AF_INET6)
except (socket.error, AttributeError):
self.warn("could not set socket to accept also IPV4")
listen_sock.bind(self.sockaddr)
self.lhost, self.lport = listen_sock.getsockname()[:2]
if self.type == socket.SOCK_STREAM:
+6 -9
View File
@@ -242,9 +242,6 @@ class process(tube):
#: :class:`subprocess.Popen` object that backs this process
self.proc = None
# We need to keep a copy of the un-_validated environment for printing
original_env = env
if shell:
executable_val, argv_val, env_val = executable, argv, env
else:
@@ -301,7 +298,7 @@ class process(tube):
if self.isEnabledFor(logging.DEBUG):
if argv != [self.executable]: message += ' argv=%r ' % self.argv
if original_env not in (os.environ, None): message += ' env=%r ' % self.env
if env not in (os.environ, None): message += ' env=%r ' % self.env
with self.progress(message) as p:
@@ -669,7 +666,7 @@ class process(tube):
self.proc.poll()
returncode = self.proc.returncode
if returncode is not None and not self._stop_noticed:
if returncode != None and not self._stop_noticed:
self._stop_noticed = time.time()
signame = ''
if returncode < 0:
@@ -739,7 +736,7 @@ class process(tube):
return False
try:
if timeout is None:
if timeout == None:
return select.select([self.proc.stdout], [], []) == ([self.proc.stdout], [], [])
return select.select([self.proc.stdout], [], [], timeout) == ([self.proc.stdout], [], [])
@@ -752,12 +749,12 @@ class process(tube):
# ValueError: I/O operation on closed file
raise EOFError
except select.error as v:
if v.errno == errno.EINTR:
if v[0] == errno.EINTR:
return False
def connected_raw(self, direction):
if direction == 'any':
return self.poll() is None
return self.poll() == None
elif direction == 'send':
return not self.proc.stdin.closed
elif direction == 'recv':
@@ -826,7 +823,7 @@ class process(tube):
fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY)
if fd >= 0:
os.close(fd)
raise Exception('Failed to disconnect from '
raise Exception('Failed to disconnect from ' +
'controlling tty. It is still possible to open /dev/tty.')
# which exception, shouldnt' we catch explicitly .. ?
except OSError:
+1 -1
View File
@@ -99,7 +99,7 @@ class remote(sock):
sock = socket.socket(self.family, self.type, self.proto)
if timeout is not None and timeout <= 0:
if timeout != None and timeout <= 0:
sock.setblocking(0)
else:
sock.setblocking(1)
+1 -1
View File
@@ -82,7 +82,7 @@ class serialtube(tube.tube):
return False
def connected_raw(self, direction):
return self.conn is not None
return self.conn != None
def close(self):
if self.conn:
+1 -1
View File
@@ -117,7 +117,7 @@ class server(sock):
data, rhost = listen_sock.recvfrom(4096)
listen_sock.connect(rhost)
sock = listen_sock
sock.unrecv(data)
self.unrecv(data)
sock.settimeout(self.timeout)
break
except socket.error as e:
+9 -9
View File
@@ -43,7 +43,7 @@ class sock(tube):
except IOError as e:
if e.errno == errno.EAGAIN:
return None
elif e.errno in (errno.ECONNREFUSED, errno.ECONNRESET):
elif e.errno in [errno.ECONNREFUSED, errno.ECONNRESET]:
self.shutdown("recv")
raise EOFError
elif e.errno == errno.EINTR:
@@ -64,7 +64,7 @@ class sock(tube):
try:
self.sock.sendall(data)
except IOError as e:
eof_numbers = (errno.EPIPE, errno.ECONNRESET, errno.ECONNREFUSED)
eof_numbers = [errno.EPIPE, errno.ECONNRESET, errno.ECONNREFUSED]
if e.errno in eof_numbers or 'Socket is closed' in e.args:
self.shutdown("send")
raise EOFError
@@ -122,7 +122,7 @@ class sock(tube):
>>> r.connected()
True
>>> l.close()
>>> time.sleep(0.1) # Avoid race condition
>>> time.sleep(1) # Avoid race condition
>>> r.connected()
False
"""
@@ -208,8 +208,8 @@ class sock(tube):
if False not in self.closed.values():
self.close()
@classmethod
def _get_family(cls, fam):
def _get_family(self, fam):
if isinstance(fam, six.integer_types):
pass
elif fam == 'any':
@@ -220,13 +220,13 @@ class sock(tube):
fam = socket.AF_INET6
else:
self.error("%s(): socket family %r is not supported",
cls.__name__,
self.__class__.__name__,
fam)
return fam
@classmethod
def _get_type(cls, typ):
def _get_type(self, typ):
if isinstance(typ, six.integer_types):
pass
elif typ == "tcp":
@@ -235,7 +235,7 @@ class sock(tube):
typ = socket.SOCK_DGRAM
else:
self.error("%s(): socket type %r is not supported",
cls.__name__,
self.__class__.__name__,
typ)
return typ
+7 -12
View File
@@ -182,7 +182,7 @@ class ssh_channel(sock):
process has not yet finished and the exit code otherwise.
"""
if self.returncode is None and self.sock \
if self.returncode == None and self.sock \
and (block or self.sock.exit_status_ready()):
while not self.sock.status_event.is_set():
self.sock.status_event.wait(0.05)
@@ -230,7 +230,7 @@ class ssh_channel(sock):
cur = self.recv(timeout = 0.05)
cur = cur.replace(b'\r\n',b'\n')
cur = cur.replace(b'\r',b'')
if cur is None:
if cur == None:
continue
elif cur == b'\a':
# Ugly hack until term unstands bell characters
@@ -926,10 +926,6 @@ class ssh(Timeout, Logger):
#!/usr/bin/env python
import os, sys, ctypes, resource, platform, stat
from collections import OrderedDict
try:
integer_types = int, long
except NameError:
integer_types = int,
exe = %(executable)r
argv = [bytes(a) for a in %(argv)r]
env = %(env)r
@@ -1004,7 +1000,7 @@ for fd, newfd in {0: %(stdin)r, 1: %(stdout)r, 2:%(stderr)r}.items():
newfd = os.open(newfd, os.O_RDONLY if fd == 0 else (os.O_RDWR|os.O_CREAT))
os.dup2(newfd, fd)
os.close(newfd)
elif isinstance(newfd, integer_types) and newfd != fd:
elif isinstance(newfd, int) and newfd != fd:
os.dup2(fd, newfd)
if not %(aslr)r:
@@ -1101,7 +1097,7 @@ os.execve(exe, argv, env)
h.success('pid %i' % python.pid)
if not aslr and setuid and (python.uid != python.suid or python.gid != python.sgid):
if aslr == False and setuid and (python.uid != python.suid or python.gid != python.sgid):
effect = "partial" if self.aslr_ulimit else "no"
message = "Specfied aslr=False on setuid binary %s\n" % python.executable
message += "This will have %s effect. Add setuid=False to disable ASLR for debugging.\n" % effect
@@ -1552,7 +1548,6 @@ from ctypes import *; libc = CDLL('libc.so.6'); print(libc.getenv(%r))
basename = os.path.basename(remote)
local = local or '.'
local = os.path.expanduser(local)
@@ -1561,7 +1556,7 @@ from ctypes import *; libc = CDLL('libc.so.6'); print(libc.getenv(%r))
with context.local(log_level='error'):
remote_tar = self.mktemp()
cmd = 'tar -C %s -czf %s %s' % \
(sh_string(remote),
(sh_string(dirname),
sh_string(remote_tar),
sh_string(basename))
tar = self.system(cmd)
@@ -1626,7 +1621,7 @@ from ctypes import *; libc = CDLL('libc.so.6'); print(libc.getenv(%r))
remote(str): The remote filename to save it to. Default is to infer it from the local filename."""
if remote is None:
if remote == None:
remote = os.path.normpath(filename)
remote = os.path.basename(remote)
remote = os.path.join(self.cwd, remote)
@@ -1747,7 +1742,7 @@ from ctypes import *; libc = CDLL('libc.so.6'); print(libc.getenv(%r))
remote = context._decode(self.readlink('-f',remote).strip())
libs[remote] = 0
if directory is None:
if directory == None:
directory = self.host
directory = os.path.realpath(directory)
+2 -2
View File
@@ -97,11 +97,11 @@ def yesno(prompt, default=None):
cur = default
while True:
k = term.key.get()
if k in ('y', 'Y', '<left>') and cur is not True:
if k in ('y', 'Y', '<left>') and cur != True:
cur = True
hy.update(yesfocus)
hn.update(no)
elif k in ('n', 'N', '<right>') and cur is not False:
elif k in ('n', 'N', '<right>') and cur != False:
cur = False
hy.update(yes)
hn.update(nofocus)
+2 -2
View File
@@ -7,13 +7,13 @@ greatest version, Pwntools automatically checks for updates.
Since this update check takes a moment, it is only performed once
every week. It can be permanently disabled via:
::
.. code-block:: bash
$ echo never > ~/.pwntools-cache-*/update
Or adding the following lines to ~/.pwn.conf (or system-wide /etc/pwn.conf):
::
.. code-block::
[update]
interval=never
+14 -15
View File
@@ -125,9 +125,9 @@ def cyclic(length = None, alphabet = None, n = None):
if alphabet is None:
alphabet = context.cyclic_alphabet
if length is not None and len(alphabet) ** n < length:
log.error("Can't create a pattern length=%i with len(alphabet)==%i and n==%i",
length, len(alphabet), n)
if length != None and len(alphabet) ** n < length:
log.error("Can't create a pattern length=%i with len(alphabet)==%i and n==%i" \
% (length, len(alphabet), n))
generator = de_bruijn(alphabet, n)
out = iters.take(length, generator)
@@ -212,9 +212,9 @@ def cyclic_find(subseq, alphabet = None, n = None):
subseq = context._encode(subseq)
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.",
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))
subseq = subseq[:n]
@@ -284,9 +284,9 @@ def cyclic_metasploit(length = None, sets = None):
generator = metasploit_pattern(sets)
out = iters.take(length, generator)
if length is not None and len(out) < length:
log.error("Can't create a pattern of length %i with sets of lengths %s. Maximum pattern length is %i.",
length, list(map(len, sets)), len(out))
if length != None and len(out) < length:
log.error("Can't create a pattern of length %i with sets of lengths %s. Maximum pattern length is %i." \
% (length, list(map(len, sets)), len(out)))
return _join_sequence(out, sets[0])
@@ -414,18 +414,17 @@ class cyclic_gen(object):
...
StopIteration
"""
if length is not None:
if length != None:
self._chunks.append(length)
self._total_length += length
if len(self._alphabet) ** self._n < self._total_length:
log.error("Can't create a pattern length=%i with len(alphabet)==%i and n==%i",
self._total_length, len(self._alphabet), self._n)
out = [next(self._generator) for _ in range(length)]
log.error("Can't create a pattern length=%i with len(alphabet)==%i and n==%i" \
% (self._total_length, len(self._alphabet), self._n))
else:
self._chunks.append(float("inf"))
out = list(self._generator)
out = [next(self._generator) for _ in range(length)] if length != None else [next(self._generator)] + list(self._generator)
return _join_sequence(out, self._alphabet)
def find(self, subseq):
+10 -21
View File
@@ -592,9 +592,9 @@ def update_cyclic_pregenerated(size):
cyclic_pregen += packing._p8lu(next(de_bruijn_gen))
def hexdump_iter(fd, width=16, skip=True, hexii=False, begin=0, style=None,
highlight=None, cyclic=False, groupsize=4, total=True):
r"""hexdump_iter(s, width = 16, skip = True, hexii = False, begin = 0, style = None,
highlight = None, cyclic = False, groupsize=4, total = True) -> str generator
highlight=None, cyclic=False, groupsize=4):
r"""hexdump_iter(s, width = 16, skip = True, hexii = False, begin = 0,
style = None, highlight = None, cyclic = False, groupsize=4) -> str generator
Return a hexdump-dump of a string as a generator of lines. Unless you have
massive amounts of data you probably want to use :meth:`hexdump`.
@@ -609,7 +609,6 @@ def hexdump_iter(fd, width=16, skip=True, hexii=False, begin=0, style=None,
style(dict): Color scheme to use.
highlight(iterable): Byte values to highlight.
cyclic(bool): Attempt to skip consecutive, unmodified cyclic lines
total(bool): Set to True, if total bytes should be printed
Returns:
A generator producing the hexdump-dump one line at a time.
@@ -751,14 +750,13 @@ def hexdump_iter(fd, width=16, skip=True, hexii=False, begin=0, style=None,
line = line_fmt % {'offset': offset, 'hexbytes': hexbytes, 'printable': printable}
yield line
if total:
line = "%08x" % (begin + numb)
yield line
line = "%08x" % (begin + numb)
yield line
def hexdump(s, width=16, skip=True, hexii=False, begin=0, style=None,
highlight=None, cyclic=False, groupsize=4, total=True):
r"""hexdump(s, width = 16, skip = True, hexii = False, begin = 0, style = None,
highlight = None, cyclic = False, groupsize=4, total = True) -> str
def hexdump(s, width=16, skip=True, hexii=False, begin=0,
style=None, highlight=None, cyclic=False, groupsize=4):
r"""hexdump(s, width = 16, skip = True, hexii = False, begin = 0,
style = None, highlight = None, cyclic = False, groupsize=4) -> str generator
Return a hexdump-dump of a string.
@@ -772,7 +770,6 @@ def hexdump(s, width=16, skip=True, hexii=False, begin=0, style=None,
style(dict): Color scheme to use.
highlight(iterable): Byte values to highlight.
cyclic(bool): Attempt to skip consecutive, unmodified cyclic lines
total(bool): Set to True, if total bytes should be printed
Returns:
A hexdump-dump in the form of a string.
@@ -933,13 +930,6 @@ def hexdump(s, width=16, skip=True, hexii=False, begin=0, style=None,
00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAAAAAAAAAAAAAA│
00000010 41 41 41 41 41 41 41 41 │AAAAAAAA│
00000018
>>> print(hexdump('A'*24, width=16, total=False))
00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│
00000010 41 41 41 41 41 41 41 41 │AAAA│AAAA│
>>> print(hexdump('A'*24, width=16, groupsize=8, total=False))
00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAAAAAA│AAAAAAAA│
00000010 41 41 41 41 41 41 41 41 │AAAAAAAA│
"""
s = packing.flat(s)
return '\n'.join(hexdump_iter(BytesIO(s),
@@ -950,8 +940,7 @@ def hexdump(s, width=16, skip=True, hexii=False, begin=0, style=None,
style,
highlight,
cyclic,
groupsize,
total))
groupsize))
def negate(value, width = None):
"""
+11 -11
View File
@@ -821,7 +821,7 @@ def bruteforce(func, alphabet, length, method = 'upto', start = None, databag =
h = log.waitfor('Bruteforcing')
cur_iteration = 0
if start is not None:
if start != None:
consume(i, iterator)
for e in iterator:
cur = ''.join(e)
@@ -837,7 +837,7 @@ def bruteforce(func, alphabet, length, method = 'upto', start = None, databag =
if res:
h.success('Found key: "%s"' % cur)
return cur
if start is not None:
if start != None:
consume(N - 1, iterator)
h.failure('No matches found')
@@ -871,10 +871,10 @@ def mbruteforce(func, alphabet, length, method = 'upto', start = None, threads =
context.log_level = oldloglevel
databag["result"] = res
if start is None:
if start == None:
start = (1, 1)
if threads is None:
if threads == None:
try:
threads = multiprocessing.cpu_count()
except NotImplementedError:
@@ -906,9 +906,9 @@ def mbruteforce(func, alphabet, length, method = 'upto', start = None, threads =
while not done:
# log status
current_item_list = ",".join(["\"%s\"" % x["current_item"]
for x in shareddata if x is not None])
items_done = sum([x["items_done"] for x in shareddata if x is not None])
items_total = sum([x["items_total"] for x in shareddata if x is not None])
for x in shareddata if x != None])
items_done = sum([x["items_done"] for x in shareddata if x != None])
items_total = sum([x["items_total"] for x in shareddata if x != None])
progress = 100.0 * items_done / items_total if items_total != 0 else 0.0
@@ -916,23 +916,23 @@ def mbruteforce(func, alphabet, length, method = 'upto', start = None, threads =
# handle finished threads
for i in range(threads):
if processes[i] and processes[i].exitcode is not None:
if processes[i] and processes[i].exitcode != None:
# thread has terminated
res = shareddata[i]["result"]
processes[i].join()
processes[i] = None
# if successful, kill all other threads and return success
if res is not None:
if res != None:
for i in range(threads):
if processes[i] is not None:
if processes[i] != None:
processes[i].terminate()
processes[i].join()
processes[i] = None
h.success('Found key: "%s"' % res)
return res
if all([x is None for x in processes]):
if all([x == None for x in processes]):
done = True
time.sleep(0.3)
h.failure('No matches found')
+7 -30
View File
@@ -10,8 +10,6 @@ import socket
import stat
import string
import six
from pwnlib.context import context
from pwnlib.log import getLogger
from pwnlib.util import fiddling
@@ -197,9 +195,6 @@ def run_in_new_terminal(command, terminal = None, args = None):
variable), a new pane will be opened.
- If GNU Screen is detected (by the presence of the ``$STY`` environment
variable), a new screen will be opened.
- If WSL (Windows Subsystem for Linux) is detected (by the presence of
a ``wsl.exe`` binary in the ``$PATH`` and ``/proc/sys/kernel/osrelease``
containing ``Microsoft``), a new ``cmd.exe`` window will be opened.
Arguments:
command (str): The command to run.
@@ -212,6 +207,7 @@ def run_in_new_terminal(command, terminal = None, args = None):
Returns:
PID of the new terminal process
"""
if not terminal:
if context.terminal:
terminal = context.terminal[0]
@@ -219,26 +215,18 @@ def run_in_new_terminal(command, terminal = None, args = None):
elif which('pwntools-terminal'):
terminal = 'pwntools-terminal'
args = []
elif 'TMUX' in os.environ and which('tmux'):
terminal = 'tmux'
args = ['splitw']
elif 'STY' in os.environ and which('screen'):
terminal = 'screen'
args = ['-t','pwntools-gdb','bash','-c']
elif 'TERM_PROGRAM' in os.environ:
terminal = os.environ['TERM_PROGRAM']
args = []
elif 'DISPLAY' in os.environ and which('x-terminal-emulator'):
terminal = 'x-terminal-emulator'
args = ['-e']
else:
is_wsl = False
if os.path.exists('/proc/sys/kernel/osrelease'):
with open('/proc/sys/kernel/osrelease', 'rb') as f:
is_wsl = b'Microsoft' in f.read()
if is_wsl and which('cmd.exe') and which('wsl.exe') and which('bash.exe'):
terminal = 'cmd.exe'
args = ['/c', 'start', 'bash.exe', '-c']
elif 'TMUX' in os.environ and which('tmux'):
terminal = 'tmux'
args = ['splitw']
elif 'STY' in os.environ and which('screen'):
terminal = 'screen'
args = ['-t','pwntools-gdb','bash','-c']
if not terminal:
log.error('Could not find a terminal binary to use. Set context.terminal to your terminal.')
@@ -448,14 +436,3 @@ def register_sizes(regs, in_sizes):
smaller[r] = [r_ for r_ in l if sizes[r_] < sizes[r]]
return lists.concat(regs), sizes, bigger, smaller
def python_2_bytes_compatible(klass):
"""
A class decorator that defines __str__ methods under Python 2.
Under Python 3 it does nothing.
"""
if six.PY2:
if '__str__' not in klass.__dict__:
klass.__str__ = klass.__bytes__
return klass
+5 -39
View File
@@ -91,7 +91,7 @@ def getifaddrs():
`netmask` are themselves dictionaries. Their structure depend on
`family`. If `family` is not :const:`socket.AF_INET` or
:const:`socket.AF_INET6` they will be empty.
"""
"""
libc = ctypes.CDLL(ctypes.util.find_library('c'))
getifaddrs = libc.getifaddrs
getifaddrs.restype = ctypes.c_int
@@ -136,7 +136,7 @@ def interfaces(all = False):
A dictionary mapping each of the hosts interfaces to a list of it's
addresses. Each entry in the list is a tuple ``(family, addr)``, and
`family` is either :const:`socket.AF_INET` or :const:`socket.AF_INET6`.
"""
"""
out = {}
for ifa in getifaddrs():
name = ifa['name']
@@ -168,7 +168,7 @@ def interfaces4(all = False):
Examples:
>>> interfaces4(all=True) # doctest: +ELLIPSIS
{...'127.0.0.1'...}
"""
"""
out = {}
for name, addrs in interfaces(all = all).items():
addrs = [addr for fam, addr in addrs if fam == socket.AF_INET]
@@ -193,7 +193,7 @@ def interfaces6(all = False):
Examples:
>>> interfaces6() # doctest: +ELLIPSIS
{...'::1'...}
"""
"""
out = {}
for name, addrs in interfaces(all = all).items():
addrs = [addr for fam, addr in addrs if fam == socket.AF_INET6]
@@ -213,7 +213,7 @@ def sockaddr(host, port, network = 'ipv4'):
Returns:
A tuple containing the sockaddr buffer, length, and the address family.
"""
"""
address_family = {'ipv4':socket.AF_INET,'ipv6':socket.AF_INET6}[network]
for family, _, _, _, ip in socket.getaddrinfo(host, None, address_family):
@@ -237,37 +237,3 @@ def sockaddr(host, port, network = 'ipv4'):
sockaddr += host
length = len(sockaddr) + 4 # Save five bytes 'push 0'
return (sockaddr, length, getattr(address_family, "name", address_family))
def sock_match(local, remote, fam=socket.AF_UNSPEC, typ=0):
"""
Given two addresses, returns a function comparing address pairs from
psutil library against these two. Useful for filtering done in
:func:`pwnlib.util.proc.pidof`.
"""
def sockinfos(addr, f, t):
if not addr:
return set()
if f not in (socket.AF_UNSPEC, socket.AF_INET, socket.AF_INET6):
return {addr}
infos = set(socket.getaddrinfo(addr[0], addr[1], f, t))
# handle mixed IPv4-to-IPv6 and the other way round connections
for f, t, proto, _canonname, sockaddr in tuple(infos):
if f == socket.AF_INET and t != socket.SOCK_RAW:
infos |= set(socket.getaddrinfo(sockaddr[0], sockaddr[1], socket.AF_INET6, t, proto, socket.AI_V4MAPPED))
return infos
if local is not None:
local = sockinfos(local, fam, typ)
remote = sockinfos(remote, fam, typ)
def match(c):
laddrs = sockinfos(c.laddr, c.family, c.type)
raddrs = sockinfos(c.raddr, c.family, c.type)
if not (raddrs & remote):
return False
if local is None:
return True
return bool(laddrs & local)
return match
Loaded 100 of 107 files, more files were not shown because too many files have changed in this diff. Show more