Simple pwntools QoL scripts
Project description
pwnscripts
Very simple script(s) to hasten binary exploit creation. To use, pip install pwnscripts
OR run
git clone https://github.com/152334H/pwnscripts
cd pwnscripts
pip install -e .
and replace from pwn import *
with from pwnscripts import *
, e.g.
from pwnscripts import *
context.binary = './my_challenge'
...
Additionally, the libc_database()
extension of pwnscripts requires the libc-database.
You might want to look at some of the examples in user_tests_and_examples.py
.
Features
Pwnscripts has a number of different features.
Libc
Things like LibcSearcher have always felt incomplete.
Pwnscripts provides two libc classes: libc()
and libc_database()
. The easiest way to start with both is with context
:
context.libc_database = '/path/to/libc-database' # https://github.com/niklasb/libc-database
context.libc = '/path/to/pwnscripts/examples/libc.so.6'
Anything you can run with ./libc-database/[executable]
is available as a libc_database()
method:
>>> context.libc_database.dump('libc6_2.27-3ubuntu1_amd64')
b'offset___libc_start_main_ret = 0x21b97\noffset_system = 0x000000000004f440\noffset_dup2 = 0x00000000001109a0\noffset_read = 0x0000000000110070\noffset_write = 0x0000000000110140\noffset_str_bin_sh = 0x1b3e9a\n'
>>> output = context.libc_database.add()
>>> print(output.decode())
Adding local libc /path/to/pwnscripts/examples/libc.so.6 (id local-18292bd12d37bfaf58e8dded9db7f1f5da1192cb /path/to/pwnscripts/examples/libc.so.6)
-> Writing libc /path/to/pwnscripts/examples/libc.so.6 to db/local-18292bd12d37bfaf58e8dded9db7f1f5da1192cb.so
-> Writing symbols to db/local-18292bd12d37bfaf58e8dded9db7f1f5da1192cb.symbols
-> Writing version info
libc_database()
also has a few additional methods; you can look at the tests and examples and documentation to see.
The libc()
object is a subclass of pwntools' pwnlib.elf.elf.ELF()
. It starts off with a base address of 0
, but you can change that to match a remote executable by providing it with leaked addresses:
>>> context.libc.calc_base('scanf', 0x7fffa3b8b040) # Provide a leaked address to libc
>>> context.libc.address
0x7fffa3b10000
>>> context.libc.symbols['str_bin_sh'] # Symbols from libc-database are stored in context.libc
0x7fffa3cc3e9a
libc()
provides one_gadget
integration in the form of an interactive selection:
>>> context.libc.select_gadget()
0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
constraints:
rsp & 0xf == 0
rcx == NULL
0x4f322 execve("/bin/sh", rsp+0x40, environ)
constraints:
[rsp+0x40] == NULL
0x10a38c execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
[?] choose the gadget to use:
1) 0x4f2c5
2) 0x4f322
3) 0x10a38c
Choice
You're free to shut up the interactive menu by giving .select_gadget()
an argument:
>>> context.libc.select_gadget(1)
0x4f322
More features exist, but this is already too long.
Format string exploitation
pwnscripts provides the fsb
module, which can be split further into:
-
.find_offset
: helper functions to bruteforce wanted printf offsets.If you've ever found yourself spamming
%n$llx
into a terminal: this module will automate away all that. Take a look at the example code to see how.This already partially exists as a feature in pwntools (see
pwnlib.fmtstr.FmtStr
), but pwnscripts expands functionality by having bruteforcers for other important printf offsets, includingcanary
s, for defeating stack protectors,stack
addresses, to make leaking a stack pointer much easier,- other things like
code
addresses with more niche purposes
-
.leak
: a simple two-function module to make leaking values with%s
a lot easier.The simple idea is that you get a payload to leak printf values:
offset = fsb.find_offset.buffer(...) # == 6 payload = fsb.leak.deref_payload(offset, [0x400123, 0x600123]) print(payload) # b'^^%10$s||%11$s$$#\x01@\x00#\x01`\x00'
And after sending the payload, extract the values with a helper function:
r = remote(...) r.sendline(payload) print(fsb.leak.deref_extractor(r.recvline())) # [b'\x80N\x03p\x94\x7f', b' \xeb\x04p\x94\x7f']
Minor features
Pwnscripts also comes with a few minor extensions and functions:
ROP
: an extension ofpwnlib.rop.rop.ROP
. Core feature is to simplify ROP building outside of SIGROP:>>> context.arch = 'amd64' >>> r = ROP('./binary') >>> r.system_call(0x3b, ['/bin/sh', 0, 0]) >>> print(r.dump()) 0x0000: 0x41e4af pop rax; ret 0x0008: 0x3b 0x0010: 0x44a309 pop rdx; pop rsi; ret 0x0018: 0x0 [arg2] rdx = 0 0x0020: 0x0 [arg1] rsi = 0 0x0028: 0x401696 pop rdi; ret 0x0030: 0x40 [arg0] rdi = AppendedArgument(['/bin/sh'], 0x0) 0x0038: 0x4022b4 syscall 0x0040: b'/bin/sh\x00'
- other unlisted features in development
Proper examples for pwnscripts
are available in examples/
and user_tests_and_examples.py
.
I tried using it; it doesn't work!
File in an issue, if you can. With a single-digit userbase , it's hard to guess what might go wrong, but potentially:
-
pwnscripts is broken
-
Python is outdated (try python3.8+)
-
libc-database is not properly installed/initalised (did you run ./get?)
-
The binary provided is neither i386 or amd64; other architectures aren't implemented (yet).
-
The challenge is amd64, but
context.arch
wasn't set toamd64
- Set
context.binary
appropriately, or setcontext.arch
manually if no binary is given
- Set
-
Other unknown reasons. Try making a pull-request if you're interested.
Updates
v0.2.0 - libc-database update
New features
-
pwnlib.context.context
is now extended for pwnscripts:context.libc
andcontext.libc_database
have been added as extensions. -
pwnscripts.libcdb_query
has undergone a revamp:- Two new classes have been created:
libc_database()
andlibc()
. libc()
is the replacement forlibc_db()
, and inherits frompwnlib.elf.elf.ELF
to simplify libc offset calculation.libc_database()
is a class to represent an existing installation of thelibc-database
The older
libc_db()
class (and the associatedlibc_find()
) will remain as deprecated features for the time being. - Two new classes have been created:
Bugfixes and internal changes
- Internal code: removal of
attrib_set_to()
& replacement withcontext.local
internally - Tests & examples have been pruned to ensure that neither file has copied examples from the other.
- More error catching for libcdb_query.py
- Lots and lots of documentation + tests
v0.1.0 - Initial release
pwnscripts is out of pre-alpha, and will follow Semantic Versioning where possible.
20-09
Begin following PEP 440
NEW: fsb.find_offset
extended with offset-matching searches.
NEW: pwntools
' ROP
class has been extended with new features.
libc_db() can (must) now be initialised with either a filepath to a libc.so.6 binary
, or with an identifier id
.
This breaks the original behaviour of allowing e.g. libc_db('/path/to/libc-database', '<identifier>')
20-08.1
NEW: printf() functions are now kept under the pwnscripts.fsb
module. Older prototypes for find_printf_* functions remain available for now.
Addition of a lot of docstrings, plus example binaries.
20-08
Added a lot of whitespace.
Added a wrapper object for libc-database: the libc_db
object. This is mostly a reinvention of tools like LibcSearcher
, although I have yet to see another project tack on one_gadget
searching, which is a (hacky) feature added for libc_db
.
Minor adjustments to printf. Logging is suppressed for offset bruteforcing; new feature to make a leak payload.
Extended readme.
20-06
Added module packaging stuff, so that pip install -e .
works
You can now see a test example of this library in test.py
.
Gradual updates expected as I continue to do pwn.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for pwnscripts-0.2.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9dba4bcbf0e78b50c7d39de1e1c81b392e4e86014c794703bd5e49355778c693 |
|
MD5 | 724633cf12a9f95a7d3543b60153e7f9 |
|
BLAKE2b-256 | abac1400f1e2702bad86de5202222398147e63a757f12872b90070d2a823f66c |