Skip to main content

pwnscripts

Tests PyPI package Python

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, including

    1. canarys, for defeating stack protectors,
    2. stack addresses, to make leaking a stack pointer much easier,
    3. 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 of pwnlib.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 to amd64

    • Set context.binary appropriately, or set context.arch manually if no binary is given
  • Other unknown reasons. Try making a pull-request if you're interested.

Updates

v0.2.1 - Hotfix: libc.select_gadget() will return with the correct libc.address adjusted value

v0.2.0 - libc-database update

New features

  • pwnlib.context.context is now extended for pwnscripts: context.libc and context.libc_database have been added as extensions.

  • pwnscripts.libcdb_query has undergone a revamp:

    • Two new classes have been created: libc_database() and libc().
    • libc() is the replacement for libc_db(), and inherits from pwnlib.elf.elf.ELF to simplify libc offset calculation.
    • libc_database() is a class to represent an existing installation of the libc-database

    The older libc_db() class (and the associated libc_find()) will remain as deprecated features for the time being.

Bugfixes and internal changes

  • Internal code: removal of attrib_set_to() & replacement with context.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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pwnscripts-0.2.1.tar.gz (19.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pwnscripts-0.2.1-py3-none-any.whl (30.7 kB view details)

Uploaded Python 3

File details

Details for the file pwnscripts-0.2.1.tar.gz.

File metadata

  • Download URL: pwnscripts-0.2.1.tar.gz
  • Upload date:
  • Size: 19.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.0 requests-toolbelt/0.9.1 tqdm/4.49.0 CPython/3.8.5

File hashes

Hashes for pwnscripts-0.2.1.tar.gz
Algorithm Hash digest
SHA256 77d3c8ebedbb7f3157e59d59862610dbdae2665b78d08a3dfffc668f97d4dcbe
MD5 9c500673705f5919093b22be4f1cef9b
BLAKE2b-256 e6d4b2c820f7b8ad35e161941ec64e3a9030ec9ae6973de3f38864674a393c96

See more details on using hashes here.

File details

Details for the file pwnscripts-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: pwnscripts-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 30.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/47.1.0 requests-toolbelt/0.9.1 tqdm/4.49.0 CPython/3.8.5

File hashes

Hashes for pwnscripts-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 a9b2badc2f5638852c9158207c5dc957580e109a0810638d196c013de8b032b8
MD5 40ab51b7646b70e1841ef8d3b5d9daa9
BLAKE2b-256 4dac2366eeece0ddf16a7f342b0301b3160393589844b6fd7240917e88ff907f

See more details on using hashes here.

Release history Release notifications | RSS feed

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.1

2 files

0.3.0

2 files

This release

0.2.1 This release

2 files

0.2.0

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

3 files

0.1.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page