https://github.com/nambers/python-audit_hook_head_finder
PWNable pyjail
https://github.com/nambers/python-audit_hook_head_finder
audithook pyjail
Last synced: about 1 year ago
JSON representation
PWNable pyjail
- Host: GitHub
- URL: https://github.com/nambers/python-audit_hook_head_finder
- Owner: Nambers
- License: mit
- Created: 2024-02-11T20:55:13.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2025-01-13T05:15:04.000Z (over 1 year ago)
- Last Synced: 2025-03-29T02:51:28.927Z (over 1 year ago)
- Topics: audithook, pyjail
- Language: Python
- Homepage:
- Size: 56.6 KB
- Stars: 11
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Audit: audit_hook_head_finder.c
Awesome Lists containing this project
README
# python audit_hooks head finder
This POC intends to show how to find the audit hook and use `ctypes` to pop it (~~SMASH it~~).
The idea is inspired by `misc/diligent-auditor` and `misc/IRS` challeneges and their solve scripts from [dicectf-quals-2024 CTF](https://github.com/dicegang/dicectf-quals-2024-challenges/).
# Ref
Diligent auditor from *organizers*:
IRS writeup from *Maple Bacon*:
## Tested environment
```
Python 3.12.4 (main, Jun 7 2024, 06:33:07) [GCC 14.1.1 20240522] on linux
Python 3.12.3 (tags/v3.12.3:f6650f9ad7, Jun 24 2024, 16:32:34) [GCC 14.1.1 20240522] on linux
Python 3.12.1 (tags/v3.12.1:2305ca5144, Jun 24 2024, 18:55:02) [GCC 14.1.1 20240522] on linux
Python 3.11.9 (main, Jun 23 2024, 04:47:27) [GCC 14.1.1 20240522] on linux
Python 3.13.1 (main, Dec 4 2024, 18:05:56) [GCC 14.2.1 20240910] on linux
```
## Offsets
### For ctypes
```python
# ONLY TESTED ON PYTHON 3.11, 3.12, 3.13
# the offsets are from POC.py
if sys.version_info[:2] == (3, 12):
if sys.version_info[2] <= 3:
PTR_OFFSET = [0x41448, -0x11df0] # <= 3.12.3
else:
PTR_OFFSET = [0x41448, -0x11e20] # for python3.12.4
elif sys.version_info[:2] == (3, 13):
PTR_OFFSET = [0x2aa0, -0x13030] # 3.13.1
else:
# python 3.11
PTR_OFFSET = [0xe00, -0xe388]
```
### For UAF
```python
# ONLY TESTED ON PYTHON 3.11, 3.12, 3.13
# the offsets are from POC-no-ctypes.py
# offset for audit hook set by Python and C
if sys.version_info[:2] == (3, 12):
if sys.version_info[2] <= 3:
PTR_OFFSET = [24, 48, 0x468f0, -0xc948] # <= 3.12.3
else:
PTR_OFFSET = [24, 48, 0x46920, -0xc948] # for python3.12.4
elif sys.version_info[:2] == (3, 13):
PTR_OFFSET = [24, 48, 0x7fd0, -0xdb00] # 3.13.1
else:
# there are multiple offsets for 3.11? check the result of POC-no-ctypes.py
PTR_OFFSET = [24, 48, 0x4d558, 0x3e3d0]
```
## Smash Audit hook using `ctypes`
### Concept
For audit hook set in Python: according to the "fixed" offsets between `ctypes.byref(ctypes.py_object(()))` and `GET_INTERP_ADDR()->audit_hooks` pointer under `PyInterpreterState`, we can cast `audit_hook` to `Py_ListObject` by address and pop it.
For audit hook set in C: according to the "fixed" offsets between `ctypes.byref(ctypes.py_object(()))` and `_PyRuntime.audit_hooks.head` pointer under `PyRuntimeState`, we can directly rewrite the head of audit hooks to `NULL`.
### How to use
```bash
# or ./build311.sh
./build.sh
./POC.py
./POC2.py
```
### Output
```bash
> ./POC.py
C audit hook triggered! event=sys.addaudithook
--- finished setup ---
PyInterpreterState_addr=0x64df082debe8
PyRuntimeState_addr=0x64df082cc180
PyInterpreterState.audit_hooks_ptr_addr=0x64df0831ffb0
PyRuntimeState.audit_hooks_ptr_addr=0x64df082ccd78
audit_hook_ptr_offset_by_py=0x41448
audit_hook_ptr_offset_by_c=-0x11df0
len=1 should be 1
C audit hook triggered! event=os.system
audit hook triggered! ('os.system', (b"echo 'test audit hook -- this will trigger hook'",))
test audit hook -- this will trigger hook
test audit hook -- this will not
> ./POC2.py
audit hook triggered! ('sys.addaudithook', ())
--- finished setup ---
C audit hook triggered! event=os.system
audit hook triggered! ('os.system', (b"echo 'test audit hook -- this will trigger hook'",))
test audit hook -- this will trigger hook
test audit hook -- this will not
```
## Smash Audit hook without `ctypes`
> ref:
[UAF POC](./UAF-issue91153.md)
### How to use
```bash
# or ./build311.sh
# build the helper binary
./build.sh
# brute-force the offsets
./POC-no-ctypes.py
# verify the offsets works
./POC2-no-ctypes.py
```
## Smash Audit hook with fake bytearray
> ref: and
> more context:
### How to use
```bash
./build.sh
./POC-fake-bytearray.py
```
## TODO
- [x] Use to smash it without `ctypes`
- [x] Find a way to get the `audit_hook` address without using `ctypes`
- [ ] Use to smash it?