mirror of
https://github.com/Gallopsled/pwntools.git
synced 2026-11-07 17:14:22 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
957a5a5835 | ||
|
|
2efb5a0a73 | ||
|
|
442fedeef0 | ||
|
|
138188eb1c | ||
|
|
5dfcb53964 | ||
|
|
5db149adc2 | ||
|
|
ddb5798b8c | ||
|
|
f1624dc8ac | ||
|
|
a824e83bcb | ||
|
|
dff2e807cd | ||
|
|
b8ca473a39 | ||
|
|
09541e042b | ||
|
|
dd92ca6c61 | ||
|
|
5e279e7993 | ||
|
|
846f98294f | ||
|
|
f227796a09 | ||
|
|
baa4fc5a9f | ||
|
|
78df70c986 | ||
|
|
53ecb27948 | ||
|
|
b5de88e118 | ||
|
|
8b1c25f441 | ||
|
|
db0312e0fe | ||
|
|
7b130aec79 | ||
|
|
13960bac08 | ||
|
|
230a42ffc0 | ||
|
|
31465d7570 | ||
|
|
07c7dd6242 | ||
|
|
6f8319519b | ||
|
|
3469f4a4f7 | ||
|
|
b22e3e611d | ||
|
|
3be97b7ab5 | ||
|
|
1a9dce025f | ||
|
|
cbb57c0148 | ||
|
|
92810cbeb2 | ||
|
|
039f2439b5 | ||
|
|
a190726caf | ||
|
|
745f8e7716 | ||
|
|
a3bf833a9a | ||
|
|
f2cb7babcf | ||
|
|
ce0966d186 | ||
|
|
d143af398e | ||
|
|
a1b0ff6b29 | ||
|
|
1b130cfe5d | ||
|
|
c3e39f57f8 | ||
|
|
ede4ed13e0 | ||
|
|
316cf359c1 | ||
|
|
343dff5c51 | ||
|
|
a0d61dcea5 | ||
|
|
f02e5b5e45 | ||
|
|
c293318cbd | ||
|
|
ddf5cdcb3f | ||
|
|
761d446fa3 | ||
|
|
5e012ebf95 | ||
|
|
7d6cb3f61f | ||
|
|
a414d788fe | ||
|
|
4134e60c8d | ||
|
|
88084975ad | ||
|
|
4b14e27523 | ||
|
|
45eb8bcc81 | ||
|
|
8b6e6ed67d | ||
|
|
18a7a9458c | ||
|
|
3cca881881 | ||
|
|
2a68da3dad | ||
|
|
9f5b24d889 | ||
|
|
e9b24a6159 | ||
|
|
39a3b2e8ff | ||
|
|
09caa4ba63 | ||
|
|
a0eeb30e0b | ||
|
|
f1628b80fe | ||
|
|
5c65b8a03e | ||
|
|
c2a61b30db | ||
|
|
82a7074d86 | ||
|
|
8a21b0306d | ||
|
|
c0afb8ef29 | ||
|
|
baed2d5bbc | ||
|
|
cccbc4555c | ||
|
|
df3835a611 | ||
|
|
758b86c4b0 | ||
|
|
16f8c419bc | ||
|
|
1eca50e421 | ||
|
|
d2e84c1a30 | ||
|
|
1c1615da2f | ||
|
|
cb4e01b4df | ||
|
|
00f65f2c53 | ||
|
|
ac2522fe91 | ||
|
|
82f20b28cf | ||
|
|
fd8ed5883e | ||
|
|
5fea8d25a8 | ||
|
|
01fb378320 | ||
|
|
3f8c92b233 | ||
|
|
c846f94c8e | ||
|
|
a5bf7c50f4 | ||
|
|
8066b2353b | ||
|
|
b81c61cae4 | ||
|
|
54d3f674e1 | ||
|
|
14f5ab6b90 | ||
|
|
555dec78d9 | ||
|
|
267879c91a | ||
|
|
2d48220165 | ||
|
|
4d9242ae89 | ||
|
|
fae86c3dec | ||
|
|
24211219d8 | ||
|
|
2c0d63b569 | ||
|
|
e254c5fa62 | ||
|
|
aba16247b4 | ||
|
|
6fc0914dc0 | ||
|
|
8137494932 | ||
|
|
baad3927b9 | ||
|
|
94647d6c10 | ||
|
|
e1aedff092 | ||
|
|
8a2b77131e | ||
|
|
b5dd858897 | ||
|
|
70d42fb076 | ||
|
|
9ede4b8eea | ||
|
|
d944a9ec68 | ||
|
|
bbd82ac6fe | ||
|
|
4439849d66 | ||
|
|
061d0fd953 | ||
|
|
43c4eef53b | ||
|
|
ef40a31ac8 | ||
|
|
59ce329431 |
No files matched your search
@@ -17,4 +17,13 @@ jobs:
|
||||
|
||||
- name: Check changelog for updates
|
||||
run: |
|
||||
git log --stat ${GITHUB_BASE}..HEAD | grep CHANGELOG.md
|
||||
if git log --stat ${GITHUB_BASE}..HEAD | grep CHANGELOG.md; then
|
||||
echo 'Changelog updated :D'
|
||||
else
|
||||
if git log --stat ${GITHUB_BASE}..HEAD | grep '++\|--'; then
|
||||
echo 'Major changes detected, changelog required!'
|
||||
false
|
||||
else
|
||||
echo 'Minor changes detected, no changelog required!'
|
||||
fi
|
||||
fi
|
||||
@@ -2,7 +2,7 @@ name: Continuous Integration
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [2.7, 3.8]
|
||||
@@ -74,11 +74,20 @@ jobs:
|
||||
binutils-arm-linux-gnueabihf \
|
||||
binutils-mips-linux-gnu \
|
||||
binutils-powerpc-linux-gnu \
|
||||
binutils-sparc64-linux-gnu \
|
||||
gcc-multilib \
|
||||
libc6-dbg \
|
||||
$ANDROID_JRE
|
||||
|
||||
- name: Install android avd
|
||||
- name: Testing Corefiles
|
||||
run: |
|
||||
ulimit -a
|
||||
ulimit -c unlimited
|
||||
cat /proc/sys/kernel/core_pattern
|
||||
cat /proc/sys/kernel/core_uses_pid
|
||||
( cd $(mktemp -d); sh -c 'kill -11 $$' || true; ls -la ./*core* /var/crash/*.crash;) || true
|
||||
|
||||
- name: Install Android AVD
|
||||
if: steps.java-needed.outputs.need
|
||||
run: |
|
||||
USER=travis source travis/install.sh
|
||||
@@ -101,13 +110,12 @@ jobs:
|
||||
- name: Install documentation dependencies
|
||||
run: pip install -r docs/requirements.txt
|
||||
|
||||
- name: Disable broken tests
|
||||
run: |
|
||||
rm -f docs/source/elf/corefile.rst
|
||||
|
||||
- name: Manually install non-broken Unicorn
|
||||
run: pip install unicorn==1.0.2rc3
|
||||
|
||||
- name: Version Check
|
||||
run: PWNLIB_NOTERM=1 pwn version
|
||||
|
||||
- name: Coverage doctests
|
||||
run: |
|
||||
source .android.env || :
|
||||
@@ -186,7 +194,7 @@ jobs:
|
||||
staging-merge:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'Gallopsled' && github.event_name == 'push' && startsWith(github.event.ref, 'refs/heads/') && endsWith(github.event.ref, '-staging')
|
||||
needs: build
|
||||
needs: test
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
@@ -199,11 +207,12 @@ jobs:
|
||||
TARGET=${BRANCH%-staging}
|
||||
git branch -f "$TARGET"
|
||||
git push origin "$TARGET"
|
||||
git push origin --delete "$BRANCH"
|
||||
|
||||
pypi:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
|
||||
needs: build
|
||||
needs: test
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
|
||||
@@ -2,7 +2,7 @@ name: Lint
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
lint:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.8]
|
||||
@@ -11,9 +11,6 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache for pip
|
||||
uses: actions/cache@v1
|
||||
id: cache-pip
|
||||
@@ -26,8 +23,13 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Lint
|
||||
- name: Critical 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__
|
||||
flake8 . --count --select=E9,F63,F7,E71 --show-source --statistics --exclude=android-?dk # TODO: Add F82
|
||||
|
||||
- name: Style lint
|
||||
run: |
|
||||
flake8 pwnlib setup.py docs travis --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
flake8 examples --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --ignore='F403,F405'
|
||||
flake8 pwn --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --ignore='F401,F403,F405'
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Check for merge markers
|
||||
on: [pull_request]
|
||||
env:
|
||||
GITHUB_BASE: origin/${{ github.event.pull_request.base.ref }}
|
||||
|
||||
jobs:
|
||||
mergecheck:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check for merge conflict markers commited
|
||||
run: |
|
||||
if git show ${GITHUB_BASE}..HEAD | grep -EB15 --color=always '^\+\+(>>>>>|=====|<<<<<)'; then
|
||||
echo 'WARNING: Merge marker commits found in history.'
|
||||
if git diff ${GITHUB_BASE}..HEAD | grep -EB15 --color=always '^\+(>>>>>|=====|<<<<<)'; then
|
||||
echo 'ERROR: Merge markers still present! Do something!'
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo 'Congrats! All the merges you did were clean or resolved correctly :)'
|
||||
fi
|
||||
@@ -20,6 +20,7 @@ addons:
|
||||
- binutils-arm-linux-gnueabihf
|
||||
- binutils-mips-linux-gnu
|
||||
- binutils-powerpc-linux-gnu
|
||||
- binutils-sparc64-linux-gnu
|
||||
- bash-static
|
||||
cache:
|
||||
- pip
|
||||
|
||||
+99
-7
@@ -9,9 +9,16 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
|
||||
| Version | Branch | Release Date |
|
||||
| ---------------- | -------- | ---------------------- |
|
||||
| [4.3.0](#430) | `dev` | Jun 30, 2020 (planned)
|
||||
| [4.2.0](#420) | `beta` | Jun 5, 2020 (planned)
|
||||
| [4.1.1](#411) | `stable` | Jun 3, 2020
|
||||
| [4.5.0](#450) | `dev` | Dec 20, 2020 (planned)
|
||||
| [4.4.0](#440) | `beta` | Nov 20, 2020 (planned)
|
||||
| [4.3.0](#430) | `stable` | Oct 20, 2020
|
||||
| [4.2.0](#420) | | Jul 3, 2020
|
||||
| [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
|
||||
@@ -49,13 +56,98 @@ The table below shows which release corresponds to each branch, and what date th
|
||||
| [3.0.0](#300) | | Aug 20, 2016
|
||||
| [2.2.0](#220) | | Jan 5, 2015
|
||||
|
||||
## 4.3.0 (`dev`)
|
||||
## 4.5.0 (`dev`)
|
||||
|
||||
To be released on Jun 30, 2020.
|
||||
- [#1261][1261] Misc `run_in_new_terminal` improvements (notably gdb terminated by default)
|
||||
- [#1695][1695] Allow using GDB Python API
|
||||
|
||||
## 4.2.0 (`beta`)
|
||||
[1261]: https://github.com/Gallopsled/pwntools/pull/1261
|
||||
[1695]: https://github.com/Gallopsled/pwntools/pull/1695
|
||||
|
||||
To be released on Jun 5, 2020.
|
||||
## 4.4.0 (`beta`)
|
||||
|
||||
- [#1541][1541] Use `context.newline` for tubes by default
|
||||
- [#1602][1602] Fix bytes handling in ssh tubes
|
||||
- [#1606][1606] Fix `asm()` and `disasm()` for MSP430, S390
|
||||
- [#1616][1616] Fix `cyclic` cli for 64 bit integers
|
||||
- [#1632][1632] Enable usage of Pwntools in jupyter
|
||||
- [#1633][1633] Open a shell if `pwn template` cannot download the remote file
|
||||
- [#1644][1644] Enable and support SNI for SSL-wrapped tubes
|
||||
- [#1651][1651] Make `pwn shellcraft` faster
|
||||
- [#1654][1654] Docker images (`pwntools/pwntools:stable` etc) now use Python3 by default, and includes assemblers for a few common architectures
|
||||
- [#1667][1667] Add i386 encoder `ascii_shellcode` (Fixed docs in #1693)
|
||||
- Fix syscall instruction lists for SROP on `i386` and `amd64`
|
||||
- Fix migration to another ROP
|
||||
- [#1673][1673] Add `base=` argument to `ROP.chain()` and `ROP.dump()`
|
||||
- [#1675][1675] Gdbserver now correctly accepts multiple libraries in `LD_PRELOAD` and `LD_LIBRARY_PATH`
|
||||
- [#1678][1678] ROPGadget multibr
|
||||
- [#1682][1682] ROPGadget multibr fix
|
||||
- [#1687][1687] Actually import `requests` when doing `from pwn import *`
|
||||
- [#1688][1688] Add `__setattr__` and `__call__` interfaces to `ROP` for setting registers
|
||||
- [#1692][1692] Remove python2 shebangs where appropriate
|
||||
- [#1703][1703] Update libcdb buildid offsets for amd64 and i386
|
||||
- [#1704][1704] Try https://libc.rip/ for libcdb lookup
|
||||
|
||||
[1541]: https://github.com/Gallopsled/pwntools/pull/1541
|
||||
[1602]: https://github.com/Gallopsled/pwntools/pull/1602
|
||||
[1606]: https://github.com/Gallopsled/pwntools/pull/1606
|
||||
[1616]: https://github.com/Gallopsled/pwntools/pull/1616
|
||||
[1632]: https://github.com/Gallopsled/pwntools/pull/1632
|
||||
[1633]: https://github.com/Gallopsled/pwntools/pull/1633
|
||||
[1644]: https://github.com/Gallopsled/pwntools/pull/1644
|
||||
[1651]: https://github.com/Gallopsled/pwntools/pull/1651
|
||||
[1654]: https://github.com/Gallopsled/pwntools/pull/1654
|
||||
[1667]: https://github.com/Gallopsled/pwntools/pull/1667
|
||||
[1673]: https://github.com/Gallopsled/pwntools/pull/1673
|
||||
[1675]: https://github.com/Gallopsled/pwntools/pull/1675
|
||||
[1678]: https://github.com/Gallopsled/pwntools/pull/1678
|
||||
[1682]: https://github.com/Gallopsled/pwntools/pull/1679
|
||||
[1687]: https://github.com/Gallopsled/pwntools/pull/1687
|
||||
[1688]: https://github.com/Gallopsled/pwntools/pull/1688
|
||||
[1692]: https://github.com/Gallopsled/pwntools/pull/1692
|
||||
[1703]: https://github.com/Gallopsled/pwntools/pull/1703
|
||||
[1704]: https://github.com/Gallopsled/pwntools/pull/1704
|
||||
|
||||
## 4.3.1 (`stable`)
|
||||
|
||||
- [#1732][1732] Fix shellcraft SSTI vulnerability (first major pwntools vuln!)
|
||||
|
||||
[1732]: https://github.com/Gallopsled/pwntools/pull/1732
|
||||
|
||||
## 4.3.0
|
||||
|
||||
- [#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`
|
||||
- [#1616][1616] Fix `cyclic` cli for 64 bit integers
|
||||
- [#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
|
||||
[1616]: https://github.com/Gallopsled/pwntools/pull/1616
|
||||
[1564]: https://github.com/Gallopsled/pwntools/pull/1564
|
||||
[1621]: https://github.com/Gallopsled/pwntools/pull/1621
|
||||
|
||||
## 4.2.1
|
||||
|
||||
- [#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)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# pwntools - CTF toolkit
|
||||

|
||||
|
||||
[](https://docs.pwntools.com/)
|
||||
[](https://pypi.python.org/pypi/pwntools/)
|
||||
[](https://travis-ci.org/Gallopsled/pwntools)
|
||||
[](https://coveralls.io/github/Gallopsled/pwntools?branch=dev)
|
||||
[](https://twitter.com/pwntools)
|
||||
[](https://docs.pwntools.com/)
|
||||
[](https://travis-ci.org/Gallopsled/pwntools)
|
||||

|
||||
[](https://coveralls.io/github/Gallopsled/pwntools?branch=dev)
|
||||
[](http://choosealicense.com/licenses/mit/)
|
||||
[](https://twitter.com/pwntools)
|
||||
|
||||
Pwntools is a CTF framework and exploit development library. Written in Python, it is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.
|
||||
|
||||
@@ -20,10 +21,6 @@ r.send(asm(shellcraft.sh()))
|
||||
r.interactive()
|
||||
```
|
||||
|
||||
# Try It Now!
|
||||
|
||||
You can now do a live demo of Pwntools, [right in your browser](https://demo.pwntools.com).
|
||||
|
||||
# Documentation
|
||||
|
||||
Our documentation is available at [docs.pwntools.com](https://docs.pwntools.com/)
|
||||
@@ -32,7 +29,7 @@ To get you started, we've provided some example solutions for past CTF challenge
|
||||
|
||||
# Installation
|
||||
|
||||
Pwntools is best supported on 64-bit Ubuntu LTE releases (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 (14.04, 16.04, 18.04, and 20.04). Most functionality should work on any Posix-like distribution (Debian, Arch, FreeBSD, OSX, etc.). Python >= 2.7 is required (Python 3 suggested as best).
|
||||
|
||||
Most of the functionality of pwntools is self-contained and Python-only. You should be able to get running quickly with
|
||||
|
||||
@@ -40,7 +37,7 @@ Most of the functionality of pwntools is self-contained and Python-only. You sh
|
||||
apt-get update
|
||||
apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install --upgrade git+https://github.com/Gallopsled/pwntools.git@dev
|
||||
python3 -m 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
-8
@@ -340,7 +340,7 @@ def linkcode_resolve(domain, info):
|
||||
val = mod
|
||||
for k in info['fullname'].split('.'):
|
||||
val = getattr(val, k, None)
|
||||
if val == None:
|
||||
if val is None:
|
||||
break
|
||||
|
||||
# Special case for shellcraft
|
||||
@@ -410,13 +410,6 @@ def py2_doctest_init(self, checker=None, verbose=None, optionflags=0):
|
||||
checker = Py2OutputChecker()
|
||||
doctest.DocTestRunner.__init__(self, checker, verbose, optionflags)
|
||||
|
||||
class EndlessLoop(Exception): pass
|
||||
def alrm_handler(sig, frame):
|
||||
signal.alarm(180) # three minutes
|
||||
raise EndlessLoop()
|
||||
signal.signal(signal.SIGALRM, alrm_handler)
|
||||
signal.alarm(600) # ten minutes
|
||||
|
||||
if 'doctest' in sys.argv:
|
||||
def setup(app):
|
||||
app.connect('autodoc-skip-member', dont_skip_any_doctests)
|
||||
|
||||
+16
-16
@@ -17,19 +17,19 @@
|
||||
count ,
|
||||
cycle ,
|
||||
dropwhile ,
|
||||
filter ,
|
||||
filterfalse ,
|
||||
groupby ,
|
||||
ifilter ,
|
||||
ifilterfalse ,
|
||||
imap ,
|
||||
islice ,
|
||||
izip ,
|
||||
izip_longest ,
|
||||
map ,
|
||||
permutations ,
|
||||
product ,
|
||||
repeat ,
|
||||
starmap ,
|
||||
takewhile ,
|
||||
tee
|
||||
tee ,
|
||||
zip ,
|
||||
zip_longest
|
||||
|
||||
.. function:: chain
|
||||
|
||||
@@ -63,29 +63,29 @@
|
||||
|
||||
Alias for :func:`itertools.groupby`
|
||||
|
||||
.. function:: ifilter
|
||||
.. function:: filter
|
||||
|
||||
Alias for :func:`itertools.ifilter`
|
||||
Alias for python3-style :func:`filter`
|
||||
|
||||
.. function:: ifilterfalse
|
||||
.. function:: filterfalse
|
||||
|
||||
Alias for :func:`itertools.ifilterfalse`
|
||||
Alias for :func:`itertools.filterfalse`
|
||||
|
||||
.. function:: imap
|
||||
.. function:: map
|
||||
|
||||
Alias for :func:`itertools.imap`
|
||||
Alias for python3-style :func:`map`
|
||||
|
||||
.. function:: islice
|
||||
|
||||
Alias for :func:`itertools.islice`
|
||||
|
||||
.. function:: izip
|
||||
.. function:: zip
|
||||
|
||||
Alias for :func:`itertools.izip`
|
||||
Alias for python3-style :func:`zip`
|
||||
|
||||
.. function:: izip_longest
|
||||
.. function:: zip_longest
|
||||
|
||||
Alias for :func:`itertools.izip_longest`
|
||||
Alias for :func:`itertools.zip_longest`
|
||||
|
||||
.. function:: permutations
|
||||
|
||||
|
||||
@@ -36,5 +36,14 @@ print(shell.echo("single string"))
|
||||
print(shell.echo(["list","of","strings"]))
|
||||
print(shell["echo single statement"])
|
||||
|
||||
# ssh.process() is the most flexible way to run a command)
|
||||
io = shell.process(['/bin/bash', '-c', 'echo Hello $FOO'],
|
||||
env={'FOO': 'World'}, # Set environment
|
||||
stderr='/dev/null', # Override file descriptors
|
||||
aslr=False, # Disable ASLR on processes
|
||||
setuid=False, # Disable setuid bit so processes can be debugged
|
||||
shell=False) # Enable or disable shell evaluation
|
||||
print(io.recvall())
|
||||
|
||||
# Show off the interactive shell
|
||||
shell.interactive()
|
||||
+1
-1
@@ -1 +1 @@
|
||||
xenial
|
||||
bionic
|
||||
@@ -0,0 +1,26 @@
|
||||
############################################################
|
||||
# Dockerfile to build Pwntools container
|
||||
# Based on Ubuntu
|
||||
############################################################
|
||||
|
||||
FROM ubuntu:bionic
|
||||
MAINTAINER Maintainer Gallopsled et al.
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
build-essential \
|
||||
git \
|
||||
libssl-dev \
|
||||
libffi-dev \
|
||||
python2.7 \
|
||||
python-pip \
|
||||
python-dev \
|
||||
&& pip install --upgrade pip \
|
||||
&& python -m pip install --upgrade pwntools \
|
||||
&& PWNLIB_NOTERM=1 pwn update \
|
||||
&& apt-get install -y sudo \
|
||||
&& useradd -m pwntools \
|
||||
&& passwd --delete --unlock pwntools \
|
||||
&& echo "pwntools ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/pwntools
|
||||
USER pwntools
|
||||
WORKDIR /home/pwntools
|
||||
+1
-1
@@ -80,4 +80,4 @@ info = log.info
|
||||
debug = log.debug
|
||||
success = log.success
|
||||
|
||||
__all__ = [x for x in globals().keys() if x != '__name__']
|
||||
__all__ = [x for x in tuple(globals()) if x != '__name__']
|
||||
+6
-4
@@ -827,10 +827,12 @@ def which(name, all = False, *a, **kw):
|
||||
"""
|
||||
# Unfortunately, there is no native 'which' on many phones.
|
||||
which_cmd = '''
|
||||
echo $PATH | while read -d: directory; do
|
||||
[ -x "$directory/{name}" ] || continue;
|
||||
echo -n "$directory/{name}\\x00";
|
||||
done
|
||||
(IFS=:
|
||||
for directory in $PATH; do
|
||||
[ -x "$directory/{name}" ] || continue;
|
||||
echo -n "$directory/{name}\\x00";
|
||||
done
|
||||
)
|
||||
[ -x "{name}" ] && echo -n "$PWD/{name}\\x00"
|
||||
'''.format(name=name)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import division
|
||||
import ctypes
|
||||
import io
|
||||
import os
|
||||
import six
|
||||
import sys
|
||||
|
||||
from pwnlib.log import getLogger
|
||||
@@ -64,7 +65,7 @@ class BootloaderImage(object):
|
||||
Returns:
|
||||
Contents of the image.
|
||||
"""
|
||||
if isinstance(index_or_name, int):
|
||||
if isinstance(index_or_name, six.integer_types):
|
||||
index = index_or_name
|
||||
else:
|
||||
for i in range(len(self.img_info)):
|
||||
|
||||
+29
-14
@@ -167,6 +167,9 @@ def which_binutils(util):
|
||||
'i386': ['x86_64', 'amd64'],
|
||||
'i686': ['x86_64', 'amd64'],
|
||||
'amd64': ['x86_64', 'i386'],
|
||||
'mips64': ['mips'],
|
||||
'powerpc64': ['powerpc'],
|
||||
'sparc64': ['sparc'],
|
||||
}.get(arch, [])
|
||||
|
||||
# If one of the candidate architectures matches the native
|
||||
@@ -190,16 +193,18 @@ def which_binutils(util):
|
||||
for gutil in utils:
|
||||
# e.g. objdump
|
||||
if arch is None:
|
||||
pattern = gutil
|
||||
patterns = [gutil]
|
||||
|
||||
# e.g. aarch64-linux-gnu-objdump
|
||||
# e.g. aarch64-linux-gnu-objdump, avr-objdump
|
||||
else:
|
||||
pattern = '%s*linux*-%s' % (arch,gutil)
|
||||
patterns = ['%s*linux*-%s' % (arch, gutil),
|
||||
'%s-%s' % (arch, gutil)]
|
||||
|
||||
for dir in environ['PATH'].split(':'):
|
||||
res = sorted(glob(path.join(dir, pattern)))
|
||||
if res:
|
||||
return res[0]
|
||||
for pattern in patterns:
|
||||
for dir in environ['PATH'].split(':'):
|
||||
res = sorted(glob(path.join(dir, pattern)))
|
||||
if res:
|
||||
return res[0]
|
||||
|
||||
# No dice!
|
||||
print_binutils_instructions(util, context)
|
||||
@@ -245,9 +250,9 @@ def _assembler():
|
||||
stderr=subprocess.STDOUT, universal_newlines=True)
|
||||
version = re.search(r' (\d\.\d+)', result).group(1)
|
||||
if version < '2.19':
|
||||
log.warn_once('Your binutils version is too old and may not work!\n' + \
|
||||
'Try updating with: https://docs.pwntools.com/en/stable/install/binutils.html\n' + \
|
||||
'Reported Version: %r' % result.strip())
|
||||
log.warn_once('Your binutils version is too old and may not work!\n'
|
||||
'Try updating with: https://docs.pwntools.com/en/stable/install/binutils.html\n'
|
||||
'Reported Version: %r', result.strip())
|
||||
|
||||
|
||||
return assembler
|
||||
@@ -322,6 +327,7 @@ def _bfdname():
|
||||
'amd64' : 'elf64-x86-64',
|
||||
'arm' : 'elf32-%sarm' % E,
|
||||
'thumb' : 'elf32-%sarm' % E,
|
||||
'avr' : 'elf32-avr',
|
||||
'mips' : 'elf32-trad%smips' % E,
|
||||
'mips64' : 'elf64-trad%smips' % E,
|
||||
'alpha' : 'elf64-alpha',
|
||||
@@ -344,10 +350,13 @@ def _bfdname():
|
||||
def _bfdarch():
|
||||
arch = context.arch
|
||||
convert = {
|
||||
'i386': 'i386',
|
||||
'amd64': 'i386:x86-64',
|
||||
'thumb': 'arm',
|
||||
'ia64': 'ia64-elf64'
|
||||
'amd64': 'i386:x86-64',
|
||||
'i386': 'i386',
|
||||
'ia64': 'ia64-elf64',
|
||||
'mips64': 'mips',
|
||||
'powerpc64': 'powerpc',
|
||||
'sparc64': 'sparc',
|
||||
'thumb': 'arm',
|
||||
}
|
||||
|
||||
if arch in convert:
|
||||
@@ -749,6 +758,12 @@ def disasm(data, vma = 0, byte = True, offset = True, instructions = True):
|
||||
>>> print(disasm(unhex('656664676665400F18A4000000000051'), byte=0, arch='amd64'))
|
||||
0: gs data16 fs data16 rex nop/reserved BYTE PTR gs:[eax+eax*1+0x0]
|
||||
f: push rcx
|
||||
>>> print(disasm(unhex('01000000'), arch='sparc64'))
|
||||
0: 01 00 00 00 nop
|
||||
>>> print(disasm(unhex('60000000'), arch='powerpc64'))
|
||||
0: 60 00 00 00 nop
|
||||
>>> print(disasm(unhex('00000000'), arch='mips64'))
|
||||
0: 00000000 nop
|
||||
"""
|
||||
result = ''
|
||||
|
||||
|
||||
@@ -18,5 +18,6 @@ __all__ = [
|
||||
'scramble',
|
||||
'shellcraft',
|
||||
'unhex',
|
||||
'update'
|
||||
'update',
|
||||
'version'
|
||||
]
|
||||
Regular → Executable
+12
-24
@@ -4,7 +4,6 @@ from __future__ import division
|
||||
|
||||
import argparse
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
|
||||
import pwnlib
|
||||
@@ -19,25 +18,22 @@ p = common.parser_commands.add_parser(
|
||||
formatter_class = argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
|
||||
group = p.add_mutually_exclusive_group()
|
||||
group.add_argument(
|
||||
p.add_argument(
|
||||
'-e', '--exact',
|
||||
metavar = 'constant',
|
||||
# nargs = 1,
|
||||
default = None,
|
||||
help = 'Do an exact match for a constant instead of searching for a regex',
|
||||
action='store_true',
|
||||
help='Do an exact match for a constant instead of searching for a regex',
|
||||
)
|
||||
group.add_argument(
|
||||
|
||||
p.add_argument(
|
||||
'regex',
|
||||
nargs = '?',
|
||||
default = '',
|
||||
help = 'The regex matching constant you want to find',
|
||||
help='The regex matching constant you want to find',
|
||||
)
|
||||
|
||||
p.add_argument(
|
||||
'constant',
|
||||
nargs = '?',
|
||||
default = None,
|
||||
type = safeeval.expr,
|
||||
help = 'The constant to find',
|
||||
)
|
||||
|
||||
@@ -65,7 +61,7 @@ p.add_argument(
|
||||
def main(args):
|
||||
if args.exact:
|
||||
# This is the simple case
|
||||
print(cpp(args.exact).strip())
|
||||
print(cpp(args.regex).strip())
|
||||
else:
|
||||
# New we search in the right module.
|
||||
# But first: We find the right module
|
||||
@@ -80,20 +76,12 @@ def main(args):
|
||||
else:
|
||||
matcher = re.compile(args.regex)
|
||||
|
||||
|
||||
# Evaluate the given constant
|
||||
if args.constant:
|
||||
try:
|
||||
constant = safeeval.expr(args.constant)
|
||||
except:
|
||||
log.error("Could not evaluate constant %r" % args.constant)
|
||||
else:
|
||||
constant = None
|
||||
|
||||
# The found matching constants and the length of the longest string
|
||||
out = []
|
||||
maxlen = 0
|
||||
|
||||
constant = args.constant
|
||||
|
||||
for k in dir(mod):
|
||||
# No python stuff
|
||||
if k.endswith('__') and k.startswith('__'):
|
||||
@@ -104,7 +92,7 @@ def main(args):
|
||||
continue
|
||||
|
||||
# Check the constant
|
||||
if constant != None:
|
||||
if constant is not None:
|
||||
val = getattr(mod, k)
|
||||
if args.mask_mode:
|
||||
if constant & val != val:
|
||||
@@ -124,7 +112,7 @@ def main(args):
|
||||
# If we are in match_mode, then try to find a combination of
|
||||
# constants that yield the exact given value
|
||||
# We do not want to find combinations using the value 0.
|
||||
if not (constant == None or constant == 0) and args.mask_mode:
|
||||
if constant and args.mask_mode:
|
||||
mask = constant
|
||||
good = []
|
||||
out = [(v, k) for v, k in out if v != 0]
|
||||
|
||||
@@ -21,6 +21,7 @@ from pwnlib.commandline import shellcraft
|
||||
from pwnlib.commandline import template
|
||||
from pwnlib.commandline import unhex
|
||||
from pwnlib.commandline import update
|
||||
from pwnlib.commandline import version
|
||||
from pwnlib.commandline.common import parser
|
||||
from pwnlib.context import context
|
||||
|
||||
@@ -43,6 +44,7 @@ commands = {
|
||||
'template': template.main,
|
||||
'unhex': unhex.main,
|
||||
'update': update.main,
|
||||
'version': version.main,
|
||||
}
|
||||
|
||||
def main():
|
||||
|
||||
@@ -18,9 +18,10 @@ parser.add_argument('exe', nargs='?', help='Target binary')
|
||||
parser.add_argument('--host', help='Remote host / SSH server')
|
||||
parser.add_argument('--port', help='Remote port / SSH port', type=int)
|
||||
parser.add_argument('--user', help='SSH Username')
|
||||
parser.add_argument('--pass', help='SSH Password', dest='password')
|
||||
parser.add_argument('--pass', '--password', help='SSH Password', dest='password')
|
||||
parser.add_argument('--path', help='Remote path of file on SSH server')
|
||||
parser.add_argument('--quiet', help='Less verbose template comments', action='store_true')
|
||||
parser.add_argument('--color', help='Print the output in color', choices=['never', 'always', 'auto'], default='auto')
|
||||
|
||||
def main(args):
|
||||
cache = None
|
||||
@@ -57,8 +58,16 @@ def main(args):
|
||||
# Fix Mako formatting bs
|
||||
output = re.sub('\n\n\n', '\n\n', output)
|
||||
|
||||
# Colorize the output if it's a TTY
|
||||
if args.color == 'always' or (args.color == 'auto' and sys.stdout.isatty()):
|
||||
from pygments import highlight
|
||||
from pygments.formatters import TerminalFormatter
|
||||
from pygments.lexers.python import PythonLexer
|
||||
output = highlight(output, PythonLexer(), TerminalFormatter())
|
||||
|
||||
print(output)
|
||||
|
||||
# If redirected to a file, make the resulting script executable
|
||||
if not sys.stdout.isatty():
|
||||
try: os.fchmod(sys.stdout.fileno(), 0o700)
|
||||
except OSError: pass
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import pwnlib
|
||||
pwnlib.args.free_form = False
|
||||
|
||||
from pwn import *
|
||||
from pwnlib.commandline import common
|
||||
|
||||
parser = common.parser_commands.add_parser(
|
||||
'version',
|
||||
help = 'Pwntools version'
|
||||
)
|
||||
|
||||
def main(a):
|
||||
version = pwnlib.version
|
||||
|
||||
git_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
if os.path.exists(os.path.join(git_root, '.git')):
|
||||
gitver = subprocess.check_output(['git', '-C', git_root, 'log', '-1', '--format=%h (%cr)'])
|
||||
branch = subprocess.check_output(['git', '-C', git_root, 'rev-parse', '--abbrev-ref', 'HEAD'])
|
||||
version = '%s-%s-%s' % (version, branch.decode().strip(), gitver.decode())
|
||||
|
||||
log.info("Pwntools v%s" % version)
|
||||
|
||||
if __name__ == '__main__':
|
||||
pwnlib.commandline.common.main(__file__)
|
||||
@@ -92,7 +92,7 @@ class ConstantsModule(ModuleType):
|
||||
# Special case for __all__, we want to return the contextually
|
||||
# relevant module.
|
||||
if key == '__all__':
|
||||
return self.guess().__dict__.keys()
|
||||
return list(self.guess().__dict__.keys())
|
||||
|
||||
# Special case for all other special properties which aren't defined
|
||||
if key.endswith('__'):
|
||||
@@ -145,7 +145,13 @@ class ConstantsModule(ModuleType):
|
||||
if key not in self._env_store:
|
||||
self._env_store[key] = {key: getattr(self, key) for key in dir(self) if not key.endswith('__')}
|
||||
|
||||
return Constant('(%s)' % string, safeeval.values(string, self._env_store[key]))
|
||||
val = safeeval.values(string, self._env_store[key])
|
||||
|
||||
# if the expression is not assembly-safe, it is not so vital to preserve it
|
||||
if set(string) & (set(bytearray(range(32)).decode()) | set('"#$\',.;@[\\]`{}')):
|
||||
string = val
|
||||
|
||||
return Constant('(%s)' % string, val)
|
||||
|
||||
|
||||
# To prevent garbage collection
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import absolute_import
|
||||
from pwnlib.data.elf import fmtstr
|
||||
from pwnlib.data.elf import relro
|
||||
from pwnlib.data.elf import ret2dlresolve
|
||||
|
||||
import os
|
||||
path = os.path.dirname(__file__)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
all: i386 amd64
|
||||
|
||||
i386: vuln.c
|
||||
gcc "$^" -fno-stack-protector -no-pie -m32 -o $@
|
||||
|
||||
amd64: vuln.c
|
||||
gcc "$^" -fno-stack-protector -no-pie -o $@
|
||||
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
path = os.path.dirname(__file__)
|
||||
|
||||
def get(x):
|
||||
return os.path.join(path, x)
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
#include <unistd.h>
|
||||
void vuln(void){
|
||||
char buf[64];
|
||||
read(STDIN_FILENO, buf, 200);
|
||||
}
|
||||
int main(int argc, char** argv){
|
||||
vuln();
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python2
|
||||
from __future__ import division
|
||||
import argparse
|
||||
import keyword
|
||||
import os
|
||||
|
||||
from pwnlib import constants
|
||||
@@ -62,7 +63,7 @@ CALL = """
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -75,8 +76,8 @@ CALL = """
|
||||
|
||||
# The argument is not a register. It is a string value, and we
|
||||
# are expecting a string value
|
||||
elif name in can_pushstr and isinstance(arg, (bytes, six.text_type)):
|
||||
if not isinstance(arg, bytes):
|
||||
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
|
||||
if isinstance(arg, six.text_type):
|
||||
arg = arg.encode('utf-8')
|
||||
string_arguments[name] = arg
|
||||
|
||||
@@ -144,12 +145,11 @@ def can_be_array(arg):
|
||||
|
||||
|
||||
def fix_bad_arg_names(func, arg):
|
||||
if arg.name == 'str':
|
||||
return 'str_'
|
||||
if arg.name == 'len':
|
||||
return 'length'
|
||||
if arg.name == 'repr':
|
||||
return 'repr_'
|
||||
|
||||
if arg.name in ('str', 'repr') or keyword.iskeyword(arg.name):
|
||||
return arg.name + '_'
|
||||
|
||||
if func.name == 'open' and arg.name == 'vararg':
|
||||
return 'mode'
|
||||
@@ -277,8 +277,10 @@ def generate_one(target):
|
||||
CALL.format(**template_variables)
|
||||
]
|
||||
|
||||
with open(os.path.join(target, name + '.asm'), 'wt+') as f:
|
||||
f.write('\n'.join(map(str.strip, lines)))
|
||||
if keyword.iskeyword(name):
|
||||
name += '_'
|
||||
with open(os.path.join(target, name + '.asm'), 'wt') as f:
|
||||
f.write('\n'.join(map(str.strip, lines)) + '\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
p = argparse.ArgumentParser()
|
||||
|
||||
@@ -21,8 +21,8 @@ class KernelConfig(object):
|
||||
self.excludes = set(excludes)
|
||||
|
||||
#: Kernel version that this check should be enforced on
|
||||
self.minver = map(int, str(minver).split('.'))
|
||||
self.maxver = map(int, str(maxver).split('.'))
|
||||
self.minver = list(map(int, str(minver).split('.')))
|
||||
self.maxver = list(map(int, str(maxver).split('.')))
|
||||
|
||||
def relevant(self, config):
|
||||
|
||||
|
||||
+10
-10
@@ -219,8 +219,8 @@ class Mapping(object):
|
||||
stop += self.stop
|
||||
|
||||
if not (self.start <= start <= stop <= self.stop):
|
||||
log.error("Byte range [%#x:%#x] not within range [%#x:%#x]" \
|
||||
% (start, stop, self.start, self.stop))
|
||||
log.error("Byte range [%#x:%#x] not within range [%#x:%#x]",
|
||||
start, stop, self.start, self.stop)
|
||||
|
||||
data = self._core.read(start, stop-start)
|
||||
|
||||
@@ -431,7 +431,7 @@ class Corefile(ELF):
|
||||
|
||||
Corefiles can also be pulled from remote machines via SSH!
|
||||
|
||||
>>> s = ssh(host='example.pwnme')
|
||||
>>> s = ssh(user='travis', host='example.pwnme', password='demopass')
|
||||
>>> _ = s.set_working_directory()
|
||||
>>> elf = ELF.from_assembly(shellcraft.trap())
|
||||
>>> path = s.upload(elf.path)
|
||||
@@ -551,15 +551,15 @@ class Corefile(ELF):
|
||||
self.load_addr = 0
|
||||
self._address = 0
|
||||
|
||||
if not self.elftype == 'CORE':
|
||||
if self.elftype != 'CORE':
|
||||
log.error("%s is not a valid corefile" % self.file.name)
|
||||
|
||||
if not self.arch in prstatus_types.keys():
|
||||
if self.arch not in prstatus_types:
|
||||
log.warn_once("%s does not use a supported corefile architecture, registers are unavailable" % self.file.name)
|
||||
|
||||
prstatus_type = prstatus_types.get(self.arch, None)
|
||||
prpsinfo_type = prpsinfo_types.get(self.bits, None)
|
||||
siginfo_type = siginfo_types.get(self.bits, None)
|
||||
prstatus_type = prstatus_types.get(self.arch)
|
||||
prpsinfo_type = prpsinfo_types.get(self.bits)
|
||||
siginfo_type = siginfo_types.get(self.bits)
|
||||
|
||||
with log.waitfor("Parsing corefile...") as w:
|
||||
self._load_mappings()
|
||||
@@ -669,8 +669,8 @@ class Corefile(ELF):
|
||||
continue
|
||||
|
||||
if mapping.start == self.at_sysinfo_ehdr \
|
||||
or (not vdso and mapping.size in [0x1000, 0x2000] \
|
||||
and mapping.flags == 5 \
|
||||
or (not vdso and mapping.size in [0x1000, 0x2000]
|
||||
and mapping.flags == 5
|
||||
and self.read(mapping.start, 4) == b'\x7fELF'):
|
||||
mapping.name = '[vdso]'
|
||||
vdso = True
|
||||
|
||||
+48
-14
@@ -90,6 +90,12 @@ log = getLogger(__name__)
|
||||
|
||||
__all__ = ['load', 'ELF']
|
||||
|
||||
def _iter_symbols(sec):
|
||||
# Cache result of iter_symbols.
|
||||
if not hasattr(sec, '_symbols'):
|
||||
sec._symbols = list(sec.iter_symbols())
|
||||
return iter(sec._symbols)
|
||||
|
||||
class Function(object):
|
||||
"""Encapsulates information about a function in an :class:`.ELF` binary.
|
||||
|
||||
@@ -269,6 +275,9 @@ class ELF(ELFFile):
|
||||
self.arch = 'mips64'
|
||||
self.bits = 64
|
||||
|
||||
self._sections = None
|
||||
self._segments = None
|
||||
|
||||
#: IntervalTree which maps all of the loaded memory segments
|
||||
self.memory = intervaltree.IntervalTree()
|
||||
self._populate_memory()
|
||||
@@ -310,7 +319,7 @@ class ELF(ELFFile):
|
||||
config = gz.read()
|
||||
|
||||
if config:
|
||||
self.config = parse_kconfig(config)
|
||||
self.config = parse_kconfig(config.decode())
|
||||
|
||||
#: ``True`` if the ELF is a statically linked executable
|
||||
self.statically_linked = bool(self.elftype == 'EXEC' and self.load_addr)
|
||||
@@ -455,9 +464,6 @@ class ELF(ELFFile):
|
||||
self.checksec(*a, **kw)
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return "ELF(%r)" % self.path
|
||||
|
||||
def get_machine_arch(self):
|
||||
return {
|
||||
'EM_X86_64': 'amd64',
|
||||
@@ -485,6 +491,13 @@ class ELF(ELFFile):
|
||||
""":class:`str`: ELF type (``EXEC``, ``DYN``, etc)"""
|
||||
return describe_e_type(self.header.e_type).split()[0]
|
||||
|
||||
def iter_segments(self):
|
||||
# Yield and cache all the segments in the file
|
||||
if self._segments is None:
|
||||
self._segments = [self.get_segment(i) for i in range(self.num_segments())]
|
||||
|
||||
return iter(self._segments)
|
||||
|
||||
@property
|
||||
def segments(self):
|
||||
"""
|
||||
@@ -537,6 +550,13 @@ class ELF(ELFFile):
|
||||
|
||||
return None
|
||||
|
||||
def iter_sections(self):
|
||||
# Yield and cache all the sections in the file
|
||||
if self._sections is None:
|
||||
self._sections = [self.get_section(i) for i in range(self.num_sections())]
|
||||
|
||||
return iter(self._sections)
|
||||
|
||||
@property
|
||||
def sections(self):
|
||||
"""
|
||||
@@ -842,7 +862,7 @@ class ELF(ELFFile):
|
||||
if not isinstance(sec, SymbolTableSection):
|
||||
continue
|
||||
|
||||
for sym in sec.iter_symbols():
|
||||
for sym in _iter_symbols(sec):
|
||||
# Avoid duplicates
|
||||
if sym.name in self.functions:
|
||||
continue
|
||||
@@ -866,7 +886,7 @@ class ELF(ELFFile):
|
||||
if not isinstance(section, SymbolTableSection):
|
||||
continue
|
||||
|
||||
for symbol in section.iter_symbols():
|
||||
for symbol in _iter_symbols(section):
|
||||
value = symbol.entry.st_value
|
||||
if not value:
|
||||
continue
|
||||
@@ -907,7 +927,7 @@ class ELF(ELFFile):
|
||||
if self.statically_linked:
|
||||
return
|
||||
|
||||
for section in self.iter_sections():
|
||||
for section in self.sections:
|
||||
# We are only interested in relocations
|
||||
if not isinstance(section, RelocationSection):
|
||||
continue
|
||||
@@ -961,7 +981,7 @@ class ELF(ELFFile):
|
||||
|
||||
# Iterate over the dynamic symbol table
|
||||
dynsym = self.get_section_by_name('.dynsym')
|
||||
symbol_iter = dynsym.iter_symbols()
|
||||
symbol_iter = _iter_symbols(dynsym)
|
||||
|
||||
# 'gotsym' is the index of the first GOT symbol
|
||||
gotsym = self.dynamic_value_by_tag('DT_MIPS_GOTSYM')
|
||||
@@ -1003,9 +1023,10 @@ class ELF(ELFFile):
|
||||
# In particular, this is where EBX points when it points into the GOT.
|
||||
dt_pltgot = self.dynamic_value_by_tag('DT_PLTGOT') or 0
|
||||
|
||||
# There are two PLTs we may need to search
|
||||
# There are three PLTs we may need to search
|
||||
plt = self.get_section_by_name('.plt') # <-- Functions only
|
||||
plt_got = self.get_section_by_name('.plt.got') # <-- Functions used as data
|
||||
plt_sec = self.get_section_by_name('.plt.sec')
|
||||
plt_mips = self.get_section_by_name('.MIPS.stubs')
|
||||
|
||||
# Invert the GOT symbols we already have, so we can look up by address
|
||||
@@ -1013,7 +1034,7 @@ class ELF(ELFFile):
|
||||
inv_symbols.update({v:k for k,v in self.symbols.items()})
|
||||
|
||||
with context.local(arch=self.arch, bits=self.bits, endian=self.endian):
|
||||
for section in (plt, plt_got, plt_mips):
|
||||
for section in (plt, plt_got, plt_sec, plt_mips):
|
||||
if not section:
|
||||
continue
|
||||
|
||||
@@ -1034,7 +1055,10 @@ class ELF(ELFFile):
|
||||
return
|
||||
|
||||
banner = self.string(self.symbols.linux_banner)
|
||||
|
||||
|
||||
# convert banner into a utf-8 string since re.search does not accept bytes anymore
|
||||
banner = banner.decode('utf-8')
|
||||
|
||||
# 'Linux version 3.18.31-gd0846ecc
|
||||
regex = r'Linux version (\S+)'
|
||||
match = re.search(regex, banner)
|
||||
@@ -1092,8 +1116,8 @@ class ELF(ELFFile):
|
||||
return_from_main = int(return_from_main[ : return_from_main.index(':') ], 16)
|
||||
return return_from_main
|
||||
|
||||
def search(self, needle, writable = False):
|
||||
"""search(needle, writable = False) -> generator
|
||||
def search(self, needle, writable = False, executable = False):
|
||||
"""search(needle, writable = False, executable = False) -> generator
|
||||
|
||||
Search the ELF's virtual address space for the specified string.
|
||||
|
||||
@@ -1106,6 +1130,7 @@ class ELF(ELFFile):
|
||||
Arguments:
|
||||
needle(str): String to search for.
|
||||
writable(bool): Search only writable sections.
|
||||
executable(bool): Search only executable sections.
|
||||
|
||||
Yields:
|
||||
An iterator for each virtual address that matches.
|
||||
@@ -1123,11 +1148,20 @@ class ELF(ELFFile):
|
||||
|
||||
>>> len(list(bash.search(b'GNU bash'))) > 0
|
||||
True
|
||||
|
||||
It is also possible to search for instructions in executable sections.
|
||||
|
||||
>>> binary = ELF.from_assembly('nop; mov eax, 0; jmp esp; ret')
|
||||
>>> jmp_addr = next(binary.search(asm('jmp esp'), executable = True))
|
||||
>>> binary.read(jmp_addr, 2) == asm('jmp esp')
|
||||
True
|
||||
"""
|
||||
load_address_fixup = (self.address - self.load_addr)
|
||||
|
||||
if writable:
|
||||
segments = self.writable_segments
|
||||
elif executable:
|
||||
segments = self.executable_segments
|
||||
else:
|
||||
segments = self.segments
|
||||
|
||||
@@ -1822,7 +1856,7 @@ class ELF(ELFFile):
|
||||
# Check for Linux configuration, it must contain more than
|
||||
# just the version.
|
||||
if len(self.config) > 1:
|
||||
config_opts = collections.defaultdict(lambda: [])
|
||||
config_opts = collections.defaultdict(list)
|
||||
for checker in kernel_configuration:
|
||||
result, message = checker(self.config)
|
||||
|
||||
|
||||
+25
-9
@@ -36,13 +36,17 @@ def emulate_plt_instructions(elf, got, address, data, targets):
|
||||
data = packing.unpack_many(data, bits=32, endian='little')
|
||||
data = packing.flat(data, bits=32, endian='big')
|
||||
|
||||
uc, ctx = prepare_unicorn_and_context(elf, got, address, data)
|
||||
|
||||
# Brute force addresses, assume that PLT entry points are at 4-byte aligned
|
||||
# Do not emulate more than a handful of instructions.
|
||||
for i, pc in enumerate(range(address, address + len(data), 4)):
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
log.debug('%s %#x', fiddling.enhex(data[i*4:(i+1) * 4]), pc)
|
||||
log.debug(elf.disasm(pc, 4))
|
||||
target = emulate_plt_instructions_inner(elf, got, pc, data[i*4:], targets)
|
||||
|
||||
uc.context_restore(ctx)
|
||||
target = emulate_plt_instructions_inner(uc, elf, got, pc, data[i*4:], targets)
|
||||
|
||||
if target in targets:
|
||||
log.debug("%#x -> %#x", pc, target)
|
||||
@@ -50,8 +54,7 @@ def emulate_plt_instructions(elf, got, address, data, targets):
|
||||
|
||||
return rv
|
||||
|
||||
def emulate_plt_instructions_inner(elf, got, pc, data, targets):
|
||||
# Deferred import to not affect load time
|
||||
def prepare_unicorn_and_context(elf, got, address, data):
|
||||
import unicorn as U
|
||||
|
||||
# Instantiate the emulator with the correct arguments for the current
|
||||
@@ -88,15 +91,15 @@ def emulate_plt_instructions_inner(elf, got, pc, data, targets):
|
||||
uc = U.Uc(arch, mode)
|
||||
|
||||
# Map the page of memory, and fill it with the contents
|
||||
start = pc & (~0xfff)
|
||||
stop = (pc + len(data) + 0xfff) & (~0xfff)
|
||||
start = address & (~0xfff)
|
||||
stop = (address + len(data) + 0xfff) & (~0xfff)
|
||||
|
||||
if not (0 <= start <= stop <= (1 << elf.bits)):
|
||||
return None
|
||||
|
||||
uc.mem_map(start, stop-start)
|
||||
uc.mem_write(pc, data)
|
||||
assert uc.mem_read(pc, len(data)) == data
|
||||
uc.mem_write(address, data)
|
||||
assert uc.mem_read(address, len(data)) == data
|
||||
|
||||
# MIPS is unique in that it relies entirely on _DYNAMIC, at the beginning
|
||||
# of the GOT. Each PLT stub loads an address stored here.
|
||||
@@ -129,9 +132,17 @@ def emulate_plt_instructions_inner(elf, got, pc, data, targets):
|
||||
trap = packing.p32(0x34000000, endian=elf.endian)
|
||||
uc.mem_write(magic_addr, trap)
|
||||
|
||||
return uc, uc.context_save()
|
||||
|
||||
def emulate_plt_instructions_inner(uc, elf, got, pc, data, targets):
|
||||
import unicorn as U
|
||||
|
||||
# Hook invalid addresses and any accesses out of the specified address range
|
||||
stopped_addr = []
|
||||
|
||||
# For MIPS. Explanation at prepare_unicorn_and_context.
|
||||
magic_addr = 0xdbdbdbdb
|
||||
|
||||
def hook_mem(uc, access, address, size, value, user_data):
|
||||
# Special case to allow MIPS to dereference the _DYNAMIC pointer
|
||||
# in the GOT.
|
||||
@@ -142,8 +153,10 @@ def emulate_plt_instructions_inner(elf, got, pc, data, targets):
|
||||
uc.emu_stop()
|
||||
return False
|
||||
|
||||
uc.hook_add(U.UC_HOOK_MEM_READ, hook_mem, stopped_addr)
|
||||
uc.hook_add(U.UC_HOOK_MEM_UNMAPPED, hook_mem, stopped_addr)
|
||||
hooks = [
|
||||
uc.hook_add(U.UC_HOOK_MEM_READ, hook_mem, stopped_addr),
|
||||
uc.hook_add(U.UC_HOOK_MEM_UNMAPPED, hook_mem, stopped_addr)
|
||||
]
|
||||
|
||||
# callback for tracing instructions
|
||||
# def hook_code(uc, address, size, user_data):
|
||||
@@ -178,4 +191,7 @@ def emulate_plt_instructions_inner(elf, got, pc, data, targets):
|
||||
if stopped_addr:
|
||||
retval = stopped_addr.pop()
|
||||
|
||||
for hook in hooks:
|
||||
uc.hook_del(hook)
|
||||
|
||||
return retval
|
||||
@@ -44,4 +44,4 @@ data:
|
||||
blacklist = set(raw)
|
||||
|
||||
encode = amd64DeltaEncoder()
|
||||
__all__ = [encode]
|
||||
__all__ = ['encode']
|
||||
@@ -32,7 +32,7 @@ class ArmEncoder(Encoder):
|
||||
enc_dec_loop = b.encDecoderLoopBuilder(dec_loop)
|
||||
dec = b.DecoderBuilder(dec_loop, self.icache_flush)
|
||||
|
||||
output,dec = b.buildInit(dec);
|
||||
output, dec = b.buildInit(dec)
|
||||
|
||||
output += dec
|
||||
output += enc_dec_loop
|
||||
|
||||
@@ -42,10 +42,10 @@ def off_gen(c):
|
||||
return x
|
||||
return 0
|
||||
|
||||
# return an alphanumeric value ret such that c XOR ret is also alphanumeric
|
||||
# =========================================================================
|
||||
# return an alphanumeric value ret such that c XOR ret is also alphanumeric
|
||||
# =========================================================================
|
||||
def alphanumeric_get_complement(c):
|
||||
c &= 0xff;
|
||||
c &= 0xff
|
||||
while True:
|
||||
ret = alphanumeric_get_byte()
|
||||
if alphanumeric_check(c ^ ret):
|
||||
|
||||
+10
-3
@@ -3,9 +3,12 @@
|
||||
r"""
|
||||
File Structure Exploitation
|
||||
|
||||
struct FILE (_IO_FILE) is the structure for File Streams. This offers various targets for exploitation on an existing bug in the code. Examples - _IO_buf_base and _IO_buf_end for reading data to arbitrary location.
|
||||
struct FILE (_IO_FILE) is the structure for File Streams.
|
||||
This offers various targets for exploitation on an existing bug in the code.
|
||||
Examples - ``_IO_buf_base`` and ``_IO_buf_end`` for reading data to arbitrary location.
|
||||
|
||||
Remembering the offsets of various structure members while faking a FILE structure can be difficult, so this python class helps you with that. Example-
|
||||
Remembering the offsets of various structure members while faking a FILE structure can be difficult,
|
||||
so this python class helps you with that. Example-
|
||||
|
||||
>>> context.clear(arch='amd64')
|
||||
>>> fileStr = FileStructure(null=0xdeadbeef)
|
||||
@@ -24,6 +27,7 @@ from __future__ import division
|
||||
|
||||
from pwnlib.context import context
|
||||
from pwnlib.log import getLogger
|
||||
from pwnlib.util.misc import python_2_bytes_compatible
|
||||
from pwnlib.util.packing import pack
|
||||
|
||||
log = getLogger(__name__)
|
||||
@@ -62,6 +66,8 @@ variables={
|
||||
26:{name:'vtable',size:length}
|
||||
}
|
||||
|
||||
del name, size, length
|
||||
|
||||
|
||||
def update_var(l):
|
||||
r"""
|
||||
@@ -91,6 +97,8 @@ def update_var(l):
|
||||
var['unknown2']=48
|
||||
return var
|
||||
|
||||
|
||||
@python_2_bytes_compatible
|
||||
class FileStructure(object):
|
||||
r"""
|
||||
Crafts a FILE structure, with default values for some fields, like _lock which should point to null ideally, set.
|
||||
@@ -187,7 +195,6 @@ class FileStructure(object):
|
||||
else:
|
||||
structure += pack(self.__getattr__(val), self.length[val]*8)
|
||||
return structure
|
||||
__str__ = __bytes__
|
||||
|
||||
def struntil(self,v):
|
||||
r"""
|
||||
|
||||
+1
-3
@@ -11,7 +11,6 @@ from pwnlib.tubes.remote import remote
|
||||
|
||||
env_server = args.get('FLAG_HOST', 'flag-submission-server').strip()
|
||||
env_port = args.get('FLAG_PORT', '31337').strip()
|
||||
env_proto = args.get('FLAG_PROTO', 'tcp').strip()
|
||||
env_file = args.get('FLAG_FILE', '/does/not/exist').strip()
|
||||
env_exploit_name = args.get('EXPLOIT_NAME', 'unnamed-exploit').strip()
|
||||
env_target_host = args.get('TARGET_HOST', 'unknown-target').strip()
|
||||
@@ -24,7 +23,6 @@ def submit_flag(flag,
|
||||
target=env_target_host,
|
||||
server=env_server,
|
||||
port=env_port,
|
||||
proto=env_proto,
|
||||
team=env_team_name):
|
||||
"""
|
||||
Submits a flag to the game server
|
||||
@@ -35,7 +33,7 @@ def submit_flag(flag,
|
||||
target(str): Target identifier, optional
|
||||
server(str): Flag server host name, optional
|
||||
port(int): Flag server port, optional
|
||||
proto(str), Flag server protocol, optional
|
||||
team(str): Team identifier, optional
|
||||
|
||||
Optional arguments are inferred from the environment,
|
||||
or omitted if none is set.
|
||||
|
||||
+3
-4
@@ -834,14 +834,13 @@ class FmtStr(object):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, execute_fmt, offset = None, padlen = 0, numbwritten = 0):
|
||||
def __init__(self, execute_fmt, offset=None, padlen=0, numbwritten=0):
|
||||
self.execute_fmt = execute_fmt
|
||||
self.offset = offset
|
||||
self.padlen = padlen
|
||||
self.numbwritten = numbwritten
|
||||
|
||||
|
||||
if self.offset == None:
|
||||
if self.offset is None:
|
||||
self.offset, self.padlen = self.find_offset()
|
||||
log.info("Found format string offset: %d", self.offset)
|
||||
|
||||
@@ -903,7 +902,7 @@ class FmtStr(object):
|
||||
|
||||
"""
|
||||
fmtstr = randoms(self.padlen).encode()
|
||||
fmtstr += fmtstr_payload(self.offset, self.writes, numbwritten=self.padlen, write_size='byte')
|
||||
fmtstr += fmtstr_payload(self.offset, self.writes, numbwritten=self.padlen + self.numbwritten, write_size='byte')
|
||||
self.execute_fmt(fmtstr)
|
||||
self.writes = {}
|
||||
|
||||
|
||||
+18
-7
@@ -237,13 +237,14 @@ def _gdbserver_args(pid=None, path=None, args=None, which=None, env=None):
|
||||
if pid:
|
||||
gdbserver_args += ['--once', '--attach']
|
||||
|
||||
if env:
|
||||
if env is not None:
|
||||
env_args = []
|
||||
for key in tuple(env):
|
||||
if key.startswith('LD_'): # LD_PRELOAD / LD_LIBRARY_PATH etc.
|
||||
env_args.append('{}={}'.format(key, env.pop(key)))
|
||||
if env_args:
|
||||
gdbserver_args += ['--wrapper', 'env'] + env_args + ['--']
|
||||
else:
|
||||
env_args.append('{}={}'.format(key, env[key]))
|
||||
gdbserver_args += ['--wrapper', 'env', '-i'] + env_args + ['--']
|
||||
|
||||
gdbserver_args += ['localhost:0']
|
||||
gdbserver_args += args
|
||||
@@ -399,7 +400,7 @@ def debug(args, gdbscript=None, exe=None, ssh=None, env=None, sysroot=None, **kw
|
||||
>>> io.interactive() # doctest: +SKIP
|
||||
>>> io.close()
|
||||
"""
|
||||
if isinstance(args, (int, tubes.process.process, tubes.ssh.ssh_channel)):
|
||||
if isinstance(args, six.integer_types + (tubes.process.process, tubes.ssh.ssh_channel)):
|
||||
log.error("Use gdb.attach() to debug a running process")
|
||||
|
||||
if isinstance(args, (bytes, six.text_type)):
|
||||
@@ -496,7 +497,7 @@ def binary():
|
||||
|
||||
if multiarch:
|
||||
return multiarch
|
||||
log.warn_once('Cross-architecture debugging usually requires gdb-multiarch\n' \
|
||||
log.warn_once('Cross-architecture debugging usually requires gdb-multiarch\n'
|
||||
'$ apt-get install gdb-multiarch')
|
||||
|
||||
if not gdb:
|
||||
@@ -631,6 +632,9 @@ def attach(target, gdbscript = '', exe = None, gdb_args = None, ssh = None, sysr
|
||||
if context.os == 'android':
|
||||
pre += 'set gnutarget ' + _bfdname() + '\n'
|
||||
|
||||
if exe:
|
||||
pre += 'file %s\n' % exe
|
||||
|
||||
# let's see if we can find a pid to attach to
|
||||
pid = None
|
||||
if isinstance(target, six.integer_types):
|
||||
@@ -980,7 +984,7 @@ def corefile(process):
|
||||
# This is effectively the same as what the 'gcore' binary does
|
||||
gdb_args = ['-batch',
|
||||
'-q',
|
||||
'--nx',
|
||||
'-nx',
|
||||
'-ex', '"set pagination off"',
|
||||
'-ex', '"set height 0"',
|
||||
'-ex', '"set width 0"',
|
||||
@@ -991,7 +995,14 @@ def corefile(process):
|
||||
with context.local(terminal = ['sh', '-c']):
|
||||
with context.quiet:
|
||||
pid = attach(process, gdb_args=gdb_args)
|
||||
os.waitpid(pid, 0)
|
||||
log.debug("Got GDB pid %d", pid)
|
||||
try:
|
||||
os.waitpid(pid, 0)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not os.path.exists(corefile_path):
|
||||
log.error("Could not generate a corefile for process %d", process.pid)
|
||||
|
||||
return elf.corefile.Core(corefile_path)
|
||||
|
||||
|
||||
+8
-1
@@ -98,6 +98,7 @@ import logging
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import six
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
@@ -183,6 +184,9 @@ class Progress(object):
|
||||
self.last_status = 0
|
||||
|
||||
def _log(self, status, args, kwargs, msgtype):
|
||||
# Logs are strings, not bytes. Handle Python3 bytes() objects.
|
||||
status = six.ensure_text(status)
|
||||
|
||||
# this progress logger is stopped, so don't generate any more records
|
||||
if self._stopped:
|
||||
return
|
||||
@@ -279,11 +283,14 @@ class Logger(object):
|
||||
self._logger = logger
|
||||
|
||||
def _getlevel(self, levelString):
|
||||
if isinstance(levelString, int):
|
||||
if isinstance(levelString, six.integer_types):
|
||||
return levelString
|
||||
return logging._levelNames[levelString.upper()]
|
||||
|
||||
def _log(self, level, msg, args, kwargs, msgtype, progress = None):
|
||||
# Logs are strings, not bytes. Handle Python3 bytes() objects.
|
||||
msg = six.ensure_text(msg)
|
||||
|
||||
extra = kwargs.get('extra', {})
|
||||
extra.setdefault('pwnlib_msgtype', msgtype)
|
||||
extra.setdefault('pwnlib_progress', progress)
|
||||
|
||||
+6
-5
@@ -5,6 +5,7 @@ import ctypes
|
||||
import functools
|
||||
import string
|
||||
|
||||
import six
|
||||
from six.moves import range
|
||||
|
||||
from pwnlib.context import context
|
||||
@@ -63,7 +64,7 @@ class MemLeak(object):
|
||||
... if addr & 0xff == 0:
|
||||
... return None
|
||||
... return binsh[addr:addr+4]
|
||||
>>> leaker_nonulls.d(0) == None
|
||||
>>> leaker_nonulls.d(0) is None
|
||||
leaking 0x0
|
||||
True
|
||||
>>> leaker_nonulls[0x100:0x104] == binsh[0x100:0x104]
|
||||
@@ -155,17 +156,17 @@ class MemLeak(object):
|
||||
Arguments:
|
||||
address(int): Base address to calculate offsets from
|
||||
field(obj): Instance of a ctypes field
|
||||
expected(int,str): Expected value
|
||||
expected(int,bytes): Expected value
|
||||
|
||||
Return Value:
|
||||
The type of the return value will be dictated by
|
||||
the type of ``field``.
|
||||
"""
|
||||
if not isinstance(expected, (int, bytes)):
|
||||
raise TypeError("Expected value must be an int or bytes")
|
||||
|
||||
if isinstance(expected, int):
|
||||
if isinstance(expected, six.integer_types):
|
||||
expected = pack(expected, bytes=obj.size)
|
||||
elif not isinstance(expected, bytes):
|
||||
raise TypeError("Expected value must be an int or bytes")
|
||||
|
||||
assert obj.size == len(expected)
|
||||
|
||||
|
||||
@@ -109,8 +109,8 @@ class AdbClient(Logger):
|
||||
process(context.adb + ['start-server']).recvall()
|
||||
time.sleep(0.3)
|
||||
else:
|
||||
log.exception('Could not connect to ADB server (%s:%s)' % \
|
||||
(self.host, self.port))
|
||||
log.exception('Could not connect to ADB server (%s:%s)',
|
||||
self.host, self.port)
|
||||
|
||||
# Final attempt...
|
||||
if not self._c:
|
||||
@@ -462,7 +462,7 @@ class AdbClient(Logger):
|
||||
>>> expected = {'mode': 16749, 'size': 0, 'time': 0}
|
||||
>>> pwnlib.protocols.adb.AdbClient().stat('/proc') == expected
|
||||
True
|
||||
>>> pwnlib.protocols.adb.AdbClient().stat('/does/not/exist') == None
|
||||
>>> pwnlib.protocols.adb.AdbClient().stat('/does/not/exist') is None
|
||||
True
|
||||
"""
|
||||
if isinstance(path, six.text_type):
|
||||
|
||||
+1
-1
@@ -243,7 +243,7 @@ def regsort(in_out, all_regs, tmp = None, xchg = True, randomize = None):
|
||||
# Collapse constant values
|
||||
#
|
||||
# For eaxmple, {'eax': 0, 'ebx': 0} => {'eax': 0, 'ebx': 'eax'}
|
||||
v_k = defaultdict(lambda: [])
|
||||
v_k = defaultdict(list)
|
||||
for k,v in sorted(in_out.items()):
|
||||
if v not in all_regs and v != 0:
|
||||
v_k[v].append(k)
|
||||
|
||||
+4
-2
@@ -9,6 +9,8 @@ from pwnlib.util import packing
|
||||
|
||||
import six
|
||||
|
||||
from pwnlib.util.misc import python_2_bytes_compatible
|
||||
|
||||
|
||||
class Unresolved(object):
|
||||
"""
|
||||
@@ -55,6 +57,8 @@ class StackAdjustment(Unresolved):
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@python_2_bytes_compatible
|
||||
class AppendedArgument(Unresolved):
|
||||
"""
|
||||
Encapsulates information about a pointer argument, and the data
|
||||
@@ -186,8 +190,6 @@ class AppendedArgument(Unresolved):
|
||||
|
||||
def __bytes__(self):
|
||||
return packing.flat(self.resolve())
|
||||
if six.PY2:
|
||||
__str__ = __bytes__
|
||||
|
||||
def __repr__(self):
|
||||
if isinstance(self.address, six.integer_types):
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import six
|
||||
|
||||
class Gadget(object):
|
||||
"""
|
||||
@@ -54,12 +55,12 @@ class Gadget(object):
|
||||
|
||||
def __getitem__(self, key):
|
||||
# Backward compatibility
|
||||
if isinstance(key, int):
|
||||
if isinstance(key, six.integer_types):
|
||||
key = self.__indices[key]
|
||||
return getattr(self, key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
# Backward compatibility
|
||||
if isinstance(key, int):
|
||||
if isinstance(key, six.integer_types):
|
||||
key = self.__indices[key]
|
||||
return setattr(self, key, value)
|
||||
+54
-41
@@ -2,65 +2,61 @@ r"""
|
||||
Provides automatic payload generation for exploiting buffer overflows
|
||||
using ret2dlresolve.
|
||||
|
||||
Example:
|
||||
We use the following example program:
|
||||
|
||||
>>> program = tempfile.mktemp()
|
||||
>>> source = program + ".c"
|
||||
>>> write(source, '''
|
||||
... #include <unistd.h>
|
||||
... void vuln(void){
|
||||
... char buf[64];
|
||||
... read(STDIN_FILENO, buf, 200);
|
||||
... }
|
||||
... int main(int argc, char** argv){
|
||||
... vuln();
|
||||
... }''')
|
||||
>>> cmdline = ["gcc", source, "-fno-stack-protector", "-no-pie", "-m32", "-o", program]
|
||||
>>> process(cmdline).wait_for_close()
|
||||
::
|
||||
|
||||
>>> context.binary = program
|
||||
>>> elf = ELF(program)
|
||||
>>> rop = ROP(elf)
|
||||
#include <unistd.h>
|
||||
void vuln(void){
|
||||
char buf[64];
|
||||
read(STDIN_FILENO, buf, 200);
|
||||
}
|
||||
int main(int argc, char** argv){
|
||||
vuln();
|
||||
}
|
||||
|
||||
We can automate the process of exploitation with these some example binaries.
|
||||
|
||||
>>> context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('i386'))
|
||||
>>> rop = ROP(context.binary)
|
||||
>>> dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["echo pwned"])
|
||||
>>> rop.read(0, dlresolve.data_addr) # do not forget this step, but use whatever function you like
|
||||
>>> rop.ret2dlresolve(dlresolve)
|
||||
>>> raw_rop = rop.chain()
|
||||
>>> print(rop.dump()) # doctest: +SKIP
|
||||
0x0000: 0x8049030 read(0, 0x804ce00)
|
||||
0x0004: 0x8049208 <adjust @0x10> pop edi; pop ebp; ret
|
||||
>>> print(rop.dump())
|
||||
0x0000: 0x80482e0 read(0, 0x804ae00)
|
||||
0x0004: 0x80484ea <adjust @0x10> pop edi; pop ebp; ret
|
||||
0x0008: 0x0 arg0
|
||||
0x000c: 0x804ce00 arg1
|
||||
0x0010: 0x8049020 [plt_init] system(0x804ce30)
|
||||
0x0014: 0x4b74 [dlresolve index]
|
||||
0x000c: 0x804ae00 arg1
|
||||
0x0010: 0x80482d0 [plt_init] system(0x804ae24)
|
||||
0x0014: 0x2b84 [dlresolve index]
|
||||
0x0018: b'gaaa' <return address>
|
||||
0x001c: 0x804ce30 arg0
|
||||
>>> p = process(program)
|
||||
0x001c: 0x804ae24 arg0
|
||||
>>> p = elf.process()
|
||||
>>> p.sendline(fit({64+context.bytes*3: raw_rop, 200: dlresolve.payload}))
|
||||
>>> p.recvline()
|
||||
b'pwned\n'
|
||||
|
||||
>>> # and now for 64 bits
|
||||
>>> cmdline = ["gcc", source, "-fno-stack-protector", "-no-pie", "-o", program]
|
||||
>>> process(cmdline).wait_for_close()
|
||||
>>> context.binary = program
|
||||
>>> elf = ELF(program)
|
||||
You can also use ``Ret2dlresolve`` on AMD64:
|
||||
|
||||
>>> context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
|
||||
>>> rop = ROP(elf)
|
||||
>>> dlresolve = Ret2dlresolvePayload(elf, symbol="system", args=["echo pwned"])
|
||||
>>> rop.read(0, dlresolve.data_addr) # do not forget this step, but use whatever function you like
|
||||
>>> rop.ret2dlresolve(dlresolve)
|
||||
>>> raw_rop = rop.chain()
|
||||
>>> print(rop.dump()) # doctest: +SKIP
|
||||
0x0000: 0x4011aa pop rdi; ret
|
||||
>>> print(rop.dump())
|
||||
0x0000: 0x400593 pop rdi; ret
|
||||
0x0008: 0x0 [arg0] rdi = 0
|
||||
0x0010: 0x4011a8 pop rsi; pop r15; ret
|
||||
0x0018: 0x404e00 [arg1] rsi = 4214272
|
||||
0x0010: 0x400591 pop rsi; pop r15; ret
|
||||
0x0018: 0x601e00 [arg1] rsi = 6299136
|
||||
0x0020: b'iaaajaaa' <pad r15>
|
||||
0x0028: 0x401030 read
|
||||
0x0030: 0x4011aa pop rdi; ret
|
||||
0x0038: 0x404e58 [arg0] rdi = 4214360
|
||||
0x0040: 0x401020 [plt_init] system
|
||||
0x0048: 0x318 [dlresolve index]
|
||||
>>> p = process(program)
|
||||
0x0028: 0x4003f0 read
|
||||
0x0030: 0x400593 pop rdi; ret
|
||||
0x0038: 0x601e48 [arg0] rdi = 6299208
|
||||
0x0040: 0x4003e0 [plt_init] system
|
||||
0x0048: 0x15670 [dlresolve index]
|
||||
>>> p = elf.process()
|
||||
>>> p.sendline(fit({64+context.bytes: raw_rop, 200: dlresolve.payload}))
|
||||
>>> if dlresolve.unreliable:
|
||||
... p.poll(True) == -signal.SIGSEGV
|
||||
@@ -69,6 +65,7 @@ Example:
|
||||
True
|
||||
"""
|
||||
|
||||
import six
|
||||
from copy import deepcopy
|
||||
|
||||
from pwnlib.context import context
|
||||
@@ -82,6 +79,7 @@ ELF32_R_SYM_SHIFT = 8
|
||||
ELF64_R_SYM_SHIFT = 32
|
||||
|
||||
class Elf32_Rel(object):
|
||||
''
|
||||
"""
|
||||
.. code-block:: c
|
||||
|
||||
@@ -103,6 +101,7 @@ class Elf32_Rel(object):
|
||||
|
||||
|
||||
class Elf64_Rel(object):
|
||||
''
|
||||
"""
|
||||
.. code-block:: c
|
||||
|
||||
@@ -124,6 +123,7 @@ class Elf64_Rel(object):
|
||||
|
||||
|
||||
class Elf32_Sym(object):
|
||||
''
|
||||
"""
|
||||
.. code-block:: c
|
||||
|
||||
@@ -158,6 +158,7 @@ class Elf32_Sym(object):
|
||||
|
||||
|
||||
class Elf64_Sym(object):
|
||||
''
|
||||
"""
|
||||
.. code-block:: c
|
||||
|
||||
@@ -192,6 +193,7 @@ class Elf64_Sym(object):
|
||||
|
||||
|
||||
class Queue(list):
|
||||
''
|
||||
def size(self):
|
||||
size = 0
|
||||
for v in self:
|
||||
@@ -205,10 +207,21 @@ class Queue(list):
|
||||
|
||||
|
||||
class MarkedBytes(bytes):
|
||||
''
|
||||
pass
|
||||
|
||||
|
||||
class Ret2dlresolvePayload(object):
|
||||
"""Create a ret2dlresolve payload
|
||||
|
||||
Arguments:
|
||||
elf (ELF): Binary to search
|
||||
symbol (str): Function to search for
|
||||
args (list): List of arguments to pass to the function
|
||||
|
||||
Returns:
|
||||
A ``Ret2dlresolvePayload`` object which can be passed to ``rop.ret2dlresolve``
|
||||
"""
|
||||
def __init__(self, elf, symbol, args, data_addr=None):
|
||||
self.elf = elf
|
||||
self.elf_load_address_fixup = self.elf.address - self.elf.load_addr
|
||||
@@ -344,7 +357,7 @@ class Ret2dlresolvePayload(object):
|
||||
elif isinstance(top, bytes):
|
||||
top = pack(self.data_addr + len(self.payload) + queue.size())
|
||||
queue.append(MarkedBytes(queue[0]))
|
||||
elif isinstance(top, int):
|
||||
elif isinstance(top, six.integer_types):
|
||||
top = pack(top)
|
||||
|
||||
self.payload += top
|
||||
|
||||
+58
-9
@@ -88,6 +88,36 @@ You can also append complex arguments onto stack when the stack pointer is known
|
||||
0x7fffe038: b'-c\x00$'
|
||||
0x7fffe03c: b'ls\x00$'
|
||||
|
||||
ROP also detects 'jmp $sp' gadget to help exploit binaries with NX disabled.
|
||||
You can get this gadget on 'i386':
|
||||
|
||||
>>> context.clear(arch='i386')
|
||||
>>> elf = ELF.from_assembly('nop; jmp esp; ret')
|
||||
>>> rop = ROP(elf)
|
||||
>>> jmp_gadget = rop.jmp_esp
|
||||
>>> elf.read(jmp_gadget.address, 2) == asm('jmp esp')
|
||||
True
|
||||
|
||||
You can also get this gadget on 'amd64':
|
||||
|
||||
>>> context.clear(arch='amd64')
|
||||
>>> elf = ELF.from_assembly('nop; jmp rsp; ret')
|
||||
>>> rop = ROP(elf)
|
||||
>>> jmp_gadget = rop.jmp_rsp
|
||||
>>> elf.read(jmp_gadget.address, 2) == asm('jmp rsp')
|
||||
True
|
||||
|
||||
Gadgets whose address has badchar are filtered out:
|
||||
|
||||
>>> context.clear(arch='i386')
|
||||
>>> elf = ELF.from_assembly('nop; pop eax; jmp esp; int 0x80; jmp esp; ret')
|
||||
>>> rop = ROP(elf, badchars=b'\x02')
|
||||
>>> jmp_gadget = rop.jmp_esp # It returns the second gadget
|
||||
>>> elf.read(jmp_gadget.address, 2) == asm('jmp esp')
|
||||
True
|
||||
>>> rop = ROP(elf, badchars=b'\x02\x06')
|
||||
>>> rop.jmp_esp == None # The address of both gadgets has badchar
|
||||
True
|
||||
|
||||
ROP Example
|
||||
-------------------
|
||||
@@ -302,6 +332,7 @@ from pwnlib.util import lists
|
||||
from pwnlib.util import packing
|
||||
from pwnlib.util.cyclic import cyclic
|
||||
from pwnlib.util.packing import pack
|
||||
from pwnlib.util.misc import python_2_bytes_compatible
|
||||
|
||||
log = getLogger(__name__)
|
||||
__all__ = ['ROP']
|
||||
@@ -340,7 +371,7 @@ class DescriptiveStack(list):
|
||||
descriptions = {}
|
||||
|
||||
def __init__(self, address):
|
||||
self.descriptions = collections.defaultdict(lambda: [])
|
||||
self.descriptions = collections.defaultdict(list)
|
||||
self.address = address or 0
|
||||
self._next_next = 0
|
||||
self._next_last = 0
|
||||
@@ -382,6 +413,7 @@ class DescriptiveStack(list):
|
||||
return '\n'.join(rv)
|
||||
|
||||
|
||||
@python_2_bytes_compatible
|
||||
class ROP(object):
|
||||
r"""Class which simplifies the generation of ROP-chains.
|
||||
|
||||
@@ -751,7 +783,6 @@ class ROP(object):
|
||||
stack.describe(self.describe(slot))
|
||||
if not isinstance(slot, bytes):
|
||||
slot = slot.encode()
|
||||
slot += self.generatePadding(stack.next, len(slot) % context.bytes)
|
||||
|
||||
for chunk in lists.group(context.bytes, slot):
|
||||
stack.append(chunk)
|
||||
@@ -1057,9 +1088,6 @@ class ROP(object):
|
||||
"""Returns: Raw bytes of the ROP chain"""
|
||||
return self.chain()
|
||||
|
||||
def __str__(self):
|
||||
return str(self.chain())
|
||||
|
||||
def __get_cachefile_name(self, files):
|
||||
"""Given an ELF or list of ELF objects, return a cache file for the set of files"""
|
||||
cachedir = os.path.join(tempfile.gettempdir(), 'pwntools-rop-cache-%d.%d' % sys.version_info[:2])
|
||||
@@ -1101,7 +1129,7 @@ class ROP(object):
|
||||
#
|
||||
# - leave
|
||||
# - pop reg
|
||||
# - add $sp, value
|
||||
# - add $sp, <hexadecimal value>
|
||||
# - ret
|
||||
#
|
||||
# Currently, ROPgadget does not detect multi-byte "C2" ret.
|
||||
@@ -1109,7 +1137,7 @@ class ROP(object):
|
||||
#
|
||||
|
||||
pop = re.compile(r'^pop (.{3})')
|
||||
add = re.compile(r'^add [er]sp, (\S+)$')
|
||||
add = re.compile(r'^add [er]sp, ((?:0[xX])?[0-9a-fA-F]+)$')
|
||||
ret = re.compile(r'^ret$')
|
||||
leave = re.compile(r'^leave$')
|
||||
int80 = re.compile(r'int +0x80')
|
||||
@@ -1125,6 +1153,8 @@ class ROP(object):
|
||||
# False
|
||||
# >>> valid('add esp, 0x24')
|
||||
# True
|
||||
# >>> valid('add esp, esi')
|
||||
# False
|
||||
#
|
||||
valid = lambda insn: any(map(lambda pattern: pattern.match(insn), [pop,add,ret,leave,int80,syscall,sysenter]))
|
||||
|
||||
@@ -1306,7 +1336,7 @@ class ROP(object):
|
||||
self.raw(call)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
"""Helper to make finding ROP gadets easier.
|
||||
"""Helper to make finding ROP gadgets easier.
|
||||
|
||||
Also provides a shorthand for ``.call()``:
|
||||
``rop.function(args)`` is equivalent to ``rop.call(function, args)``
|
||||
@@ -1319,7 +1349,7 @@ class ROP(object):
|
||||
True
|
||||
>>> rop.ret_8 == rop.search(move=8)
|
||||
True
|
||||
>>> rop.ret != None
|
||||
>>> rop.ret is not None
|
||||
True
|
||||
"""
|
||||
gadget = collections.namedtuple('gadget', ['address', 'details'])
|
||||
@@ -1343,6 +1373,25 @@ class ROP(object):
|
||||
count = int(attr.split('_')[1])
|
||||
return self.search(move=count)
|
||||
|
||||
#
|
||||
# Check for 'jmp_esp'('i386') or 'jmp_rsp'('amd64')
|
||||
#
|
||||
if attr == 'jmp_esp' and context.arch == 'i386' \
|
||||
or attr == 'jmp_rsp' and context.arch == 'amd64':
|
||||
jmp_sp = {'i386': 'jmp esp',
|
||||
'amd64': 'jmp rsp'
|
||||
}[context.arch]
|
||||
|
||||
insn_asm = b'\xff\xe4'
|
||||
|
||||
for elf in self.elfs:
|
||||
for addr in elf.search(insn_asm, executable = True):
|
||||
if set(pack(addr)) & self._badchars:
|
||||
continue
|
||||
|
||||
return Gadget(addr, [jmp_sp], [], context.bytes)
|
||||
return None
|
||||
|
||||
if attr in ('int80', 'syscall', 'sysenter'):
|
||||
mapping = {'int80': 'int 0x80',
|
||||
'syscall': 'syscall',
|
||||
|
||||
@@ -142,8 +142,11 @@ class module(ModuleType):
|
||||
return constants.eval(item)
|
||||
|
||||
def pretty(self, n, comment=True):
|
||||
if isinstance(n, str):
|
||||
return repr(n)
|
||||
if isinstance(n, (str, bytes, list, tuple, dict)):
|
||||
r = repr(n)
|
||||
if not comment: # then it can be inside a comment!
|
||||
r = r.replace('*/', r'\x2a/')
|
||||
return r
|
||||
if not isinstance(n, six.integer_types):
|
||||
return n
|
||||
if isinstance(n, constants.Constant):
|
||||
@@ -155,7 +158,7 @@ class module(ModuleType):
|
||||
return hex(n)
|
||||
|
||||
def okay(self, s, *a, **kw):
|
||||
if isinstance(s, int):
|
||||
if isinstance(s, six.integer_types):
|
||||
s = packing.pack(s, *a, **kw)
|
||||
return b'\0' not in s and b'\n' not in s
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ def init_mako():
|
||||
from mako import ast
|
||||
import threading
|
||||
|
||||
if lookup != None:
|
||||
if lookup is not None:
|
||||
return
|
||||
|
||||
class IsInsideManager(object):
|
||||
|
||||
@@ -33,13 +33,13 @@ Example:
|
||||
args = []
|
||||
else:
|
||||
syscall_repr = 'syscall(%s)'
|
||||
if syscall == None:
|
||||
if syscall is None:
|
||||
args = ['?']
|
||||
else:
|
||||
args = [repr(syscall)]
|
||||
args = [pretty(syscall, False)]
|
||||
|
||||
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
|
||||
if arg == None:
|
||||
if arg is None:
|
||||
args.append('?')
|
||||
else:
|
||||
args.append(pretty(arg, False))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%
|
||||
import six
|
||||
from pwnlib.shellcraft.aarch64 import mov
|
||||
from pwnlib.shellcraft.aarch64.linux import read, readn, mmap
|
||||
from pwnlib import constants as C
|
||||
@@ -28,7 +29,7 @@ Example:
|
||||
protection = C.PROT_READ | C.PROT_WRITE | C.PROT_EXEC
|
||||
flags = C.MAP_ANONYMOUS | C.MAP_PRIVATE
|
||||
|
||||
assert isinstance(fd, int)
|
||||
assert isinstance(fd, six.integer_types)
|
||||
%>
|
||||
%if length is None:
|
||||
/* How many bytes should we receive? */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<%
|
||||
from pwnlib.shellcraft import aarch64
|
||||
from pwnlib.shellcraft import aarch64, pretty
|
||||
from pwnlib.constants import eval
|
||||
from pwnlib.abi import linux_aarch64_syscall as abi
|
||||
from six import text_type
|
||||
@@ -14,7 +14,7 @@ Any of the arguments can be expressions to be evaluated by :func:`pwnlib.constan
|
||||
Example:
|
||||
|
||||
>>> print(shellcraft.aarch64.linux.syscall(11, 1, 'sp', 2, 0).rstrip())
|
||||
/* call syscall(11, 1, 'sp', 2, 0) */
|
||||
/* call syscall(0xb, 1, 'sp', 2, 0) */
|
||||
mov x0, #1
|
||||
mov x1, sp
|
||||
mov x2, #2
|
||||
@@ -56,16 +56,16 @@ Example:
|
||||
args = []
|
||||
else:
|
||||
syscall_repr = 'syscall(%s)'
|
||||
if syscall == None:
|
||||
if syscall is None:
|
||||
args = ['?']
|
||||
else:
|
||||
args = [repr(syscall)]
|
||||
args = [pretty(syscall, False)]
|
||||
|
||||
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
|
||||
if arg == None:
|
||||
if arg is None:
|
||||
args.append('?')
|
||||
else:
|
||||
args.append(repr(arg))
|
||||
args.append(pretty(arg, False))
|
||||
while args and args[-1] == '?':
|
||||
args.pop()
|
||||
syscall_repr = syscall_repr % ', '.join(args)
|
||||
|
||||
@@ -39,7 +39,7 @@ string = b''.join(array)
|
||||
if len(array) * 8 > 4095:
|
||||
raise Exception("Array size is too large (%i), max=4095" % len(array))
|
||||
%>\
|
||||
/* push argument array ${repr(array)} */
|
||||
/* push argument array ${shellcraft.pretty(array, False)} */
|
||||
${shellcraft.pushstr(string, register1=register1, register2=register2)}
|
||||
|
||||
/* push null terminator */
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%
|
||||
import six
|
||||
from pwnlib.shellcraft import pretty, common, aarch64, registers
|
||||
from pwnlib.shellcraft.registers import aarch64 as regs
|
||||
from pwnlib.util.packing import pack, unpack
|
||||
@@ -39,7 +40,7 @@ if not key in regs:
|
||||
key_str = key
|
||||
key_int = key
|
||||
|
||||
if isinstance(key, int):
|
||||
if isinstance(key, six.integer_types):
|
||||
key_str = pack(key, bytes=4)
|
||||
else:
|
||||
key_int = unpack(key, 'all')
|
||||
|
||||
@@ -76,13 +76,13 @@ Example:
|
||||
args = []
|
||||
else:
|
||||
syscall_repr = 'syscall(%s)'
|
||||
if syscall == None:
|
||||
if syscall is None:
|
||||
args = ['?']
|
||||
else:
|
||||
args = [repr(syscall)]
|
||||
args = [pretty(syscall, False)]
|
||||
|
||||
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
|
||||
if arg == None:
|
||||
if arg is None:
|
||||
args.append('?')
|
||||
else:
|
||||
args.append(pretty(arg, False))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%
|
||||
import six
|
||||
from pwnlib.shellcraft import amd64, pretty, common
|
||||
from pwnlib.util.packing import pack, unpack
|
||||
from pwnlib.util.lists import group
|
||||
@@ -24,7 +25,7 @@ done = common.label('egghunter_done')
|
||||
next_page = common.label('egghunter_nextpage')
|
||||
|
||||
egg_str = egg
|
||||
if isinstance(egg, int):
|
||||
if isinstance(egg, six.integer_types):
|
||||
egg_str = pack(egg, bytes=4)
|
||||
|
||||
if len(egg_str) % 4:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%
|
||||
import six
|
||||
from pwnlib.shellcraft.amd64 import push
|
||||
from pwnlib.shellcraft.amd64.linux import read, readn, mmap
|
||||
from pwnlib import constants as C
|
||||
@@ -28,7 +29,7 @@ Example:
|
||||
protection = C.PROT_READ | C.PROT_WRITE | C.PROT_EXEC
|
||||
flags = C.MAP_ANONYMOUS | C.MAP_PRIVATE
|
||||
|
||||
assert isinstance(fd, int)
|
||||
assert isinstance(fd, six.integer_types)
|
||||
%>
|
||||
%if length is None:
|
||||
/* How many bytes should we receive? */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<%
|
||||
from pwnlib.shellcraft import amd64
|
||||
from pwnlib.shellcraft import amd64, pretty
|
||||
from pwnlib.constants import Constant
|
||||
from pwnlib.abi import linux_amd64_syscall as abi
|
||||
from six import text_type
|
||||
@@ -54,7 +54,7 @@ Example:
|
||||
... 'PROT_READ | PROT_WRITE | PROT_EXEC',
|
||||
... 'MAP_PRIVATE | MAP_ANONYMOUS',
|
||||
... -1, 0).rstrip())
|
||||
/* call mmap(0, 4096, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE | MAP_ANONYMOUS', -1, 0) */
|
||||
/* call mmap(0, 0x1000, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE | MAP_ANONYMOUS', -1, 0) */
|
||||
push (MAP_PRIVATE | MAP_ANONYMOUS) /* 0x22 */
|
||||
pop r10
|
||||
push -1
|
||||
@@ -84,6 +84,20 @@ Example:
|
||||
push SYS_open /* 2 */
|
||||
pop rax
|
||||
syscall
|
||||
>>> print(shellcraft.amd64.write(0, '*/', 2).rstrip())
|
||||
/* write(fd=0, buf='\x2a/', n=2) */
|
||||
/* push b'\x2a/\x00' */
|
||||
push 0x1010101 ^ 0x2f2a
|
||||
xor dword ptr [rsp], 0x1010101
|
||||
mov rsi, rsp
|
||||
xor edi, edi /* 0 */
|
||||
push 2
|
||||
pop rdx
|
||||
/* call write() */
|
||||
push SYS_write /* 1 */
|
||||
pop rax
|
||||
syscall
|
||||
|
||||
</%docstring>
|
||||
<%
|
||||
append_cdq = False
|
||||
@@ -92,16 +106,16 @@ Example:
|
||||
args = []
|
||||
else:
|
||||
syscall_repr = 'syscall(%s)'
|
||||
if syscall == None:
|
||||
if syscall is None:
|
||||
args = ['?']
|
||||
else:
|
||||
args = [repr(syscall)]
|
||||
args = [pretty(syscall, False)]
|
||||
|
||||
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
|
||||
if arg == None:
|
||||
if arg is None:
|
||||
args.append('?')
|
||||
else:
|
||||
args.append(repr(arg))
|
||||
args.append(pretty(arg, False))
|
||||
while args and args[-1] == '?':
|
||||
args.pop()
|
||||
syscall_repr = syscall_repr % ', '.join(args)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<%
|
||||
from pwnlib.util import packing
|
||||
from pwnlib.shellcraft import amd64
|
||||
from pwnlib.shellcraft import amd64, pretty
|
||||
from pwnlib.shellcraft.amd64 import pushstr
|
||||
from pwnlib import constants
|
||||
from pwnlib.shellcraft.registers import amd64 as regs
|
||||
@@ -31,7 +31,7 @@ Example:
|
||||
/* push 1 */
|
||||
push 1
|
||||
>>> print(pwnlib.shellcraft.amd64.push(256).rstrip())
|
||||
/* push 256 */
|
||||
/* push 0x100 */
|
||||
push 0x1010201 ^ 0x100
|
||||
xor dword ptr [rsp], 0x1010201
|
||||
>>> with context.local(os = 'linux'):
|
||||
@@ -58,7 +58,7 @@ Example:
|
||||
pass
|
||||
%>
|
||||
%if not is_reg:
|
||||
/* push ${repr(value_orig)} */
|
||||
/* push ${pretty(value_orig, False)} */
|
||||
${re.sub(r'^\s*/.*\n', '', amd64.pushstr(packing.pack(value), False), 1)}
|
||||
% else:
|
||||
push ${value}
|
||||
|
||||
@@ -77,7 +77,7 @@ Args:
|
||||
else:
|
||||
extend = b'\x00'
|
||||
%>\
|
||||
/* push ${repr(string)} */
|
||||
/* push ${pretty(string, False)} */
|
||||
% for word in lists.group(8, string, 'fill', extend)[::-1]:
|
||||
<%
|
||||
sign = packing.u64(word, endian='little', sign='signed')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<% from pwnlib.shellcraft import amd64 %>
|
||||
<% from pwnlib.shellcraft import amd64, pretty %>
|
||||
<%docstring>
|
||||
Pushes an array/envp-style array of pointers onto the stack.
|
||||
|
||||
@@ -25,14 +25,14 @@ word_size = 8
|
||||
offset = len(array_str) + word_size
|
||||
|
||||
%>\
|
||||
/* push argument array ${repr(array)} */
|
||||
/* push argument array ${pretty(array, False)} */
|
||||
${amd64.pushstr(array_str)}
|
||||
${amd64.mov(reg, 0)}
|
||||
push ${reg} /* null terminate */
|
||||
% for i,arg in enumerate(reversed(array)):
|
||||
${amd64.mov(reg, offset + word_size*i - len(arg))}
|
||||
add ${reg}, rsp
|
||||
push ${reg} /* ${repr(arg)} */
|
||||
push ${reg} /* ${pretty(arg, False)} */
|
||||
<% offset -= len(arg) %>\
|
||||
% endfor
|
||||
${amd64.mov(reg,'rsp')}
|
||||
@@ -6,7 +6,7 @@ Args:
|
||||
</%docstring>
|
||||
<%page args="return_value = None"/>
|
||||
|
||||
% if return_value != None:
|
||||
% if return_value is not None:
|
||||
${amd64.mov('rax', return_value)}
|
||||
% endif
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%
|
||||
import six
|
||||
from pwnlib.regsort import regsort
|
||||
from pwnlib.shellcraft import registers, eval
|
||||
from pwnlib.shellcraft.amd64 import mov
|
||||
@@ -50,7 +51,7 @@ if isinstance(edx, str):
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
if isinstance(eax, int) and isinstance(edx, int) and eax >> 63 == edx:
|
||||
if isinstance(eax, six.integer_types) and isinstance(edx, six.integer_types) and eax >> 63 == edx:
|
||||
cdq = True
|
||||
reg_context.pop('rdx')
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%
|
||||
import six
|
||||
from pwnlib.shellcraft import pretty, common, amd64, registers
|
||||
from pwnlib.util.packing import pack, unpack
|
||||
from pwnlib.context import context as ctx
|
||||
@@ -45,7 +46,7 @@ else:
|
||||
key_str = key
|
||||
key_int = key
|
||||
|
||||
if isinstance(key, int):
|
||||
if isinstance(key, six.integer_types):
|
||||
key_str = pack(key, bytes=4)
|
||||
else:
|
||||
key_int = unpack(key, 'all')
|
||||
|
||||
@@ -33,13 +33,13 @@ Example:
|
||||
args = []
|
||||
else:
|
||||
syscall_repr = 'syscall(%s)'
|
||||
if syscall == None:
|
||||
if syscall is None:
|
||||
args = ['?']
|
||||
else:
|
||||
args = [repr(syscall)]
|
||||
args = [pretty(syscall, False)]
|
||||
|
||||
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
|
||||
if arg == None:
|
||||
if arg is None:
|
||||
args.append('?')
|
||||
else:
|
||||
args.append(pretty(arg, False))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<% import six %>
|
||||
<% from pwnlib.shellcraft.arm import mov %>
|
||||
<% from pwnlib.util.packing import unpack %>
|
||||
<% from pwnlib import constants %>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<% import six %>
|
||||
<%page args="filepath, flags = 'O_RDONLY', mode = 0644"/>
|
||||
<%docstring>Opens a file. Leaves the file descriptor in r0.
|
||||
|
||||
@@ -11,6 +12,7 @@ Args:
|
||||
from pwnlib.asm import cpp
|
||||
from pwnlib.util.safeeval import expr
|
||||
from pwnlib.constants.linux import arm as consts
|
||||
from pwnlib.shellcraft import pretty
|
||||
filepath_lab, after = label("filepath"), label("after")
|
||||
filepath_out = [hex(ord(c)) for c in filepath]
|
||||
while True:
|
||||
@@ -30,7 +32,7 @@ Args:
|
||||
svc SYS_open
|
||||
b ${after}
|
||||
|
||||
/* The string ${repr(str(filepath))} */
|
||||
/* The string ${pretty(str(filepath), False)} */
|
||||
${filepath_lab}: .byte ${filepath_out}
|
||||
|
||||
${after}:
|
||||
@@ -1,5 +1,5 @@
|
||||
<%
|
||||
from pwnlib.shellcraft import arm
|
||||
from pwnlib.shellcraft import arm, pretty
|
||||
from pwnlib.constants import eval
|
||||
from pwnlib.abi import linux_arm_syscall as abi
|
||||
from six import text_type
|
||||
@@ -14,7 +14,7 @@ Any of the arguments can be expressions to be evaluated by :func:`pwnlib.constan
|
||||
Example:
|
||||
|
||||
>>> print(shellcraft.arm.linux.syscall(11, 1, 'sp', 2, 0).rstrip())
|
||||
/* call syscall(11, 1, 'sp', 2, 0) */
|
||||
/* call syscall(0xb, 1, 'sp', 2, 0) */
|
||||
mov r0, #1
|
||||
mov r1, sp
|
||||
mov r2, #2
|
||||
@@ -54,16 +54,16 @@ Example:
|
||||
args = []
|
||||
else:
|
||||
syscall_repr = 'syscall(%s)'
|
||||
if syscall == None:
|
||||
if syscall is None:
|
||||
args = ['?']
|
||||
else:
|
||||
args = [repr(syscall)]
|
||||
args = [pretty(syscall, False)]
|
||||
|
||||
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
|
||||
if arg == None:
|
||||
if arg is None:
|
||||
args.append('?')
|
||||
else:
|
||||
args.append(repr(arg))
|
||||
args.append(pretty(arg, False))
|
||||
while args and args[-1] == '?':
|
||||
args.pop()
|
||||
syscall_repr = syscall_repr % ', '.join(args)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<% from pwnlib.util import lists, packing, fiddling %>
|
||||
<% from pwnlib.shellcraft.arm import push %>
|
||||
<% from pwnlib.shellcraft import pretty %>
|
||||
<% import six %>
|
||||
<%page args="string, append_null = True, register='r7'"/>
|
||||
<%docstring>
|
||||
@@ -32,7 +33,7 @@ Examples:
|
||||
while len(string) % 4:
|
||||
string += b'\x41'
|
||||
%>\
|
||||
/* push ${repr(string)} */
|
||||
/* push ${pretty(string, False)} */
|
||||
% for word in packing.unpack_many(string, 32)[::-1]:
|
||||
${push(word, register)}
|
||||
% endfor
|
||||
@@ -1,4 +1,4 @@
|
||||
<% from pwnlib.shellcraft import arm %>
|
||||
<% from pwnlib.shellcraft import arm, pretty %>
|
||||
<%docstring>
|
||||
Pushes an array/envp-style array of pointers onto the stack.
|
||||
|
||||
@@ -25,13 +25,13 @@ word_size = 4
|
||||
offset = len(array_str) + word_size
|
||||
|
||||
%>\
|
||||
/* push argument array ${repr(array)} */
|
||||
/* push argument array ${pretty(array, False)} */
|
||||
${arm.pushstr(array_str)}
|
||||
${arm.push(0)} /* null terminate */
|
||||
% for i,arg in enumerate(reversed(array)):
|
||||
${arm.mov(reg, offset + word_size*i - len(arg))}
|
||||
add ${reg}, sp
|
||||
${arm.push(reg)} /* ${repr(arg)} */
|
||||
${arm.push(reg)} /* ${pretty(arg, False)} */
|
||||
<% offset -= len(arg) %>\
|
||||
% endfor
|
||||
${arm.mov(reg,'sp')}
|
||||
@@ -15,7 +15,7 @@ Examples:
|
||||
</%docstring>
|
||||
<%page args="return_value = None"/>
|
||||
|
||||
% if return_value != None:
|
||||
% if return_value is not None:
|
||||
${arm.mov('r0', return_value)}
|
||||
% endif
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%
|
||||
import six
|
||||
from pwnlib.shellcraft import pretty, common, arm, registers
|
||||
from pwnlib.shellcraft.registers import arm as regs
|
||||
from pwnlib.util.packing import pack, unpack
|
||||
@@ -39,7 +40,7 @@ if not key in regs:
|
||||
key_str = key
|
||||
key_int = key
|
||||
|
||||
if isinstance(key, int):
|
||||
if isinstance(key, six.integer_types):
|
||||
key_str = pack(key, bytes=4)
|
||||
else:
|
||||
key_int = unpack(key, 'all')
|
||||
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -41,7 +41,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -100,4 +100,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -42,7 +42,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -101,4 +101,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -40,7 +40,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -99,4 +99,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -43,7 +43,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -102,4 +102,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -40,7 +40,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -99,4 +99,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -42,7 +42,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -101,4 +101,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -40,7 +40,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -99,4 +99,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -41,7 +41,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -100,4 +100,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -5,7 +5,7 @@ import pwnlib.constants
|
||||
import pwnlib.shellcraft
|
||||
import six
|
||||
%>
|
||||
<%docstring>break_(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
|
||||
<%docstring>break(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
|
||||
|
||||
Invokes the syscall break.
|
||||
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -86,7 +86,7 @@ Returns:
|
||||
else:
|
||||
raise Exception("Could not locate any syscalls: %r" % syscalls)
|
||||
%>
|
||||
/* break_(${', '.join(syscall_repr)}) */
|
||||
/* break(${', '.join(syscall_repr)}) */
|
||||
%for name, arg in string_arguments.items():
|
||||
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
|
||||
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
|
||||
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -41,7 +41,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -100,4 +100,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -40,7 +40,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -99,4 +99,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -40,7 +40,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -99,4 +99,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -39,7 +39,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -98,4 +98,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -40,7 +40,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -99,4 +99,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
@@ -41,7 +41,7 @@ Returns:
|
||||
|
||||
for name, arg in zip(argument_names, argument_values):
|
||||
if arg is not None:
|
||||
syscall_repr.append('%s=%r' % (name, arg))
|
||||
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
|
||||
|
||||
# If the argument itself (input) is a register...
|
||||
if arg in allregs:
|
||||
@@ -100,4 +100,4 @@ Returns:
|
||||
${pwnlib.shellcraft.push(arg)}
|
||||
%endfor
|
||||
${pwnlib.shellcraft.setregs(register_arguments)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
${pwnlib.shellcraft.syscall(syscall)}
|
||||
Loaded 100 of 525 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user