Skip to main content

Pwntools Extension that Just Works

Project description

PwNo

✨ Pwntools Extensions that Just Works! ✨

license

pypi python

GitHub last commit

快速拓展你的 pwntools,使其更加易用,针对 pwn 开发

Features

  • 开箱即用
  • 完整的类型注解
  • 好用简单的小工具
  • And more...

TL;DR

一键缩写

from pwno import *

p = process(['/path/to/your/elf'])

sl(b'cat /flag')
ia()  # 无需设置!

see abbr

可选命令行参数

# 只需使用同一份代码!
from pwno import *

sh = gen_sh()
dbg('b *$rebase(0x1145)')
sl(b'A'*0x20 + p64(elf.sym['backdoor']))
libc.address = uu64(recv(6)) - 0x114514
ia()
python exp.py  # 默认为 ./pwn
python exp.py my_challenge  # 生成 ./my_challenge
python exp.py -r my.challenge.pwn:11451 -l libc.so.6 # 远程调试,此时自动禁用 debug 模式

see CommandArgs

一键模板

# 快速设置!
from pwno import *

io = IO_FILE_plus()
io._flags = 1
io.vtable = ...

send(bytes(io))


cat = HouseOfCat()
cat.rdi = b'/bin/sh'
cat.call_addr = libc.sym['system']
send(bytes(cat))
ia()

一键获取 gadget

$ pwno libc-2.23.so
pop_rax_ret = libc.address + 0x3a738  # pop rax; ret;
pop_rdi_ret = libc.address + 0x21112  # pop rdi; ret;
pop_rdx_ret = libc.address + 0x1b92  # pop rdx; ret;
pop_rsi_ret = libc.address + 0x202f8  # pop rsi; ret;
syscall_ret = libc.address + 0xbc3f5  # syscall; ret;
binsh = libc.address + 0x18ce57  # /bin/sh

And More ...

Installation

使用 pip 安装
pip install PwNo --upgrade
本地安装
git clone https://github.com/MuelNova/PwNo
cd PwNo
pip install -e .

Usage

只需在你的 exp.py 导入

from pwno import *

Docs

context

abbr

PwNo 为脚本实现了缩写功能以加速你的脚本编写,而你不需要做任何操作

默认的导出:

​ >>> send = process.send ​ >>> sl = process.sendline ​ >>> sa = process.sendafter ​ >>> sla = process.sendlineafter

​ >>> recv = process.recv ​ >>> recvu = process.recvuntil ​ >>> recvn = process.recvn ​ >>> recvl = process.recvline

​ >>> ia = process.interactive

from pwno import *

p = process(['/path/to/your/elf'])

sl(b'cat /flag')  # equals to p.sendline(b'cat /flag')
ia()  # equals to p.interactive()

这对变量名没有任何要求

from pwno import *

I_Hate_PWN = remote('weird.challenge.pwn', 11451)

sl(b'cat /flag')  # equals to I_Hate_PWN.sendline(b'cat /flag')
ia()  # equals to I_Hate_PWN.interactive()

同时也支持循环操作,甚至修改变量名!在原来的 process 不可用的情况下,PwNo 会重新找到最新创建的 process/remote

from pwno import *

p = process(['/path/to/your/elf'])
# I hate the name 'p'
p.close()
while True:
    sh = process(['/path/to/your/elf'])

    sl('I like sh!')  # equals to sh.sendline('I like sh!')
    sh.close()

不喜欢 PwNo 设置的缩写?Make your own!

使用 abbr,你可以轻松的设置你自己的缩写,或是设置全局的缩写

from pwno import *

p = process(['/path/to/your/elf'])
sh = process(['/path/to/your/elf'])

new_sl = abbr(process.sendline)  # Global Abbreviation
new_sl(b'sh')  # equals to sh.sendline(b'sh')


my_sl = abbr(p.sendline)
my_sl(b'OH~~~')  # equals to p.sendline(b'OH~~~')
new_sl(b'sh')  # equals to sh.sendline(b'sh')

sh.close()
new_sl(b'p')  # equals to p.sendline(b'p')

!注意!

对于全局缩写,为了优化性能,脚本在命令使用一次后将会把此时最新的 process 与命令进行绑定,此后除非绑定 process 不可用,否则都会指向绑定 process

from pwno import *

sh = process(['/path/to/your/elf'])
sl(b'I send here, I bind here')  # `sl` will be bind to `sh`

p = process(['/path/to/your/elf'])
send(b'I send, I bind p')  # call `p.send`
sl(b'AM I still sh?')  # call `sh.sendline`

typing

pack

PwNo 为常用的包装与解包函数添加了类型注解,现在你终于不需要对着标红的 p64 \ u32 眉头紧皱了!

TypeHint

helper

PwNo 提供了省时省力的小工具加快你的解题。

uu64 / uu32

泄露地址仍然使用 u64(recv(6).ljust(8, b'\x00'))?为什么不试试

uu64(recv(6))

dbg

自动添加 pause() 与判断是否远程的 dbg 工具

在不指定前会使用最新的一个 process 实例

from pwno import *

p = process('./pwn')
sh = gen_sh()  # or sh = process('./pwn')  or sh = remote('your.challenge.pwn', 11451)
dbg('b *$rebase(0x1145)', s=5)

dbg('set follow-fork-mode parent', sh=sh)

log

PwNo 使用更多的黑魔法让你的调试变得更快更好

libc_base = u64(p.recv(6).ljust(8, b'\x00'))
success(f"libc_base: {hex(libc_base)}")

# 为什么不试试
libc.addr = uu64(recv(6))
success(libc.addr)

"
[+] libc.address: 0xdeadbeef(3735928559)
"

payload = asm(shellcraft.sh())
info(payload)

"""
[+] payload
    00000000  6a 68 48 b8  2f 62 69 6e  2f 2f 2f 73  50 48 89 e7  │jhH·│/bin│///s│PH··│
    00000010  68 72 69 01  01 81 34 24  01 01 01 01  31 f6 56 6a  │hri·│··4$│····│1·Vj│
    00000020  08 5e 48 01  e6 56 48 89  e6 31 d2 6a  3b 58 0f 05  │·^H·│·VH·│·1·j│;X··│
    00000030
"""

IO_FILE / IO_FILE_plus

PwNo 使得你可以简便的设置 fake_IO

from pwno import *

io = IO_FILE_plus()
io._flags = 1
io.vtable = ...
send(bytes(io))

io2 = IO_FILE()
io._IO_write_ptr = 0xdeadbeef
io._IO_write_base = p64(0xc0decafe)
send(bytes(io))

House

PwNo 提供了简便设置各种漏洞利用结构体的方法

house_of_cat

from pwno import *
    """
    FSOP 版本的 house_of_cat,在 2.35 下测试通过,返回一个 fake_IO payload
        rdi: 仅能设置 rdi 指针所指向的内容
        rdx: rdx 寄存器内容
        fake_io_addr: fake_IO 的地址
        call_addr: 调用的地址

        e.g.
            cat = house_of_cat()
            cat.fake_io_addr = heap
            cat.rdi = b"/bin/sh\x00"
            cat.rdx = p64(0xcafec0de)
            cat.call_addr = p64(backd00r)
            cat.vtable = p64(libc.sym['_IO_wfile_jumps'] + 0x30)

            send(bytes(cat))
    """
cat = HouseOfCat()
cat.rdi = b'/bin/sh'
cat.rdx = 0xcafec0de
cat.call_addr = lib.sym['setcontext'] + 61
cat.fake_io = heap

send(cat)

Gadget

PwNo 提供了 Ropper 的包装,使你能够更迅速地查找 gadgets

load_gadgets

def load_gadgets(file: ELFType, force=None, **kwargs) -> RopperService:
    """
    查找 file 的 gadgets,如果 file 是 DYN 类型的 ELF,则会缓存 gadgets

    Args:
        file (ELFType): 要查找 gadgets 的 ELF 文件
        force (bool, optional): 是否不使用缓存查找 gadgets. Defaults to None.

    Returns:
        RopperService: RopperService 实例
    """

pprint_gadgets

def pprint_gadgets_default(
    file: ELFType,
    force: bool = False,
    prefix: str = "libc.address",
    regs: list[str] = [],
    insts: list[str] = [],
    strs: list[str] = [],
    **kwargs,
) -> None:
    """
    打印 file 的 gadgets, 以及 strings。返回可在 exp 中使用的常量

    Args:
        file (ELFType): 要查找 gadgets 的 ELF 文件
        force (bool, optional): 是否不使用缓存查找 gadgets. Defaults to False.
        prefix (str, optional): 变量的前缀. Defaults to "libc.address".
        regs (list[str], optional): 寄存器列表. Defaults to [].
        insts (list[str], optional): 指令列表. Defaults to [].
        strs (list[str], optional): 字符串列表. Defaults to [].

    Returns:
        None
    """

CommandArgs

PwNo 提供了开箱即用的命令行参数方便使用,你无需任何设置,这并非强制的,它们都设置好了默认值。但 PwNo 推荐你结合 PwNo 提供的一些方法使得它更易用。

# python exp.py --help
usage: exp.py [-h] [--libc [LIBC]] [--debug DBG] [--no-debug] [--remote REMOTE] [--host HOST] [--port PORT] [--gdb]
              [--gdb-script GDB_SCRIPT] [--args RUNARGS]
              [ATTACHMENT]

Pwnable Commandline

positional arguments:
  ATTACHMENT

options:
  -h, --help            show this help message and exit
  --libc [LIBC], -l [LIBC]
  --debug DBG, -d DBG   Which dbg() to be executed, default is `all`, use comma to split. e.g. `-d 0,1,3`
  --no-debug, -D        Disable debug mode
  --remote REMOTE, -r REMOTE
                        Remote host:port
  --host HOST, -H HOST  Remote host, if remote is set, this option will be ignored
  --port PORT, -p PORT  Remote port, if remote is set, this option will be ignored
  --gdb, -g             Run binary using gdb.debug
  --gdb-script GDB_SCRIPT, -G GDB_SCRIPT
                        GDB script to run
  --args RUNARGS, -a RUNARGS
                        Arguments to run binary
# exp.py
from pwno import *

gen_sh

尽管这不是必须的,我们更推荐你直接使用 gen_sh 生成 process 实例。你只需要专心 exp 的编写,剩下的事交给 PwNo 就好

from pwno import *

# REMOTE = 0
# if REMOTE:
#     sh = remote(...)
# else:
#     # sh = gdb.debug(...)
#     sh = process(...)

# 为什么不试试
sh = gen_sh()
# 本地测试
python exp.py
# 本地测试(非 DEBUG)
python exp.py -D
# 远程
python exp.py -r easy.challenge.pwn:12345
# or
python exp.py -h easy.challenge.pwn -p 12345

Elf、libc

PwNo 会导出两个对象,Elflibc,而它们的值即为命令行参数所传入的值。例如

python exp.py -l libc.so.6 heapMaster

# Elf: ELF('./heapMaster')
# libc: ELF('./libc.so.6')

默认情况下,Elf 将会指向当前工作目录 (CWD) 中的第一个 ELF 文件,而 libc 将会指向 /bin/sh 使用的 libc,因为这会更加便于调试。

dbg 的行为

dbg 的行为将会收到命令行参数的影响,你如果设置了 host, port / remote,或是设置了 --gdbgdb.debug 模式下运行,又或是指定了 -D 禁用了 debug 模式,dbg 将不会使用 gdb 附加或是等待。

pwno

PwNo 现在会在安装时增加一个 pwno 可执行程序,利用它,你可以方便的寻找 gadget(未来可以做到更多...)

$ pwno --help
usage: pwno [-h] [--force] [--prefix PREFIX] [--regs [REGS ...]] [--insts [INSTS ...]] [--strs [STRS ...]] file

Search gadgets in binary

positional arguments:
  file                  The binary file to search gadgets in

options:
  -h, --help            show this help message and exit
  --force, -f           Force search gadgets
  --prefix PREFIX, -p PREFIX
                        The prefix to use for the variables
  --regs [REGS ...], -r [REGS ...]
                        The registers to use for the variables
  --insts [INSTS ...], -i [INSTS ...]
                        The instructions together with a `ret`
  --strs [STRS ...], -s [STRS ...]
                        The strings to search for
gadget 查找

选择一个 ELF 文件,pwno 就会自动产生一些常用的 gadget 地址。相同的 libc gadget 将被存放在缓存目录下,使其能够更迅速的被查找。 当前它会对 libc 文件产生 pop rdi|rsi|rdx|rax; retsyscall/bin/sh 的地址 你可以通过 --regs--insts--strs 来自定义

当然,未来,PwNo 也将支持默认配置的设置,从而使其更加符合你的需要

$ pwno libc-2.23.so
pop_rax_ret = libc.address + 0x3a738  # pop rax; ret;
pop_rdi_ret = libc.address + 0x21112  # pop rdi; ret;
pop_rdx_ret = libc.address + 0x1b92  # pop rdx; ret;
pop_rsi_ret = libc.address + 0x202f8  # pop rsi; ret;
syscall_ret = libc.address + 0xbc3f5  # syscall; ret;
binsh = libc.address + 0x18ce57  # /bin/sh

0.58s

ToDos

自动的 glibc 替换

PwNo 计划支持根据全局的配置自动解决 glibc 版本不对应的问题

自动的 gadget 查找

PwNo 计划支持自动寻找 elf 或 libc 中 gadget 的功能

Editing...

Project details


Download files

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

Source Distribution

pwno-0.1.6a1.tar.gz (28.9 kB view details)

Uploaded Source

Built Distribution

pwno-0.1.6a1-py3-none-any.whl (23.6 kB view details)

Uploaded Python 3

File details

Details for the file pwno-0.1.6a1.tar.gz.

File metadata

  • Download URL: pwno-0.1.6a1.tar.gz
  • Upload date:
  • Size: 28.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for pwno-0.1.6a1.tar.gz
Algorithm Hash digest
SHA256 ef616ebd6c3a9b9eda814cea418b4ea4594c16dd04035892c67434ec13a18def
MD5 8c6915581c00a4217dd0f8a9aa757ecd
BLAKE2b-256 ea8148f7d76df46b5f61eedca08a3aafeea08ed48184df26c3727d73d1ed93b4

See more details on using hashes here.

File details

Details for the file pwno-0.1.6a1-py3-none-any.whl.

File metadata

  • Download URL: pwno-0.1.6a1-py3-none-any.whl
  • Upload date:
  • Size: 23.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for pwno-0.1.6a1-py3-none-any.whl
Algorithm Hash digest
SHA256 ca002276cf3eb7a30c9b2825b370984de66256f1058deee6e5a12b5fe2940f97
MD5 96f45c46268e6cdc59f6aa73e5cf74cb
BLAKE2b-256 ffb94b3d51765fc51d54af0f8eea34a7b60834fba4d809d1c64c02857c89ae58

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page