{"id":13577665,"url":"https://github.com/MuelNova/PwNo","last_synced_at":"2025-04-05T12:31:00.371Z","repository":{"id":200905018,"uuid":"706467168","full_name":"MuelNova/PwNo","owner":"MuelNova","description":"Pwntools Extension with No Extra Effort!","archived":false,"fork":false,"pushed_at":"2024-11-09T05:13:43.000Z","size":432,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-10T08:04:37.150Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MuelNova.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-18T02:31:02.000Z","updated_at":"2025-03-07T22:55:25.000Z","dependencies_parsed_at":"2023-10-20T10:11:54.481Z","dependency_job_id":"48312348-0f06-4fc7-aad1-acdc79c5edba","html_url":"https://github.com/MuelNova/PwNo","commit_stats":null,"previous_names":["muelnova/pwno"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MuelNova%2FPwNo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MuelNova%2FPwNo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MuelNova%2FPwNo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MuelNova%2FPwNo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MuelNova","download_url":"https://codeload.github.com/MuelNova/PwNo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247338616,"owners_count":20922989,"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":[],"created_at":"2024-08-01T15:01:23.392Z","updated_at":"2025-04-05T12:30:55.361Z","avatar_url":"https://github.com/MuelNova.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# PwNo\n\n_✨ Pwntools Extensions that Just Works! ✨_\n\n\u003cp\u003e\n\u003ca href=\"./LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/MuelNova/PwNo.svg\" alt=\"license\"\u003e\n\u003c/a\u003e\n\u003c/p\u003e\n\u003ca href=\"https://pypi.python.org/pypi/PwNo\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/v/PwNo.svg\" alt=\"pypi\"\u003e\n\u003c/a\u003e\n\u003cimg src=\"https://img.shields.io/badge/python-3.10+-blue.svg\" alt=\"python\"\u003e\n\n\u003cp\u003e\n\u003cimg alt=\"GitHub last commit\" src=\"https://img.shields.io/github/last-commit/MuelNova/PwNo?logo=github\u0026style=for-the-badge\"\u003e\n\u003c/p\u003e\n\n\u003c/div\u003e\n\n快速拓展你的 [pwntools](https://github.com/Gallopsled/pwntools)，使其更加易用，针对 pwn 开发\n\n## Features\n\n- [x] 开箱即用\n- [x] 完整的类型注解\n- [x] 好用简单的小工具\n- [ ] And more...\n\n## TL;DR\n\n### 一键缩写\n\n```python\nfrom pwno import *\n\np = process(['/path/to/your/elf'])\n\nsl(b'cat /flag')\nia()  # 无需设置！\n```\n\nsee [abbr](#abbr)\n\n### 可选命令行参数\n\n```python\n# 只需使用同一份代码！\nfrom pwno import *\n\nsh = gen_sh()\ndbg('b *$rebase(0x1145)')\nsl(b'A'*0x20 + p64(elf.sym['backdoor']))\nlibc.address = uu64(recv(6)) - 0x114514\nia()\n```\n\n```sh\npython exp.py  # 默认为 ./pwn\npython exp.py my_challenge  # 生成 ./my_challenge\npython exp.py -r my.challenge.pwn:11451 -l libc.so.6 # 远程调试，此时自动禁用 debug 模式\n```\n\nsee [CommandArgs](#CommandArgs)\n\n### 一键模板\n\n```python\n# 快速设置！\nfrom pwno import *\n\nio = IO_FILE_plus()\nio._flags = 1\nio.vtable = ...\n\nsend(bytes(io))\n\n\ncat = HouseOfCat()\ncat.rdi = b'/bin/sh'\ncat.call_addr = libc.sym['system']\nsend(bytes(cat))\nia()\n```\n\n### 一键获取 gadget\n\n```sh\n$ pwno libc-2.23.so\npop_rax_ret = libc.address + 0x3a738  # pop rax; ret;\npop_rdi_ret = libc.address + 0x21112  # pop rdi; ret;\npop_rdx_ret = libc.address + 0x1b92  # pop rdx; ret;\npop_rsi_ret = libc.address + 0x202f8  # pop rsi; ret;\nsyscall_ret = libc.address + 0xbc3f5  # syscall; ret;\nbinsh = libc.address + 0x18ce57  # /bin/sh\n```\n\n### And More ...\n\n## Installation\n\n\u003cdetails\u003e\n\u003csummary\u003e使用 pip 安装\u003c/summary\u003e\n\n    pip install PwNo --upgrade\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e本地安装\u003c/summary\u003e\n\n    git clone https://github.com/MuelNova/PwNo\n    cd PwNo\n    pip install -e .\n\n\u003c/details\u003e\n\n## Usage\n\n只需在你的 exp.py 导入\n\n```python\nfrom pwno import *\n```\n\n## Docs\n\n### context\n\n#### abbr\n\nPwNo 为脚本实现了缩写功能以加速你的脚本编写，而你不需要做任何操作\n\n\u003e 默认的导出：\n\u003e\n\u003e ​ \u003e\u003e\u003e send = process.send\n\u003e ​ \u003e\u003e\u003e sl = process.sendline\n\u003e ​ \u003e\u003e\u003e sa = process.sendafter\n\u003e ​ \u003e\u003e\u003e sla = process.sendlineafter\n\u003e\n\u003e ​ \u003e\u003e\u003e recv = process.recv\n\u003e ​ \u003e\u003e\u003e recvu = process.recvuntil\n\u003e ​ \u003e\u003e\u003e recvn = process.recvn\n\u003e ​ \u003e\u003e\u003e recvl = process.recvline\n\u003e\n\u003e ​ \u003e\u003e\u003e ia = process.interactive\n\n```python\nfrom pwno import *\n\np = process(['/path/to/your/elf'])\n\nsl(b'cat /flag')  # equals to p.sendline(b'cat /flag')\nia()  # equals to p.interactive()\n```\n\n这对变量名没有任何要求\n\n```python\nfrom pwno import *\n\nI_Hate_PWN = remote('weird.challenge.pwn', 11451)\n\nsl(b'cat /flag')  # equals to I_Hate_PWN.sendline(b'cat /flag')\nia()  # equals to I_Hate_PWN.interactive()\n```\n\n同时也支持循环操作，甚至修改变量名！在原来的 process 不可用的情况下，PwNo 会重新找到最新创建的 process/remote\n\n```python\nfrom pwno import *\n\np = process(['/path/to/your/elf'])\n# I hate the name 'p'\np.close()\nwhile True:\n    sh = process(['/path/to/your/elf'])\n\n    sl('I like sh!')  # equals to sh.sendline('I like sh!')\n    sh.close()\n```\n\n不喜欢 PwNo 设置的缩写？Make your own!\n\n使用 `abbr`，你可以轻松的设置你自己的缩写，或是设置全局的缩写\n\n```python\nfrom pwno import *\n\np = process(['/path/to/your/elf'])\nsh = process(['/path/to/your/elf'])\n\nnew_sl = abbr(process.sendline)  # Global Abbreviation\nnew_sl(b'sh')  # equals to sh.sendline(b'sh')\n\n\nmy_sl = abbr(p.sendline)\nmy_sl(b'OH~~~')  # equals to p.sendline(b'OH~~~')\nnew_sl(b'sh')  # equals to sh.sendline(b'sh')\n\nsh.close()\nnew_sl(b'p')  # equals to p.sendline(b'p')\n```\n\n**！注意！**\n\n对于全局缩写，为了优化性能，脚本在命令使用一次后将会把此时最新的 `process` 与命令进行绑定，此后除非绑定 `process` 不可用，否则都会指向绑定 `process`。\n\n```python\nfrom pwno import *\n\nsh = process(['/path/to/your/elf'])\nsl(b'I send here, I bind here')  # `sl` will be bind to `sh`\n\np = process(['/path/to/your/elf'])\nsend(b'I send, I bind p')  # call `p.send`\nsl(b'AM I still sh?')  # call `sh.sendline`\n```\n\n### typing\n\n#### pack\n\nPwNo 为常用的包装与解包函数添加了类型注解，现在你终于不需要对着标红的 `p64` \\ `u32` 眉头紧皱了！\n\n![TypeHint](docs/img/1.png)\n\n### helper\n\nPwNo 提供了省时省力的小工具加快你的解题。\n\n#### uu64 / uu32\n\n泄露地址仍然使用 `u64(recv(6).ljust(8, b'\\x00'))`？为什么不试试\n\n```python\nuu64(recv(6))\n```\n\n#### dbg\n\n自动添加 `pause()` 与判断是否远程的 dbg 工具\n\n在不指定前会使用最新的一个 `process` 实例\n\n```python\nfrom pwno import *\n\np = process('./pwn')\nsh = gen_sh()  # or sh = process('./pwn')  or sh = remote('your.challenge.pwn', 11451)\ndbg('b *$rebase(0x1145)', s=5)\n\ndbg('set follow-fork-mode parent', sh=sh)\n```\n\n#### log\n\nPwNo 使用更多的黑魔法让你的调试变得更快更好\n\n```python\nlibc_base = u64(p.recv(6).ljust(8, b'\\x00'))\nsuccess(f\"libc_base: {hex(libc_base)}\")\n\n# 为什么不试试\nlibc.addr = uu64(recv(6))\nsuccess(libc.addr)\n\n\"\n[+] libc.address: 0xdeadbeef(3735928559)\n\"\n\npayload = asm(shellcraft.sh())\ninfo(payload)\n\n\"\"\"\n[+] payload\n    00000000  6a 68 48 b8  2f 62 69 6e  2f 2f 2f 73  50 48 89 e7  │jhH·│/bin│///s│PH··│\n    00000010  68 72 69 01  01 81 34 24  01 01 01 01  31 f6 56 6a  │hri·│··4$│····│1·Vj│\n    00000020  08 5e 48 01  e6 56 48 89  e6 31 d2 6a  3b 58 0f 05  │·^H·│·VH·│·1·j│;X··│\n    00000030\n\"\"\"\n```\n\n### IO_FILE / IO_FILE_plus\n\nPwNo 使得你可以简便的设置 fake_IO\n\n```python\nfrom pwno import *\n\nio = IO_FILE_plus()\nio._flags = 1\nio.vtable = ...\nsend(bytes(io))\n\nio2 = IO_FILE()\nio._IO_write_ptr = 0xdeadbeef\nio._IO_write_base = p64(0xc0decafe)\nsend(bytes(io))\n```\n\n### House\n\nPwNo 提供了简便设置各种漏洞利用结构体的方法\n\n#### house_of_cat\n\n```python\nfrom pwno import *\n    \"\"\"\n    FSOP 版本的 house_of_cat，在 2.35 下测试通过，返回一个 fake_IO payload\n        rdi: 仅能设置 rdi 指针所指向的内容\n        rdx: rdx 寄存器内容\n        fake_io_addr: fake_IO 的地址\n        call_addr: 调用的地址\n\n        e.g.\n            cat = house_of_cat()\n            cat.fake_io_addr = heap\n            cat.rdi = b\"/bin/sh\\x00\"\n            cat.rdx = p64(0xcafec0de)\n            cat.call_addr = p64(backd00r)\n            cat.vtable = p64(libc.sym['_IO_wfile_jumps'] + 0x30)\n\n            send(bytes(cat))\n    \"\"\"\ncat = HouseOfCat()\ncat.rdi = b'/bin/sh'\ncat.rdx = 0xcafec0de\ncat.call_addr = lib.sym['setcontext'] + 61\ncat.fake_io = heap\n\nsend(cat)\n```\n\n### Gadget\n\nPwNo 提供了 Ropper 的包装，使你能够更迅速地查找 gadgets\n\n### load_gadgets\n\n```python\ndef load_gadgets(file: ELFType, force=None, **kwargs) -\u003e RopperService:\n    \"\"\"\n    查找 file 的 gadgets，如果 file 是 DYN 类型的 ELF，则会缓存 gadgets\n\n    Args:\n        file (ELFType): 要查找 gadgets 的 ELF 文件\n        force (bool, optional): 是否不使用缓存查找 gadgets. Defaults to None.\n\n    Returns:\n        RopperService: RopperService 实例\n    \"\"\"\n```\n\n### pprint_gadgets\n\n```python\ndef pprint_gadgets_default(\n    file: ELFType,\n    force: bool = False,\n    prefix: str = \"libc.address\",\n    regs: list[str] = [],\n    insts: list[str] = [],\n    strs: list[str] = [],\n    **kwargs,\n) -\u003e None:\n    \"\"\"\n    打印 file 的 gadgets, 以及 strings。返回可在 exp 中使用的常量\n\n    Args:\n        file (ELFType): 要查找 gadgets 的 ELF 文件\n        force (bool, optional): 是否不使用缓存查找 gadgets. Defaults to False.\n        prefix (str, optional): 变量的前缀. Defaults to \"libc.address\".\n        regs (list[str], optional): 寄存器列表. Defaults to [].\n        insts (list[str], optional): 指令列表. Defaults to [].\n        strs (list[str], optional): 字符串列表. Defaults to [].\n\n    Returns:\n        None\n    \"\"\"\n```\n\n### CommandArgs\n\nPwNo 提供了开箱即用的命令行参数方便使用，你无需任何设置，这并非强制的，它们都设置好了默认值。但 PwNo 推荐你结合 PwNo 提供的一些方法使得它更易用。\n\n```sh\n# python exp.py --help\nusage: exp.py [-h] [--libc [LIBC]] [--debug DBG] [--no-debug] [--remote REMOTE] [--host HOST] [--port PORT] [--gdb]\n              [--gdb-script GDB_SCRIPT] [--args RUNARGS]\n              [ATTACHMENT]\n\nPwnable Commandline\n\npositional arguments:\n  ATTACHMENT\n\noptions:\n  -h, --help            show this help message and exit\n  --libc [LIBC], -l [LIBC]\n  --debug DBG, -d DBG   Which dbg() to be executed, default is `all`, use comma to split. e.g. `-d 0,1,3`\n  --no-debug, -D        Disable debug mode\n  --remote REMOTE, -r REMOTE\n                        Remote host:port\n  --host HOST, -H HOST  Remote host, if remote is set, this option will be ignored\n  --port PORT, -p PORT  Remote port, if remote is set, this option will be ignored\n  --gdb, -g             Run binary using gdb.debug\n  --gdb-script GDB_SCRIPT, -G GDB_SCRIPT\n                        GDB script to run\n  --args RUNARGS, -a RUNARGS\n                        Arguments to run binary\n```\n\n```python\n# exp.py\nfrom pwno import *\n```\n\n#### gen_sh\n\n尽管这不是必须的，我们更推荐你直接使用 `gen_sh` 生成 `process` 实例。你只需要专心 exp 的编写，剩下的事交给 PwNo 就好\n\n```python\nfrom pwno import *\n\n# REMOTE = 0\n# if REMOTE:\n#     sh = remote(...)\n# else:\n#     # sh = gdb.debug(...)\n#     sh = process(...)\n\n# 为什么不试试\nsh = gen_sh()\n\n```\n\n```sh\n# 本地测试\npython exp.py\n# 本地测试（非 DEBUG）\npython exp.py -D\n# 远程\npython exp.py -r easy.challenge.pwn:12345\n# or\npython exp.py -h easy.challenge.pwn -p 12345\n```\n\n#### Elf、libc\n\nPwNo 会导出两个对象，`Elf` 和 `libc`，而它们的值即为命令行参数所传入的值。例如\n\n```sh\npython exp.py -l libc.so.6 heapMaster\n\n# Elf: ELF('./heapMaster')\n# libc: ELF('./libc.so.6')\n```\n\n默认情况下，`Elf` 将会指向当前工作目录 (CWD) 中的第一个 `ELF` 文件，而 `libc` 将会指向 `/bin/sh` 使用的 libc，因为这会更加便于调试。\n\n#### dbg 的行为\n\n[dbg](#dbg) 的行为将会收到命令行参数的影响，你如果设置了 `host, port / remote`，或是设置了 `--gdb` 在 `gdb.debug` 模式下运行，又或是指定了 `-D` 禁用了 debug 模式，dbg 将不会使用 gdb 附加或是等待。\n\n#### pwno\n\nPwNo 现在会在安装时增加一个 `pwno` 可执行程序，利用它，你可以方便的寻找 gadget（未来可以做到更多...）\n\n```sh\n$ pwno --help\nusage: pwno [-h] [--force] [--prefix PREFIX] [--regs [REGS ...]] [--insts [INSTS ...]] [--strs [STRS ...]] file\n\nSearch gadgets in binary\n\npositional arguments:\n  file                  The binary file to search gadgets in\n\noptions:\n  -h, --help            show this help message and exit\n  --force, -f           Force search gadgets\n  --prefix PREFIX, -p PREFIX\n                        The prefix to use for the variables\n  --regs [REGS ...], -r [REGS ...]\n                        The registers to use for the variables\n  --insts [INSTS ...], -i [INSTS ...]\n                        The instructions together with a `ret`\n  --strs [STRS ...], -s [STRS ...]\n                        The strings to search for\n```\n\n##### gadget 查找\n\n选择一个 ELF 文件，pwno 就会自动产生一些常用的 gadget 地址。相同的 libc gadget 将被存放在缓存目录下，使其能够更迅速的被查找。\n当前它会对 `libc` 文件产生 `pop rdi|rsi|rdx|rax; ret`、`syscall` 和 `/bin/sh` 的地址\n你可以通过 `--regs`、`--insts` 和 `--strs` 来自定义\n\n当然，未来，PwNo 也将支持默认配置的设置，从而使其更加符合你的需要\n\n```sh\n$ pwno libc-2.23.so\npop_rax_ret = libc.address + 0x3a738  # pop rax; ret;\npop_rdi_ret = libc.address + 0x21112  # pop rdi; ret;\npop_rdx_ret = libc.address + 0x1b92  # pop rdx; ret;\npop_rsi_ret = libc.address + 0x202f8  # pop rsi; ret;\nsyscall_ret = libc.address + 0xbc3f5  # syscall; ret;\nbinsh = libc.address + 0x18ce57  # /bin/sh\n\n0.58s\n```\n\n## ToDos\n\n### 自动的 glibc 替换\n\nPwNo 计划支持根据全局的配置自动解决 glibc 版本不对应的问题\n\n### 自动的 gadget 查找\n\nPwNo 计划支持自动寻找 elf 或 libc 中 gadget 的功能\n\n## Editing...\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMuelNova%2FPwNo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMuelNova%2FPwNo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMuelNova%2FPwNo/lists"}