Skip to content

A library to assist writing memory-unsafe code in "pure" python, without any imports (i.e. no ctypes etc.)

License

Notifications You must be signed in to change notification settings

DavidBuchanan314/unsafe-python

Repository files navigation

unsafe-python

A library to assist writing memory-unsafe code in "pure" python, without any imports (i.e. no ctypes etc.)

Supports CPython 3.11 and below (3.12 support coming soon?)

Note: This is a toy. You probably shouldn't use it for anything serious (or anything at all, really).

Core features:

  • addrof(obj) - A trivial alias of the id() builtin.
  • fakeobj(addr) - Allows for crafting fake heap objects.
  • getmem() - Returns a bytearray view of the current process's virtual memory.
  • setrip(addr) - Sets the RIP register. Argument passing etc. coming soon™.
  • do_rop(payload) - Execute a ROP payload.

A trivial example, showing how to dereference a null pointer in pure python. The future is now!

>>> import unsafe  # (If "no imports" is a requirement, then you can just copy-paste the code)
>>> mem = unsafe.getmem()
>>> mem[0]
Segmentation fault (core dumped)

For a less trivial example, check out shellcode_example_nocheats.py, which uses ROP to mprotect a shellcode buffer, and then jump into it.

Why?

I don't know.

How?

The CPython bytecode interpreter has documented memory-unsafety bug/features. Notably, the LOAD_CONST opcode (used to load a constant from the co_consts tuple) does not have any bounds checks, presumably for performance reasons. This has been used in the past to execute arbitrary code and escape sandboxes. Until now, these exploits have relied on custom bytecode generation, which is inherently fragile because the bytecode specification changes between different versions and/or implementations of python.

This project uses CPython's code object introspection APIs, along with a heap grooming technique, in order to craft "vulnerable" code objects using CPython's own bytecode compiler. This technique allows us to craft fake python objects on the heap, similar to the "fakeobj()" primitive you might see in exploits for JavaScript engines. For example, we can craft a bytearray with a base address of 0 and a length of SSIZE_MAX, giving us read and write access to raw memory.

TODO:

  • Perform ROP gadget search without "cheating" by reading /proc/self/maps. i.e. find a reliable way to leak libc base. (Edit: the buffered reader exploit linked below implements this)

See Also:

An incomplete list of known CPython memory safety issues:

About

A library to assist writing memory-unsafe code in "pure" python, without any imports (i.e. no ctypes etc.)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages