pwntools¶
pwntools
is a CTF framework and exploit development library.
Written in Python, it is designed for rapid prototyping and development,
and intended to make exploit writing as simple as possible.
The primary location for this documentation is at docs.pwntools.com, which uses readthedocs. It comes in three primary flavors:
Getting Started¶
关于 pwntools¶
无论你是用pwntools编写exp,还是将它作为一个其它软件工程的一部分,你都可以决定如何使用它。
历史上, pwntools是被用来编写一系列exp的领域特定语言(DSL)。在当前的pwntools版本中,我们只需要简单地用 from pwn import *
短短一行代码就可以使用各种漂亮的作用。
当我们重构pwntools的2.0版本时,我们注意到了两个相反的目标:
- 我们更愿意构造一个“寻常的”python模块结构,来使得使用者更快速地了解和使用pwntools。
- 我们想拥有更多的炫酷效果,尤其是将终端设为raw模式。
为了实现上面两个目标,我们决定开发两个不同的python模块: pwnlib
是一个整洁的python模块,而 pwn
则是我们在CTF中使用和编写exp的模块。
pwnlib
— 标准的python模块¶
这个模块是我们使用“纯净”的python开发的。一般地,我们不想在引用 pwnlib
或是在使用其子模块时出现这样那样的副作用。
大多数情况下,你只会得到你想使用的功能。例如,如果你不使用 import pwnlib.util
,你将没有权使用 pwnlib.util.packing
这个子模块。
尽管pwnlib中有一些特例,例如 pwnlib.shellcraft
, 影响这整个模块的简洁,但它们仍可在没有隐性副作用的情况下被使用。
安装¶
pwntools对ubuntu 12.04和 14.04系统支持地最好,但大多数功能在符合Posix标准的系统上(Debian, Arch, FreeBSD, OSX等等)应该也可以正常使用。
准备¶
为了能够充分利用 pwntools 的功能,你应该安装下列的系统库。
二进制工具¶
对国外的系统架构的汇编(比如在Mac OS X上汇编Sparc shellcode),我们需要安装交叉编译版本的binutils,我们尽可能使得这个安装过程流畅一点。
在下列的例子中,使用你的系统架构代替$ARCH(例如arm, mips64, vax等等)。
在一个现代化的8核计算机上编译binutils大约花费60秒。
Ubuntu¶
对于Ubuntu 12.04到15.10的发行版,你需要添加pwntools的 个人包存档库。
Ubuntu Xenial (16.04) 已经拥有官方的包,不需要做下面的步骤。
$ apt-get install software-properties-common
$ apt-add-repository ppa:pwntools/binutils
$ apt-get update
接着,针对于你的系统架构安装binutils。
$ apt-get install binutils-$ARCH-linux-gnu
Mac OS X¶
在Mac OS X上安装binutils非常简单,但是需要源码编译安装。然而,既然我们已经有了homebrew,我们就可以使用一条命令来解决。安装 brew 之后, 我们只需要从binutils中获取我们的二进制工具: binutils repo.
$ brew install https://raw.githubusercontent.com/Gallopsled/pwntools-binutils/master/osx/binutils-$ARCH.rb
其他系统¶
如果你想通过自己的手动编译安装,并且不是上面两个系统之一,编译binutils也非常简单,运行下面的脚本即可。
#!/usr/bin/env bash
V=2.25 # Binutils Version
ARCH=arm # Target architecture
cd /tmp
wget -nc https://ftp.gnu.org/gnu/binutils/binutils-$V.tar.gz
wget -nc https://ftp.gnu.org/gnu/binutils/binutils-$V.tar.gz.sig
gpg --keyserver keys.gnupg.net --recv-keys 4AE55E93
gpg --verify binutils-$V.tar.gz.sig
tar xf binutils-$V.tar.gz
mkdir binutils-build
cd binutils-build
export AR=ar
export AS=as
../binutils-$V/configure \
--prefix=/usr/local \
--target=$ARCH-unknown-linux-gnu \
--disable-static \
--disable-multilib \
--disable-werror \
--disable-nls
MAKE=gmake
hash gmake || MAKE=make
$MAKE -j clean all
sudo $MAKE install
最新发行版¶
你可以利用 pip
安装pwntools。
$ apt-get update
$ apt-get install python2.7 python-pip python-dev git libssl-dev libffi-dev
$ pip install --upgrade pwntools
开发版¶
如果你要在本地定制自己的pwntools,你应该这样做:
$ git clone https://github.com/Gallopsled/pwntools
$ pip install --upgrade --editable ./pwntools
开始使用¶
为了能够让你亲身实践一下pwntools,首先,我们来看几个简单的例子。
当在编写自己的exp时,我们一般会采用下面的方法,这样的话,pwntools就会将会它的所有功能都导入进来。
>>> from pwn import *
显然,这样的话,你将在全局空间里引用pwntools的所有函数。你现在可以用一些简单函数进行汇编,反汇编,pack,unpack等等其他操作。
整个pwntools的使用文档在这里查看: from pwn import *.
连接¶
如果你想要pwn一个程序的话,你肯定需要和它进行交互,对吧?pwntools使用它的模块 pwnlib.tubes
使这个变得相当简单。
这个模块会建立一个与进程、socket、端口和其他相关的连接。例如,远程操作连接可以通过 pwnlib.tubes.remote
来实现。
>>> conn = remote('ftp.debian.org',21)
>>> conn.recvline()
'220 ...'
>>> conn.send('USER anonymous\r\n')
>>> conn.recvuntil(' ', drop=True)
'331'
>>> conn.recvline()
'Please specify the password.\r\n'
>>> conn.close()
它也可以很容易地使得一个监听者处于等待状态:
>>> l = listen()
>>> r = remote('localhost', l.lport)
>>> c = l.wait_for_connection()
>>> r.send('hello')
>>> c.recv()
'hello'
此外,我们也可以利用 pwnlib.tubes.process
来简单地和进程进程交互。
>>> sh = process('/bin/sh')
>>> sh.sendline('sleep 3; echo hello world;')
>>> sh.recvline(timeout=1)
''
>>> sh.recvline(timeout=5)
'hello world\n'
>>> sh.close()
当然,你不仅可以利用程序来和进程进行通信,也可以直接与之 交互 :
>>> sh.interactive()
$ whoami
user
当你通过ssh方式进行漏洞利用的时候,可以使用 pwnlib.tubes.ssh
.
>>> shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0')
>>> shell['whoami']
'bandit0'
>>> shell.download_file('/etc/motd')
>>> sh = shell.run('sh')
>>> sh.sendline('sleep 3; echo hello world;')
>>> sh.recvline(timeout=1)
''
>>> sh.recvline(timeout=5)
'hello world\n'
>>> shell.close()
包装整数¶
在编写exp时,最常见的工作就是在整数之间转换,而且转换后,它们的表现形式就是一个字节序列。通常情况下,我们使用 struct
这个模块。
pwntools通过 pwnlib.util.packing
使之十分简单。这样我们就不需要再记住解包装的代码, 只需要看着说明文档编写代码就行.
>>> import struct
>>> p32(0xdeadbeef) == struct.pack('I', 0xdeadbeef)
True
>>> leet = '37130000'.decode('hex')
>>> u32('abcd') == struct.unpack('I', 'abcd')[0]
True
此外,pack和unpack的操作也支持其它字长,比如8位字长:
>>> u8('A') == 0x41
True
设置目标系统架构及操作系统¶
我们在操作中特别指定目标机器的系统架构:
>>> asm('nop')
'\x90'
>>> asm('nop', arch='arm')
'\x00\xf0 \xe3'
- 此外,我们也可以通过一次性地在全局的参数 ``context``中设置,操作系统,字节序,大小端,位宽都可以在那里设定。
>>> context.arch = 'i386' >>> context.os = 'linux' >>> context.endian = 'little' >>> context.word_size = 32
当然,你也可以一次性设置好这些变量:
>>> asm('nop')
'\x90'
>>> context(arch='arm', os='linux', endian='big', word_size=32)
>>> asm('nop')
'\xe3 \xf0\x00'
设置日志记录级别¶
你可以通过context来控制日志记录的级别:
例如,这样设置:
>>> context.log_level = 'debug'
这样,通过管道发送和接收的数据都会被打印在屏幕上。
汇编和反汇编¶
有时候,你可能需要从互联网上下载一些shellcode,这时你可以使用 pwnlib.asm
模块。
>>> asm('mov eax, 0').encode('hex')
'b800000000'
如果你按照下面的方式来做,会更加容易:
>>> print disasm('6a0258cd80ebf9'.decode('hex'))
0: 6a 02 push 0x2
2: 58 pop eax
3: cd 80 int 0x80
5: eb f9 jmp 0x0
而且,你甚至不需要大部分时间去写shellcode。pwntools提供了 pwnlib.shellcraft
,可以在你编写shellcode的时候提供帮助。
如果说我们想执行 setreuid(getuid(), getuid()),之后复制文件描述符4到 stdin, stdout 以及 stderr, 然后弹出一个shell!,那我们就可以这么做
>>> asm(shellcraft.setreuid() + shellcraft.dupsh(4)).encode('hex')
'6a3158cd80...'
杂项工具¶
多亏有了 pwnlib.util.fiddling
这个模块,我们不需要写另外的hexdump。
我们可以通过使用模块 pwnlib.cyclic
在触发的崩溃中寻找偏移量或缓冲区大小。
>>> print cyclic(20)
aaaabaaacaaadaaaeaaa
>>> # Assume EIP = 0x62616166 ('faab' which is pack(0x62616166)) at crash time
>>> print cyclic_find('faab')
120
操纵ELF文件¶
我们也不需要进行硬编码了,因为我们可以使用 pwnlib.elf
来在运行时查看对应的参数。
>>> e = ELF('/bin/cat')
>>> print hex(e.address)
0x400000
>>> print hex(e.symbols['write'])
0x401680
>>> print hex(e.got['write'])
0x60b070
>>> print hex(e.plt['write'])
0x401680
你也可以给ELF文件打补丁或是保存。
>>> e = ELF('/bin/cat')
>>> e.read(e.address+1, 3)
'ELF'
>>> e.asm(e.address, 'ret')
>>> e.save('/tmp/quiet-cat')
>>> disasm(file('/tmp/quiet-cat','rb').read(1))
' 0: c3 ret'
from pwn import *
¶
The most common way that you’ll see pwntools used is
>>> from pwn import *
Which imports a bazillion things into the global namespace to make your life easier.
This is a quick list of most of the objects and routines imported, in rough order of importance and frequency of use.
context
pwnlib.context.context
- Responsible for most of the pwntools convenience settings
- Set context.log_level = ‘debug’ when troubleshooting your exploit
- Scope-aware, so you can disable logging for a subsection of code via
pwnlib.context.ContextType.local
remote
,listen
,ssh
,process
pwnlib.tubes
- Super convenient wrappers around all of the common functionality for CTF challenges
- Connect to anything, anywhere, and it works the way you want it to
- Helpers for common tasks like
recvline
,recvuntil
,clean
, etc. - Interact directly with the application via
.interactive()
p32
andu32
pwnlib.util.packing
- Useful functions to make sure you never have to remember if
'>'
means signed or unsigned forstruct.pack
, and no more ugly[0]
index at the end. - Set
signed
andendian
in sane manners (also these can be set once oncontext
and not bothered with again) - Most common sizes are pre-defined (
u8
,u64
, etc), andpwnlib.util.packing.pack()
lets you define your own.
log
pwnlib.log
- Make your output pretty!
cyclic
andcyclic_func
pwnlib.util.cyclic
- Utilities for generating strings such that you can find the offset of any given substring given only N (usually 4) bytes. This is super useful for straight buffer overflows. Instead of looking at 0x41414141, you could know that 0x61616171 means you control EIP at offset 64 in your buffer.
asm
anddisasm
pwnlib.asm
- Quickly turn assembly into some bytes, or vice-versa, without mucking about
- Supports any architecture for which you have a binutils installed
- Over 20 different architectures have pre-built binaries at ppa:pwntools/binutils.
shellcraft
pwnlib.shellcraft
- Library of shellcode ready to go
asm(shellcraft.sh())
gives you a shell- Templating library for reusability of shellcode fragments
ELF
pwnlib.elf
- ELF binary manipulation tools, including symbol lookup, virtual memory to file offset helpers, and the ability to modify and save binaries back to disk
DynELF
pwnlib.dynelf
- Dynamically resolve functions given only a pointer to any loaded module, and a function which can leak data at any address
ROP
pwnlib.rop
- Automatically generate ROP chains using a DSL to describe what you want to do, rather than raw addresses
gdb.debug
andgdb.attach
pwnlib.gdb
- Launch a binary under GDB and pop up a new terminal to interact with it. Automates setting breakpoints and makes iteration on exploits MUCH faster.
- Alternately, attach to a running process given a PID,
pwnlib.tubes
object, or even just a socket that’s connected to it
args
- Dictionary contining all-caps command-line arguments for quick access
- Run via
python foo.py REMOTE=1
andargs['REMOTE'] == '1'
. - Can also control logging verbosity and terminal fancyness
- NOTERM
- SILENT
- DEBUG
randoms
,rol
,ror
,xor
,bits
pwnlib.util.fiddling
- Useful utilities for generating random data from a given alphabet, or simplifying math operations that usually require masking off with 0xffffffff or calling ord and chr an ugly number of times
net
pwnlib.util.net
- Routines for querying about network interfaces
proc
pwnlib.util.proc
- Routines for querying about processes
pause
- It’s the new
getch
- It’s the new
safeeval
pwnlib.util.safeeval
- Functions for safely evalutaing python code without nasty side-effects.
These are all pretty self explanatory, but are useful to have in the global namespace.
hexdump
read
andwrite
enhex
andunhex
more
group
align
andalign_down
urlencode
andurldecode
which
wget
Additionally, all of the following modules are auto-imported for you. You were going to do it anyway.
os
sys
time
requests
re
random
命令行工具¶
pwntools附带一些有用的命令行工具,作为内部功能的封装器。
pwn¶
Pwntools Command-line Interface
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
-h
,
--help
¶
show this help message and exit
pwn asm¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
line
¶
Lines to assemble. If none are supplied, use stdin
-
-h
,
--help
¶
show this help message and exit
-
-f
{raw,hex,string,elf}
,
--format
{raw,hex,string,elf}
¶ Output format (defaults to hex for ttys, otherwise raw)
-
-o
<file>
,
--output
<file>
¶ Output file (defaults to stdout)
-
-c
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
,
--context
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
¶ The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: [‘16’, ‘32’, ‘64’, ‘android’, ‘cgc’, ‘freebsd’, ‘linux’, ‘windows’, ‘powerpc64’, ‘aarch64’, ‘sparc64’, ‘powerpc’, ‘mips64’, ‘msp430’, ‘thumb’, ‘amd64’, ‘sparc’, ‘alpha’, ‘s390’, ‘i386’, ‘m68k’, ‘mips’, ‘ia64’, ‘cris’, ‘vax’, ‘avr’, ‘arm’, ‘little’, ‘big’, ‘el’, ‘le’, ‘be’, ‘eb’]
-
-v
<avoid>
,
--avoid
<avoid>
¶ Encode the shellcode to avoid the listed bytes (provided as hex; default: 000a)
-
-n
,
--newline
¶
Encode the shellcode to avoid newlines
-
-z
,
--zero
¶
Encode the shellcode to avoid NULL bytes
-
-d
,
--debug
¶
Debug the shellcode with GDB
-
-e
<encoder>
,
--encoder
<encoder>
¶ Specific encoder to use
-
-i
<infile>
,
--infile
<infile>
¶ Specify input file
-
-r
,
--run
¶
Run output
pwn checksec¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
elf
¶
Files to check
-
-h
,
--help
¶
show this help message and exit
-
--file
<elf>
¶ File to check (for compatibility with checksec.sh)
pwn constgrep¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
regex
¶
The regex matching constant you want to find
-
constant
¶
The constant to find
-
-h
,
--help
¶
show this help message and exit
-
-e
<constant>
,
--exact
<constant>
¶ Do an exact match for a constant instead of searching for a regex
-
-i
,
--case-insensitive
¶
Search case insensitive
-
-m
,
--mask-mode
¶
Instead of searching for a specific constant value, search for values not containing strictly less bits that the given value.
-
-c
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
,
--context
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
¶ The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: [‘16’, ‘32’, ‘64’, ‘android’, ‘cgc’, ‘freebsd’, ‘linux’, ‘windows’, ‘powerpc64’, ‘aarch64’, ‘sparc64’, ‘powerpc’, ‘mips64’, ‘msp430’, ‘thumb’, ‘amd64’, ‘sparc’, ‘alpha’, ‘s390’, ‘i386’, ‘m68k’, ‘mips’, ‘ia64’, ‘cris’, ‘vax’, ‘avr’, ‘arm’, ‘little’, ‘big’, ‘el’, ‘le’, ‘be’, ‘eb’]
pwn cyclic¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
count
¶
Number of characters to print
-
-h
,
--help
¶
show this help message and exit
-
-a
<alphabet>
,
--alphabet
<alphabet>
¶ The alphabet to use in the cyclic pattern (defaults to all lower case letters)
-
-n
<length>
,
--length
<length>
¶ Size of the unique subsequences (defaults to 4).
-
-c
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
,
--context
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
¶ The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: [‘16’, ‘32’, ‘64’, ‘android’, ‘cgc’, ‘freebsd’, ‘linux’, ‘windows’, ‘powerpc64’, ‘aarch64’, ‘sparc64’, ‘powerpc’, ‘mips64’, ‘msp430’, ‘thumb’, ‘amd64’, ‘sparc’, ‘alpha’, ‘s390’, ‘i386’, ‘m68k’, ‘mips’, ‘ia64’, ‘cris’, ‘vax’, ‘avr’, ‘arm’, ‘little’, ‘big’, ‘el’, ‘le’, ‘be’, ‘eb’]
-
-l
<lookup_value>
,
-o
<lookup_value>
,
--offset
<lookup_value>
,
--lookup
<lookup_value>
¶ Do a lookup instead printing the alphabet
pwn disasm¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
hex
¶
Hex-string to disasemble. If none are supplied, then it uses stdin in non-hex mode.
-
-h
,
--help
¶
show this help message and exit
-
-c
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
,
--context
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
¶ The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: [‘16’, ‘32’, ‘64’, ‘android’, ‘cgc’, ‘freebsd’, ‘linux’, ‘windows’, ‘powerpc64’, ‘aarch64’, ‘sparc64’, ‘powerpc’, ‘mips64’, ‘msp430’, ‘thumb’, ‘amd64’, ‘sparc’, ‘alpha’, ‘s390’, ‘i386’, ‘m68k’, ‘mips’, ‘ia64’, ‘cris’, ‘vax’, ‘avr’, ‘arm’, ‘little’, ‘big’, ‘el’, ‘le’, ‘be’, ‘eb’]
-
-a
<address>
,
--address
<address>
¶ Base address
-
--color
¶
Color output
-
--no-color
¶
Disable color output
pwn elfdiff¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
a
¶
-
b
¶
-
-h
,
--help
¶
show this help message and exit
pwn elfpatch¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
-h
,
--help
¶
show this help message and exit
pwn errno¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
error
¶
Error message or value
-
-h
,
--help
¶
show this help message and exit
pwn hex¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
data
¶
Data to convert into hex
-
-h
,
--help
¶
show this help message and exit
pwn phd¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
file
¶
File to hexdump. Reads from stdin if missing.
-
-h
,
--help
¶
show this help message and exit
-
-w
<width>
,
--width
<width>
¶ Number of bytes per line.
-
-l
<highlight>
,
--highlight
<highlight>
¶ Byte to highlight.
-
-s
<skip>
,
--skip
<skip>
¶ Skip this many initial bytes.
-
-c
<count>
,
--count
<count>
¶ Only show this many bytes.
-
-o
<offset>
,
--offset
<offset>
¶ Addresses in left hand column starts at this address.
-
--color
{always,never,auto}
¶ Colorize the output. When ‘auto’ output is colorized exactly when stdout is a TTY. Default is ‘auto’.
pwn pwnstrip¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
file
¶
-
-h
,
--help
¶
show this help message and exit
-
-b
,
--build-id
¶
Strip build ID
-
-p
<function>
,
--patch
<function>
¶ Patch function
-
-o
<output>
,
--output
<output>
¶
pwn scramble¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
-h
,
--help
¶
show this help message and exit
-
-f
{raw,hex,string,elf}
,
--format
{raw,hex,string,elf}
¶ Output format (defaults to hex for ttys, otherwise raw)
-
-o
<file>
,
--output
<file>
¶ Output file (defaults to stdout)
-
-c
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
,
--context
{16,32,64,android,cgc,freebsd,linux,windows,powerpc64,aarch64,sparc64,powerpc,mips64,msp430,thumb,amd64,sparc,alpha,s390,i386,m68k,mips,ia64,cris,vax,avr,arm,little,big,el,le,be,eb}
¶ The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: [‘16’, ‘32’, ‘64’, ‘android’, ‘cgc’, ‘freebsd’, ‘linux’, ‘windows’, ‘powerpc64’, ‘aarch64’, ‘sparc64’, ‘powerpc’, ‘mips64’, ‘msp430’, ‘thumb’, ‘amd64’, ‘sparc’, ‘alpha’, ‘s390’, ‘i386’, ‘m68k’, ‘mips’, ‘ia64’, ‘cris’, ‘vax’, ‘avr’, ‘arm’, ‘little’, ‘big’, ‘el’, ‘le’, ‘be’, ‘eb’]
-
-p
,
--alphanumeric
¶
Encode the shellcode with an alphanumeric encoder
-
-v
<avoid>
,
--avoid
<avoid>
¶ Encode the shellcode to avoid the listed bytes
-
-n
,
--newline
¶
Encode the shellcode to avoid newlines
-
-z
,
--zero
¶
Encode the shellcode to avoid NULL bytes
-
-d
,
--debug
¶
Debug the shellcode with GDB
pwn shellcraft¶
usage: pwn [-h] {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update} ...
-
shellcode
¶
The shellcode you want
-
arg
¶
Argument to the chosen shellcode
-
-h
,
--help
¶
show this help message and exit
-
-
?
,
--show
¶
Show shellcode documentation
-
-o
<file>
,
--out
<file>
¶ Output file (default: stdout)
-
-f
{r,raw,s,str,string,c,h,hex,a,asm,assembly,p,i,hexii,e,elf,d,escaped,default}
,
--format
{r,raw,s,str,string,c,h,hex,a,asm,assembly,p,i,hexii,e,elf,d,escaped,default}
¶ Output format (default: hex), choose from {e}lf, {r}aw, {s}tring, {c}-style array, {h}ex string, hex{i}i, {a}ssembly code, {p}reprocssed code, escape{d} hex string
-
-d
,
--debug
¶
Debug the shellcode with GDB
-
-b
,
--before
¶
Insert a debug trap before the code
-
-a
,
--after
¶
Insert a debug trap after the code
-
-v
<avoid>
,
--avoid
<avoid>
¶ Encode the shellcode to avoid the listed bytes
-
-n
,
--newline
¶
Encode the shellcode to avoid newlines
-
-z
,
--zero
¶
Encode the shellcode to avoid NULL bytes
-
-r
,
--run
¶
Run output
-
--color
¶
Color output
-
--no-color
¶
Disable color output
-
--syscalls
¶
List syscalls
-
--address
<address>
¶ Load address
-
-l
,
--list
¶
List available shellcodes, optionally provide a filter
Module Index¶
Each of the pwntools
modules is documented here.
pwnlib.adb
— Android Debug Bridge¶
Provides utilities for interacting with Android devices via the Android Debug Bridge.
Using Android Devices with Pwntools¶
Pwntools tries to be as easy as possible to use with Android devices.
If you have only one device attached, everything “just works”.
If you have multiple devices, you have a handful of options to select one, or iterate over the devices.
First and most important is the context.device
property, which declares the “currently”
selected device in any scope. It can be set manually to a serial number, or to a Device
instance.
# Take the first available device
context.device = adb.wait_for_device()
# Set a device by serial number
context.device = 'ZX1G22LH8S'
# Set a device by its product name
for device in adb.devices():
if device.product == 'shamu':
break
else:
error("Could not find any shamus!")
Once a device is selected, you can operate on it with any of the functions in
the pwnlib.adb
module.
# Get a process listing
print adb.process(['ps']).recvall()
# Fetch properties
print adb.properties.ro.build.fingerprint
# Read and write files
print adb.read('/proc/version')
adb.write('/data/local/tmp/foo', 'my data')
-
class
pwnlib.adb.adb.
AdbDevice
(serial, type, port=None, product='unknown', model='unknown', device='unknown', features=None, **kw)[source]¶ Encapsulates information about a connected device.
Example
>>> device = adb.wait_for_device() >>> device.arch 'arm' >>> device.bits 32 >>> device.os 'android' >>> device.product 'sdk_phone_armv7' >>> device.serial 'emulator-5554'
-
pwnlib.adb.adb.
adb
(argv, *a, **kw)[source]¶ Returns the output of an ADB subcommand.
>>> adb.adb(['get-serialno']) 'emulator-5554\n'
-
pwnlib.adb.adb.
boot_time
() → int[source]¶ Returns: Boot time of the device, in Unix time, rounded to the nearest second.
-
pwnlib.adb.adb.
current_device
(any=False)[source]¶ Returns an
AdbDevice
instance for the currently-selected device (viacontext.device
).Example
>>> device = adb.current_device(any=True) >>> device AdbDevice(serial='emulator-5554', type='device', port='emulator', product='sdk_phone_armv7', model='sdk phone armv7', device='generic') >>> device.port 'emulator'
-
pwnlib.adb.adb.
devices
(*a, **kw)[source]¶ Returns a list of
Device
objects corresponding to the connected devices.
-
pwnlib.adb.adb.
exists
(*a, **kw)[source]¶ Return
True
ifpath
exists on the target device.Examples
>>> adb.exists('/') True >>> adb.exists('/init') True >>> adb.exists('/does/not/exist') False
-
pwnlib.adb.adb.
find_ndk_project_root
(source)[source]¶ Given a directory path, find the topmost project root.
tl;dr “foo/bar/jni/baz.cpp” ==> “foo/bar”
-
pwnlib.adb.adb.
getprop
(*a, **kw)[source]¶ Reads a properties from the system property store.
Parameters: name (str) – Optional, read a single property. Returns: If name
is not specified, adict
of all properties is returned. Otherwise, a string is returned with the contents of the named property.
-
pwnlib.adb.adb.
install
(apk, *arguments)[source]¶ Install an APK onto the device.
This is a wrapper around ‘pm install’, which backs ‘adb install’.
Parameters: - apk (str) – Path to the APK to intall (e.g.
'foo.apk'
) - arguments – Supplementary arguments to ‘pm install’,
e.g.
'-l', '-g'
.
- apk (str) – Path to the APK to intall (e.g.
-
pwnlib.adb.adb.
isdir
(*a, **kw)[source]¶ Return
True
ifpath
is a on the target device.Examples
>>> adb.isdir('/') True >>> adb.isdir('/init') False >>> adb.isdir('/does/not/exist') False
-
pwnlib.adb.adb.
listdir
(*a, **kw)[source]¶ Returns a list containing the entries in the provided directory.
Note
This uses the SYNC LIST functionality, which runs in the adbd SELinux context. If adbd is running in the su domain (‘adb root’), this behaves as expected.
Otherwise, less files may be returned due to restrictive SELinux policies on adbd.
-
pwnlib.adb.adb.
logcat
(*a, **kw)[source]¶ Reads the system log file.
By default, causes logcat to exit after reading the file.
Parameters: stream (bool) – If True
, the contents are streamed rather than read in a one-shot manner. Default isFalse
.Returns: If stream
isFalse
, returns a string containing the log data. Otherwise, it returns apwnlib.tubes.tube.tube
connected to the log output.
-
pwnlib.adb.adb.
makedirs
(*a, **kw)[source]¶ Create a directory and all parent directories on the target device.
Note
Silently succeeds if the directory already exists.
Examples
>>> adb.makedirs('/data/local/tmp/this/is/a/directory/heirarchy') >>> adb.listdir('/data/local/tmp/this/is/a/directory') ['heirarchy']
-
pwnlib.adb.adb.
mkdir
(*a, **kw)[source]¶ Create a directory on the target device.
Note
Silently succeeds if the directory already exists.
Parameters: path (str) – Directory to create. Examples
>>> adb.mkdir('/')
>>> path = '/data/local/tmp/mkdir_test' >>> adb.exists(path) False >>> adb.mkdir(path) >>> adb.exists(path) True
>>> adb.mkdir('/init') Traceback (most recent call last): ... PwnlibException: mkdir failed for /init, File exists
-
pwnlib.adb.adb.
proc_exe
(*a, **kw)[source]¶ Returns the full path of the executable for the provided PID.
-
pwnlib.adb.adb.
process
(*a, **kw)[source]¶ Execute a process on the device.
See
pwnlib.tubes.process.process
documentation for more info.Returns: A pwnlib.tubes.process.process
tube.Examples
>>> adb.root() >>> print adb.process(['cat','/proc/version']).recvall() Linux version ...
-
pwnlib.adb.adb.
pull
(*a, **kw)[source]¶ Download a file from the device.
Parameters: Returns: The contents of the file.
Example
>>> _=adb.pull('/proc/version', './proc-version') >>> print read('./proc-version') Linux version ...
-
pwnlib.adb.adb.
push
(*a, **kw)[source]¶ Upload a file to the device.
Parameters: Returns: Remote path of the file.
Example
>>> write('./filename', 'contents') >>> adb.push('./filename', '/data/local/tmp') '/data/local/tmp/filename' >>> adb.read('/data/local/tmp/filename') 'contents' >>> adb.push('./filename', '/does/not/exist') Traceback (most recent call last): ... PwnlibException: Could not stat '/does/not/exist'
-
pwnlib.adb.adb.
read
(*a, **kw)[source]¶ Download a file from the device, and extract its contents.
Parameters: Examples
>>> print adb.read('/proc/version') Linux version ... >>> adb.read('/does/not/exist') Traceback (most recent call last): ... PwnlibException: Could not stat '/does/not/exist'
-
pwnlib.adb.adb.
uninstall
(package, *arguments)[source]¶ Uninstall an APK from the device.
This is a wrapper around ‘pm uninstall’, which backs ‘adb uninstall’.
Parameters: - package (str) – Name of the package to uninstall (e.g.
'com.foo.MyPackage'
) - arguments – Supplementary arguments to
'pm install'
, e.g.'-k'
.
- package (str) – Name of the package to uninstall (e.g.
-
pwnlib.adb.adb.
unlink
(*a, **kw)[source]¶ Unlinks a file or directory on the target device.
Examples
>>> adb.unlink("/does/not/exist") Traceback (most recent call last): ... PwnlibException: Could not unlink '/does/not/exist': Does not exist
>>> filename = '/data/local/tmp/unlink-test' >>> adb.write(filename, 'hello') >>> adb.exists(filename) True >>> adb.unlink(filename) >>> adb.exists(filename) False
>>> adb.mkdir(filename) >>> adb.write(filename + '/contents', 'hello') >>> adb.unlink(filename) Traceback (most recent call last): ... PwnlibException: Cannot delete non-empty directory '/data/local/tmp/unlink-test' without recursive=True
>>> adb.unlink(filename, recursive=True) >>> adb.exists(filename) False
-
pwnlib.adb.adb.
unlock_bootloader
(*a, **kw)[source]¶ Unlocks the bootloader of the device.
Note
This requires physical interaction with the device.
-
pwnlib.adb.adb.
wait_for_device
(*a, **kw)[source]¶ Waits for a device to be connected.
By default, waits for the currently-selected device (via
context.device
). To wait for a specific device, setcontext.device
. To wait for any device, clearcontext.device
.Returns: An AdbDevice
instance for the device.Examples
>>> device = adb.wait_for_device()
-
pwnlib.adb.adb.
which
(*a, **kw)[source]¶ Retrieves the full path to a binary in
$PATH
on the deviceParameters: - name (str) – Binary name
- all (bool) – Whether to return all paths, or just the first
- *a – Additional arguments for
adb.process()
- **kw – Additional arguments for
adb.process()
Returns: Either a path, or list of paths
Example
>>> adb.which('sh') '/system/bin/sh' >>> adb.which('sh', all=True) ['/system/bin/sh']
>>> adb.which('foobar') is None True >>> adb.which('foobar', all=True) []
This file exists only for backward compatibility
pwnlib.args
— Magic Command-Line Arguments¶
Pwntools exposes several magic command-line arguments and environment variables when operating in from pwn import * mode.
The arguments extracted from the command-line and removed from sys.argv
.
Arguments can be set by appending them to the command-line, or setting
them in the environment prefixed by PWNLIB_
.
The easiest example is to enable more verbose debugging. Just set DEBUG
.
$ PWNLIB_DEBUG=1 python exploit.py
$ python exploit.py DEBUG
These arguments are automatically extracted, regardless of their name, and
exposed via pwnlib.args.args
, which is exposed as the global variable
args
. Arguments which pwntools
reserves internally are not exposed
this way.
$ python -c 'from pwn import *; print args' A=1 B=Hello HOST=1.2.3.4 DEBUG
defaultdict(<type 'str'>, {'A': '1', 'HOST': '1.2.3.4', 'B': 'Hello'})
This is very useful for conditional code, for example determining whether to run an exploit locally or to connect to a remote server. Arguments which are not specified evaluate to an empty string.
if args['REMOTE']:
io = remote('exploitme.com', 4141)
else:
io = process('./pwnable')
The full list of supported “magic arguments” and their effects are listed below.
-
pwnlib.args.
DEBUG
(x)[source]¶ Sets the logging verbosity to
debug
which displays much more information, including logging each byte sent by tubes.
-
pwnlib.args.
LOG_FILE
(x)[source]¶ Sets a log file to be used via
context.log_file
, e.g.LOG_FILE=./log.txt
-
pwnlib.args.
LOG_LEVEL
(x)[source]¶ Sets the logging verbosity used via
context.log_level
, e.g.LOG_LEVEL=debug
.
-
pwnlib.args.
NOPTRACE
(v)[source]¶ Disables facilities which require
ptrace
such asgdb.attach()
statements, viacontext.noptrace
.
pwnlib.asm
— Assembler functions¶
Utilities for assembling and disassembling code.
Architecture Selection¶
Assembly¶
To assemble code, simply invoke
asm()
on the code to assemble.>>> asm('mov eax, 0') '\xb8\x00\x00\x00\x00'Additionally, you can use constants as defined in the
pwnlib.constants
module.>>> asm('mov eax, SYS_execve') '\xb8\x0b\x00\x00\x00'Finally,
asm()
is used to assemble shellcode provided bypwntools
in theshellcraft
module.>>> asm(shellcraft.nop()) '\x90'
Disassembly¶
To disassemble code, simply invoke
disasm()
on the bytes to disassemble.>>> disasm('\xb8\x0b\x00\x00\x00') ' 0: b8 0b 00 00 00 mov eax,0xb'
-
pwnlib.asm.
asm
(code, vma = 0, extract = True, shared = False, ...) → str[source]¶ Runs
cpp()
over a given shellcode and then assembles it into bytes.To see which architectures or operating systems are supported, look in
pwnlib.contex
.Assembling shellcode requires that the GNU assembler is installed for the target architecture. See Installing Binutils for more information.
Parameters: - shellcode (str) – Assembler code to assemble.
- vma (int) – Virtual memory address of the beginning of assembly
- extract (bool) – Extract the raw assembly bytes from the assembled
file. If
False
, returns the path to an ELF file with the assembly embedded. - shared (bool) – Create a shared object.
- kwargs (dict) – Any attributes on
context
can be set, e.g.setarch='arm'
.
Examples
>>> asm("mov eax, SYS_select", arch = 'i386', os = 'freebsd') '\xb8]\x00\x00\x00' >>> asm("mov eax, SYS_select", arch = 'amd64', os = 'linux') '\xb8\x17\x00\x00\x00' >>> asm("mov rax, SYS_select", arch = 'amd64', os = 'linux') 'H\xc7\xc0\x17\x00\x00\x00' >>> asm("mov r0, #SYS_select", arch = 'arm', os = 'linux', bits=32) 'R\x00\xa0\xe3'
-
pwnlib.asm.
cpp
(shellcode, ...) → str[source]¶ Runs CPP over the given shellcode.
The output will always contain exactly one newline at the end.
Parameters: shellcode (str) – Shellcode to preprocess - Kwargs:
- Any arguments/properties that can be set on
context
Examples
>>> cpp("mov al, SYS_setresuid", arch = "i386", os = "linux") 'mov al, 164\n' >>> cpp("weee SYS_setresuid", arch = "arm", os = "linux") 'weee (0+164)\n' >>> cpp("SYS_setresuid", arch = "thumb", os = "linux") '(0+164)\n' >>> cpp("SYS_setresuid", os = "freebsd") '311\n'
-
pwnlib.asm.
disasm
(data, ...) → str[source]¶ Disassembles a bytestring into human readable assembler.
To see which architectures are supported, look in
pwnlib.contex
.To support all these architecture, we bundle the GNU objcopy and objdump with pwntools.
Parameters: - Kwargs:
- Any arguments/properties that can be set on
context
Examples
>>> print disasm('b85d000000'.decode('hex'), arch = 'i386') 0: b8 5d 00 00 00 mov eax,0x5d >>> print disasm('b85d000000'.decode('hex'), arch = 'i386', byte = 0) 0: mov eax,0x5d >>> print disasm('b85d000000'.decode('hex'), arch = 'i386', byte = 0, offset = 0) mov eax,0x5d >>> print disasm('b817000000'.decode('hex'), arch = 'amd64') 0: b8 17 00 00 00 mov eax,0x17 >>> print disasm('48c7c017000000'.decode('hex'), arch = 'amd64') 0: 48 c7 c0 17 00 00 00 mov rax,0x17 >>> print disasm('04001fe552009000'.decode('hex'), arch = 'arm') 0: e51f0004 ldr r0, [pc, #-4] ; 0x4 4: 00900052 addseq r0, r0, r2, asr r0 >>> print disasm('4ff00500'.decode('hex'), arch = 'thumb', bits=32) 0: f04f 0005 mov.w r0, #5
-
pwnlib.asm.
make_elf
(data, vma=None, strip=True, extract=True, shared=False, **kwargs) → str[source]¶ Builds an ELF file with the specified binary data as its executable code.
Parameters: - data (str) – Assembled code
- vma (int) – Load address for the ELF file
- strip (bool) – Strip the resulting ELF file. Only matters if
extract=False
. (Default:True
) - extract (bool) – Extract the assembly from the ELF file.
If
False
, the path of the ELF file is returned. (Default:True
) - shared (bool) – Create a Dynamic Shared Object (DSO, i.e. a
.so
) which can be loaded viadlopen
orLD_PRELOAD
.
Examples
This example creates an i386 ELF that just does execve(‘/bin/sh’,...).
>>> context.clear(arch='i386') >>> bin_sh = '6a68682f2f2f73682f62696e89e331c96a0b5899cd80'.decode('hex') >>> filename = make_elf(bin_sh, extract=False) >>> p = process(filename) >>> p.sendline('echo Hello; exit') >>> p.recvline() 'Hello\n'
-
pwnlib.asm.
make_elf_from_assembly
(assembly, vma=None, extract=None, shared=False, strip=False, **kwargs) → str[source]¶ Builds an ELF file with the specified assembly as its executable code.
This differs from
make_elf()
in that all ELF symbols are preserved, such as labels and local variables. Usemake_elf()
if size matters. Additionally, the default value forextract
inmake_elf()
is different.Note
This is effectively a wrapper around
asm()
. with settingextract=False
,vma=0x10000000
, and marking the resulting file as executable (chmod +x
).Note
ELF files created with arch=thumb will prepend an ARM stub which switches to Thumb mode.
Parameters: - assembly (str) – Assembly code to build into an ELF
- vma (int) – Load address of the binary
(Default:
0x10000000
, or0
ifshared=True
) - extract (bool) – Extract the full ELF data from the file.
(Default:
False
) - shared (bool) – Create a shared library
(Default:
False
) - kwargs (dict) – Arguments to pass to
asm()
.
Returns: The path to the assembled ELF (extract=False), or the data of the assembled ELF.
Example
This example shows how to create a shared library, and load it via
LD_PRELOAD
.>>> context.clear() >>> context.arch = 'amd64' >>> sc = 'push rbp; mov rbp, rsp;' >>> sc += shellcraft.echo('Hello\n') >>> sc += 'mov rsp, rbp; pop rbp; ret' >>> solib = make_elf_from_assembly(sc, shared=1) >>> subprocess.check_output(['echo', 'World'], env={'LD_PRELOAD': solib}) 'Hello\nWorld\n'
The same thing can be done with
make_elf()
, though the sizes are different. They both>>> file_a = make_elf(asm('nop'), extract=True) >>> file_b = make_elf_from_assembly('nop', extract=True) >>> file_a[:4] == file_b[:4] True >>> len(file_a) < 0x200 True >>> len(file_b) > 0x1000 True
pwnlib.atexception
— Callbacks on unhandled exception¶
Analogous to atexit, this module allows the programmer to register functions to be run if an unhandled exception occurs.
-
pwnlib.atexception.
register
(func, *args, **kwargs)[source]¶ Registers a function to be called when an unhandled exception occurs. The function will be called with positional arguments args and keyword arguments kwargs, i.e.
func(*args, **kwargs)
. The current context is recorded and will be the one used when the handler is run.E.g. to suppress logging output from an exception-handler one could write:
with context.local(log_level = 'error'): atexception.register(handler)
An identifier is returned which can be used to unregister the exception-handler.
This function can be used as a decorator:
@atexception.register def handler(): ...
Notice however that this will bind
handler
to the identifier and not the actual exception-handler. The exception-handler can then be unregistered with:atexception.unregister(handler)
This function is thread safe.
pwnlib.atexit
— Replacement for atexit¶
Replacement for the Python standard library’s atexit.py.
Whereas the standard atexit
module only defines atexit.register()
,
this replacement module also defines unregister()
.
This module also fixes a the issue that exceptions raised by an exit handler is
printed twice when the standard atexit
is used.
-
pwnlib.atexit.
register
(func, *args, **kwargs)[source]¶ Registers a function to be called on program termination. The function will be called with positional arguments args and keyword arguments kwargs, i.e.
func(*args, **kwargs)
. The current context is recorded and will be the one used when the handler is run.E.g. to suppress logging output from an exit-handler one could write:
with context.local(log_level = 'error'): atexit.register(handler)
An identifier is returned which can be used to unregister the exit-handler.
This function can be used as a decorator:
@atexit.register def handler(): ...
Notice however that this will bind
handler
to the identifier and not the actual exit-handler. The exit-handler can then be unregistered with:atexit.unregister(handler)
This function is thread safe.
pwnlib.constants
— Easy access to header file constants¶
Module containing constants extracted from header files.
The purpose of this module is to provide quick access to constants from different architectures and operating systems.
The constants are wrapped by a convenience class that allows accessing the name of the constant, while performing all normal mathematical operations on it.
Example
>>> str(constants.freebsd.SYS_stat)
'SYS_stat'
>>> int(constants.freebsd.SYS_stat)
188
>>> hex(constants.freebsd.SYS_stat)
'0xbc'
>>> 0 | constants.linux.i386.SYS_stat
106
>>> 0 + constants.linux.amd64.SYS_stat
4
The submodule freebsd
contains all constants for FreeBSD, while the
constants for Linux have been split up by architecture.
The variables of the submodules will be “lifted up” by setting the
pwnlib.context.arch
or pwnlib.context.os
in a manner similar to
what happens in pwnlib.shellcraft
.
Example
>>> with context.local(os = 'freebsd'):
... print int(constants.SYS_stat)
188
>>> with context.local(os = 'linux', arch = 'i386'):
... print int(constants.SYS_stat)
106
>>> with context.local(os = 'linux', arch = 'amd64'):
... print int(constants.SYS_stat)
4
pwnlib.context
— Setting runtime variables¶
-
pwnlib.context.
context
= ContextType()[source]¶ Global
ContextType
object, used to store commonly-used pwntools settings.In most cases, the context is used to infer default variables values. For example,
asm()
can take anarch
parameter as a keyword argument.If it is not supplied, the
arch
specified bycontext
is used instead.Consider it a shorthand to passing
os=
andarch=
to every single function call.
-
class
pwnlib.context.
ContextType
(**kwargs)[source]¶ Class for specifying information about the target machine. Intended for use as a pseudo-singleton through the global variable
context
, available viafrom pwn import *
ascontext
.The context is usually specified at the top of the Python file for clarity.
#!/usr/bin/env python context.update(arch='i386', os='linux')
Currently supported properties and their defaults are listed below. The defaults are inherited from
pwnlib.context.ContextType.defaults
.Additionally, the context is thread-aware when using
pwnlib.context.Thread
instead ofthreading.Thread
(all internalpwntools
threads use the former).The context is also scope-aware by using the
with
keyword.Examples
>>> context.clear() >>> context.update(os='linux') >>> context.os == 'linux' True >>> context.arch = 'arm' >>> vars(context) == {'arch': 'arm', 'bits': 32, 'endian': 'little', 'os': 'linux'} True >>> context.endian 'little' >>> context.bits 32 >>> def nop(): ... print pwnlib.asm.asm('nop').encode('hex') >>> nop() 00f020e3 >>> with context.local(arch = 'i386'): ... nop() 90 >>> from pwnlib.context import Thread as PwnThread >>> from threading import Thread as NormalThread >>> with context.local(arch = 'mips'): ... pwnthread = PwnThread(target=nop) ... thread = NormalThread(target=nop) >>> # Normal thread uses the default value for arch, 'i386' >>> _=(thread.start(), thread.join()) 90 >>> # Pwnthread uses the correct context from creation-time >>> _=(pwnthread.start(), pwnthread.join()) 00000000 >>> nop() 00f020e3
-
class
Thread
(*args, **kwargs)[source]¶ Instantiates a context-aware thread, which inherit its context when it is instantiated. The class can be accessed both on the context module as pwnlib.context.Thread and on the context singleton object inside the context module as pwnlib.context.context.Thread.
Threads created by using the native :class`threading`.Thread` will have a clean (default) context.
Regardless of the mechanism used to create any thread, the context is de-coupled from the parent thread, so changes do not cascade to child or parent.
Saves a copy of the context when instantiated (at
__init__
) and updates the new thread’s context before passing control to the user code viarun
ortarget=
.Examples
>>> context.clear() >>> context.update(arch='arm') >>> def p(): ... print context.arch ... context.arch = 'mips' ... print context.arch >>> # Note that a normal Thread starts with a clean context >>> # (i386 is the default architecture) >>> t = threading.Thread(target=p) >>> _=(t.start(), t.join()) i386 mips >>> # Note that the main Thread's context is unchanged >>> print context.arch arm >>> # Note that a context-aware Thread receives a copy of the context >>> t = pwnlib.context.Thread(target=p) >>> _=(t.start(), t.join()) arm mips >>> # Again, the main thread is unchanged >>> print context.arch arm
Implementation Details:
This class implemented by hooking the private function
threading.Thread._Thread_bootstrap()
, which is called before passing control tothreading.Thread.run()
.This could be done by overriding
run
itself, but we would have to ensure that all uses of the class would only ever use the keywordtarget=
for__init__
, or that all subclasses invokesuper(Subclass.self).set_up_context()
or similar.
-
ContextType.
adb
[source]¶ Returns an argument array for connecting to adb.
Unless
$ADB_PATH
is set, uses the defaultadb
binary in$PATH
.
-
ContextType.
adb_host
[source]¶ Sets the target host which is used for ADB.
This is useful for Android exploitation.
The default value is inherited from ANDROID_ADB_SERVER_HOST, or set to the default ‘localhost’.
-
ContextType.
adb_port
[source]¶ Sets the target port which is used for ADB.
This is useful for Android exploitation.
The default value is inherited from ANDROID_ADB_SERVER_PORT, or set to the default 5037.
-
ContextType.
arch
[source]¶ Target binary architecture.
Allowed values are listed in
pwnlib.context.ContextType.architectures
.Side Effects:
If an architecture is specified which also implies additional attributes (e.g. ‘amd64’ implies 64-bit words, ‘powerpc’ implies big-endian), these attributes will be set on the context if a user has not already set a value.
The following properties may be modified.
bits
endian
Raises: AttributeError
– An invalid architecture was specifiedExamples
>>> context.clear() >>> context.arch == 'i386' # Default architecture True
>>> context.arch = 'mips' >>> context.arch == 'mips' True
>>> context.arch = 'doge' Traceback (most recent call last): ... AttributeError: arch must be one of ['aarch64', ..., 'thumb']
>>> context.arch = 'ppc' >>> context.arch == 'powerpc' # Aliased architecture True
>>> context.clear() >>> context.bits == 32 # Default value True >>> context.arch = 'amd64' >>> context.bits == 64 # New value True
Note that expressly setting
bits
means that we use that value instead of the default>>> context.clear() >>> context.bits = 32 >>> context.arch = 'amd64' >>> context.bits == 32 True
Setting the architecture can override the defaults for both
endian
andbits
>>> context.clear() >>> context.arch = 'powerpc64' >>> vars(context) == {'arch': 'powerpc64', 'bits': 64, 'endian': 'big'} True
-
ContextType.
architectures
= OrderedDict([('powerpc64', {'bits': 64, 'endian': 'big'}), ('aarch64', {'bits': 64, 'endian': 'little'}), ('sparc64', {'bits': 64, 'endian': 'big'}), ('powerpc', {'bits': 32, 'endian': 'big'}), ('mips64', {'bits': 64, 'endian': 'little'}), ('msp430', {'bits': 16, 'endian': 'little'}), ('thumb', {'bits': 32, 'endian': 'little'}), ('amd64', {'bits': 64, 'endian': 'little'}), ('sparc', {'bits': 32, 'endian': 'big'}), ('alpha', {'bits': 64, 'endian': 'little'}), ('s390', {'bits': 32, 'endian': 'big'}), ('i386', {'bits': 32, 'endian': 'little'}), ('m68k', {'bits': 32, 'endian': 'big'}), ('mips', {'bits': 32, 'endian': 'little'}), ('ia64', {'bits': 64, 'endian': 'big'}), ('cris', {'bits': 32, 'endian': 'little'}), ('vax', {'bits': 32, 'endian': 'little'}), ('avr', {'bits': 8, 'endian': 'little'}), ('arm', {'bits': 32, 'endian': 'little'})])[source]¶ Keys are valid values for
pwnlib.context.ContextType.arch()
. Values are defaults which are set whenpwnlib.context.ContextType.arch
is set
-
ContextType.
aslr
[source]¶ ASLR settings for new processes.
If
False
, attempt to disable ASLR in all processes which are created viapersonality
(setarch -R
) andsetrlimit
(ulimit -s unlimited
).The
setarch
changes are lost if asetuid
binary is executed.
-
ContextType.
binary
[source]¶ Infer target architecture, bit-with, and endianness from a binary file. Data type is a
pwnlib.elf.ELF
object.Examples
>>> context.clear() >>> context.arch, context.bits ('i386', 32) >>> context.binary = '/bin/bash' >>> context.arch, context.bits ('amd64', 64) >>> context.binary ELF('/bin/bash')
-
ContextType.
bits
[source]¶ Target machine word size, in bits (i.e. the size of general purpose registers).
The default value is
32
, but changes according toarch
.Examples
>>> context.clear() >>> context.bits == 32 True >>> context.bits = 64 >>> context.bits == 64 True >>> context.bits = -1 Traceback (most recent call last): ... AttributeError: bits must be > 0 (-1)
-
ContextType.
buffer_size
[source]¶ Internal buffer size to use for
pwnlib.tubes.tube.tube
objects.This is not the maximum size of the buffer, but this is the amount of data which is passed to each raw
read
syscall (or equivalent).
-
ContextType.
bytes
[source]¶ Target machine word size, in bytes (i.e. the size of general purpose registers).
This is a convenience wrapper around
bits / 8
.Examples
>>> context.bytes = 1 >>> context.bits == 8 True
>>> context.bytes = 0 Traceback (most recent call last): ... AttributeError: bits must be > 0 (0)
-
ContextType.
cache_dir
[source]¶ Directory used for caching data.
Note
May be either a path string, or
None
.Example
>>> cache_dir = context.cache_dir >>> cache_dir is not None True >>> os.chmod(cache_dir, 0o000) >>> context.cache_dir is None True >>> os.chmod(cache_dir, 0o755) >>> cache_dir == context.cache_dir True
-
ContextType.
clear
(*a, **kw)[source]¶ Clears the contents of the context. All values are set to their defaults.
Parameters: - a – Arguments passed to
update
- kw – Arguments passed to
update
Examples
>>> # Default value >>> context.clear() >>> context.arch == 'i386' True >>> context.arch = 'arm' >>> context.arch == 'i386' False >>> context.clear() >>> context.arch == 'i386' True
- a – Arguments passed to
-
ContextType.
copy
() → dict[source]¶ Returns a copy of the current context as a dictionary.
Examples
>>> context.clear() >>> context.os = 'linux' >>> vars(context) == {'os': 'linux'} True
-
ContextType.
defaults
= {'kernel': None, 'noptrace': False, 'delete_corefiles': False, 'randomize': False, 'binary': None, 'log_level': 20, 'terminal': None, 'bits': 32, 'rename_corefiles': True, 'newline': '\n', 'proxy': None, 'device': None, 'buffer_size': 4096, 'arch': 'i386', 'aslr': True, 'adb_port': 5037, 'signed': False, 'adb_host': 'localhost', 'timeout': pwnlib.timeout.maximum, 'endian': 'little', 'log_file': <pwnlib.context._devnull object>, 'os': 'linux', 'log_console': <open file '<stdout>', mode 'w'>}[source]¶ Default values for
pwnlib.context.ContextType
-
ContextType.
delete_corefiles
[source]¶ Whether pwntools automatically deletes corefiles after exiting. This only affects corefiles accessed via
process.corefile
.Default value is
False
.
-
ContextType.
endian
[source]¶ Endianness of the target machine.
The default value is
'little'
, but changes according toarch
.Raises: AttributeError
– An invalid endianness was providedExamples
>>> context.clear() >>> context.endian == 'little' True
>>> context.endian = 'big' >>> context.endian 'big'
>>> context.endian = 'be' >>> context.endian == 'big' True
>>> context.endian = 'foobar' Traceback (most recent call last): ... AttributeError: endian must be one of ['be', 'big', 'eb', 'el', 'le', 'little']
-
ContextType.
endianness
[source]¶ Legacy alias for
endian
.Examples
>>> context.endian == context.endianness True
-
ContextType.
endiannesses
= OrderedDict([('little', 'little'), ('big', 'big'), ('el', 'little'), ('le', 'little'), ('be', 'big'), ('eb', 'big')])[source]¶ Valid values for
endian
-
ContextType.
kernel
[source]¶ Target machine’s kernel architecture.
Usually, this is the same as
arch
, except when running a 32-bit binary on a 64-bit kernel (e.g. i386-on-amd64).Even then, this doesn’t matter much – only when the the segment registers need to be known
-
ContextType.
local
(**kwargs) → context manager[source]¶ Create a context manager for use with the
with
statement.For more information, see the example below or PEP 343.
Parameters: kwargs – Variables to be assigned in the new environment. Returns: ContextType manager for managing the old and new environment. Examples
>>> context.clear() >>> context.timeout = 1 >>> context.timeout == 1 True >>> print context.timeout 1.0 >>> with context.local(timeout = 2): ... print context.timeout ... context.timeout = 3 ... print context.timeout 2.0 3.0 >>> print context.timeout 1.0
-
ContextType.
log_console
[source]¶ Sets the default logging console target.
Examples
>>> context.log_level = 'warn' >>> log.warn("Hello") [!] Hello >>> context.log_console=open('/dev/null', 'w') >>> log.warn("Hello") >>> context.clear()
-
ContextType.
log_file
[source]¶ Sets the target file for all logging output.
Works in a similar fashion to
log_level
.Examples
>>> context.log_file = 'foo.txt' >>> log.debug('Hello!') >>> with context.local(log_level='ERROR'): ... log.info('Hello again!') >>> with context.local(log_file='bar.txt'): ... log.debug('Hello from bar!') >>> log.info('Hello from foo!') >>> file('foo.txt').readlines()[-3] '...:DEBUG:...:Hello!\n' >>> file('foo.txt').readlines()[-2] '...:INFO:...:Hello again!\n' >>> file('foo.txt').readlines()[-1] '...:INFO:...:Hello from foo!\n' >>> file('bar.txt').readlines()[-1] '...:DEBUG:...:Hello from bar!\n'
-
ContextType.
log_level
[source]¶ Sets the verbosity of
pwntools
logging mechanism.More specifically it controls the filtering of messages that happens inside the handler for logging to the screen. So if you want e.g. log all messages to a file, then this attribute makes no difference to you.
Valid values are specified by the standard Python
logging
module.Default value is set to
INFO
.Examples
>>> context.log_level = 'error' >>> context.log_level == logging.ERROR True >>> context.log_level = 10 >>> context.log_level = 'foobar' Traceback (most recent call last): ... AttributeError: log_level must be an integer or one of ['CRITICAL', 'DEBUG', 'ERROR', 'INFO', 'NOTSET', 'WARN', 'WARNING']
-
ContextType.
noptrace
[source]¶ Disable all actions which rely on ptrace.
This is useful for switching between local exploitation with a debugger, and remote exploitation (without a debugger).
This option can be set with the
NOPTRACE
command-line argument.
-
ContextType.
os
[source]¶ Operating system of the target machine.
The default value is
linux
.Allowed values are listed in
pwnlib.context.ContextType.oses
.Examples
>>> context.os = 'linux' >>> context.os = 'foobar' Traceback (most recent call last): ... AttributeError: os must be one of ['android', 'cgc', 'freebsd', 'linux', 'windows']
-
ContextType.
oses
= ['android', 'cgc', 'freebsd', 'linux', 'windows'][source]¶ Valid values for
pwnlib.context.ContextType.os()
-
ContextType.
proxy
[source]¶ Default proxy for all socket connections.
Accepts either a string (hostname or IP address) for a SOCKS5 proxy on the default port, or a
tuple
passed tosocks.set_default_proxy
, e.g.(socks.SOCKS4, 'localhost', 1234)
.>>> context.proxy = 'localhost' >>> r=remote('google.com', 80) Traceback (most recent call last): ... ProxyConnectionError: Error connecting to SOCKS5 proxy localhost:1080: [Errno 111] Connection refused
>>> context.proxy = None >>> r=remote('google.com', 80, level='error')
-
ContextType.
quiet
[source]¶ Disables all non-error logging within the enclosed scope, unless the debugging level is set to ‘debug’ or lower.
-
ContextType.
rename_corefiles
[source]¶ Whether pwntools automatically renames corefiles.
This is useful for two things:
- Prevent corefiles from being overwritten, if
kernel.core_pattern
is something simple like"core"
. - Ensure corefiles are generated, if
kernel.core_pattern
usesapport
, which refuses to overwrite any existing files.
This only affects corefiles accessed via
process.corefile
.Default value is
True
.- Prevent corefiles from being overwritten, if
-
ContextType.
signed
[source]¶ Signed-ness for packing operation when it’s not explicitly set.
Can be set to any non-string truthy value, or the specific string values
'signed'
or'unsigned'
which are converted intoTrue
andFalse
correspondingly.Examples
>>> context.signed False >>> context.signed = 1 >>> context.signed True >>> context.signed = 'signed' >>> context.signed True >>> context.signed = 'unsigned' >>> context.signed False >>> context.signed = 'foobar' Traceback (most recent call last): ... AttributeError: signed must be one of ['no', 'signed', 'unsigned', 'yes'] or a non-string truthy value
-
ContextType.
signednesses
= {'yes': True, 'unsigned': False, 'signed': True, 'no': False}[source]¶ Valid string values for
signed
-
ContextType.
terminal
[source]¶ Default terminal used by
pwnlib.util.misc.run_in_new_terminal()
. Can be a string or an iterable of strings. In the latter case the first entry is the terminal and the rest are default arguments.
-
ContextType.
timeout
[source]¶ Default amount of time to wait for a blocking operation before it times out, specified in seconds.
The default value is to have an infinite timeout.
See
pwnlib.timeout.Timeout
for additional information on valid values.
-
ContextType.
update
(*args, **kwargs)[source]¶ Convenience function, which is shorthand for setting multiple variables at once.
It is a simple shorthand such that:
context.update(os = 'linux', arch = 'arm', ...)
is equivalent to:
context.os = 'linux' context.arch = 'arm' ...
The following syntax is also valid:
context.update({'os': 'linux', 'arch': 'arm'})
Parameters: kwargs – Variables to be assigned in the environment. Examples
>>> context.clear() >>> context.update(arch = 'i386', os = 'linux') >>> context.arch, context.os ('i386', 'linux')
-
class
-
class
pwnlib.context.
Thread
(*args, **kwargs)[source]¶ Instantiates a context-aware thread, which inherit its context when it is instantiated. The class can be accessed both on the context module as pwnlib.context.Thread and on the context singleton object inside the context module as pwnlib.context.context.Thread.
Threads created by using the native :class`threading`.Thread` will have a clean (default) context.
Regardless of the mechanism used to create any thread, the context is de-coupled from the parent thread, so changes do not cascade to child or parent.
Saves a copy of the context when instantiated (at
__init__
) and updates the new thread’s context before passing control to the user code viarun
ortarget=
.Examples
>>> context.clear() >>> context.update(arch='arm') >>> def p(): ... print context.arch ... context.arch = 'mips' ... print context.arch >>> # Note that a normal Thread starts with a clean context >>> # (i386 is the default architecture) >>> t = threading.Thread(target=p) >>> _=(t.start(), t.join()) i386 mips >>> # Note that the main Thread's context is unchanged >>> print context.arch arm >>> # Note that a context-aware Thread receives a copy of the context >>> t = pwnlib.context.Thread(target=p) >>> _=(t.start(), t.join()) arm mips >>> # Again, the main thread is unchanged >>> print context.arch arm
Implementation Details:
This class implemented by hooking the private function
threading.Thread._Thread_bootstrap()
, which is called before passing control tothreading.Thread.run()
.This could be done by overriding
run
itself, but we would have to ensure that all uses of the class would only ever use the keywordtarget=
for__init__
, or that all subclasses invokesuper(Subclass.self).set_up_context()
or similar.
pwnlib.dynelf
— 使用leak解析远程函数¶
这个模块主要用于解析ELF文件中加载的以及动态链接的符号。只要给一个可以泄漏任 何地址内容的函数,我们就可以解析加载的库中的任何地址。
例子
# Assume a process or remote connection
p = process('./pwnme')
# Declare a function that takes a single address, and
# leaks at least one byte at that address.
def leak(address):
data = p.read(address, 4)
log.debug("%#x => %s" % (address, (data or '').encode('hex')))
return data
# For the sake of this example, let's say that we
# have any of these pointers. One is a pointer into
# the target binary, the other two are pointers into libc
main = 0xfeedf4ce
libc = 0xdeadb000
system = 0xdeadbeef
# With our leaker, and a pointer into our target binary,
# we can resolve the address of anything.
#
# We do not actually need to have a copy of the target
# binary for this to work.
d = DynELF(leak, main)
assert d.lookup(None, 'libc') == libc
assert d.lookup('system', 'libc') == system
# However, if we *do* have a copy of the target binary,
# we can speed up some of the steps.
d = DynELF(leak, main, elf=ELF('./pwnme'))
assert d.lookup(None, 'libc') == libc
assert d.lookup('system', 'libc') == system
# Alternately, we can resolve symbols inside another library,
# given a pointer into it.
d = DynELF(leak, libc + 0x1234)
assert d.lookup('system') == system
DynELF
class pwnlib.dynelf.DynELF(leak,pointer,elf=None)
Dynelf 知道如何借助 pwnlib.memleak.MemLeak
. 通过 infoleak 或者 memleak 漏洞解
析远程程序中的符号地址。
应用细节
解析函数:
ELF文件(例如
libc.so
)一般会导出自己声明的符号,以便于其他库使用。这样,就会存在一系列的表格,它们会给出导出符号的名字,地址,以及这些导出符号的hash
值。通过将hash函数应用在期望符号上(例如printf
),我们就可以在hash表中找到对应的位置。其相应的索引提供了到string name table( strtab )和symbol address( symtab ) 的寻找的方式。假设我们有
libc.so
的基地址,解析printf
的地址的方式就是去定位symtab
,strtab
,hashtabe
。字符串"printf"
根据 hash 表的风格( YSV 或者 GNU )被hash,因此我们可以遍历hashtable来找到一个匹配的入口。我们可以通过检查 strtab 来验证一个匹配,然后从 symtab 中获取其在libc.so
中的偏移。解析库地址:
__init__(self, leak, pointer=None, elf=None)()
这是DynELF的一个实例化方法,通过它,如果我们给了
pwnlib.memleak.MemLeak
leaker, 以及一个binary文件中的指针,我们可以生成一个可以解析运行库中符号的实例对象。
- 参数:
- leak (MemLeak) - 泄漏内存的 pwnlib.memleak.MemLeak 的实例。
- pointer (int) - 已经被load的ELF文件中的一个指针。
- elf (str,ELF) - ELF文件对应的路径,或者说一个已经加载的
pwnlib.elf.ELF
。
bases()
解析所有已经被加载的二进制文件的基地址。
返回一个将库路径映射到它的基地址的字典。
static find_base(leak,ptr)()
给定一个
pwnlib.memleak.Memleak
对象,以及一个其二进制文件内部的binary,找到它的基地址。
heap()
通过 __curbrk 来查找当前堆的基地址,这个符号在链接器中已经被导出了,指向当前的brk。
lookup(symb=None,lib=None)-->int()
在lib中找到对应符号的地址。参数如下
- symb (str) - 要查找的名字。
- lib (str) - 用来匹配库文件名的子串。缺省情况下会搜索当前的库,如果设置为
libc
, ``libc.so``就会被查找。返回对应符号的地址,或者None。
stack()
通过 __envrion (这个符号是由libc导出的,指向环境变量部分)来寻找一个指向栈上的变量,
dynamic()
返回指向
.DYNAMIC
的指针。
elfclass(self)()
返回对应的二进制文件的类型。
libc(self)()
得到远程libc.so的build版本,下载对应的文件,并且使用正确的基地址加载
ELF
对象。返回一个ELF对象,或者什么也不返回。
link_map(self)()
返回指向运行时的link_map对象。
pwnlib.dynelf.gnu_hash(str)-->int
为字符串生成GNU格式的hash值。
pwnlib.dynelf.sysv_hash(str)-->int
为字符串生成SYSV格式的hash值。
pwnlib.encoders
— Encoding Shellcode¶
Encode shellcode to avoid input filtering and impress your friends!
-
pwnlib.encoders.encoder.
alphanumeric
(raw_bytes) → str[source]¶ Encode the shellcode
raw_bytes
such that it does not contain any bytes except for [A-Za-z0-9].Accepts the same arguments as
encode()
.
-
pwnlib.encoders.encoder.
encode
(raw_bytes, avoid, expr, force) → str[source]¶ Encode shellcode
raw_bytes
such that it does not contain any bytes inavoid
orexpr
.Parameters:
-
pwnlib.encoders.encoder.
line
(raw_bytes) → str[source]¶ Encode the shellcode
raw_bytes
such that it does not contain any NULL bytes or whitespace.Accepts the same arguments as
encode()
.
-
pwnlib.encoders.encoder.
null
(raw_bytes) → str[source]¶ Encode the shellcode
raw_bytes
such that it does not contain any NULL bytes.Accepts the same arguments as
encode()
.
-
pwnlib.encoders.encoder.
printable
(raw_bytes) → str[source]¶ Encode the shellcode
raw_bytes
such that it only contains non-space printable bytes.Accepts the same arguments as
encode()
.
-
pwnlib.encoders.encoder.
scramble
(raw_bytes) → str[source]¶ Encodes the input data with a random encoder.
Accepts the same arguments as
encode()
.
-
class
pwnlib.encoders.i386.xor.
i386XorEncoder
[source]¶ Generates an XOR decoder for i386.
>>> context.clear(arch='i386') >>> shellcode = asm(shellcraft.sh()) >>> avoid = '/bin/sh\xcc\xcd\x80' >>> encoded = pwnlib.encoders.i386.xor.encode(shellcode, avoid) >>> assert not any(c in encoded for c in avoid) >>> p = run_shellcode(encoded) >>> p.sendline('echo hello; exit') >>> p.recvline() 'hello\n'
pwnlib.elf
— Working with ELF binaries¶
Most exploitable CTF challenges are provided in the Executable and Linkable
Format (ELF
). Generally, it is very useful to be able to interact with
these files to extract data such as function addresses, ROP gadgets, and
writable page addresses.
-
class
pwnlib.elf.
ELF
(path)[source]¶ Encapsulates information about an ELF file.
Example
>>> bash = ELF(which('bash')) >>> hex(bash.symbols['read']) 0x41dac0 >>> hex(bash.plt['read']) 0x41dac0 >>> u32(bash.read(bash.got['read'], 4)) 0x41dac6 >>> print bash.disasm(bash.plt.read, 16) 0: ff 25 1a 18 2d 00 jmp QWORD PTR [rip+0x2d181a] # 0x2d1820 6: 68 59 00 00 00 push 0x59 b: e9 50 fa ff ff jmp 0xfffffffffffffa60
-
address
[source]¶ int
– Address of the lowest segment loaded in the ELF.When updated, the addresses of the following fields are also updated:
symbols
got
plt
functions
However, the following fields are NOT updated:
Example
>>> bash = ELF('/bin/bash') >>> read = bash.symbols['read'] >>> text = bash.get_section_by_name('.text').header.sh_addr >>> bash.address += 0x1000 >>> read + 0x1000 == bash.symbols['read'] True >>> text == bash.get_section_by_name('.text').header.sh_addr True
-
asm
(address, assembly)[source]¶ Assembles the specified instructions and inserts them into the ELF at the specified address.
This modifies the ELF in-pace. The resulting binary can be saved with
ELF.save()
-
checksec
(banner=True)[source]¶ Prints out information in the binary, similar to
checksec.sh
.Parameters: banner (bool) – Whether to print the path to the ELF binary.
-
data
[source]¶ str
– Raw data of the ELF file.- See:
get_data()
-
debug
(argv=[], *a, **kw) → tube[source]¶ Debug the ELF with
gdb.debug()
.Parameters: - argv (list) – List of arguments to the binary
- *args – Extra arguments to
gdb.debug()
- **kwargs – Extra arguments to
gdb.debug()
Returns: See
gdb.debug()
Return type:
-
disasm
(address, n_bytes) → str[source]¶ Returns a string of disassembled instructions at the specified virtual memory address
-
dynamic_by_tag
(tag) → tag[source]¶ Parameters: tag (str) – Named DT_XXX
tag (e.g.'DT_STRTAB'
).Returns: elftools.elf.dynamic.DynamicTag
-
dynamic_string
(offset) → bytes[source]¶ Fetches an enumerated string from the
DT_STRTAB
table.Parameters: offset (int) – String index Returns: String from the table as raw bytes. Return type: str
-
executable_segments
[source]¶ list
– List of all segments which are executable.- See:
ELF.segments
-
fit
(address, *a, **kw)[source]¶ Writes fitted data into the specified address.
See:
packing.fit()
-
flat
(address, *a, **kw)[source]¶ Writes a full array of values to the specified address.
See:
packing.flat()
-
static
from_assembly
(assembly) → ELF[source]¶ Given an assembly listing, return a fully loaded ELF object which contains that assembly at its entry point.
Parameters: Example
>>> e = ELF.from_assembly('nop; foo: int 0x80', vma = 0x400000) >>> e.symbols['foo'] = 0x400001 >>> e.disasm(e.entry, 1) ' 400000: 90 nop' >>> e.disasm(e.symbols['foo'], 2) ' 400001: cd 80 int 0x80'
-
static
from_bytes
(bytes) → ELF[source]¶ Given a sequence of bytes, return a fully loaded ELF object which contains those bytes at its entry point.
Parameters: Example
>>> e = ELF.from_bytes('\x90\xcd\x80', vma=0xc000) >>> print(e.disasm(e.entry, 3)) c000: 90 nop c001: cd 80 int 0x80
-
get_data
() → bytes[source]¶ Retrieve the raw data from the ELF file.
>>> bash = ELF(which('bash')) >>> fd = open(which('bash')) >>> bash.get_data() == fd.read() True
-
libc
[source]¶ ELF
– If thisELF
imports any libraries which contain'libc[.-]
, and we can determine the appropriate path to it on the local system, returns a newELF
object pertaining to that library.If not found, the value will be
None
.
-
non_writable_segments
[source]¶ list
– List of all segments which are NOT writeable.- See:
ELF.segments
-
offset_to_vaddr
(offset) → int[source]¶ Translates the specified offset to a virtual address.
Parameters: offset (int) – Offset to translate Returns: Virtual address which corresponds to the file offset, or None
.Return type: int Examples
This example shows that regardless of changes to the virtual address layout by modifying
ELF.address
, the offset for any given address doesn’t change.>>> bash = ELF('/bin/bash') >>> bash.address == bash.offset_to_vaddr(0) True >>> bash.address += 0x123456 >>> bash.address == bash.offset_to_vaddr(0) True
-
process
(argv=[], *a, **kw) → process[source]¶ Execute the binary with
process
. Note thatargv
is a list of arguments, and should not includeargv[0]
.Parameters: Returns:
-
read
(address, count) → bytes[source]¶ Read data from the specified virtual address
Parameters: Returns: A
str
object, orNone
.Examples
The simplest example is just to read the ELF header.
>>> bash = ELF(which('bash')) >>> bash.read(bash.address, 4) '\x7fELF'
ELF segments do not have to contain all of the data on-disk that gets loaded into memory.
First, let’s create an ELF file has some code in two sections.
>>> assembly = ''' ... .section .A,"awx" ... .global A ... A: nop ... .section .B,"awx" ... .global B ... B: int3 ... ''' >>> e = ELF.from_assembly(assembly, vma=False)
By default, these come right after eachother in memory.
>>> e.read(e.symbols.A, 2) '\x90\xcc' >>> e.symbols.B - e.symbols.A 1
Let’s move the sections so that B is a little bit further away.
>>> objcopy = pwnlib.asm._objcopy() >>> objcopy += [ ... '--change-section-vma', '.B+5', ... '--change-section-lma', '.B+5', ... e.path ... ] >>> subprocess.check_call(objcopy) 0
Now let’s re-load the ELF, and check again
>>> e = ELF(e.path) >>> e.symbols.B - e.symbols.A 6 >>> e.read(e.symbols.A, 2) '\x90\x00' >>> e.read(e.symbols.A, 7) '\x90\x00\x00\x00\x00\x00\xcc' >>> e.read(e.symbols.A, 10) '\x90\x00\x00\x00\x00\x00\xcc\x00\x00\x00'
Everything is relative to the user-selected base address, so moving things around keeps everything working.
>>> e.address += 0x1000 >>> e.read(e.symbols.A, 10) '\x90\x00\x00\x00\x00\x00\xcc\x00\x00\x00'
-
rwx_segments
[source]¶ list
– List of all segments which are writeable and executable.- See:
ELF.segments
-
save
(path=None)[source]¶ Save the ELF to a file
>>> bash = ELF(which('bash')) >>> bash.save('/tmp/bash_copy') >>> copy = file('/tmp/bash_copy') >>> bash = file(which('bash')) >>> bash.read() == copy.read() True
-
search
(needle, writable = False) → generator[source]¶ Search the ELF’s virtual address space for the specified string.
Notes
Does not search empty space between segments, or uninitialized data. This will only return data that actually exists in the ELF file. Searching for a long string of NULL bytes probably won’t work.
Parameters: Yields: An iterator for each virtual address that matches.
Examples
An ELF header starts with the bytes
\x7fELF
, so we sould be able to find it easily.>>> bash = ELF('/bin/bash') >>> bash.address + 1 == next(bash.search('ELF')) True
We can also search for string the binary.
>>> len(list(bash.search('GNU bash'))) > 0 True
-
section
(name) → bytes[source]¶ Gets data for the named section
Parameters: name (str) – Name of the section Returns: String containing the bytes for that section Return type: str
-
sections
[source]¶ list
– A list ofelftools.elf.sections.Section
objects for the segments in the ELF.
-
segments
[source]¶ list
– A list ofelftools.elf.segments.Segment
objects for the segments in the ELF.
-
ubsan
[source]¶ bool
– Whether the current binary was built with Undefined Behavior Sanitizer (UBSAN
).
-
vaddr_to_offset
(address) → int[source]¶ Translates the specified virtual address to a file offset
Parameters: address (int) – Virtual address to translate Returns: Offset within the ELF file which corresponds to the address, or None
.Return type: int Examples
>>> bash = ELF(which('bash')) >>> bash.vaddr_to_offset(bash.address) 0 >>> bash.address += 0x123456 >>> bash.vaddr_to_offset(bash.address) 0 >>> bash.vaddr_to_offset(0) is None True
-
writable_segments
[source]¶ list
– List of all segments which are writeable.- See:
ELF.segments
-
write
(address, data)[source]¶ Writes data to the specified virtual address
Parameters: Note
This routine does not check the bounds on the write to ensure that it stays in the same segment.
Examples
>>> bash = ELF(which('bash')) >>> bash.read(bash.address+1, 3) 'ELF' >>> bash.write(bash.address, "HELO") >>> bash.read(bash.address, 4) 'HELO'
-
pwnlib.exception
— Pwnlib exceptions¶
pwnlib.flag
— CTF Flag Management¶
-
pwnlib.flag.
submit_flag
(flag, exploit='unnamed-exploit', target='unknown-target', server='flag-submission-server', port='31337', proto='tcp', team='unknown-team')[source]¶ Submits a flag to the game server
Parameters: Optional arguments are inferred from the environment, or omitted if none is set.
Returns: A string indicating the status of the key submission, or an error code. Doctest:
>>> l = listen() >>> _ = submit_flag('flag', server='localhost', port=l.lport) >>> c = l.wait_for_connection() >>> c.recvall().split() ['flag', 'unnamed-exploit', 'unknown-target', 'unknown-team']
pwnlib.fmtstr
— Format string bug exploitation tools¶
Provide some tools to exploit format string bug
Examples
>>> program = tempfile.mktemp()
>>> source = program + ".c"
>>> write(source, '''
... #include <stdio.h>
... #include <stdlib.h>
... #include <unistd.h>
... #include <sys/mman.h>
... #define MEMORY_ADDRESS ((void*)0x11111000)
... #define MEMORY_SIZE 1024
... #define TARGET ((int *) 0x11111110)
... int main(int argc, char const *argv[])
... {
... char buff[1024];
... void *ptr = NULL;
... int *my_var = TARGET;
... ptr = mmap(MEMORY_ADDRESS, MEMORY_SIZE, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
... if(ptr != MEMORY_ADDRESS)
... {
... perror("mmap");
... return EXIT_FAILURE;
... }
... *my_var = 0x41414141;
... write(1, &my_var, sizeof(int *));
... scanf("%s", buff);
... dprintf(2, buff);
... write(1, my_var, sizeof(int));
... return 0;
... }''')
>>> cmdline = ["gcc", source, "-Wno-format-security", "-m32", "-o", program]
>>> process(cmdline).wait_for_close()
>>> def exec_fmt(payload):
... p = process(program)
... p.sendline(payload)
... return p.recvall()
...
>>> autofmt = FmtStr(exec_fmt)
>>> offset = autofmt.offset
>>> p = process(program, stderr=PIPE)
>>> addr = unpack(p.recv(4))
>>> payload = fmtstr_payload(offset, {addr: 0x1337babe})
>>> p.sendline(payload)
>>> print hex(unpack(p.recv(4)))
0x1337babe
Example - Payload generation¶
# we want to do 3 writes
writes = {0x08041337: 0xbfffffff,
0x08041337+4: 0x1337babe,
0x08041337+8: 0xdeadbeef}
# the printf() call already writes some bytes
# for example :
# strcat(dest, "blabla :", 256);
# strcat(dest, your_input, 256);
# printf(dest);
# Here, numbwritten parameter must be 8
payload = fmtstr_payload(5, writes, numbwritten=8)
Example - Automated exploitation¶
# Assume a process that reads a string
# and gives this string as the first argument
# of a printf() call
# It do this indefinitely
p = process('./vulnerable')
# Function called in order to send a payload
def send_payload(payload):
log.info("payload = %s" % repr(payload))
p.sendline(payload)
return p.recv()
# Create a FmtStr object and give to him the function
format_string = FmtStr(execute_fmt=send_payload)
format_string.write(0x0, 0x1337babe) # write 0x1337babe at 0x0
format_string.write(0x1337babe, 0x0) # write 0x0 at 0x1337babe
format_string.execute_writes()
-
class
pwnlib.fmtstr.
FmtStr
(execute_fmt, offset=None, padlen=0, numbwritten=0)[source]¶ Provides an automated format string exploitation.
It takes a function which is called every time the automated process want to communicate with the vulnerable process. this function takes a parameter with the payload that you have to send to the vulnerable process and must return the process returns.
If the offset parameter is not given, then try to find the right offset by leaking stack data.
Parameters: -
write
(addr, data) → None[source]¶ In order to tell : I want to write
data
ataddr
.Parameters: Returns: None
Examples
>>> def send_fmt_payload(payload): ... print repr(payload) ... >>> f = FmtStr(send_fmt_payload, offset=5) >>> f.write(0x08040506, 0x1337babe) >>> f.execute_writes() '\x06\x05\x04\x08\x07\x05\x04\x08\x08\x05\x04\x08\t\x05\x04\x08%174c%5$hhn%252c%6$hhn%125c%7$hhn%220c%8$hhn'
-
-
pwnlib.fmtstr.
fmtstr_payload
(offset, writes, numbwritten=0, write_size='byte') → str[source]¶ Makes payload with given parameter. It can generate payload for 32 or 64 bits architectures. The size of the addr is taken from
context.bits
Parameters: - offset (int) – the first formatter’s offset you control
- writes (dict) – dict with addr, value
{addr: value, addr2: value2}
- numbwritten (int) – number of byte already written by the printf function
- write_size (str) – must be
byte
,short
orint
. Tells if you want to write byte by byte, short by short or int by int (hhn, hn or n)
Returns: The payload in order to do needed writes
Examples
>>> context.clear(arch = 'amd64') >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='int')) '\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00%322419374c%1$n%3972547906c%2$n' >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='short')) '\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00%47774c%1$hn%22649c%2$hn%60617c%3$hn%4$hn' >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='byte')) '\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00%126c%1$hhn%252c%2$hhn%125c%3$hhn%220c%4$hhn%237c%5$hhn%6$hhn%7$hhn%8$hhn' >>> context.clear(arch = 'i386') >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='int')) '\x00\x00\x00\x00%322419386c%1$n' >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='short')) '\x00\x00\x00\x00\x02\x00\x00\x00%47798c%1$hn%22649c%2$hn' >>> print repr(fmtstr_payload(1, {0x0: 0x1337babe}, write_size='byte')) '\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00%174c%1$hhn%252c%2$hhn%125c%3$hhn%220c%4$hhn'
pwnlib.gdb
— Working with GDB¶
attach(target, execute = None, exe = None, arch = None, ssh = None) -> None
在新的终端中启动终端,并将其attach到 target 上。除了 target 是 (host, port)
外,pwnlib.util.proc.pidof()
用来寻找 target 的PID。在那种情况下, target 应该为 一个GDB Server。
如果在本地运行,并且没有提供 exe ,那么我们就尝试分析运行
GDB Server(qemu,gdbserver) 命令的程序,寻找目标二进制文件的路径。注意,如果PID 是一
个已知的(当目标不是GDB Server), exe 将会从 /proc/<pid>/exe
中读取。
如果安装了gdb-multiarch, 我们就使用它,否则就使用gdb。参数如下
- target - 要被attach到的target。
- execute (str or file) - attach 之后,GDB 要运行的脚本。
- exe (str) - 目标二进制程序的路径
- arch (str) - 目标二进制程序的架构,如果 exe 已知的话,GDB 将会进行自动检测(如果支持的话)。
返回值为None。
pwnlib.gdb.debug(args) -> tube
使用给定的命令行启动GDB Server,然后启动GDB,并将其attach到GDB Server上。
参数如下:
- args - 与传给
pwnlib.tubes.process
的参数一致。- ssh - 用于启动进程的远程ssh会话。这样的话,就会自动启动端口转发,然后gdb就可以在本地运行了。
返回值为连接到目标进程的tube。
pwnlib.gdb.debug_shellcode(*a,**kw)
创建一个ELF文件,并且使用GDB启动它。
参数如下:
- data (str) - 经过汇编的shellcode。
- kwargs (dict) - 传给context的参数(e.g arch=’arm’)。
返回一个管道,这个管道会和stdin/stdout/stderr连接在一起。
pwnlib.gdb.debug_assembly(*a,**kw)
创建一个ELF文件,并且使用GDB启动它。
这和debug_shellcode一样,不仅可以使用所有已经定义在GDB里的符号,而且它还省去了我们对asm的显式调用。
pwnlib.gdb.find_module_addresses(binary,ssh=None,ulimit=False)
通过使用gdb来查找模块。
由于一些服务器会禁止 proc/$pid/map
,所以我们不能够使用这个。这个虽然阻断了GDB中的 info proc
,但是 info sharedlibrary
仍然可以执行。
除此之外, info sharedlibrary
也在FreeBSD上工作,但是,这上面可能没有启动procfs或者说它不可用。
输出的结果就像这个一样:
info proc mapping
process 13961
warning: unable to open /proc file '/proc/13961/maps'
info sharedlibrary
From To Syms Read Shared Object Library
0xf7c820 0xf7ff505f Yes (*) /lib/ld-linux.so.2
0xf7fbb650 0xf7fc79f8 Yes /lib32/libpthread.so.0
0xf7e26f10 0xf7f5b51c Yes (*) /lib32/libc.so.6
(*): Shared library is missing debugging information.
注意由 info sharedlibrary
提供的最初始的地址就是 .text
段的地址,并不是镜像基地址。
这个方法自动化了下面的流程:
- 从远程下载二进制文件。
- 爬取GDB的信息。
- 为ELF文件加载每一个库。
- 修复基地址 vs
.text
段地址
参数如下:
- binary (str) - 远程服务器上二进制文件的路径。
- ssh (pwnlib.tubes.tube) - 通过该种方式加载二进制文件的方式,如果什么也不填的话,将会使用
pwnlib.tubes.process.process
- ulimit (bool) - 如果设置为真的话,将会在启动GDB之前执行
ulimit -s unlimited
返回值一个列表,其中每个元素都具有正确的基地址。 :: OB
>>> with context.local(log_level=9999):
... shell = ssh(host='bandit.labs.overthewire.org',user='bandit0',password='bandit0')
... bash_libs = gdb.find_module_addresses('/bin/bash', shell)
>>> os.path.basename(bash_libs[0].path)
'libc.so.6'
>>> hex(bash_libs[0].symbols['system'])
'0x7ffff7634660'
pwnlib.log
— Logging stuff¶
Logging module for printing status during an exploit, and internally
within pwntools
.
Exploit Developers¶
By using the standard from pwn import *
, an object named log
will
be inserted into the global namespace. You can use this to print out
status messages during exploitation.
For example,:
log.info('Hello, world!')
prints:
[*] Hello, world!
Additionally, there are some nifty mechanisms for performing status updates on a running job (e.g. when brute-forcing).:
p = log.progress('Working')
p.status('Reticulating splines')
time.sleep(1)
p.success('Got a shell!')
The verbosity of logging can be most easily controlled by setting
log_level
on the global context
object.:
log.info("No you see me")
context.log_level = 'error'
log.info("Now you don't")
The purpose of this attribute is to control what gets printed to the screen, not what gets emitted. This means that you can put all logging events into a log file, while only wanting to see a small subset of them on your screen.
Pwnlib Developers¶
A module-specific logger can be imported into the module via:
from pwnlib.log import getLogger
log = getLogger(__name__)
This provides an easy way to filter logging programmatically or via a configuration file for debugging.
When using progress
, you should use the with
keyword to manage scoping, to ensure the spinner stops if an
exception is thrown.
Technical details¶
Familiarity with the logging
module is assumed.
A pwnlib root logger named ‘pwnlib’ is created and a custom handler and
formatter is installed for it. The handler determines its logging level from
context.log_level
.
Ideally context.log_level
should only affect which records will be
emitted by the handler such that e.g. logging to a file will not be changed by
it. But for performance reasons it is not feasible log everything in the normal
case. In particular there are tight loops inside pwnlib.tubes.tube
, which
we would like to be able to debug, but if we are not debugging them, they should
not spit out messages (even to a log file). For this reason there are a few places
inside pwnlib, that will not even emit a record without context.log_level
being set to logging.DEBUG or below.
Log records created by Progress
and Logger
objects will set
'pwnlib_msgtype'
on the extra
field to signal which kind of message was
generated. This information is used by the formatter to prepend a symbol to the
message, e.g. '[+] '
in '[+] got a shell!'
This field is ignored when using the logging
module’s standard formatters.
All status updates (which are not dropped due to throttling) on progress loggers
result in a log record being created. The extra
field then carries a
reference to the Progress
logger as 'pwnlib_progress'
.
If the custom handler determines that term.term_mode
is enabled, log
records that have a 'pwnlib_progess'
in their extra
field will not
result in a message being emitted but rather an animated progress line (with a
spinner!) being created. Note that other handlers will still see a meaningful
log record.
The custom handler will only handle log records whith a level of at least
context.log_level
. Thus if e.g. the level for the
'pwnlib.tubes.ssh'
is set to 'DEBUG'
no additional output will show up
unless context.log_level
is also set to 'DEBUG'
. Other handlers
will however see the extra log records generated by the 'pwnlib.tubes.ssh'
logger.
-
class
pwnlib.log.
Progress
(logger, msg, status, level, args, kwargs)[source]¶ Progress logger used to generate log records associated with some running job. Instances can be used as context managers which will automatically declare the running job a success upon exit or a failure upon a thrown exception. After
success()
orfailure()
is called the status can no longer be updated.This class is intended for internal use. Progress loggers should be created using
Logger.progress()
.-
status
(status, *args, **kwargs)[source]¶ Logs a status update for the running job.
If the progress logger is animated the status line will be updated in place.
Status updates are throttled at one update per 100ms.
-
-
class
pwnlib.log.
Logger
(logger=None)[source]¶ A class akin to the
logging.LoggerAdapter
class. All public methods defined onlogging.Logger
instances are defined on this class.Also adds some
pwnlib
flavor:progress()
(aliaswaitfor()
)success()
failure()
indented()
info_once()
warning_once()
(aliaswarn_once()
)
Adds
pwnlib
-specific information for coloring, indentation and progress logging via log recordsextra
field.Loggers instantiated with
getLogger()
will be of this class.-
progress
(message, status = '', *args, level = logging.INFO, **kwargs) → Progress[source]¶ Creates a new progress logger which creates log records with log level level.
Progress status can be updated using
Progress.status()
and stopped usingProgress.success()
orProgress.failure()
.If term.term_mode is enabled the progress logger will be animated.
The progress manager also functions as a context manager. Using context managers ensures that animations stop even if an exception is raised.
with log.progress('Trying something...') as p: for i in range(10): p.status("At %i" % i) time.sleep(0.5) x = 1/0
-
waitfor
(*args, **kwargs)[source]¶ Alias for
progress()
.
-
indented
(message, *args, level = logging.INFO, **kwargs)[source]¶ Log a message but don’t put a line prefix on it.
Parameters: level (int) – Alternate log level at which to set the indented message. Defaults to logging.INFO
.
-
info_once
(message, *args, **kwargs)[source]¶ Logs an info message. The same message is never printed again.
-
warning_once
(message, *args, **kwargs)[source]¶ Logs a warning message. The same message is never printed again.
-
warn_once
(*args, **kwargs)[source]¶ Alias for
warning_once()
.
-
error
(message, *args, **kwargs)[source]¶ To be called outside an exception handler.
Logs an error message, then raises a
PwnlibException
.
-
exception
(message, *args, **kwargs)[source]¶ To be called from an exception handler.
Logs a error message, then re-raises the current exception.
-
log
(level, message, *args, **kwargs)[source]¶ Logs a message with log level level. The
pwnlib
formatter will use the defaultlogging
formater to format this message.
-
class
pwnlib.log.
Handler
(stream=None)[source]¶ A custom handler class. This class will report whatever
context.log_level
is currently set to as its log level.If
term.term_mode
is enabled log records originating from a progress logger will not be emitted but rather an animated progress line will be created.An instance of this handler is added to the
'pwnlib'
logger.
-
class
pwnlib.log.
Formatter
(fmt=None, datefmt=None)[source]¶ Logging formatter which performs custom formatting for log records containing the
'pwnlib_msgtype'
attribute. Other records are formatted using the logging modules default formatter.If
'pwnlib_msgtype'
is set, it performs the following actions:- A prefix looked up in _msgtype_prefixes is prepended to the message.
- The message is prefixed such that it starts on column four.
- If the message spans multiple lines they are split, and all subsequent lines are indented.
This formatter is used by the handler installed on the
'pwnlib'
logger.
pwnlib.memleak
— Helper class for leaking memory¶
-
class
pwnlib.memleak.
MemLeak
(f, search_range=20, reraise=True, relative=False)[source]¶ MemLeak is a caching and heuristic tool for exploiting memory leaks.
It can be used as a decorator, around functions of the form:
- def some_leaker(addr):
- ... return data_as_string_or_None
It will cache leaked memory (which requires either non-randomized static data or a continouous session). If required, dynamic or known data can be set with the set-functions, but this is usually not required. If a byte cannot be recovered, it will try to leak nearby bytes in the hope that the byte is recovered as a side-effect.
Parameters: Example
>>> import pwnlib >>> binsh = pwnlib.util.misc.read('/bin/sh') >>> @pwnlib.memleak.MemLeak ... def leaker(addr): ... print "leaking 0x%x" % addr ... return binsh[addr:addr+4] >>> leaker.s(0)[:4] leaking 0x0 leaking 0x4 '\x7fELF' >>> leaker[:4] '\x7fELF' >>> hex(leaker.d(0)) '0x464c457f' >>> hex(leaker.clearb(1)) '0x45' >>> hex(leaker.d(0)) leaking 0x1 '0x464c457f' >>> @pwnlib.memleak.MemLeak ... def leaker_nonulls(addr): ... print "leaking 0x%x" % addr ... if addr & 0xff == 0: ... return None ... return binsh[addr:addr+4] >>> leaker_nonulls.d(0) == None leaking 0x0 True >>> leaker_nonulls[0x100:0x104] == binsh[0x100:0x104] leaking 0x100 leaking 0xff leaking 0x103 True
>>> memory = {-4+i: c for i,c in enumerate('wxyzABCDE')} >>> def relative_leak(index): ... return memory.get(index, None) >>> leak = pwnlib.memleak.MemLeak(relative_leak, relative = True) >>> leak[-1:2] 'zAB'
-
static
NoNewlines
(function)[source]¶ Wrapper for leak functions such that addresses which contain newline bytes are not leaked.
This is useful if the address which is used for the leak is provided by e.g.
fgets()
.
-
static
NoNulls
(function)[source]¶ Wrapper for leak functions such that addresses which contain NULL bytes are not leaked.
This is useful if the address which is used for the leak is read in via a string-reading function like
scanf("%s")
or smilar.
-
static
NoWhitespace
(function)[source]¶ Wrapper for leak functions such that addresses which contain whitespace bytes are not leaked.
This is useful if the address which is used for the leak is read in via e.g.
scanf()
.
-
static
String
(function)[source]¶ Wrapper for leak functions which leak strings, such that a NULL terminator is automaticall added.
This is useful if the data leaked is printed out as a NULL-terminated string, via e.g.
printf()
.
-
b
(addr, ndx = 0) → int[source]¶ Leak byte at
((uint8_t*) addr)[ndx]
Examples
>>> import string >>> data = string.ascii_lowercase >>> l = MemLeak(lambda a: data[a:a+2], reraise=False) >>> l.b(0) == ord('a') True >>> l.b(25) == ord('z') True >>> l.b(26) is None True
-
clearb
(addr, ndx = 0) → int[source]¶ Clears byte at
((uint8_t*)addr)[ndx]
from the cache and returns the removed value or None if the address was not completely set.Examples
>>> l = MemLeak(lambda a: None) >>> l.cache = {0:'a'} >>> l.n(0,1) == 'a' True >>> l.clearb(0) == unpack('a', 8) True >>> l.cache {} >>> l.clearb(0) is None True
-
cleard
(addr, ndx = 0) → int[source]¶ Clears dword at
((uint32_t*)addr)[ndx]
from the cache and returns the removed value or None if the address was not completely set.Examples
>>> l = MemLeak(lambda a: None) >>> l.cache = {0:'a', 1: 'b', 2: 'c', 3: 'd'} >>> l.n(0, 4) == 'abcd' True >>> l.cleard(0) == unpack('abcd', 32) True >>> l.cache {}
-
clearq
(addr, ndx = 0) → int[source]¶ Clears qword at
((uint64_t*)addr)[ndx]
from the cache and returns the removed value or None if the address was not completely set.Examples
>>> c = MemLeak(lambda addr: '') >>> c.cache = {x:'x' for x in range(0x100, 0x108)} >>> c.clearq(0x100) == unpack('xxxxxxxx', 64) True >>> c.cache == {} True
-
clearw
(addr, ndx = 0) → int[source]¶ Clears word at
((uint16_t*)addr)[ndx]
from the cache and returns the removed value or None if the address was not completely set.Examples
>>> l = MemLeak(lambda a: None) >>> l.cache = {0:'a', 1: 'b'} >>> l.n(0, 2) == 'ab' True >>> l.clearw(0) == unpack('ab', 16) True >>> l.cache {}
-
d
(addr, ndx = 0) → int[source]¶ Leak dword at
((uint32_t*) addr)[ndx]
Examples
>>> import string >>> data = string.ascii_lowercase >>> l = MemLeak(lambda a: data[a:a+8], reraise=False) >>> l.d(0) == unpack('abcd', 32) True >>> l.d(22) == unpack('wxyz', 32) True >>> l.d(23) is None True
-
field
(address, obj)[source]¶ field(address, field) => a structure field.
Leak a field from a structure.
Parameters: - address (int) – Base address to calculate offsets from
- field (obj) – Instance of a ctypes field
- Return Value:
- The type of the return value will be dictated by
the type of
field
.
-
field_compare
(address, obj, expected)[source]¶ field_compare(address, field, expected) ==> bool
Leak a field from a structure, with an expected value. As soon as any mismatch is found, stop leaking the structure.
Parameters: - Return Value:
- The type of the return value will be dictated by
the type of
field
.
-
n
(addr, ndx = 0) → str[source]¶ Leak numb bytes at addr.
Returns: A string with the leaked bytes, will return None if any are missing Examples
>>> import string >>> data = string.ascii_lowercase >>> l = MemLeak(lambda a: data[a:a+4], reraise=False) >>> l.n(0,1) == 'a' True >>> l.n(0,26) == data True >>> len(l.n(0,26)) == 26 True >>> l.n(0,27) is None True
-
p16
(addr, val, ndx=0)[source]¶ Sets word at
((uint16_t*)addr)[ndx]
to val in the cache.Examples
>>> l = MemLeak(lambda x: '') >>> l.cache == {} True >>> l.setw(33, 0x41) >>> l.cache == {33: 'A', 34: '\x00'} True
-
p32
(addr, val, ndx=0)[source]¶ Sets dword at
((uint32_t*)addr)[ndx]
to val in the cache.Examples
See
setw()
.
-
p64
(addr, val, ndx=0)[source]¶ Sets qword at
((uint64_t*)addr)[ndx]
to val in the cache.Examples
See
setw()
.
-
p8
(addr, val, ndx=0)[source]¶ Sets byte at
((uint8_t*)addr)[ndx]
to val in the cache.Examples
>>> l = MemLeak(lambda x: '') >>> l.cache == {} True >>> l.setb(33, 0x41) >>> l.cache == {33: 'A'} True
-
q
(addr, ndx = 0) → int[source]¶ Leak qword at
((uint64_t*) addr)[ndx]
Examples
>>> import string >>> data = string.ascii_lowercase >>> l = MemLeak(lambda a: data[a:a+16], reraise=False) >>> l.q(0) == unpack('abcdefgh', 64) True >>> l.q(18) == unpack('stuvwxyz', 64) True >>> l.q(19) is None True
-
s
(addr) → str[source]¶ Leak bytes at addr until failure or a nullbyte is found
Returns: A string, without a NULL terminator. The returned string will be empty if the first byte is a NULL terminator, or if the first byte could not be retrieved. Examples
>>> data = "Hello\x00World" >>> l = MemLeak(lambda a: data[a:a+4], reraise=False) >>> l.s(0) == "Hello" True >>> l.s(5) == "" True >>> l.s(6) == "World" True >>> l.s(999) == "" True
-
setb
(addr, val, ndx=0)[source]¶ Sets byte at
((uint8_t*)addr)[ndx]
to val in the cache.Examples
>>> l = MemLeak(lambda x: '') >>> l.cache == {} True >>> l.setb(33, 0x41) >>> l.cache == {33: 'A'} True
-
setd
(addr, val, ndx=0)[source]¶ Sets dword at
((uint32_t*)addr)[ndx]
to val in the cache.Examples
See
setw()
.
-
setq
(addr, val, ndx=0)[source]¶ Sets qword at
((uint64_t*)addr)[ndx]
to val in the cache.Examples
See
setw()
.
-
sets
(addr, val, null_terminate=True)[source]¶ Set known string at addr, which will be optionally be null-terminated
Note that this method is a bit dumb about how it handles the data. It will null-terminate the data, but it will not stop at the first null.
Examples
>>> l = MemLeak(lambda x: '') >>> l.cache == {} True >>> l.sets(0, 'H\x00ello') >>> l.cache == {0: 'H', 1: '\x00', 2: 'e', 3: 'l', 4: 'l', 5: 'o', 6: '\x00'} True
-
setw
(addr, val, ndx=0)[source]¶ Sets word at
((uint16_t*)addr)[ndx]
to val in the cache.Examples
>>> l = MemLeak(lambda x: '') >>> l.cache == {} True >>> l.setw(33, 0x41) >>> l.cache == {33: 'A', 34: '\x00'} True
-
struct
(address, struct)[source]¶ struct(address, struct) => structure object Leak an entire structure. :param address: Addess of structure in memory :type address: int :param struct: A ctypes structure to be instantiated with leaked data :type struct: class
- Return Value:
- An instance of the provided struct class, with the leaked data decoded
Examples
>>> @pwnlib.memleak.MemLeak ... def leaker(addr): ... return "A" >>> e = leaker.struct(0, pwnlib.elf.Elf32_Phdr) >>> hex(e.p_paddr) '0x41414141'
-
u16
(addr, ndx=0)[source]¶ w(addr, ndx = 0) -> int
Leak word at
((uint16_t*) addr)[ndx]
Examples
>>> import string >>> data = string.ascii_lowercase >>> l = MemLeak(lambda a: data[a:a+4], reraise=False) >>> l.w(0) == unpack('ab', 16) True >>> l.w(24) == unpack('yz', 16) True >>> l.w(25) is None True
-
u32
(addr, ndx=0)[source]¶ d(addr, ndx = 0) -> int
Leak dword at
((uint32_t*) addr)[ndx]
Examples
>>> import string >>> data = string.ascii_lowercase >>> l = MemLeak(lambda a: data[a:a+8], reraise=False) >>> l.d(0) == unpack('abcd', 32) True >>> l.d(22) == unpack('wxyz', 32) True >>> l.d(23) is None True
-
u64
(addr, ndx=0)[source]¶ q(addr, ndx = 0) -> int
Leak qword at
((uint64_t*) addr)[ndx]
Examples
>>> import string >>> data = string.ascii_lowercase >>> l = MemLeak(lambda a: data[a:a+16], reraise=False) >>> l.q(0) == unpack('abcdefgh', 64) True >>> l.q(18) == unpack('stuvwxyz', 64) True >>> l.q(19) is None True
pwnlib.replacements
— Replacements for various functions¶
Improved replacements for standard functions
-
pwnlib.replacements.
sleep
(n)[source]¶ Replacement for
time.sleep()
, which does not return if a signal is received.Parameters: n (int) – Number of seconds to sleep.
pwnlib.rop
— Return Oriented Programming¶
Submodules¶
pwnlib.rop.rop
— Return Oriented Programming¶
Return Oriented Programming
Manual ROP¶
The ROP tool can be used to build stacks pretty trivially. Let’s create a fake binary which has some symbols which might have been useful.
>>> context.clear(arch='i386')
>>> binary = ELF.from_assembly('add esp, 0x10; ret')
>>> binary.symbols = {'read': 0xdeadbeef, 'write': 0xdecafbad, 'exit': 0xfeedface}
Creating a ROP object which looks up symbols in the binary is pretty straightforward.
>>> rop = ROP(binary)
With the ROP object, you can manually add stack frames.
>>> rop.raw(0)
>>> rop.raw(unpack('abcd'))
>>> rop.raw(2)
Inspecting the ROP stack is easy, and laid out in an easy-to-read manner.
>>> print rop.dump()
0x0000: 0x0
0x0004: 0x64636261
0x0008: 0x2
The ROP module is also aware of how to make function calls with standard Linux ABIs.
>>> rop.call('read', [4,5,6])
>>> print rop.dump()
0x0000: 0x0
0x0004: 0x64636261
0x0008: 0x2
0x000c: 0xdeadbeef read(4, 5, 6)
0x0010: 'eaaa' <pad>
0x0014: 0x4 arg0
0x0018: 0x5 arg1
0x001c: 0x6 arg2
You can also use a shorthand to invoke calls. The stack is automatically adjusted for the next frame
>>> rop.write(7,8,9)
>>> rop.exit()
>>> print rop.dump()
0x0000: 0x0
0x0004: 0x64636261
0x0008: 0x2
0x000c: 0xdeadbeef read(4, 5, 6)
0x0010: 0x10000000 <adjust: add esp, 0x10; ret>
0x0014: 0x4 arg0
0x0018: 0x5 arg1
0x001c: 0x6 arg2
0x0020: 'iaaa' <pad>
0x0024: 0xdecafbad write(7, 8, 9)
0x0028: 0x10000000 <adjust: add esp, 0x10; ret>
0x002c: 0x7 arg0
0x0030: 0x8 arg1
0x0034: 0x9 arg2
0x0038: 'oaaa' <pad>
0x003c: 0xfeedface exit()
0x0040: 'qaaa' <pad>
ROP Example¶
Let’s assume we have a trivial binary that just reads some data onto the stack, and returns.
>>> context.clear(arch='i386')
>>> c = constants
>>> assembly = 'read:' + shellcraft.read(c.STDIN_FILENO, 'esp', 1024)
>>> assembly += 'ret\n'
Let’s provide some simple gadgets:
>>> assembly += 'add_esp: add esp, 0x10; ret\n'
And perhaps a nice “write” function.
>>> assembly += 'write: enter 0,0\n'
>>> assembly += ' mov ebx, [ebp+4+4]\n'
>>> assembly += ' mov ecx, [ebp+4+8]\n'
>>> assembly += ' mov edx, [ebp+4+12]\n'
>>> assembly += shellcraft.write('ebx', 'ecx', 'edx')
>>> assembly += ' leave\n'
>>> assembly += ' ret\n'
>>> assembly += 'flag: .asciz "The flag"\n'
And a way to exit cleanly.
>>> assembly += 'exit: ' + shellcraft.exit(0)
>>> binary = ELF.from_assembly(assembly)
Finally, let’s build our ROP stack
>>> rop = ROP(binary)
>>> rop.write(c.STDOUT_FILENO, binary.symbols['flag'], 8)
>>> rop.exit()
>>> print rop.dump()
0x0000: 0x10000012 write(STDOUT_FILENO, 268435494, 8)
0x0004: 0x1000000e <adjust: add esp, 0x10; ret>
0x0008: 0x1 arg0
0x000c: 0x10000026 flag
0x0010: 0x8 arg2
0x0014: 'faaa' <pad>
0x0018: 0x1000002f exit()
0x001c: 'haaa' <pad>
The raw data from the ROP stack is available via str.
>>> raw_rop = str(rop)
>>> print enhex(raw_rop)
120000100e000010010000002600001008000000666161612f00001068616161
Let’s try it out!
>>> p = process(binary.path)
>>> p.send(raw_rop)
>>> print p.recvall(timeout=5)
The flag
ROP + Sigreturn¶
In some cases, control of the desired register is not available. However, if you have control of the stack, EAX, and can find a int 0x80 gadget, you can use sigreturn.
Even better, this happens automagically.
Our example binary will read some data onto the stack, and not do anything else interesting.
>>> context.clear(arch='i386')
>>> c = constants
>>> assembly = 'read:' + shellcraft.read(c.STDIN_FILENO, 'esp', 1024)
>>> assembly += 'ret\n'
>>> assembly += 'pop eax; ret\n'
>>> assembly += 'int 0x80\n'
>>> assembly += 'binsh: .asciz "/bin/sh"'
>>> binary = ELF.from_assembly(assembly)
Let’s create a ROP object and invoke the call.
>>> context.kernel = 'amd64'
>>> rop = ROP(binary)
>>> binsh = binary.symbols['binsh']
>>> rop.execve(binsh, 0, 0)
That’s all there is to it.
>>> print rop.dump()
0x0000: 0x1000000e pop eax; ret
0x0004: 0x77
0x0008: 0x1000000b int 0x80
0x000c: 0x0 gs
0x0010: 0x0 fs
0x0014: 0x0 es
0x0018: 0x0 ds
0x001c: 0x0 edi
0x0020: 0x0 esi
0x0024: 0x0 ebp
0x0028: 0x0 esp
0x002c: 0x10000012 ebx = binsh
0x0030: 0x0 edx
0x0034: 0x0 ecx
0x0038: 0xb eax
0x003c: 0x0 trapno
0x0040: 0x0 err
0x0044: 0x1000000b int 0x80
0x0048: 0x23 cs
0x004c: 0x0 eflags
0x0050: 0x0 esp_at_signal
0x0054: 0x2b ss
0x0058: 0x0 fpstate
Let’s try it out!
>>> p = process(binary.path)
>>> p.send(str(rop))
>>> time.sleep(1)
>>> p.sendline('echo hello; exit')
>>> p.recvline()
'hello\n'
-
class
pwnlib.rop.rop.
ROP
(elfs, base=None, **kwargs)[source]¶ Class which simplifies the generation of ROP-chains.
Example:
elf = ELF('ropasaurusrex') rop = ROP(elf) rop.read(0, elf.bss(0x80)) rop.dump() # ['0x0000: 0x80482fc (read)', # '0x0004: 0xdeadbeef', # '0x0008: 0x0', # '0x000c: 0x80496a8'] str(rop) # '\xfc\x82\x04\x08\xef\xbe\xad\xde\x00\x00\x00\x00\xa8\x96\x04\x08'
>>> context.clear(arch = "i386", kernel = 'amd64') >>> assembly = 'int 0x80; ret; add esp, 0x10; ret; pop eax; ret' >>> e = ELF.from_assembly(assembly) >>> e.symbols['funcname'] = e.address + 0x1234 >>> r = ROP(e) >>> r.funcname(1, 2) >>> r.funcname(3) >>> r.execve(4, 5, 6) >>> print r.dump() 0x0000: 0x10001234 funcname(1, 2) 0x0004: 0x10000003 <adjust: add esp, 0x10; ret> 0x0008: 0x1 arg0 0x000c: 0x2 arg1 0x0010: 'eaaa' <pad> 0x0014: 'faaa' <pad> 0x0018: 0x10001234 funcname(3) 0x001c: 0x10000007 <adjust: pop eax; ret> 0x0020: 0x3 arg0 0x0024: 0x10000007 pop eax; ret 0x0028: 0x77 0x002c: 0x10000000 int 0x80 0x0030: 0x0 gs 0x0034: 0x0 fs 0x0038: 0x0 es 0x003c: 0x0 ds 0x0040: 0x0 edi 0x0044: 0x0 esi 0x0048: 0x0 ebp 0x004c: 0x0 esp 0x0050: 0x4 ebx 0x0054: 0x6 edx 0x0058: 0x5 ecx 0x005c: 0xb eax 0x0060: 0x0 trapno 0x0064: 0x0 err 0x0068: 0x10000000 int 0x80 0x006c: 0x23 cs 0x0070: 0x0 eflags 0x0074: 0x0 esp_at_signal 0x0078: 0x2b ss 0x007c: 0x0 fpstate
>>> r = ROP(e, 0x8048000) >>> r.funcname(1, 2) >>> r.funcname(3) >>> r.execve(4, 5, 6) >>> print r.dump() 0x8048000: 0x10001234 funcname(1, 2) 0x8048004: 0x10000003 <adjust: add esp, 0x10; ret> 0x8048008: 0x1 arg0 0x804800c: 0x2 arg1 0x8048010: 'eaaa' <pad> 0x8048014: 'faaa' <pad> 0x8048018: 0x10001234 funcname(3) 0x804801c: 0x10000007 <adjust: pop eax; ret> 0x8048020: 0x3 arg0 0x8048024: 0x10000007 pop eax; ret 0x8048028: 0x77 0x804802c: 0x10000000 int 0x80 0x8048030: 0x0 gs 0x8048034: 0x0 fs 0x8048038: 0x0 es 0x804803c: 0x0 ds 0x8048040: 0x0 edi 0x8048044: 0x0 esi 0x8048048: 0x0 ebp 0x804804c: 0x8048080 esp 0x8048050: 0x4 ebx 0x8048054: 0x6 edx 0x8048058: 0x5 ecx 0x804805c: 0xb eax 0x8048060: 0x0 trapno 0x8048064: 0x0 err 0x8048068: 0x10000000 int 0x80 0x804806c: 0x23 cs 0x8048070: 0x0 eflags 0x8048074: 0x0 esp_at_signal 0x8048078: 0x2b ss 0x804807c: 0x0 fpstate
-
build
(base=None, description=None)[source]¶ Construct the ROP chain into a list of elements which can be passed to
flat()
.Parameters:
-
find_gadget
(instructions)[source]¶ Returns a gadget with the exact sequence of instructions specified in the
instructions
argument.
-
migrated
= False[source]¶ Whether or not the ROP chain directly sets the stack pointer to a value which is not contiguous
-
raw
(value)[source]¶ Adds a raw integer or string to the ROP chain.
If your architecture requires aligned values, then make sure that any given string is aligned!
Parameters: data (int/str) – The raw value to put onto the rop chain.
-
resolve
(resolvable)[source]¶ Resolves a symbol to an address
Parameters: resolvable (str,int) – Thing to convert into an address Returns: int containing address of ‘resolvable’, or None
-
search
(move=0, regs=None, order='size')[source]¶ Search for a gadget which matches the specified criteria.
Parameters: The search will try to minimize the number of bytes popped more than requested, the number of registers touched besides the requested and the address.
If
order == 'size'
, then gadgets are compared lexicographically by(total_moves, total_regs, addr)
, otherwise by(total_regs, total_moves, addr)
.Returns: A Gadget
object
-
search_iter
(move=None, regs=None)[source]¶ Iterate through all gadgets which move the stack pointer by at least
move
bytes, and which allow you to set all registers inregs
.
-
setRegisters
(registers)[source]¶ Returns an OrderedDict of addresses/values which will set the specified register context.
Parameters: registers (dict) – Dictionary of {register name: value}
Returns: sequence of gadgets, values, etc.}``. Return type: An OrderedDict of ``{register
-
unresolve
(value)[source]¶ Inverts ‘resolve’. Given an address, it attempts to find a symbol for it in the loaded ELF files. If none is found, it searches all known gadgets, and returns the disassembly
Parameters: value (int) – Address to look up Returns: String containing the symbol name for the address, disassembly for a gadget (if there’s one at that address), or an empty string.
-
pwnlib.rop.srop
— Sigreturn Oriented Programming¶
Sigreturn ROP (SROP)
Sigreturn is a syscall used to restore the entire register context from memory pointed at by ESP.
We can leverage this during ROP to gain control of registers for which there are not convenient gadgets. The main caveat is that all registers are set, including ESP and EIP (or their equivalents). This means that in order to continue after using a sigreturn frame, the stack pointer must be set accordingly.
i386 Example:
Let’s just print a message out using SROP.
>>> message = "Hello, World"First, we’ll create our example binary. It just reads some data onto the stack, and invokes the
sigreturn
syscall. We also make anint 0x80
gadget available, followed immediately byexit(0)
.>>> context.clear(arch='i386') >>> assembly = 'read:' + shellcraft.read(constants.STDIN_FILENO, 'esp', 1024) >>> assembly += 'sigreturn:' + shellcraft.sigreturn() >>> assembly += 'int3:' + shellcraft.trap() >>> assembly += 'syscall: ' + shellcraft.syscall() >>> assembly += 'exit: ' + 'xor ebx, ebx; mov eax, 1; int 0x80;' >>> assembly += 'message: ' + ('.asciz "%s"' % message) >>> binary = ELF.from_assembly(assembly)Let’s construct our frame to have it invoke a
write
syscall, and dump the message to stdout.>>> frame = SigreturnFrame(kernel='amd64') >>> frame.eax = constants.SYS_write >>> frame.ebx = constants.STDOUT_FILENO >>> frame.ecx = binary.symbols['message'] >>> frame.edx = len(message) >>> frame.esp = 0xdeadbeef >>> frame.eip = binary.symbols['syscall']Let’s start the process, send the data, and check the message.
>>> p = process(binary.path) >>> p.send(str(frame)) >>> p.recvn(len(message)) == message True >>> p.wait_for_close() >>> p.poll() == 0 True
amd64 Example:
>>> context.clear()
>>> context.arch = "amd64"
>>> assembly = 'read:' + shellcraft.read(constants.STDIN_FILENO, 'rsp', 1024)
>>> assembly += 'sigreturn:' + shellcraft.sigreturn()
>>> assembly += 'int3:' + shellcraft.trap()
>>> assembly += 'syscall: ' + shellcraft.syscall()
>>> assembly += 'exit: ' + 'xor rdi, rdi; mov rax, 60; syscall;'
>>> assembly += 'message: ' + ('.asciz "%s"' % message)
>>> binary = ELF.from_assembly(assembly)
>>> frame = SigreturnFrame()
>>> frame.rax = constants.SYS_write
>>> frame.rdi = constants.STDOUT_FILENO
>>> frame.rsi = binary.symbols['message']
>>> frame.rdx = len(message)
>>> frame.rsp = 0xdeadbeef
>>> frame.rip = binary.symbols['syscall']
>>> p = process(binary.path)
>>> p.send(str(frame))
>>> p.recvn(len(message)) == message
True
>>> p.wait_for_close()
>>> p.poll() == 0
True
arm Example:
>>> context.clear()
>>> context.arch = "arm"
>>> assembly = 'read:' + shellcraft.read(constants.STDIN_FILENO, 'sp', 1024)
>>> assembly += 'sigreturn:' + shellcraft.sigreturn()
>>> assembly += 'int3:' + shellcraft.trap()
>>> assembly += 'syscall: ' + shellcraft.syscall()
>>> assembly += 'exit: ' + 'eor r0, r0; mov r7, 0x1; swi #0;'
>>> assembly += 'message: ' + ('.asciz "%s"' % message)
>>> binary = ELF.from_assembly(assembly)
>>> frame = SigreturnFrame()
>>> frame.r7 = constants.SYS_write
>>> frame.r0 = constants.STDOUT_FILENO
>>> frame.r1 = binary.symbols['message']
>>> frame.r2 = len(message)
>>> frame.sp = 0xdead0000
>>> frame.pc = binary.symbols['syscall']
>>> p = process(binary.path)
>>> p.send(str(frame))
>>> p.recvn(len(message)) == message
True
>>> p.wait_for_close()
>>> p.poll() == 0
True
Mips Example:
>>> context.clear()
>>> context.arch = "mips"
>>> context.endian = "big"
>>> assembly = 'read:' + shellcraft.read(constants.STDIN_FILENO, '$sp', 1024)
>>> assembly += 'sigreturn:' + shellcraft.sigreturn()
>>> assembly += 'syscall: ' + shellcraft.syscall()
>>> assembly += 'exit: ' + shellcraft.exit(0)
>>> assembly += 'message: ' + ('.asciz "%s"' % message)
>>> binary = ELF.from_assembly(assembly)
>>> frame = SigreturnFrame()
>>> frame.v0 = constants.SYS_write
>>> frame.a0 = constants.STDOUT_FILENO
>>> frame.a1 = binary.symbols['message']
>>> frame.a2 = len(message)
>>> frame.sp = 0xdead0000
>>> frame.pc = binary.symbols['syscall']
>>> p = process(binary.path)
>>> p.send(str(frame))
>>> p.recvn(len(message)) == message
True
>>> p.wait_for_close()
>>> p.poll() == 0
True
Mipsel Example:
>>> context.clear()
>>> context.arch = "mips"
>>> context.endian = "little"
>>> assembly = 'read:' + shellcraft.read(constants.STDIN_FILENO, '$sp', 1024)
>>> assembly += 'sigreturn:' + shellcraft.sigreturn()
>>> assembly += 'syscall: ' + shellcraft.syscall()
>>> assembly += 'exit: ' + shellcraft.exit(0)
>>> assembly += 'message: ' + ('.asciz "%s"' % message)
>>> binary = ELF.from_assembly(assembly)
>>> frame = SigreturnFrame()
>>> frame.v0 = constants.SYS_write
>>> frame.a0 = constants.STDOUT_FILENO
>>> frame.a1 = binary.symbols['message']
>>> frame.a2 = len(message)
>>> frame.sp = 0xdead0000
>>> frame.pc = binary.symbols['syscall']
>>> p = process(binary.path)
>>> p.send(str(frame))
>>> p.recvn(len(message)) == message
True
>>> p.wait_for_close()
>>> p.poll() == 0
True
-
class
pwnlib.rop.srop.
SigreturnFrame
(*a, **kw)[source]¶ Crafts a sigreturn frame with values that are loaded up into registers.
Parameters: arch (str) – The architecture. Currently i386
andamd64
are supported.Examples
Crafting a SigreturnFrame that calls mprotect on amd64
>>> context.clear(arch='amd64') >>> s = SigreturnFrame() >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0] >>> assert len(s) == 248 >>> s.rax = 0xa >>> s.rdi = 0x00601000 >>> s.rsi = 0x1000 >>> s.rdx = 0x7 >>> assert len(str(s)) == 248 >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6295552, 4096, 0, 0, 7, 10, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0]
Crafting a SigreturnFrame that calls mprotect on i386
>>> context.clear(arch='i386') >>> s = SigreturnFrame(kernel='i386') >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 0, 0, 123, 0] >>> assert len(s) == 80 >>> s.eax = 125 >>> s.ebx = 0x00601000 >>> s.ecx = 0x1000 >>> s.edx = 0x7 >>> assert len(str(s)) == 80 >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 6295552, 7, 4096, 125, 0, 0, 0, 115, 0, 0, 123, 0]
Crafting a SigreturnFrame that calls mprotect on ARM
>>> s = SigreturnFrame(arch='arm') >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1073741840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1447448577, 288] >>> s.r0 = 125 >>> s.r1 = 0x00601000 >>> s.r2 = 0x1000 >>> s.r3 = 0x7 >>> assert len(str(s)) == 240 >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 6, 0, 0, 125, 6295552, 4096, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1073741840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1447448577, 288]
Crafting a SigreturnFrame that calls mprotect on MIPS
>>> context.clear() >>> context.endian = "big" >>> s = SigreturnFrame(arch='mips') >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] >>> s.v0 = 0x101d >>> s.a0 = 0x00601000 >>> s.a1 = 0x1000 >>> s.a2 = 0x7 >>> assert len(str(s)) == 296 >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4125, 0, 0, 0, 6295552, 0, 4096, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Crafting a SigreturnFrame that calls mprotect on MIPSel
>>> context.clear() >>> context.endian = "little" >>> s = SigreturnFrame(arch='mips') >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] >>> s.v0 = 0x101d >>> s.a0 = 0x00601000 >>> s.a1 = 0x1000 >>> s.a2 = 0x7 >>> assert len(str(s)) == 292 >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4125, 0, 0, 0, 6295552, 0, 4096, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Crafting a SigreturnFrame that calls mprotect on Aarch64
>>> context.clear() >>> context.endian = "little" >>> s = SigreturnFrame(arch='aarch64') >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1179680769, 528] >>> s.x8 = 0xe2 >>> s.x0 = 0x4000 >>> s.x1 = 0x1000 >>> s.x2 = 0x7 >>> assert len(str(s)) == 600 >>> unpack_many(str(s)) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16384, 0, 4096, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1179680769, 528]
pwnlib.runner
— Running Shellcode¶
-
pwnlib.runner.
run_assembly
(*a, **kw)[source]¶ Given an assembly listing, assemble and execute it.
Returns: A pwnlib.tubes.process.process
tube to interact with the process.Example
>>> p = run_assembly('mov ebx, 3; mov eax, SYS_exit; int 0x80;') >>> p.wait_for_close() >>> p.poll() 3
>>> p = run_assembly('mov r0, #12; mov r7, #1; svc #0', arch='arm') >>> p.wait_for_close() >>> p.poll() 12
-
pwnlib.runner.
run_shellcode
(*a, **kw)[source]¶ Given assembled machine code bytes, execute them.
Example
>>> bytes = asm('mov ebx, 3; mov eax, SYS_exit; int 0x80;') >>> p = run_shellcode(bytes) >>> p.wait_for_close() >>> p.poll() 3
>>> bytes = asm('mov r0, #12; mov r7, #1; svc #0', arch='arm') >>> p = run_shellcode(bytes, arch='arm') >>> p.wait_for_close() >>> p.poll() 12
pwnlib.shellcraft
— Shellcode generation¶
The shellcode module.
This module contains functions for generating shellcode.
It is organized first by architecture and then by operating system.
Submodules¶
pwnlib.shellcraft.amd64
— Shellcode for AMD64¶
pwnlib.shellcraft.amd64
¶
Shellcraft module containing generic Intel x86_64 shellcodes.
-
pwnlib.shellcraft.amd64.
crash
()[source]¶ Crash.
Example
>>> run_assembly(shellcraft.crash()).poll(True) -11
-
pwnlib.shellcraft.amd64.
itoa
(v, buffer='rsp', allocate_stack=True)[source]¶ Converts an integer into its string representation, and pushes it onto the stack.
Parameters: Example
>>> sc = shellcraft.amd64.mov('rax', 0xdeadbeef) >>> sc += shellcraft.amd64.itoa('rax') >>> sc += shellcraft.amd64.linux.write(1, 'rsp', 32) >>> run_assembly(sc).recvuntil('\x00') '3735928559\x00'
-
pwnlib.shellcraft.amd64.
memcpy
(dest, src, n)[source]¶ Copies memory.
Parameters: - dest – Destination address
- src – Source address
- n – Number of bytes
-
pwnlib.shellcraft.amd64.
mov
(dest, src, stack_allowed=True)[source]¶ Move src into dest without newlines and null bytes.
If the src is a register smaller than the dest, then it will be zero-extended to fit inside the larger register.
If the src is a register larger than the dest, then only some of the bits will be used.
If src is a string that is not a register, then it will locally set context.arch to ‘amd64’ and use
pwnlib.constants.eval()
to evaluate the string. Note that this means that this shellcode can change behavior depending on the value of context.os.Example
>>> print shellcraft.amd64.mov('eax','ebx').rstrip() mov eax, ebx >>> print shellcraft.amd64.mov('eax', 0).rstrip() xor eax, eax /* 0 */ >>> print shellcraft.amd64.mov('ax', 0).rstrip() xor ax, ax /* 0 */ >>> print shellcraft.amd64.mov('rax', 0).rstrip() xor eax, eax /* 0 */ >>> print shellcraft.amd64.mov('rdi', 'ax').rstrip() movzx edi, ax >>> print shellcraft.amd64.mov('al', 'ax').rstrip() /* moving ax into al, but this is a no-op */ >>> print shellcraft.amd64.mov('ax', 'bl').rstrip() movzx ax, bl >>> print shellcraft.amd64.mov('eax', 1).rstrip() push 1 pop rax >>> print shellcraft.amd64.mov('rax', 0xc0).rstrip() xor eax, eax mov al, 0xc0 >>> print shellcraft.amd64.mov('rax', 0xc000).rstrip() xor eax, eax mov ah, 0xc000 >> 8 >>> print shellcraft.amd64.mov('rax', 0xc0c0).rstrip() xor eax, eax mov ax, 0xc0c0 >>> print shellcraft.amd64.mov('rdi', 0xff).rstrip() mov edi, 0x1010101 /* 255 == 0xff */ xor edi, 0x10101fe >>> print shellcraft.amd64.mov('rax', 0xdead00ff).rstrip() mov eax, 0x1010101 /* 3735879935 == 0xdead00ff */ xor eax, 0xdfac01fe >>> print shellcraft.amd64.mov('rax', 0x11dead00ff).rstrip() mov rax, 0x101010101010101 /* 76750323967 == 0x11dead00ff */ push rax mov rax, 0x1010110dfac01fe xor [rsp], rax pop rax >>> print shellcraft.amd64.mov('rax', 0xffffffff).rstrip() mov eax, 0xffffffff >>> print shellcraft.amd64.mov('rax', 0x7fffffff).rstrip() mov eax, 0x7fffffff >>> print shellcraft.amd64.mov('rax', 0x80010101).rstrip() mov eax, 0x80010101 >>> print shellcraft.amd64.mov('rax', 0x80000000).rstrip() mov eax, 0x1010101 /* 2147483648 == 0x80000000 */ xor eax, 0x81010101 >>> print shellcraft.amd64.mov('rax', 0xffffffffffffffff).rstrip() push 0xffffffffffffffff pop rax >>> with context.local(os = 'linux'): ... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip() xor eax, eax /* SYS_read */ >>> with context.local(os = 'freebsd'): ... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip() push SYS_read /* 3 */ pop rax >>> with context.local(os = 'linux'): ... print shellcraft.amd64.mov('eax', 'PROT_READ | PROT_WRITE | PROT_EXEC').rstrip() push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */ pop rax
Parameters:
-
pwnlib.shellcraft.amd64.
popad
()[source]¶ Pop all of the registers onto the stack which i386 popad does, in the same order.
-
pwnlib.shellcraft.amd64.
push
(value)[source]¶ Pushes a value onto the stack without using null bytes or newline characters.
If src is a string, then we try to evaluate with context.arch = ‘amd64’ using
pwnlib.constants.eval()
before determining how to push it. Note that this means that this shellcode can change behavior depending on the value of context.os.Parameters: value (int,str) – The value or register to push Example
>>> print pwnlib.shellcraft.amd64.push(0).rstrip() /* push 0 */ push 1 dec byte ptr [rsp] >>> print pwnlib.shellcraft.amd64.push(1).rstrip() /* push 1 */ push 1 >>> print pwnlib.shellcraft.amd64.push(256).rstrip() /* push 256 */ push 0x1010201 ^ 0x100 xor dword ptr [rsp], 0x1010201 >>> with context.local(os = 'linux'): ... print pwnlib.shellcraft.amd64.push('SYS_write').rstrip() /* push 'SYS_write' */ push 1 >>> with context.local(os = 'freebsd'): ... print pwnlib.shellcraft.amd64.push('SYS_write').rstrip() /* push 'SYS_write' */ push 4
-
pwnlib.shellcraft.amd64.
pushad
()[source]¶ Push all of the registers onto the stack which i386 pushad does, in the same order.
-
pwnlib.shellcraft.amd64.
pushstr
(string, append_null=True)[source]¶ Pushes a string onto the stack without using null bytes or newline characters.
Example
>>> print shellcraft.amd64.pushstr('').rstrip() /* push '\x00' */ push 1 dec byte ptr [rsp] >>> print shellcraft.amd64.pushstr('a').rstrip() /* push 'a\x00' */ push 0x61 >>> print shellcraft.amd64.pushstr('aa').rstrip() /* push 'aa\x00' */ push 0x1010101 ^ 0x6161 xor dword ptr [rsp], 0x1010101 >>> print shellcraft.amd64.pushstr('aaa').rstrip() /* push 'aaa\x00' */ push 0x1010101 ^ 0x616161 xor dword ptr [rsp], 0x1010101 >>> print shellcraft.amd64.pushstr('aaaa').rstrip() /* push 'aaaa\x00' */ push 0x61616161 >>> print shellcraft.amd64.pushstr('aaa\xc3').rstrip() /* push 'aaa\xc3\x00' */ mov rax, 0x101010101010101 push rax mov rax, 0x101010101010101 ^ 0xc3616161 xor [rsp], rax >>> print shellcraft.amd64.pushstr('aaa\xc3', append_null = False).rstrip() /* push 'aaa\xc3' */ push -0x3c9e9e9f >>> print shellcraft.amd64.pushstr('\xc3').rstrip() /* push '\xc3\x00' */ push 0x1010101 ^ 0xc3 xor dword ptr [rsp], 0x1010101 >>> print shellcraft.amd64.pushstr('\xc3', append_null = False).rstrip() /* push '\xc3' */ push -0x3d >>> with context.local(): ... context.arch = 'amd64' ... print enhex(asm(shellcraft.pushstr("/bin/sh"))) 48b801010101010101015048b82e63686f2e72690148310424 >>> with context.local(): ... context.arch = 'amd64' ... print enhex(asm(shellcraft.pushstr(""))) 6a01fe0c24 >>> with context.local(): ... context.arch = 'amd64' ... print enhex(asm(shellcraft.pushstr("\x00", False))) 6a01fe0c24
Parameters:
-
pwnlib.shellcraft.amd64.
pushstr_array
(reg, array)[source]¶ Pushes an array/envp-style array of pointers onto the stack.
Parameters:
-
pwnlib.shellcraft.amd64.
ret
(return_value=None)[source]¶ A single-byte RET instruction.
Parameters: return_value – Value to return
-
pwnlib.shellcraft.amd64.
setregs
(reg_context, stack_allowed=True)[source]¶ Sets multiple registers, taking any register dependencies into account (i.e., given eax=1,ebx=eax, set ebx first).
Parameters: Example
>>> print shellcraft.setregs({'rax':1, 'rbx':'rax'}).rstrip() mov rbx, rax push 1 pop rax >>> print shellcraft.setregs({'rax': 'SYS_write', 'rbx':'rax'}).rstrip() mov rbx, rax push SYS_write /* 1 */ pop rax >>> print shellcraft.setregs({'rax':'rbx', 'rbx':'rax', 'rcx':'rbx'}).rstrip() mov rcx, rbx xchg rax, rbx >>> print shellcraft.setregs({'rax':1, 'rdx':0}).rstrip() push 1 pop rax cdq /* rdx=0 */
-
pwnlib.shellcraft.amd64.
strcpy
(dst, src)[source]¶ Copies a string
Example
>>> sc = 'jmp get_str\n' >>> sc += 'pop_str: pop rax\n' >>> sc += shellcraft.amd64.strcpy('rsp', 'rax') >>> sc += shellcraft.amd64.linux.write(1, 'rsp', 32) >>> sc += shellcraft.amd64.linux.exit(0) >>> sc += 'get_str: call pop_str\n' >>> sc += '.asciz "Hello, world\\n"' >>> run_assembly(sc).recvline() 'Hello, world\n'
-
pwnlib.shellcraft.amd64.
strlen
(string, reg='rcx')[source]¶ Calculate the length of the specified string.
Parameters: Example
>>> sc = 'jmp get_str\n' >>> sc += 'pop_str: pop rdi\n' >>> sc += shellcraft.amd64.strlen('rdi', 'rax') >>> sc += 'push rax;' >>> sc += shellcraft.amd64.linux.write(1, 'rsp', 8) >>> sc += shellcraft.amd64.linux.exit(0) >>> sc += 'get_str: call pop_str\n' >>> sc += '.asciz "Hello, world\\n"' >>> run_assembly(sc).unpack() == len('Hello, world\n') True
-
pwnlib.shellcraft.amd64.
xor
(key, address, count)[source]¶ XORs data a constant value.
Parameters: - key (int,str) – XOR key either as a 8-byte integer, If a string, length must be a power of two, and not longer than 8 bytes. Alternately, may be a register.
- address (int) – Address of the data (e.g. 0xdead0000, ‘esp’)
- count (int) – Number of bytes to XOR, or a register containing the number of bytes to XOR.
Example
>>> sc = shellcraft.read(0, 'rsp', 32) >>> sc += shellcraft.xor(0xdeadbeef, 'rsp', 32) >>> sc += shellcraft.write(1, 'rsp', 32) >>> io = run_assembly(sc) >>> io.send(cyclic(32)) >>> result = io.recvn(32) >>> expected = xor(cyclic(32), p32(0xdeadbeef)) >>> result == expected True
pwnlib.shellcraft.amd64.linux
¶
Shellcraft module containing Intel x86_64 shellcodes for Linux.
-
pwnlib.shellcraft.amd64.linux.
bindsh
(port, network)[source]¶ Listens on a TCP port and spawns a shell for the first to connect. Port is the TCP port to listen on, network is either ‘ipv4’ or ‘ipv6’.
-
pwnlib.shellcraft.amd64.linux.
cat
(filename, fd=1)[source]¶ Opens a file and writes its contents to the specified file descriptor.
-
pwnlib.shellcraft.amd64.linux.
connect
(host, port, network='ipv4')[source]¶ Connects to the host on the specified port. Network is either ‘ipv4’ or ‘ipv6’. Leaves the connected socket in rbp.
-
pwnlib.shellcraft.amd64.linux.
connectstager
(host, port, network='ipv4')[source]¶ connect recvsize stager :param host, where to connect to: :param port, which port to connect to: :param network, ipv4 or ipv6? (default: ipv4)
-
pwnlib.shellcraft.amd64.linux.
dup
(sock='rbp')[source]¶ Args: [sock (imm/reg) = rbp] Duplicates sock to stdin, stdout and stderr
-
pwnlib.shellcraft.amd64.linux.
dupsh
(sock='rbp')[source]¶ Args: [sock (imm/reg) = rbp] Duplicates sock to stdin, stdout and stderr and spawns a shell.
-
pwnlib.shellcraft.amd64.linux.
egghunter
(egg, start_address = 0)[source]¶ Searches memory for the byte sequence ‘egg’.
Return value is the address immediately following the match, stored in RDI.
Parameters:
-
pwnlib.shellcraft.amd64.linux.
findpeer
(port=None)[source]¶ Args: port (defaults to any port) Finds a socket, which is connected to the specified port. Leaves socket in RDI.
-
pwnlib.shellcraft.amd64.linux.
findpeersh
(port=None)[source]¶ Args: port (defaults to any) Finds an open socket which connects to a specified port, and then opens a dup2 shell on it.
-
pwnlib.shellcraft.amd64.linux.
findpeerstager
(port=None)[source]¶ Findpeer recvsize stager :param port, the port given to findpeer: :type port, the port given to findpeer: defaults to any
-
pwnlib.shellcraft.amd64.linux.
forkexit
()[source]¶ Attempts to fork. If the fork is successful, the parent exits.
-
pwnlib.shellcraft.amd64.linux.
kill
(pid, signal='SIGKILL')[source]¶ Writes a string to a file descriptor
-
pwnlib.shellcraft.amd64.linux.
killparent
()[source]¶ Kills its parent process until whatever the parent is (probably init) cannot be killed any longer.
-
pwnlib.shellcraft.amd64.linux.
listen
(port, network)[source]¶ Listens on a TCP port, accept a client and leave his socket in RAX. Port is the TCP port to listen on, network is either ‘ipv4’ or ‘ipv6’.
-
pwnlib.shellcraft.amd64.linux.
loader
(address)[source]¶ Loads a statically-linked ELF into memory and transfers control.
Parameters: address (int) – Address of the ELF as a register or integer.
-
pwnlib.shellcraft.amd64.linux.
loader_append
(data=None)[source]¶ Loads a statically-linked ELF into memory and transfers control.
Similar to loader.asm but loads an appended ELF.
Parameters: data (str) – If a valid filename, the data is loaded from the named file. Otherwise, this is treated as raw ELF data to append. If None
, it is ignored.Example
>>> gcc = process(['gcc','-m64','-xc','-static','-Wl,-Ttext-segment=0x20000000','-']) >>> gcc.write(''' ... int main() { ... printf("Hello, %s!\\n", "amd64"); ... } ... ''') >>> gcc.shutdown('send') >>> gcc.poll(True) 0 >>> sc = shellcraft.loader_append('a.out')
The following doctest is commented out because it doesn’t work on Travis for reasons I cannot diagnose. However, it should work just fine :-)
# >>> run_assembly(sc).recvline() == ‘Hello, amd64!n’ # True
-
pwnlib.shellcraft.amd64.linux.
membot
(readsock=0, writesock=1)[source]¶ Read-write access to a remote process’ memory.
Provide a single pointer-width value to determine the operation to perform:
- 0: Exit the loop
- 1: Read data
- 2: Write data
-
pwnlib.shellcraft.amd64.linux.
mmap_rwx
(size=4096, protection=7, address=None)[source]¶ Maps some memory
-
pwnlib.shellcraft.amd64.linux.
read
(fd=0, buffer='rsp', count=8)[source]¶ Reads data from the file descriptor into the provided buffer. This is a one-shot and does not fill the request.
-
pwnlib.shellcraft.amd64.linux.
read_upto
(fd=0, buffer='rsp', sizereg='rdx')[source]¶ Reads up to N bytes 8 bytes into the specified register
-
pwnlib.shellcraft.amd64.linux.
readfile
(path, dst='rdi')[source]¶ Args: [path, dst (imm/reg) = rdi ] Opens the specified file path and sends its content to the specified file descriptor.
-
pwnlib.shellcraft.amd64.linux.
readinto
(sock=0)[source]¶ Reads into a buffer of a size and location determined at runtime. When the shellcode is executing, it should send a pointer and pointer-width size to determine the location and size of buffer.
-
pwnlib.shellcraft.amd64.linux.
readloop
(sock=0)[source]¶ Reads into a buffer of a size and location determined at runtime. When the shellcode is executing, it should send a pointer and pointer-width size to determine the location and size of buffer.
-
pwnlib.shellcraft.amd64.linux.
readn
(fd, buf, nbytes)[source]¶ Reads exactly nbytes bytes from file descriptor fd into the buffer buf.
Parameters: - fd (int) – fd
- buf (void) – buf
- nbytes (size_t) – nbytes
-
pwnlib.shellcraft.amd64.linux.
readptr
(fd=0, target_reg='rdx')[source]¶ Reads 8 bytes into the specified register
-
pwnlib.shellcraft.amd64.linux.
recvsize
(sock, reg='rcx')[source]¶ Recives 4 bytes size field Useful in conjuncion with findpeer and stager :param sock, the socket to read the payload from.: :param reg, the place to put the size: :type reg, the place to put the size: default ecx
Leaves socket in ebx
-
pwnlib.shellcraft.amd64.linux.
setregid
(gid='egid')[source]¶ Args: [gid (imm/reg) = egid] Sets the real and effective group id.
-
pwnlib.shellcraft.amd64.linux.
setreuid
(uid='euid')[source]¶ Args: [uid (imm/reg) = euid] Sets the real and effective user id.
-
pwnlib.shellcraft.amd64.linux.
sh
()[source]¶ Execute a different process.
>>> p = run_assembly(shellcraft.amd64.linux.sh()) >>> p.sendline('echo Hello') >>> p.recv() 'Hello\n'
-
pwnlib.shellcraft.amd64.linux.
stage
(fd=0, length=None)[source]¶ Migrates shellcode to a new buffer.
Parameters: Example
>>> p = run_assembly(shellcraft.stage()) >>> sc = asm(shellcraft.echo("Hello\n", constants.STDOUT_FILENO)) >>> p.pack(len(sc)) >>> p.send(sc) >>> p.recvline() 'Hello\n'
-
pwnlib.shellcraft.amd64.linux.
stager
(sock, size, handle_error=False)[source]¶ Recives a fixed sized payload into a mmaped buffer Useful in conjuncion with findpeer. After running the socket will be left in RDI. :param sock, the socket to read the payload from.: :param size, the size of the payload:
-
pwnlib.shellcraft.amd64.linux.
syscall
(syscall=None, arg0=None, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None)[source]¶ - Args: [syscall_number, *args]
- Does a syscall
Any of the arguments can be expressions to be evaluated by
pwnlib.constants.eval()
.Example
>>> print pwnlib.shellcraft.amd64.linux.syscall('SYS_execve', 1, 'rsp', 2, 0).rstrip() /* call execve(1, 'rsp', 2, 0) */ xor r10d, r10d /* 0 */ push SYS_execve /* 0x3b */ pop rax push 1 pop rdi push 2 pop rdx mov rsi, rsp syscall >>> print pwnlib.shellcraft.amd64.linux.syscall('SYS_execve', 2, 1, 0, -1).rstrip() /* call execve(2, 1, 0, -1) */ push -1 pop r10 push SYS_execve /* 0x3b */ pop rax push 2 pop rdi push 1 pop rsi cdq /* rdx=0 */ syscall >>> print pwnlib.shellcraft.amd64.linux.syscall().rstrip() /* call syscall() */ syscall >>> print pwnlib.shellcraft.amd64.linux.syscall('rax', 'rdi', 'rsi').rstrip() /* call syscall('rax', 'rdi', 'rsi') */ /* setregs noop */ syscall >>> print pwnlib.shellcraft.amd64.linux.syscall('rbp', None, None, 1).rstrip() /* call syscall('rbp', ?, ?, 1) */ mov rax, rbp push 1 pop rdx syscall >>> print pwnlib.shellcraft.amd64.linux.syscall( ... 'SYS_mmap', 0, 0x1000, ... 'PROT_READ | PROT_WRITE | PROT_EXEC', ... 'MAP_PRIVATE | MAP_ANONYMOUS', ... -1, 0).rstrip() /* call mmap(0, 4096, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE | MAP_ANONYMOUS', -1, 0) */ push (MAP_PRIVATE | MAP_ANONYMOUS) /* 0x22 */ pop r10 push -1 pop r8 xor r9d, r9d /* 0 */ push SYS_mmap /* 9 */ pop rax xor edi, edi /* 0 */ push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */ pop rdx mov esi, 0x1010101 /* 4096 == 0x1000 */ xor esi, 0x1011101 syscall >>> print pwnlib.shellcraft.open('/home/pwn/flag').rstrip() /* open(file='/home/pwn/flag', oflag=0, mode=0) */ /* push '/home/pwn/flag\x00' */ mov rax, 0x101010101010101 push rax mov rax, 0x101010101010101 ^ 0x67616c662f6e xor [rsp], rax mov rax, 0x77702f656d6f682f push rax mov rdi, rsp xor edx, edx /* 0 */ xor esi, esi /* 0 */ /* call open() */ push SYS_open /* 2 */ pop rax syscall
pwnlib.shellcraft.arm
— Shellcode for ARM¶
pwnlib.shellcraft.arm
¶
Shellcraft module containing generic ARM little endian shellcodes.
-
pwnlib.shellcraft.arm.
crash
()[source]¶ Crash.
Example
>>> run_assembly(shellcraft.crash()).poll(True) -11
-
pwnlib.shellcraft.arm.
itoa
(v, buffer='sp', allocate_stack=True)[source]¶ Converts an integer into its string representation, and pushes it onto the stack. Uses registers r0-r5.
Parameters: Example
>>> sc = shellcraft.arm.mov('r0', 0xdeadbeef) >>> sc += shellcraft.arm.itoa('r0') >>> sc += shellcraft.arm.linux.write(1, 'sp', 32) >>> run_assembly(sc).recvuntil('\x00') '3735928559\x00'
-
pwnlib.shellcraft.arm.
memcpy
(dest, src, n)[source]¶ Copies memory.
Parameters: - dest – Destination address
- src – Source address
- n – Number of bytes
-
pwnlib.shellcraft.arm.
mov
(dst, src)[source]¶ Move src into dest.
Support for automatically avoiding newline and null bytes has to be done.
If src is a string that is not a register, then it will locally set context.arch to ‘arm’ and use
pwnlib.constants.eval()
to evaluate the string. Note that this means that this shellcode can change behavior depending on the value of context.os.Examples
>>> print shellcraft.arm.mov('r0','r1').rstrip() mov r0, r1 >>> print shellcraft.arm.mov('r0', 5).rstrip() mov r0, #5 >>> print shellcraft.arm.mov('r0', 0x34532).rstrip() movw r0, #0x34532 & 0xffff movt r0, #0x34532 >> 16 >>> print shellcraft.arm.mov('r0', 0x101).rstrip() movw r0, #0x101 >>> print shellcraft.arm.mov('r0', 0xff << 14).rstrip() mov r0, #0x3fc000 >>> print shellcraft.arm.mov('r0', 0xff << 15).rstrip() movw r0, #0x7f8000 & 0xffff movt r0, #0x7f8000 >> 16 >>> print shellcraft.arm.mov('r0', 0xf00d0000).rstrip() eor r0, r0 movt r0, #0xf00d0000 >> 16 >>> print shellcraft.arm.mov('r0', 0xffff00ff).rstrip() mvn r0, #(0xffff00ff ^ (-1)) >>> print shellcraft.arm.mov('r0', 0x1fffffff).rstrip() mvn r0, #(0x1fffffff ^ (-1))
Parameters:
-
pwnlib.shellcraft.arm.
push
(word, register='r12')[source]¶ Pushes a 32-bit integer onto the stack. Uses r12 as a temporary register.
r12 is defined as the inter-procedural scartch register ($ip), so this should not interfere with most usage.
Parameters:
-
pwnlib.shellcraft.arm.
pushstr
(string, append_null=True, register='r7')[source]¶ Pushes a string onto the stack.
Parameters: Examples
>>> print shellcraft.arm.pushstr("Hello!").rstrip() /* push 'Hello!\x00A' */ movw r7, #0x4100216f & 0xffff movt r7, #0x4100216f >> 16 push {r7} movw r7, #0x6c6c6548 & 0xffff movt r7, #0x6c6c6548 >> 16 push {r7}
-
pwnlib.shellcraft.arm.
pushstr_array
(reg, array)[source]¶ Pushes an array/envp-style array of pointers onto the stack.
Parameters:
-
pwnlib.shellcraft.arm.
ret
(return_value=None)[source]¶ A single-byte RET instruction.
Parameters: return_value – Value to return Examples
>>> with context.local(arch='arm'): ... print enhex(asm(shellcraft.ret())) ... print enhex(asm(shellcraft.ret(0))) ... print enhex(asm(shellcraft.ret(0xdeadbeef))) 1eff2fe1 000020e01eff2fe1 ef0e0be3ad0e4de31eff2fe1
-
pwnlib.shellcraft.arm.
setregs
(reg_context, stack_allowed=True)[source]¶ Sets multiple registers, taking any register dependencies into account (i.e., given eax=1,ebx=eax, set ebx first).
Parameters: Example
>>> print shellcraft.setregs({'r0':1, 'r2':'r3'}).rstrip() mov r0, #1 mov r2, r3 >>> print shellcraft.setregs({'r0':'r1', 'r1':'r0', 'r2':'r3'}).rstrip() mov r2, r3 eor r0, r0, r1 /* xchg r0, r1 */ eor r1, r0, r1 eor r0, r0, r1
-
pwnlib.shellcraft.arm.
udiv_10
(N)[source]¶ Divides r0 by 10. Result is stored in r0, N and Z flags are updated.
- Code is from generated from here:
- https://raw.githubusercontent.com/rofirrim/raspberry-pi-assembler/master/chapter15/magic.py
- With code:
- python magic.py 10 code_for_unsigned
-
pwnlib.shellcraft.arm.
xor
(key, address, count)[source]¶ XORs data a constant value.
Parameters: Example
>>> sc = shellcraft.read(0, 'sp', 32) >>> sc += shellcraft.xor(0xdeadbeef, 'sp', 32) >>> sc += shellcraft.write(1, 'sp', 32) >>> io = run_assembly(sc) >>> io.send(cyclic(32)) >>> result = io.recvn(32) >>> expected = xor(cyclic(32), p32(0xdeadbeef)) >>> result == expected True
pwnlib.shellcraft.arm.linux
¶
Shellcraft module containing ARM shellcodes for Linux.
-
pwnlib.shellcraft.arm.linux.
cacheflush
()[source]¶ Invokes the cache-flush operation, without using any NULL or newline bytes.
Effectively is just:
mov r0, #0 mov r1, #-1 mov r2, #0 swi 0x9F0002How this works:
... However, SWI generates a software interrupt and to the interrupt handler, 0x9F0002 is actually data and as a result will not be read via the instruction cache, so if we modify the argument to SWI in our self-modifyign code, the argument will be read correctly.
-
pwnlib.shellcraft.arm.linux.
cat
(filename, fd=1)[source]¶ Opens a file and writes its contents to the specified file descriptor.
Example
>>> f = tempfile.mktemp() >>> write(f, 'FLAG\n') >>> run_assembly(shellcraft.arm.linux.cat(f)).recvline() 'FLAG\n'
-
pwnlib.shellcraft.arm.linux.
connect
(host, port, network='ipv4')[source]¶ Connects to the host on the specified port. Network is either ‘ipv4’ or ‘ipv6’. Leaves the connected socket in R6.
-
pwnlib.shellcraft.arm.linux.
dir
(in_fd='r6', size=2048, allocate_stack=True)[source]¶ Reads to the stack from a directory.
Parameters: You can optioanlly shave a few bytes not allocating the stack space.
The size read is left in eax.
-
pwnlib.shellcraft.arm.linux.
echo
(string, sock='1')[source]¶ Writes a string to a file descriptor
Example
>>> run_assembly(shellcraft.echo('hello\n', 1)).recvline() 'hello\n'
-
pwnlib.shellcraft.arm.linux.
egghunter
(egg, start_address = 0, double_check = True)[source]¶ Searches for an egg, which is either a four byte integer or a four byte string. The egg must appear twice in a row if double_check is True. When the egg has been found the egghunter branches to the address following it. If start_address has been specified search will start on the first address of the page that contains that address.
-
pwnlib.shellcraft.arm.linux.
forkexit
()[source]¶ Attempts to fork. If the fork is successful, the parent exits.
-
pwnlib.shellcraft.arm.linux.
killparent
()[source]¶ Kills its parent process until whatever the parent is (probably init) cannot be killed any longer.
-
pwnlib.shellcraft.arm.linux.
open_file
(filepath, flags='O_RDONLY', mode=420)[source]¶ Opens a file. Leaves the file descriptor in r0.
Parameters: - filepath (str) – The file to open.
- flags (int/str) – The flags to call open with.
- mode (int/str) – The attribute to create the flag. Only matters of
flags & O_CREAT
is set.
-
pwnlib.shellcraft.arm.linux.
sh
()[source]¶ Execute a different process.
>>> p = run_assembly(shellcraft.arm.linux.sh()) >>> p.sendline('echo Hello') >>> p.recv() 'Hello\n'
-
pwnlib.shellcraft.arm.linux.
syscall
(syscall=None, arg0=None, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None, arg6=None)[source]¶ - Args: [syscall_number, *args]
- Does a syscall
Any of the arguments can be expressions to be evaluated by
pwnlib.constants.eval()
.Example
>>> print shellcraft.arm.linux.syscall(11, 1, 'sp', 2, 0).rstrip() /* call syscall(11, 1, 'sp', 2, 0) */ mov r0, #1 mov r1, sp mov r2, #2 eor r3, r3 /* 0 (#0) */ mov r7, #0xb svc 0 >>> print shellcraft.arm.linux.syscall('SYS_exit', 0).rstrip() /* call exit(0) */ eor r0, r0 /* 0 (#0) */ mov r7, #SYS_exit /* 1 */ svc 0 >>> print pwnlib.shellcraft.open('/home/pwn/flag').rstrip() /* open(file='/home/pwn/flag', oflag=0, mode=0) */ /* push '/home/pwn/flag\x00A' */ movw r7, #0x41006761 & 0xffff movt r7, #0x41006761 >> 16 push {r7} movw r7, #0x6c662f6e & 0xffff movt r7, #0x6c662f6e >> 16 push {r7} movw r7, #0x77702f65 & 0xffff movt r7, #0x77702f65 >> 16 push {r7} movw r7, #0x6d6f682f & 0xffff movt r7, #0x6d6f682f >> 16 push {r7} mov r0, sp eor r1, r1 /* 0 (#0) */ eor r2, r2 /* 0 (#0) */ /* call open() */ mov r7, #SYS_open /* 5 */ svc 0
pwnlib.shellcraft.common
— Shellcode common to all architecture¶
Shellcraft module containing shellcode common to all platforms.
pwnlib.shellcraft.i386
— Shellcode for Intel 80386¶
pwnlib.shellcraft.i386
¶
Shellcraft module containing generic Intel i386 shellcodes.
-
pwnlib.shellcraft.i386.
crash
()[source]¶ Crash.
Example
>>> run_assembly(shellcraft.crash()).poll(True) -11
-
pwnlib.shellcraft.i386.
epilog
(nargs=0)[source]¶ Function epilogue.
Parameters: nargs (int) – Number of arguments to pop off the stack.
-
pwnlib.shellcraft.i386.
function
(name, template_function, *registers)[source]¶ Converts a shellcraft template into a callable function.
Parameters: >>> shellcode = '' >>> shellcode += shellcraft.function('write', shellcraft.i386.linux.write, ) >>> hello = shellcraft.i386.linux.echo("Hello!", 'eax') >>> hello_fn = shellcraft.i386.function(hello, 'eax').strip() >>> exit = shellcraft.i386.linux.exit('edi') >>> exit_fn = shellcraft.i386.function(exit, 'edi').strip() >>> shellcode = ''' ... push STDOUT_FILENO ... call hello ... push 33 ... call exit ... hello: ... %(hello_fn)s ... exit: ... %(exit_fn)s ... ''' % (locals()) >>> p = run_assembly(shellcode) >>> p.recvall() 'Hello!' >>> p.wait_for_close() >>> p.poll() 33
Notes
Can only be used on a shellcraft template which takes all of its arguments as registers. For example, the pushstr
-
pwnlib.shellcraft.i386.
getpc
(register='ecx')[source]¶ Retrieves the value of EIP, stores it in the desired register.
Parameters: return_value – Value to return
-
pwnlib.shellcraft.i386.
itoa
(v, buffer='esp', allocate_stack=True)[source]¶ Converts an integer into its string representation, and pushes it onto the stack.
Parameters: Example
>>> sc = shellcraft.i386.mov('eax', 0xdeadbeef) >>> sc += shellcraft.i386.itoa('eax') >>> sc += shellcraft.i386.linux.write(1, 'esp', 32) >>> run_assembly(sc).recvuntil('\x00') '3735928559\x00'
-
pwnlib.shellcraft.i386.
memcpy
(dest, src, n)[source]¶ Copies memory.
Parameters: - dest – Destination address
- src – Source address
- n – Number of bytes
-
pwnlib.shellcraft.i386.
mov
(dest, src, stack_allowed=True)[source]¶ Move src into dest without newlines and null bytes.
If the src is a register smaller than the dest, then it will be zero-extended to fit inside the larger register.
If the src is a register larger than the dest, then only some of the bits will be used.
If src is a string that is not a register, then it will locally set context.arch to ‘i386’ and use
pwnlib.constants.eval()
to evaluate the string. Note that this means that this shellcode can change behavior depending on the value of context.os.Parameters: Example
>>> print shellcraft.i386.mov('eax','ebx').rstrip() mov eax, ebx >>> print shellcraft.i386.mov('eax', 0).rstrip() xor eax, eax >>> print shellcraft.i386.mov('ax', 0).rstrip() xor ax, ax >>> print shellcraft.i386.mov('ax', 17).rstrip() xor ax, ax mov al, 0x11 >>> print shellcraft.i386.mov('edi', ord('\n')).rstrip() push 9 /* mov edi, '\n' */ pop edi inc edi >>> print shellcraft.i386.mov('al', 'ax').rstrip() /* moving ax into al, but this is a no-op */ >>> print shellcraft.i386.mov('al','ax').rstrip() /* moving ax into al, but this is a no-op */ >>> print shellcraft.i386.mov('esp', 'esp').rstrip() /* moving esp into esp, but this is a no-op */ >>> print shellcraft.i386.mov('ax', 'bl').rstrip() movzx ax, bl >>> print shellcraft.i386.mov('eax', 1).rstrip() push 1 pop eax >>> print shellcraft.i386.mov('eax', 1, stack_allowed=False).rstrip() xor eax, eax mov al, 1 >>> print shellcraft.i386.mov('eax', 0xdead00ff).rstrip() mov eax, -0xdead00ff neg eax >>> print shellcraft.i386.mov('eax', 0xc0).rstrip() xor eax, eax mov al, 0xc0 >>> print shellcraft.i386.mov('edi', 0xc0).rstrip() mov edi, -0xc0 neg edi >>> print shellcraft.i386.mov('eax', 0xc000).rstrip() xor eax, eax mov ah, 0xc000 >> 8 >>> print shellcraft.i386.mov('eax', 0xffc000).rstrip() mov eax, 0x1010101 xor eax, 0x1010101 ^ 0xffc000 >>> print shellcraft.i386.mov('edi', 0xc000).rstrip() mov edi, (-1) ^ 0xc000 not edi >>> print shellcraft.i386.mov('edi', 0xf500).rstrip() mov edi, 0x1010101 xor edi, 0x1010101 ^ 0xf500 >>> print shellcraft.i386.mov('eax', 0xc0c0).rstrip() xor eax, eax mov ax, 0xc0c0 >>> print shellcraft.i386.mov('eax', 'SYS_execve').rstrip() push SYS_execve /* 0xb */ pop eax >>> with context.local(os='freebsd'): ... print shellcraft.i386.mov('eax', 'SYS_execve').rstrip() push SYS_execve /* 0x3b */ pop eax >>> print shellcraft.i386.mov('eax', 'PROT_READ | PROT_WRITE | PROT_EXEC').rstrip() push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */ pop eax
-
pwnlib.shellcraft.i386.
push
(value)[source]¶ Pushes a value onto the stack without using null bytes or newline characters.
If src is a string, then we try to evaluate with context.arch = ‘i386’ using
pwnlib.constants.eval()
before determining how to push it. Note that this means that this shellcode can change behavior depending on the value of context.os.Parameters: value (int,str) – The value or register to push Example
>>> print pwnlib.shellcraft.i386.push(0).rstrip() /* push 0 */ push 1 dec byte ptr [esp] >>> print pwnlib.shellcraft.i386.push(1).rstrip() /* push 1 */ push 1 >>> print pwnlib.shellcraft.i386.push(256).rstrip() /* push 0x100 */ push 0x1010201 xor dword ptr [esp], 0x1010301 >>> print pwnlib.shellcraft.i386.push('SYS_execve').rstrip() /* push SYS_execve (0xb) */ push 0xb >>> print pwnlib.shellcraft.i386.push('SYS_sendfile').rstrip() /* push SYS_sendfile (0xbb) */ push 0x1010101 xor dword ptr [esp], 0x10101ba >>> with context.local(os = 'freebsd'): ... print pwnlib.shellcraft.i386.push('SYS_execve').rstrip() /* push SYS_execve (0x3b) */ push 0x3b
-
pwnlib.shellcraft.i386.
pushstr
(string, append_null=True)[source]¶ Pushes a string onto the stack without using null bytes or newline characters.
Example
>>> print shellcraft.i386.pushstr('').rstrip() /* push '\x00' */ push 1 dec byte ptr [esp] >>> print shellcraft.i386.pushstr('a').rstrip() /* push 'a\x00' */ push 0x61 >>> print shellcraft.i386.pushstr('aa').rstrip() /* push 'aa\x00' */ push 0x1010101 xor dword ptr [esp], 0x1016060 >>> print shellcraft.i386.pushstr('aaa').rstrip() /* push 'aaa\x00' */ push 0x1010101 xor dword ptr [esp], 0x1606060 >>> print shellcraft.i386.pushstr('aaaa').rstrip() /* push 'aaaa\x00' */ push 1 dec byte ptr [esp] push 0x61616161 >>> print shellcraft.i386.pushstr('aaaaa').rstrip() /* push 'aaaaa\x00' */ push 0x61 push 0x61616161 >>> print shellcraft.i386.pushstr('aaaa', append_null = False).rstrip() /* push 'aaaa' */ push 0x61616161 >>> print shellcraft.i386.pushstr('\xc3').rstrip() /* push '\xc3\x00' */ push 0x1010101 xor dword ptr [esp], 0x10101c2 >>> print shellcraft.i386.pushstr('\xc3', append_null = False).rstrip() /* push '\xc3' */ push -0x3d >>> with context.local(): ... context.arch = 'i386' ... print enhex(asm(shellcraft.pushstr("/bin/sh"))) 68010101018134242e726901682f62696e >>> with context.local(): ... context.arch = 'i386' ... print enhex(asm(shellcraft.pushstr(""))) 6a01fe0c24 >>> with context.local(): ... context.arch = 'i386' ... print enhex(asm(shellcraft.pushstr("\x00", False))) 6a01fe0c24
Parameters:
-
pwnlib.shellcraft.i386.
pushstr_array
(reg, array)[source]¶ Pushes an array/envp-style array of pointers onto the stack.
Parameters:
-
pwnlib.shellcraft.i386.
ret
(return_value=None)[source]¶ A single-byte RET instruction.
Parameters: return_value – Value to return
-
pwnlib.shellcraft.i386.
setregs
(reg_context, stack_allowed=True)[source]¶ Sets multiple registers, taking any register dependencies into account (i.e., given eax=1,ebx=eax, set ebx first).
Parameters: Example
>>> print shellcraft.setregs({'eax':1, 'ebx':'eax'}).rstrip() mov ebx, eax push 1 pop eax >>> print shellcraft.setregs({'eax':'ebx', 'ebx':'eax', 'ecx':'ebx'}).rstrip() mov ecx, ebx xchg eax, ebx
-
pwnlib.shellcraft.i386.
stackarg
(index, register)[source]¶ Loads a stack-based argument into a register.
Assumes that the ‘prolog’ code was used to save EBP.
Parameters:
-
pwnlib.shellcraft.i386.
stackhunter
(cookie = 0x7afceb58)[source]¶ Returns an an egghunter, which searches from esp and upwards for a cookie. However to save bytes, it only looks at a single 4-byte alignment. Use the function stackhunter_helper to generate a suitable cookie prefix for you.
The default cookie has been chosen, because it makes it possible to shave a single byte, but other cookies can be used too.
Example
>>> with context.local(): ... context.arch = 'i386' ... print enhex(asm(shellcraft.stackhunter())) 3d58ebfc7a75faffe4 >>> with context.local(): ... context.arch = 'i386' ... print enhex(asm(shellcraft.stackhunter(0xdeadbeef))) 583defbeadde75f8ffe4
-
pwnlib.shellcraft.i386.
strcpy
(dst, src)[source]¶ Copies a string
Example
>>> sc = 'jmp get_str\n' >>> sc += 'pop_str: pop eax\n' >>> sc += shellcraft.i386.strcpy('esp', 'eax') >>> sc += shellcraft.i386.linux.write(1, 'esp', 32) >>> sc += shellcraft.i386.linux.exit(0) >>> sc += 'get_str: call pop_str\n' >>> sc += '.asciz "Hello, world\\n"' >>> run_assembly(sc).recvline() 'Hello, world\n'
-
pwnlib.shellcraft.i386.
strlen
(string, reg='ecx')[source]¶ Calculate the length of the specified string.
Parameters: Example
>>> sc = 'jmp get_str\n' >>> sc += 'pop_str: pop eax\n' >>> sc += shellcraft.i386.strlen('eax') >>> sc += 'push ecx;' >>> sc += shellcraft.i386.linux.write(1, 'esp', 4) >>> sc += shellcraft.i386.linux.exit(0) >>> sc += 'get_str: call pop_str\n' >>> sc += '.asciz "Hello, world\\n"' >>> run_assembly(sc).unpack() == len('Hello, world\n') True
-
pwnlib.shellcraft.i386.
xor
(key, address, count)[source]¶ XORs data a constant value.
Parameters: - key (int,str) – XOR key either as a 4-byte integer, If a string, length must be a power of two, and not longer than 4 bytes. Alternately, may be a register.
- address (int) – Address of the data (e.g. 0xdead0000, ‘esp’)
- count (int) – Number of bytes to XOR, or a register containing the number of bytes to XOR.
Example
>>> sc = shellcraft.read(0, 'esp', 32) >>> sc += shellcraft.xor(0xdeadbeef, 'esp', 32) >>> sc += shellcraft.write(1, 'esp', 32) >>> io = run_assembly(sc) >>> io.send(cyclic(32)) >>> result = io.recvn(32) >>> expected = xor(cyclic(32), p32(0xdeadbeef)) >>> result == expected True
pwnlib.shellcraft.i386.linux
¶
Shellcraft module containing Intel i386 shellcodes for Linux.
-
pwnlib.shellcraft.i386.linux.
acceptloop_ipv4
(port)[source]¶ Parameters: port (int) – the listening port Waits for a connection. Leaves socket in EBP. ipv4 only
-
pwnlib.shellcraft.i386.linux.
cat
(filename, fd=1)[source]¶ Opens a file and writes its contents to the specified file descriptor.
Example
>>> f = tempfile.mktemp() >>> write(f, 'FLAG') >>> run_assembly(shellcraft.i386.linux.cat(f)).recvall() 'FLAG'
-
pwnlib.shellcraft.i386.linux.
connect
(host, port, network='ipv4')[source]¶ Connects to the host on the specified port. Leaves the connected socket in edx
Parameters: Examples
>>> l = listen(timeout=5) >>> assembly = shellcraft.i386.linux.connect('localhost', l.lport) >>> assembly += shellcraft.i386.pushstr('Hello') >>> assembly += shellcraft.i386.linux.write('edx', 'esp', 5) >>> p = run_assembly(assembly) >>> l.wait_for_connection().recv() 'Hello'
>>> l = listen(fam='ipv6', timeout=5) >>> assembly = shellcraft.i386.linux.connect('ip6-localhost', l.lport, 'ipv6') >>> p = run_assembly(assembly) >>> assert l.wait_for_connection()
-
pwnlib.shellcraft.i386.linux.
connectstager
(host, port, network='ipv4')[source]¶ connect recvsize stager :param host, where to connect to: :param port, which port to connect to: :param network, ipv4 or ipv6? (default: ipv4)
-
pwnlib.shellcraft.i386.linux.
dir
(in_fd='ebp', size=2048, allocate_stack=True)[source]¶ Reads to the stack from a directory.
Parameters: You can optioanlly shave a few bytes not allocating the stack space.
The size read is left in eax.
-
pwnlib.shellcraft.i386.linux.
dupio
(sock='ebp')[source]¶ Args: [sock (imm/reg) = ebp] Duplicates sock to stdin, stdout and stderr
-
pwnlib.shellcraft.i386.linux.
dupsh
(sock='ebp')[source]¶ Args: [sock (imm/reg) = ebp] Duplicates sock to stdin, stdout and stderr and spawns a shell.
-
pwnlib.shellcraft.i386.linux.
echo
(string, sock='1')[source]¶ Writes a string to a file descriptor
Example
>>> run_assembly(shellcraft.echo('hello', 1)).recvall() 'hello'
-
pwnlib.shellcraft.i386.linux.
egghunter
(egg, start_address = 0)[source]¶ Searches memory for the byte sequence ‘egg’.
Return value is the address immediately following the match, stored in RDI.
Parameters:
-
pwnlib.shellcraft.i386.linux.
findpeer
(port=None)[source]¶ Args: port (defaults to any port) Finds a socket, which is connected to the specified port. Leaves socket in ESI.
-
pwnlib.shellcraft.i386.linux.
findpeersh
(port=None)[source]¶ Args: port (defaults to any) Finds an open socket which connects to a specified port, and then opens a dup2 shell on it.
-
pwnlib.shellcraft.i386.linux.
findpeerstager
(port=None)[source]¶ Findpeer recvsize stager :param port, the port given to findpeer: :type port, the port given to findpeer: defaults to any
-
pwnlib.shellcraft.i386.linux.
forkexit
()[source]¶ Attempts to fork. If the fork is successful, the parent exits.
-
pwnlib.shellcraft.i386.linux.
i386_to_amd64
()[source]¶ Returns code to switch from i386 to amd64 mode.
-
pwnlib.shellcraft.i386.linux.
killparent
()[source]¶ Kills its parent process until whatever the parent is (probably init) cannot be killed any longer.
-
pwnlib.shellcraft.i386.linux.
loader
(address)[source]¶ Loads a statically-linked ELF into memory and transfers control.
Parameters: address (int) – Address of the ELF as a register or integer.
-
pwnlib.shellcraft.i386.linux.
loader_append
(data=None)[source]¶ Loads a statically-linked ELF into memory and transfers control.
Similar to loader.asm but loads an appended ELF.
Parameters: data (str) – If a valid filename, the data is loaded from the named file. Otherwise, this is treated as raw ELF data to append. If None
, it is ignored.Example
>>> gcc = process(['gcc','-m32','-xc','-static','-Wl,-Ttext-segment=0x20000000','-']) >>> gcc.write(''' ... int main() { ... printf("Hello, %s!\\n", "i386"); ... } ... ''') >>> gcc.shutdown('send') >>> gcc.poll(True) 0 >>> sc = shellcraft.loader_append('a.out')
The following doctest is commented out because it doesn’t work on Travis for reasons I cannot diagnose. However, it should work just fine :-)
# >>> run_assembly(sc).recvline() == ‘Hello, i386!n’ # True
-
pwnlib.shellcraft.i386.linux.
mprotect_all
(clear_ebx=True, fix_null=False)[source]¶ Calls mprotect(page, 4096, PROT_READ | PROT_WRITE | PROT_EXEC) for every page.
It takes around 0.3 seconds on my box, but your milage may vary.
Parameters:
-
pwnlib.shellcraft.i386.linux.
pidmax
()[source]¶ Retrieves the highest numbered PID on the system, according to the sysctl kernel.pid_max.
-
pwnlib.shellcraft.i386.linux.
readfile
(path, dst='esi')[source]¶ Args: [path, dst (imm/reg) = esi ] Opens the specified file path and sends its content to the specified file descriptor.
-
pwnlib.shellcraft.i386.linux.
readn
(fd, buf, nbytes)[source]¶ Reads exactly nbytes bytes from file descriptor fd into the buffer buf.
Parameters: - fd (int) – fd
- buf (void) – buf
- nbytes (size_t) – nbytes
-
pwnlib.shellcraft.i386.linux.
recvsize
(sock, reg='ecx')[source]¶ Recives 4 bytes size field Useful in conjuncion with findpeer and stager :param sock, the socket to read the payload from.: :param reg, the place to put the size: :type reg, the place to put the size: default ecx
Leaves socket in ebx
-
pwnlib.shellcraft.i386.linux.
setregid
(gid='egid')[source]¶ Args: [gid (imm/reg) = egid] Sets the real and effective group id.
-
pwnlib.shellcraft.i386.linux.
setreuid
(uid='euid')[source]¶ Args: [uid (imm/reg) = euid] Sets the real and effective user id.
-
pwnlib.shellcraft.i386.linux.
sh
()[source]¶ Execute a different process.
>>> p = run_assembly(shellcraft.i386.linux.sh()) >>> p.sendline('echo Hello') >>> p.recv() 'Hello\n'
-
pwnlib.shellcraft.i386.linux.
socketcall
(socketcall, socket, sockaddr, sockaddr_len)[source]¶ Invokes a socket call (e.g. socket, send, recv, shutdown)
-
pwnlib.shellcraft.i386.linux.
stage
(fd=0, length=None)[source]¶ Migrates shellcode to a new buffer.
Parameters: Example
>>> p = run_assembly(shellcraft.stage()) >>> sc = asm(shellcraft.echo("Hello\n", constants.STDOUT_FILENO)) >>> p.pack(len(sc)) >>> p.send(sc) >>> p.recvline() 'Hello\n'
-
pwnlib.shellcraft.i386.linux.
stager
(sock, size, handle_error=False, tiny=False)[source]¶ Recives a fixed sized payload into a mmaped buffer Useful in conjuncion with findpeer. :param sock, the socket to read the payload from.: :param size, the size of the payload:
-
pwnlib.shellcraft.i386.linux.
syscall
(syscall=None, arg0=None, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None)[source]¶ - Args: [syscall_number, *args]
- Does a syscall
Any of the arguments can be expressions to be evaluated by
pwnlib.constants.eval()
.Example
>>> print pwnlib.shellcraft.i386.linux.syscall('SYS_execve', 1, 'esp', 2, 0).rstrip() /* call execve(1, 'esp', 2, 0) */ push SYS_execve /* 0xb */ pop eax push 1 pop ebx mov ecx, esp push 2 pop edx xor esi, esi int 0x80 >>> print pwnlib.shellcraft.i386.linux.syscall('SYS_execve', 2, 1, 0, 20).rstrip() /* call execve(2, 1, 0, 0x14) */ push SYS_execve /* 0xb */ pop eax push 2 pop ebx push 1 pop ecx push 0x14 pop esi cdq /* edx=0 */ int 0x80 >>> print pwnlib.shellcraft.i386.linux.syscall().rstrip() /* call syscall() */ int 0x80 >>> print pwnlib.shellcraft.i386.linux.syscall('eax', 'ebx', 'ecx').rstrip() /* call syscall('eax', 'ebx', 'ecx') */ /* setregs noop */ int 0x80 >>> print pwnlib.shellcraft.i386.linux.syscall('ebp', None, None, 1).rstrip() /* call syscall('ebp', ?, ?, 1) */ mov eax, ebp push 1 pop edx int 0x80 >>> print pwnlib.shellcraft.i386.linux.syscall( ... 'SYS_mmap2', 0, 0x1000, ... 'PROT_READ | PROT_WRITE | PROT_EXEC', ... 'MAP_PRIVATE | MAP_ANONYMOUS', ... -1, 0).rstrip() /* call mmap2(0, 0x1000, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE | MAP_ANONYMOUS', -1, 0) */ xor eax, eax mov al, 0xc0 xor ebp, ebp xor ebx, ebx xor ecx, ecx mov ch, 0x1000 >> 8 push -1 pop edi push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */ pop edx push (MAP_PRIVATE | MAP_ANONYMOUS) /* 0x22 */ pop esi int 0x80 >>> print pwnlib.shellcraft.open('/home/pwn/flag').rstrip() /* open(file='/home/pwn/flag', oflag=0, mode=0) */ /* push '/home/pwn/flag\x00' */ push 0x1010101 xor dword ptr [esp], 0x1016660 push 0x6c662f6e push 0x77702f65 push 0x6d6f682f mov ebx, esp xor ecx, ecx xor edx, edx /* call open() */ push SYS_open /* 5 */ pop eax int 0x80
pwnlib.shellcraft.i386.freebsd
¶
Shellcraft module containing Intel i386 shellcodes for FreeBSD.
-
pwnlib.shellcraft.i386.freebsd.
acceptloop_ipv4
(port)[source]¶ Args: port Waits for a connection. Leaves socket in EBP. ipv4 only
pwnlib.shellcraft.mips
— Shellcode for MIPS¶
pwnlib.shellcraft.mips
¶
Shellcraft module containing generic MIPS shellcodes.
-
pwnlib.shellcraft.mips.
mov
(dst, src)[source]¶ Move src into dst without newlines and null bytes.
Register $t8 and $t9 are not guarenteed to be preserved.
If src is a string that is not a register, then it will locally set context.arch to ‘mips’ and use
pwnlib.constants.eval()
to evaluate the string. Note that this means that this shellcode can change behavior depending on the value of context.os.Parameters: Example
>>> print shellcraft.mips.mov('$t0', 0).rstrip() slti $t0, $zero, 0xFFFF /* $t0 = 0 */ >>> print shellcraft.mips.mov('$t2', 0).rstrip() xor $t2, $t2, $t2 /* $t2 = 0 */ >>> print shellcraft.mips.mov('$t0', 0xcafebabe).rstrip() li $t0, 0xcafebabe >>> print shellcraft.mips.mov('$t2', 0xcafebabe).rstrip() li $t9, 0xcafebabe add $t2, $t9, $zero >>> print shellcraft.mips.mov('$s0', 0xca0000be).rstrip() li $t9, ~0xca0000be not $s0, $t9 >>> print shellcraft.mips.mov('$s0', 0xca0000ff).rstrip() li $t9, 0x1010101 ^ 0xca0000ff li $s0, 0x1010101 xor $s0, $t9, $s0 >>> print shellcraft.mips.mov('$t9', 0xca0000be).rstrip() li $t9, ~0xca0000be not $t9, $t9 >>> print shellcraft.mips.mov('$t2', 0xca0000be).rstrip() li $t9, ~0xca0000be not $t9, $t9 add $t2, $t9, $0 /* mov $t2, $t9 */ >>> print shellcraft.mips.mov('$t2', 0xca0000ff).rstrip() li $t8, 0x1010101 ^ 0xca0000ff li $t9, 0x1010101 xor $t9, $t8, $t9 add $t2, $t9, $0 /* mov $t2, $t9 */ >>> print shellcraft.mips.mov('$a0', '$t2').rstrip() add $a0, $t2, $0 /* mov $a0, $t2 */ >>> print shellcraft.mips.mov('$a0', '$t8').rstrip() sw $t8, -4($sp) /* mov $a0, $t8 */ lw $a0, -4($sp)
-
pwnlib.shellcraft.mips.
pushstr
(string, append_null=True)[source]¶ Pushes a string onto the stack without using null bytes or newline characters.
Example
>>> print shellcraft.mips.pushstr('').rstrip() /* push '\x00' */ sw $zero, -4($sp) addiu $sp, $sp, -4 >>> print shellcraft.mips.pushstr('a').rstrip() /* push 'a\x00' */ li $t9, ~0x61 not $t1, $t9 sw $t1, -4($sp) addiu $sp, $sp, -4 >>> print shellcraft.mips.pushstr('aa').rstrip() /* push 'aa\x00' */ ori $t1, $zero, 24929 sw $t1, -4($sp) addiu $sp, $sp, -4 >>> print shellcraft.mips.pushstr('aaa').rstrip() /* push 'aaa\x00' */ li $t9, ~0x616161 not $t1, $t9 sw $t1, -4($sp) addiu $sp, $sp, -4 >>> print shellcraft.mips.pushstr('aaaa').rstrip() /* push 'aaaa\x00' */ li $t1, 0x61616161 sw $t1, -8($sp) sw $zero, -4($sp) addiu $sp, $sp, -8 >>> print shellcraft.mips.pushstr('aaaaa').rstrip() /* push 'aaaaa\x00' */ li $t1, 0x61616161 sw $t1, -8($sp) li $t9, ~0x61 not $t1, $t9 sw $t1, -4($sp) addiu $sp, $sp, -8 >>> print shellcraft.mips.pushstr('aaaa', append_null = False).rstrip() /* push 'aaaa' */ li $t1, 0x61616161 sw $t1, -4($sp) addiu $sp, $sp, -4 >>> print shellcraft.mips.pushstr('\xc3').rstrip() /* push '\xc3\x00' */ li $t9, ~0xc3 not $t1, $t9 sw $t1, -4($sp) addiu $sp, $sp, -4 >>> print shellcraft.mips.pushstr('\xc3', append_null = False).rstrip() /* push '\xc3' */ li $t9, ~0xc3 not $t1, $t9 sw $t1, -4($sp) addiu $sp, $sp, -4 >>> print enhex(asm(shellcraft.mips.pushstr("/bin/sh"))) 696e093c2f622935f8ffa9af97ff193cd08c393727482003fcffa9aff8ffbd27 >>> print enhex(asm(shellcraft.mips.pushstr(""))) fcffa0affcffbd27 >>> print enhex(asm(shellcraft.mips.pushstr("\x00", False))) fcffa0affcffbd27
Parameters:
-
pwnlib.shellcraft.mips.
pushstr_array
(reg, array)[source]¶ Pushes an array/envp-style array of pointers onto the stack.
Parameters:
-
pwnlib.shellcraft.mips.
setregs
(reg_context, stack_allowed=True)[source]¶ Sets multiple registers, taking any register dependencies into account (i.e., given eax=1,ebx=eax, set ebx first).
Parameters: Example
>>> print shellcraft.setregs({'$t0':1, '$a3':'0'}).rstrip() slti $a3, $zero, 0xFFFF /* $a3 = 0 */ li $t9, ~1 not $t0, $t9 >>> print shellcraft.setregs({'$a0':'$a1', '$a1':'$a0', '$a2':'$a1'}).rstrip() sw $a1, -4($sp) /* mov $a2, $a1 */ lw $a2, -4($sp) xor $a1, $a1, $a0 /* xchg $a1, $a0 */ xor $a0, $a1, $a0 xor $a1, $a1, $a0
pwnlib.shellcraft.mips.linux
¶
Shellcraft module containing MIPS shellcodes for Linux.
-
pwnlib.shellcraft.mips.linux.
bindsh
(port, network)[source]¶ Listens on a TCP port and spawns a shell for the first to connect. Port is the TCP port to listen on, network is either ‘ipv4’ or ‘ipv6’.
-
pwnlib.shellcraft.mips.linux.
cat
(filename, fd=1)[source]¶ Opens a file and writes its contents to the specified file descriptor.
Example
>>> f = tempfile.mktemp() >>> write(f, 'FLAG') >>> asm = shellcraft.mips.linux.cat(f) >>> asm += shellcraft.mips.linux.exit(0) >>> run_assembly(asm).recvall() 'FLAG'
-
pwnlib.shellcraft.mips.linux.
connect
(host, port, network='ipv4')[source]¶ Connects to the host on the specified port. Network is either ‘ipv4’ or ‘ipv6’. Leaves the connected socket in $s0.
-
pwnlib.shellcraft.mips.linux.
dupsh
(sock='$s0')[source]¶ Args: [sock (imm/reg) = s0 ] Duplicates sock to stdin, stdout and stderr and spawns a shell.
-
pwnlib.shellcraft.mips.linux.
findpeer
(port)[source]¶ Finds a connected socket. If port is specified it is checked against the peer port. Resulting socket is left in $s0.
-
pwnlib.shellcraft.mips.linux.
findpeersh
(port)[source]¶ Finds a connected socket. If port is specified it is checked against the peer port. A dup2 shell is spawned on it.
-
pwnlib.shellcraft.mips.linux.
forkexit
()[source]¶ Attempts to fork. If the fork is successful, the parent exits.
-
pwnlib.shellcraft.mips.linux.
killparent
()[source]¶ Kills its parent process until whatever the parent is (probably init) cannot be killed any longer.
-
pwnlib.shellcraft.mips.linux.
listen
(port, network)[source]¶ Listens on a TCP port, accept a client and leave his socket in $s0. Port is the TCP port to listen on, network is either ‘ipv4’ or ‘ipv6’.
-
pwnlib.shellcraft.mips.linux.
readfile
(path, dst='$s0')[source]¶ Args: [path, dst (imm/reg) = $s0 ] Opens the specified file path and sends its content to the specified file descriptor.
-
pwnlib.shellcraft.mips.linux.
stager
(sock, size)[source]¶ Read ‘size’ bytes from ‘sock’ and place them in an executable buffer and jump to it. The socket will be left in $s0.
-
pwnlib.shellcraft.mips.linux.
syscall
(syscall=None, arg0=None, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None)[source]¶ - Args: [syscall_number, *args]
- Does a syscall
Any of the arguments can be expressions to be evaluated by
pwnlib.constants.eval()
.Example
>>> print pwnlib.shellcraft.mips.linux.syscall('SYS_execve', 1, '$sp', 2, 0).rstrip() /* call execve(1, '$sp', 2, 0) */ li $t9, ~1 not $a0, $t9 add $a1, $sp, $0 /* mov $a1, $sp */ li $t9, ~2 not $a2, $t9 slti $a3, $zero, 0xFFFF /* $a3 = 0 */ ori $v0, $zero, SYS_execve syscall 0x40404 >>> print pwnlib.shellcraft.mips.linux.syscall('SYS_execve', 2, 1, 0, 20).rstrip() /* call execve(2, 1, 0, 0x14) */ li $t9, ~2 not $a0, $t9 li $t9, ~1 not $a1, $t9 slti $a2, $zero, 0xFFFF /* $a2 = 0 */ li $t9, ~0x14 not $a3, $t9 ori $v0, $zero, SYS_execve syscall 0x40404 >>> print pwnlib.shellcraft.mips.linux.syscall().rstrip() /* call syscall() */ syscall 0x40404 >>> print pwnlib.shellcraft.mips.linux.syscall('$v0', '$a0', '$a1').rstrip() /* call syscall('$v0', '$a0', '$a1') */ /* setregs noop */ syscall 0x40404 >>> print pwnlib.shellcraft.mips.linux.syscall('$a3', None, None, 1).rstrip() /* call syscall('$a3', ?, ?, 1) */ li $t9, ~1 not $a2, $t9 sw $a3, -4($sp) /* mov $v0, $a3 */ lw $v0, -4($sp) syscall 0x40404 >>> print pwnlib.shellcraft.mips.linux.syscall( ... 'SYS_mmap2', 0, 0x1000, ... 'PROT_READ | PROT_WRITE | PROT_EXEC', ... 'MAP_PRIVATE | MAP_ANONYMOUS', ... -1, 0).rstrip() /* call mmap2(0, 0x1000, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE | MAP_ANONYMOUS', -1, 0) */ slti $a0, $zero, 0xFFFF /* $a0 = 0 */ li $t9, ~0x1000 not $a1, $t9 li $t9, ~(PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */ not $a2, $t9 ori $a3, $zero, (MAP_PRIVATE | MAP_ANONYMOUS) ori $v0, $zero, SYS_mmap2 syscall 0x40404 >>> print pwnlib.shellcraft.open('/home/pwn/flag').rstrip() /* open(file='/home/pwn/flag', oflag=0, mode=0) */ /* push '/home/pwn/flag\x00' */ li $t1, 0x6d6f682f sw $t1, -16($sp) li $t1, 0x77702f65 sw $t1, -12($sp) li $t1, 0x6c662f6e sw $t1, -8($sp) ori $t1, $zero, 26465 sw $t1, -4($sp) addiu $sp, $sp, -16 add $a0, $sp, $0 /* mov $a0, $sp */ slti $a1, $zero, 0xFFFF /* $a1 = 0 */ slti $a2, $zero, 0xFFFF /* $a2 = 0 */ /* call open() */ ori $v0, $zero, SYS_open syscall 0x40404
pwnlib.regsort
— Register sorting¶
Topographical sort
-
pwnlib.regsort.
check_cycle
(reg, assignments)[source]¶ Walk down the assignment list of a register, return the path walked if it is encountered again.
Returns: The list of register involved in the cycle. If there is no cycle, this is an empty list. Example
>>> check_cycle('a', {'a': 1}) [] >>> check_cycle('a', {'a': 'a'}) ['a'] >>> check_cycle('a', {'a': 'b', 'b': 'a'}) ['a', 'b'] >>> check_cycle('a', {'a': 'b', 'b': 'c', 'c': 'b', 'd': 'a'}) [] >>> check_cycle('a', {'a': 'b', 'b': 'c', 'c': 'd', 'd': 'a'}) ['a', 'b', 'c', 'd']
-
pwnlib.regsort.
extract_dependencies
(reg, assignments)[source]¶ Return a list of all registers which directly depend on the specified register.
Example
>>> extract_dependencies('a', {'a': 1}) [] >>> extract_dependencies('a', {'a': 'b', 'b': 1}) [] >>> extract_dependencies('a', {'a': 1, 'b': 'a'}) ['b'] >>> extract_dependencies('a', {'a': 1, 'b': 'a', 'c': 'a'}) ['b', 'c']
-
pwnlib.regsort.
regsort
(in_out, all_regs, tmp=None, xchg=True, randomize=None)[source]¶ Sorts register dependencies.
Given a dictionary of registers to desired register contents, return the optimal order in which to set the registers to those contents.
The implementation assumes that it is possible to move from any register to any other register.
If a dependency cycle is encountered, one of the following will occur:
- If
xchg
isTrue
, it is assumed that dependency cyles can be broken by swapping the contents of two register (a la thexchg
instruction on i386). - If
xchg
is not set, but not all destination registers inin_out
are involved in a cycle, one of the registers outside the cycle will be used as a temporary register, and then overwritten with its final value. - If
xchg
is not set, and all registers are involved in a dependency cycle, the named registertemporary
is used as a temporary register. - If the dependency cycle cannot be resolved as described above, an exception is raised.
Parameters: - in_out (dict) – Dictionary of desired register states. Keys are registers, values are either registers or any other value.
- all_regs (list) – List of all possible registers.
Used to determine which values in
in_out
are registers, versus regular values. - tmp (obj, str) – Named register (or other sentinel value) to use as a temporary
register. If
tmp
is a named register and appears as a source value inin_out
, dependencies are handled appropriately.tmp
cannot be a destination register inin_out
. Ifbool(tmp)==True
, this mode is enabled. - xchg (obj) – Indicates the existence of an instruction which can swap the
contents of two registers without use of a third register.
If
bool(xchg)==False
, this mode is disabled. - random (bool) – Randomize as much as possible about the order or registers.
Returns: A list of tuples of
(src, dest)
.Each register may appear more than once, if a register is used as a temporary register, and later overwritten with its final value.
If
xchg
isTrue
and it is used to break a dependency cycle, thenreg_name
will beNone
andvalue
will be a tuple of the instructions to swap.Example
>>> R = ['a', 'b', 'c', 'd', 'x', 'y', 'z']
If order doesn’t matter for any subsequence, alphabetic order is used.
>>> regsort({'a': 1, 'b': 2}, R) [('mov', 'a', 1), ('mov', 'b', 2)] >>> regsort({'a': 'b', 'b': 'a'}, R) [('xchg', 'a', 'b')] >>> regsort({'a': 'b', 'b': 'a'}, R, tmp='X') [('mov', 'X', 'a'), ('mov', 'a', 'b'), ('mov', 'b', 'X')] >>> regsort({'a': 1, 'b': 'a'}, R) [('mov', 'b', 'a'), ('mov', 'a', 1)] >>> regsort({'a': 'b', 'b': 'a', 'c': 3}, R) [('mov', 'c', 3), ('xchg', 'a', 'b')] >>> regsort({'a': 'b', 'b': 'a', 'c': 'b'}, R) [('mov', 'c', 'b'), ('xchg', 'a', 'b')] >>> regsort({'a':'b', 'b':'a', 'x':'b'}, R, tmp='y', xchg=False) [('mov', 'x', 'b'), ('mov', 'y', 'a'), ('mov', 'a', 'b'), ('mov', 'b', 'y')] >>> regsort({'a':'b', 'b':'a', 'x':'b'}, R, tmp='x', xchg=False) Traceback (most recent call last): ... PwnlibException: Cannot break dependency cycles ... >>> regsort({'a':'b','b':'c','c':'a','x':'1','y':'z','z':'c'}, R) [('mov', 'x', '1'), ('mov', 'y', 'z'), ('mov', 'z', 'c'), ('xchg', 'a', 'b'), ('xchg', 'b', 'c')] >>> regsort({'a':'b','b':'c','c':'a','x':'1','y':'z','z':'c'}, R, tmp='x') [('mov', 'y', 'z'), ('mov', 'z', 'c'), ('mov', 'x', 'a'), ('mov', 'a', 'b'), ('mov', 'b', 'c'), ('mov', 'c', 'x'), ('mov', 'x', '1')] >>> regsort({'a':'b','b':'c','c':'a','x':'1','y':'z','z':'c'}, R, xchg=0) [('mov', 'y', 'z'), ('mov', 'z', 'c'), ('mov', 'x', 'a'), ('mov', 'a', 'b'), ('mov', 'b', 'c'), ('mov', 'c', 'x'), ('mov', 'x', '1')] >>> regsort({'a': 'b', 'b': 'c'}, ['a','b','c'], xchg=0) [('mov', 'a', 'b'), ('mov', 'b', 'c')]
- If
-
pwnlib.regsort.
resolve_order
(reg, deps)[source]¶ Resolve the order of all dependencies starting at a given register.
Example
>>> want = {'a': 1, 'b': 'c', 'c': 'd', 'd': 7, 'x': 'd'} >>> deps = {'a': [], 'b': [], 'c': ['b'], 'd': ['c', 'x'], 'x': []} >>> resolve_order('a', deps) ['a'] >>> resolve_order('b', deps) ['b'] >>> resolve_order('c', deps) ['b', 'c'] >>> resolve_order('d', deps) ['b', 'c', 'x', 'd']
pwnlib.shellcraft.thumb
— Shellcode for Thumb Mode¶
pwnlib.shellcraft.thumb
¶
Shellcraft module containing generic thumb little endian shellcodes.
-
pwnlib.shellcraft.thumb.
crash
()[source]¶ Crash.
Example
>>> run_assembly(shellcraft.crash()).poll(True) < 0 True
-
pwnlib.shellcraft.thumb.
itoa
(v, buffer='sp', allocate_stack=True)[source]¶ Converts an integer into its string representation, and pushes it onto the stack. Uses registers r0-r5.
Parameters: Example
>>> sc = shellcraft.thumb.mov('r0', 0xdeadbeef) >>> sc += shellcraft.thumb.itoa('r0') >>> sc += shellcraft.thumb.linux.write(1, 'sp', 32) >>> run_assembly(sc).recvuntil('\x00') '3735928559\x00'
-
pwnlib.shellcraft.thumb.
memcpy
(dest, src, n)[source]¶ Copies memory.
Parameters: - dest – Destination address
- src – Source address
- n – Number of bytes
-
pwnlib.shellcraft.thumb.
mov
(dst, src)[source]¶ Returns THUMB code for moving the specified source value into the specified destination register.
If src is a string that is not a register, then it will locally set context.arch to ‘thumb’ and use
pwnlib.constants.eval()
to evaluate the string. Note that this means that this shellcode can change behavior depending on the value of context.os.Example
>>> print shellcraft.thumb.mov('r1','r2').rstrip() mov r1, r2 >>> print shellcraft.thumb.mov('r1', 0).rstrip() eor r1, r1 >>> print shellcraft.thumb.mov('r1', 10).rstrip() mov r1, #0xa + 1 sub r1, r1, 1 >>> print shellcraft.thumb.mov('r1', 17).rstrip() mov r1, #0x11 >>> print shellcraft.thumb.mov('r1', 'r1').rstrip() /* moving r1 into r1, but this is a no-op */ >>> print shellcraft.thumb.mov('r1', 512).rstrip() mov r1, #0x200 >>> print shellcraft.thumb.mov('r1', 0x10000001).rstrip() mov r1, #(0x10000001 >> 28) lsl r1, #28 add r1, #(0x10000001 & 0xff) >>> print shellcraft.thumb.mov('r1', 0xdead0000).rstrip() mov r1, #(0xdead0000 >> 25) lsl r1, #(25 - 16) add r1, #((0xdead0000 >> 16) & 0xff) lsl r1, #16 >>> print shellcraft.thumb.mov('r1', 0xdead00ff).rstrip() ldr r1, value_... b value_..._after value_...: .word 0xdead00ff value_..._after: >>> with context.local(os = 'linux'): ... print shellcraft.thumb.mov('r1', 'SYS_execve').rstrip() mov r1, #SYS_execve /* 0xb */ >>> with context.local(os = 'freebsd'): ... print shellcraft.thumb.mov('r1', 'SYS_execve').rstrip() mov r1, #SYS_execve /* 0x3b */ >>> with context.local(os = 'linux'): ... print shellcraft.thumb.mov('r1', 'PROT_READ | PROT_WRITE | PROT_EXEC').rstrip() mov r1, #(PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */
-
pwnlib.shellcraft.thumb.
popad
()[source]¶ Pop all of the registers onto the stack which i386 popad does, in the same order.
-
pwnlib.shellcraft.thumb.
push
(value)[source]¶ Pushes a value onto the stack without using null bytes or newline characters.
If src is a string, then we try to evaluate with context.arch = ‘thumb’ using
pwnlib.constants.eval()
before determining how to push it. Note that this means that this shellcode can change behavior depending on the value of context.os.Parameters: value (int,str) – The value or register to push Example
>>> print pwnlib.shellcraft.thumb.push('r0').rstrip() push {r0} >>> print pwnlib.shellcraft.thumb.push(0).rstrip() /* push 0 */ eor r7, r7 push {r7} >>> print pwnlib.shellcraft.thumb.push(1).rstrip() /* push 1 */ mov r7, #1 push {r7} >>> print pwnlib.shellcraft.thumb.push(256).rstrip() /* push 256 */ mov r7, #0x100 push {r7} >>> print pwnlib.shellcraft.thumb.push('SYS_execve').rstrip() /* push 'SYS_execve' */ mov r7, #0xb push {r7} >>> with context.local(os = 'freebsd'): ... print pwnlib.shellcraft.thumb.push('SYS_execve').rstrip() /* push 'SYS_execve' */ mov r7, #0x3b push {r7}
-
pwnlib.shellcraft.thumb.
pushad
()[source]¶ Push all of the registers onto the stack which i386 pushad does, in the same order.
-
pwnlib.shellcraft.thumb.
pushstr
(string, append_null=True, register='r7')[source]¶ Pushes a string onto the stack without using null bytes or newline characters.
Parameters: Examples:
Note that this doctest has two possibilities for the first result, depending on your version of binutils.
>>> enhex(asm(shellcraft.pushstr('Hello\nWorld!', True))) in [ ... '87ea070780b4dff8047001e0726c642180b4dff8047001e06f0a576f80b4dff8047001e048656c6c80b4', ... '87ea070780b4dff8067000f002b8726c642180b4dff8047000f002b86f0a576f80b4014f00f002b848656c6c80b4'] True >>> print shellcraft.pushstr('abc').rstrip() /* push 'abc\x00' */ ldr r7, value_... b value_..._after value_...: .word 0xff636261 value_..._after: lsl r7, #8 lsr r7, #8 push {r7} >>> print enhex(asm(shellcraft.pushstr('\x00', False))) 87ea070780b4
-
pwnlib.shellcraft.thumb.
pushstr_array
(reg, array)[source]¶ Pushes an array/envp-style array of pointers onto the stack.
Parameters:
-
pwnlib.shellcraft.thumb.
ret
(return_value=None)[source]¶ A single-byte RET instruction.
Parameters: return_value – Value to return
-
pwnlib.shellcraft.thumb.
setregs
(reg_context, stack_allowed=True)[source]¶ Sets multiple registers, taking any register dependencies into account (i.e., given eax=1,ebx=eax, set ebx first).
Parameters: Example
>>> print shellcraft.setregs({'r0':1, 'r2':'r3'}).rstrip() mov r0, #1 mov r2, r3 >>> print shellcraft.setregs({'r0':'r1', 'r1':'r0', 'r2':'r3'}).rstrip() mov r2, r3 eor r0, r0, r1 /* xchg r0, r1 */ eor r1, r0, r1 eor r0, r0, r1
-
pwnlib.shellcraft.thumb.
udiv_10
(N)[source]¶ Divides r0 by 10. Result is stored in r0, N and Z flags are updated.
- Code is from generated from here:
- https://raw.githubusercontent.com/rofirrim/raspberry-pi-assembler/master/chapter15/magic.py
- With code:
- python magic.py 10 code_for_unsigned
pwnlib.shellcraft.thumb.linux
¶
Shellcraft module containing THUMB shellcodes for Linux.
-
pwnlib.shellcraft.thumb.linux.
bindsh
(port, network)[source]¶ Listens on a TCP port and spawns a shell for the first to connect. Port is the TCP port to listen on, network is either ‘ipv4’ or ‘ipv6’.
-
pwnlib.shellcraft.thumb.linux.
cat
(filename, fd=1)[source]¶ Opens a file and writes its contents to the specified file descriptor.
Example
>>> f = tempfile.mktemp() >>> write(f, 'FLAG\n') >>> run_assembly(shellcraft.arm.to_thumb()+shellcraft.thumb.linux.cat(f)).recvline() 'FLAG\n'
-
pwnlib.shellcraft.thumb.linux.
connect
(host, port, network='ipv4')[source]¶ Connects to the host on the specified port. Network is either ‘ipv4’ or ‘ipv6’. Leaves the connected socket in R6.
-
pwnlib.shellcraft.thumb.linux.
connectstager
(host, port, network='ipv4')[source]¶ connect recvsize stager :param host, where to connect to: :param port, which port to connect to: :param network, ipv4 or ipv6? (default: ipv4)
-
pwnlib.shellcraft.thumb.linux.
dup
(sock='r6')[source]¶ Args: [sock (imm/reg) = r6] Duplicates sock to stdin, stdout and stderr
-
pwnlib.shellcraft.thumb.linux.
dupsh
(sock='r6')[source]¶ Args: [sock (imm/reg) = ebp] Duplicates sock to stdin, stdout and stderr and spawns a shell.
-
pwnlib.shellcraft.thumb.linux.
echo
(string, sock='1')[source]¶ Writes a string to a file descriptor
Example
>>> run_assembly(shellcraft.echo('hello\n', 1)).recvline() 'hello\n'
-
pwnlib.shellcraft.thumb.linux.
findpeer
(port)[source]¶ Finds a connected socket. If port is specified it is checked against the peer port. Resulting socket is left in r6.
-
pwnlib.shellcraft.thumb.linux.
findpeersh
(port)[source]¶ Finds a connected socket. If port is specified it is checked against the peer port. A dup2 shell is spawned on it.
-
pwnlib.shellcraft.thumb.linux.
findpeerstager
(port=None)[source]¶ Findpeer recvsize stager :param port, the port given to findpeer: :type port, the port given to findpeer: defaults to any
-
pwnlib.shellcraft.thumb.linux.
forkexit
()[source]¶ Attempts to fork. If the fork is successful, the parent exits.
-
pwnlib.shellcraft.thumb.linux.
killparent
()[source]¶ Kills its parent process until whatever the parent is (probably init) cannot be killed any longer.
-
pwnlib.shellcraft.thumb.linux.
listen
(port, network)[source]¶ Listens on a TCP port, accept a client and leave his socket in r6. Port is the TCP port to listen on, network is either ‘ipv4’ or ‘ipv6’.
-
pwnlib.shellcraft.thumb.linux.
loader
(address)[source]¶ Loads a statically-linked ELF into memory and transfers control.
Parameters: address (int) – Address of the ELF as a register or integer.
-
pwnlib.shellcraft.thumb.linux.
loader_append
(data=None)[source]¶ Loads a statically-linked ELF into memory and transfers control.
Similar to loader.asm but loads an appended ELF.
Parameters: data (str) – If a valid filename, the data is loaded from the named file. Otherwise, this is treated as raw ELF data to append. If None
, it is ignored.Example:
The following doctest is commented out because it doesn’t work on Travis for reasons I cannot diagnose. However, it should work just fine :-)
# >>> gcc = process([‘arm-linux-gnueabihf-gcc’,’-xc’,’-static’,’-Wl,-Ttext-segment=0x20000000’,’-‘]) # >>> gcc.write(‘’’ # ... int main() { # ... printf(“Hello, %s!\n”, “world”); # ... } # ... ‘’‘) # >>> gcc.shutdown(‘send’) # >>> gcc.poll(True) # 0 # >>> sc = shellcraft.loader_append(‘a.out’) # >>> run_assembly(sc).recvline() # ‘Hello, world!n’
-
pwnlib.shellcraft.thumb.linux.
readfile
(path, dst='r6')[source]¶ Args: [path, dst (imm/reg) = r6 ] Opens the specified file path and sends its content to the specified file descriptor. Leaves the destination file descriptor in r6 and the input file descriptor in r5.
-
pwnlib.shellcraft.thumb.linux.
readn
(fd, buf, nbytes)[source]¶ Reads exactly nbytes bytes from file descriptor fd into the buffer buf.
Parameters: - fd (int) – fd
- buf (void) – buf
- nbytes (size_t) – nbytes
-
pwnlib.shellcraft.thumb.linux.
recvsize
(sock, reg='r1')[source]¶ Recives 4 bytes size field Useful in conjuncion with findpeer and stager :param sock, the socket to read the payload from.: :param reg, the place to put the size: :type reg, the place to put the size: default ecx
Leaves socket in ebx
-
pwnlib.shellcraft.thumb.linux.
sh
()[source]¶ Execute a different process.
>>> p = run_assembly(shellcraft.thumb.linux.sh()) >>> p.sendline('echo Hello') >>> p.recv() 'Hello\n'
-
pwnlib.shellcraft.thumb.linux.
stage
(fd=0, length=None)[source]¶ Migrates shellcode to a new buffer.
Parameters: Example
>>> p = run_assembly(shellcraft.stage()) >>> sc = asm(shellcraft.echo("Hello\n", constants.STDOUT_FILENO)) >>> p.pack(len(sc)) >>> p.send(sc) >>> p.recvline() 'Hello\n'
-
pwnlib.shellcraft.thumb.linux.
stager
(sock, size)[source]¶ Read ‘size’ bytes from ‘sock’ and place them in an executable buffer and jump to it. The socket will be left in r6.
-
pwnlib.shellcraft.thumb.linux.
syscall
(syscall=None, arg0=None, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None, arg6=None)[source]¶ - Args: [syscall_number, *args]
- Does a syscall
Any of the arguments can be expressions to be evaluated by
pwnlib.constants.eval()
.Example
>>> print shellcraft.thumb.linux.syscall(11, 1, 'sp', 2, 0).rstrip() /* call syscall(11, 1, 'sp', 2, 0) */ mov r0, #1 mov r1, sp mov r2, #2 eor r3, r3 mov r7, #0xb svc 0x41 >>> print shellcraft.thumb.linux.syscall('SYS_exit', 0).rstrip() /* call exit(0) */ eor r0, r0 mov r7, #SYS_exit /* 1 */ svc 0x41 >>> print pwnlib.shellcraft.open('/home/pwn/flag').rstrip() /* open(file='/home/pwn/flag', oflag=0, mode=0) */ /* push '/home/pwn/flag\x00' */ mov r7, #(0x6761 >> 8) lsl r7, #8 add r7, #(0x6761 & 0xff) push {r7} ldr r7, value_... b value_..._after value_...: .word 0x6c662f6e value_..._after: push {r7} ldr r7, value_... b value_..._after value_...: .word 0x77702f65 value_..._after: push {r7} ldr r7, value_... b value_..._after value_...: .word 0x6d6f682f value_..._after: push {r7} mov r0, sp eor r1, r1 eor r2, r2 /* call open() */ mov r7, #SYS_open /* 5 */ svc 0x41
pwnlib.term
— Terminal handling¶
-
pwnlib.term.
can_init
()[source]¶ This function returns True iff stderr is a TTY and we are not inside a REPL. Iff this function returns True, a call to
init()
will letpwnlib
manage the terminal.
-
pwnlib.term.
init
()[source]¶ Calling this function will take over the terminal (iff
can_init()
returns True) until the current python interpreter is closed.It is on our TODO, to create a function to “give back” the terminal without closing the interpreter.
pwnlib.timeout
— Timeout handling¶
Timeout encapsulation, complete with countdowns and scope managers.
-
class
pwnlib.timeout.
Timeout
(timeout=pwnlib.timeout.Timeout.default)[source]¶ Implements a basic class which has a timeout, and support for scoped timeout countdowns.
Valid timeout values are:
Timeout.default
use the global default value (context.default
)Timeout.forever
orNone
never time out- Any positive float, indicates timeouts in seconds
Example
>>> context.timeout = 30 >>> t = Timeout() >>> t.timeout == 30 True >>> t = Timeout(5) >>> t.timeout == 5 True >>> i = 0 >>> with t.countdown(): ... print (4 <= t.timeout and t.timeout <= 5) ... True >>> with t.countdown(0.5): ... while t.timeout: ... print round(t.timeout,1) ... time.sleep(0.1) 0.5 0.4 0.3 0.2 0.1 >>> print t.timeout 5.0 >>> with t.local(0.5): ... for i in range(5): ... print round(t.timeout,1) ... time.sleep(0.1) 0.5 0.5 0.5 0.5 0.5 >>> print t.timeout 5.0
-
countdown
(timeout=pwnlib.timeout.Timeout.default)[source]¶ Scoped timeout setter. Sets the timeout within the scope, and restores it when leaving the scope.
When accessing
timeout
within the scope, it will be calculated against the time when the scope was entered, in a countdown fashion.If
None
is specified fortimeout
, then the current timeout is used is made. This allowsNone
to be specified as a default argument with less complexity.
-
default
= pwnlib.timeout.Timeout.default[source]¶ Value indicating that the timeout should not be changed
-
local
(timeout)[source]¶ Scoped timeout setter. Sets the timeout within the scope, and restores it when leaving the scope.
pwnlib.tubes
— Talking to the World!¶
The pwnlib is not a big truck! It’s a series of tubes!
This is our library for talking to sockets, processes, ssh connections etc. Our goal is to be able to use the same API for e.g. remote TCP servers, local TTY-programs and programs run over over SSH.
It is organized such that the majority of the functionality is implemented
in pwnlib.tubes.tube
. The remaining classes should only implement
just enough for the class to work and possibly code pertaining only to
that specific kind of tube.
Types of Tubes¶
pwnlib.tubes.process
— Processes¶
-
class
pwnlib.tubes.process.
process
(argv=None, shell=False, executable=None, cwd=None, env=None, stdin=-1, stdout=<pwnlib.tubes.process.PTY object>, stderr=-2, close_fds=True, preexec_fn=<function <lambda>>, raw=True, aslr=None, setuid=None, where='local', display=None, alarm=None, *args, **kwargs)[source]¶ Bases:
pwnlib.tubes.tube.tube
Spawns a new process, and wraps it with a tube for communication.
Parameters: - argv (list) – List of arguments to pass to the spawned process.
- shell (bool) – Set to True to interpret argv as a string to pass to the shell for interpretation instead of as argv.
- executable (str) – Path to the binary to execute. If
None
, usesargv[0]
. Cannot be used withshell
. - cwd (str) – Working directory. Uses the current working directory by default.
- env (dict) – Environment variables. By default, inherits from Python’s environment.
- stdin (int) – File object or file descriptor number to use for
stdin
. By default, a pipe is used. A pty can be used instead by setting this toPTY
. This will cause programs to behave in an interactive manner (e.g..,python
will show a>>>
prompt). If the application reads from/dev/tty
directly, use a pty. - stdout (int) – File object or file descriptor number to use for
stdout
. By default, a pty is used so that any stdout buffering by libc routines is disabled. May also bePIPE
to use a normal pipe. - stderr (int) – File object or file descriptor number to use for
stderr
. By default,STDOUT
is used. May also bePIPE
to use a separate pipe, although thepwnlib.tubes.tube.tube
wrapper will not be able to read this data. - close_fds (bool) – Close all open file descriptors except stdin, stdout, stderr.
By default,
True
is used. - preexec_fn (callable) – Callable to invoke immediately before calling
execve
. - raw (bool) – Set the created pty to raw mode (i.e. disable echo and control
characters).
True
by default. If no pty is created, this has no effect. - aslr (bool) –
If set to
False
, disable ASLR viapersonality
(setarch -R
) andsetrlimit
(ulimit -s unlimited
).This disables ASLR for the target process. However, the
setarch
changes are lost if asetuid
binary is executed.The default value is inherited from
context.aslr
. Seesetuid
below for additional options and information. - setuid (bool) –
Used to control setuid status of the target binary, and the corresponding actions taken.
By default, this value is
None
, so no assumptions are made.If
True
, treat the target binary assetuid
. This modifies the mechanisms used to disable ASLR on the process ifaslr=False
. This is useful for debugging locally, when the exploit is asetuid
binary.If
False
, preventsetuid
bits from taking effect on the target binary. This is only supported on Linux, with kernels v3.5 or greater. - where (str) – Where the process is running, used for logging purposes.
- display (list) – List of arguments to display, instead of the main executable name.
- alarm (int) – Set a SIGALRM alarm timeout on the process.
Examples
>>> p = process('python2') >>> p.sendline("print 'Hello world'") >>> p.sendline("print 'Wow, such data'"); >>> '' == p.recv(timeout=0.01) True >>> p.shutdown('send') >>> p.proc.stdin.closed True >>> p.connected('send') False >>> p.recvline() 'Hello world\n' >>> p.recvuntil(',') 'Wow,' >>> p.recvregex('.*data') ' such data' >>> p.recv() '\n' >>> p.recv() Traceback (most recent call last): ... EOFError
>>> p = process('cat') >>> d = open('/dev/urandom').read(4096) >>> p.recv(timeout=0.1) '' >>> p.write(d) >>> p.recvrepeat(0.1) == d True >>> p.recv(timeout=0.1) '' >>> p.shutdown('send') >>> p.wait_for_close() >>> p.poll() 0
>>> p = process('cat /dev/zero | head -c8', shell=True, stderr=open('/dev/null', 'w+')) >>> p.recv() '\x00\x00\x00\x00\x00\x00\x00\x00'
>>> p = process(['python','-c','import os; print os.read(2,1024)'], ... preexec_fn = lambda: os.dup2(0,2)) >>> p.sendline('hello') >>> p.recvline() 'hello\n'
>>> stack_smashing = ['python','-c','open("/dev/tty","wb").write("stack smashing detected")'] >>> process(stack_smashing).recvall() 'stack smashing detected'
>>> process(stack_smashing, stdout=PIPE).recvall() ''
>>> getpass = ['python','-c','import getpass; print getpass.getpass("XXX")'] >>> p = process(getpass, stdin=PTY) >>> p.recv() 'XXX' >>> p.sendline('hunter2') >>> p.recvall() '\nhunter2\n'
>>> process('echo hello 1>&2', shell=True).recvall() 'hello\n'
>>> process('echo hello 1>&2', shell=True, stderr=PIPE).recvall() ''
>>> a = process(['cat', '/proc/self/maps']).recvall() >>> b = process(['cat', '/proc/self/maps'], aslr=False).recvall() >>> with context.local(aslr=False): ... c = process(['cat', '/proc/self/maps']).recvall() >>> a == b False >>> b == c True
>>> process(['sh','-c','ulimit -s'], aslr=0).recvline() 'unlimited\n'
>>> io = process(['sh','-c','sleep 10; exit 7'], alarm=2) >>> io.poll(block=True) == -signal.SIGALRM True
>>> binary = ELF.from_assembly('nop', arch='mips') >>> p = process(binary.path)
-
communicate
(stdin = None) → str[source]¶ Calls
subprocess.Popen.communicate()
method on the process.
-
corefile
[source]¶ Returns a corefile for the process.
If the process is alive, attempts to create a coredump with GDB.
If the process is dead, attempts to locate the coredump created by the kernel.
-
cwd
[source]¶ Directory that the process is working in.
Example
>>> p = process('sh') >>> p.sendline('cd /tmp; echo AAA') >>> _ = p.recvuntil('AAA') >>> p.cwd == '/tmp' True >>> p.sendline('cd /proc; echo BBB;') >>> _ = p.recvuntil('BBB') >>> p.cwd '/proc'
-
leak
(address, count=1)[source]¶ Leaks memory within the process at the specified address.
Parameters: Example
>>> e = ELF('/bin/sh') >>> p = process(e.path)
In order to make sure there’s not a race condition against the process getting set up...
>>> p.sendline('echo hello') >>> p.recvuntil('hello') 'hello'
Now we can leak some data!
>>> p.leak(e.address, 4) '\x7fELF'
-
libc
[source]¶ Returns an ELF for the libc for the current process. If possible, it is adjusted to the correct address automatically.
-
libs
() → dict[source]¶ Return a dictionary mapping the path of each shared library loaded by the process to the address it is loaded at in the process’ address space.
If
/proc/$PID/maps
for the process cannot be accessed, the output ofldd
alone is used. This may give inaccurate results if ASLR is enabled.
-
poll
(block = False) → int[source]¶ Parameters: block (bool) – Wait for the process to exit Poll the exit code of the process. Will return None, if the process has not yet finished and the exit code otherwise.
-
proc
= None[source] subprocess.Popen object
pwnlib.tubes.serialtube
— Serial Ports¶
pwnlib.tubes.sock
— Sockets¶
-
class
pwnlib.tubes.sock.
sock
[source]¶ Bases:
pwnlib.tubes.tube.tube
Methods available exclusively to sockets.
-
class
pwnlib.tubes.remote.
remote
(host, port, fam='any', typ='tcp', ssl=False, sock=None, *args, **kwargs)[source]¶ Bases:
pwnlib.tubes.sock.sock
Creates a TCP or UDP-connection to a remote host. It supports both IPv4 and IPv6.
The returned object supports all the methods from
pwnlib.tubes.sock
andpwnlib.tubes.tube
.Parameters: - host (str) – The host to connect to.
- port (int) – The port to connect to.
- fam – The string “any”, “ipv4” or “ipv6” or an integer to pass to
socket.getaddrinfo()
. - typ – The string “tcp” or “udp” or an integer to pass to
socket.getaddrinfo()
. - timeout – A positive number, None or the string “default”.
- ssl (bool) – Wrap the socket with SSL
- sock (socket) – Socket to inherit, rather than connecting
Examples
>>> r = remote('google.com', 443, ssl=True) >>> r.send('GET /\r\n\r\n') >>> r.recvn(4) 'HTTP' >>> r = remote('127.0.0.1', 1) Traceback (most recent call last): ... PwnlibException: Could not connect to 127.0.0.1 on port 1 >>> import socket >>> s = socket.socket() >>> s.connect(('google.com', 80)) >>> s.send('GET /' + '\r\n'*2) 9 >>> r = remote.fromsocket(s) >>> r.recvn(4) 'HTTP'
-
class
pwnlib.tubes.listen.
listen
(port=0, bindaddr='0.0.0.0', fam='any', typ='tcp', *args, **kwargs)[source]¶ Bases:
pwnlib.tubes.sock.sock
Creates an TCP or UDP-socket to receive data on. It supports both IPv4 and IPv6.
The returned object supports all the methods from
pwnlib.tubes.sock
andpwnlib.tubes.tube
.Parameters: - port (int) – The port to connect to.
- bindaddr (str) – The address to bind to.
- fam – The string “any”, “ipv4” or “ipv6” or an integer to pass to
socket.getaddrinfo()
. - typ – The string “tcp” or “udp” or an integer to pass to
socket.getaddrinfo()
.
pwnlib.tubes.ssh
— SSH¶
-
class
pwnlib.tubes.ssh.
ssh
(user, host, port=22, password=None, key=None, keyfile=None, proxy_command=None, proxy_sock=None, level=None, cache=True, ssh_agent=False, *a, **kw)[source]¶ -
-
aslr
[source]¶ bool
– Whether ASLR is enabled on the system.Example
>>> s = ssh("esoteric3", "wargame.w3challs.com", 20202, "esoteric3") >>> s.aslr True
-
checksec
()[source]¶ Prints a helpful message about the remote system.
Parameters: banner (bool) – Whether to print the path to the ELF binary.
-
connect_remote
(host, port, timeout = Timeout.default) → ssh_connecter[source]¶ Connects to a host through an SSH connection. This is equivalent to using the
-L
flag onssh
.Returns a
pwnlib.tubes.ssh.ssh_connecter
object.Examples
>>> from pwn import * >>> l = listen() >>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> a = s.connect_remote(s.host, l.lport) >>> b = l.wait_for_connection() >>> a.sendline('Hello') >>> print repr(b.recvline()) 'Hello\n'
-
connected
()[source]¶ Returns True if we are connected.
Example
>>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> s.connected() True >>> s.close() >>> s.connected() False
-
download
(file_or_directory, local=None)[source]¶ Download a file or directory from the remote host.
Parameters:
-
download_data
(remote)[source]¶ Downloads a file from the remote server and returns it as a string.
Parameters: remote (str) – The remote filename to download. Examples
>>> with file('/tmp/bar','w+') as f: ... f.write('Hello, world') >>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass', ... cache=False) >>> s.download_data('/tmp/bar') 'Hello, world' >>> s._sftp = None >>> s._tried_sftp = True >>> s.download_data('/tmp/bar') 'Hello, world'
-
download_dir
(remote=None, local=None)[source]¶ Recursively downloads a directory from the remote server
Parameters: - local – Local directory
- remote – Remote directory
-
download_file
(remote, local=None)[source]¶ Downloads a file from the remote server.
The file is cached in /tmp/pwntools-ssh-cache using a hash of the file, so calling the function twice has little overhead.
Parameters:
-
get
(file_or_directory, local=None)[source]¶ download(file_or_directory, local=None)
Download a file or directory from the remote host.
Parameters:
-
getenv
(variable, **kwargs)[source]¶ Retrieve the address of an environment variable on the remote system.
Note
The exact address will differ based on what other environment variables are set, as well as argv[0]. In order to ensure that the path is exactly the same, it is recommended to invoke the process with
argv=[]
.
-
interactive
(shell=None)[source]¶ Create an interactive session.
This is a simple wrapper for creating a new
pwnlib.tubes.ssh.ssh_channel
object and callingpwnlib.tubes.ssh.ssh_channel.interactive()
on it.
-
libs
(remote, directory=None)[source]¶ Downloads the libraries referred to by a file.
This is done by running ldd on the remote server, parsing the output and downloading the relevant files.
The directory argument specified where to download the files. This defaults to ‘./$HOSTNAME’ where $HOSTNAME is the hostname of the remote server.
-
listen
(port=0, bind_address='', timeout=pwnlib.timeout.Timeout.default)[source]¶ listen_remote(port = 0, bind_address = ‘’, timeout = Timeout.default) -> ssh_connecter
Listens remotely through an SSH connection. This is equivalent to using the
-R
flag onssh
.Returns a
pwnlib.tubes.ssh.ssh_listener
object.Examples
>>> from pwn import * >>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> l = s.listen_remote() >>> a = remote(s.host, l.port) >>> b = l.wait_for_connection() >>> a.sendline('Hello') >>> print repr(b.recvline()) 'Hello\n'
-
listen_remote
(port = 0, bind_address = '', timeout = Timeout.default) → ssh_connecter[source]¶ Listens remotely through an SSH connection. This is equivalent to using the
-R
flag onssh
.Returns a
pwnlib.tubes.ssh.ssh_listener
object.Examples
>>> from pwn import * >>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> l = s.listen_remote() >>> a = remote(s.host, l.port) >>> b = l.wait_for_connection() >>> a.sendline('Hello') >>> print repr(b.recvline()) 'Hello\n'
-
process
(argv=None, executable=None, tty=True, cwd=None, env=None, timeout=pwnlib.timeout.Timeout.default, run=True, stdin=0, stdout=1, stderr=2, preexec_fn=None, preexec_args=[], raw=True, aslr=None, setuid=None, shell=False)[source]¶ Executes a process on the remote server, in the same fashion as pwnlib.tubes.process.process.
To achieve this, a Python script is created to call
os.execve
with the appropriate arguments.As an added bonus, the
ssh_channel
object returned has apid
property for the process pid.Parameters: - argv (list) – List of arguments to pass into the process
- executable (str) – Path to the executable to run.
If
None
,argv[0]
is used. - tty (bool) – Request a tty from the server. This usually fixes buffering problems by causing libc to write data immediately rather than buffering it. However, this disables interpretation of control codes (e.g. Ctrl+C) and breaks .shutdown.
- cwd (str) – Working directory. If
None
, uses the working directory specified oncwd
or set viaset_working_directory()
. - env (dict) – Environment variables to set in the child. If
None
, inherits the default environment. - timeout (int) – Timeout to set on the tube created to interact with the process.
- run (bool) – Set to
True
to run the program (default). IfFalse
, returns the path to an executable Python script on the remote server which, when executed, will do it. - stdin (int, str) – If an integer, replace stdin with the numbered file descriptor.
If a string, a open a file with the specified path and replace
stdin with its file descriptor. May also be one of
sys.stdin
,sys.stdout
,sys.stderr
. IfNone
, the file descriptor is closed. - stdout (int, str) – See
stdin
. - stderr (int, str) – See
stdin
. - preexec_fn (callable) – Function which is executed on the remote side before execve(). This MUST be a self-contained function – it must perform all of its own imports, and cannot refer to variables outside its scope.
- preexec_args (object) – Argument passed to
preexec_fn
. This MUST only consist of native Python objects. - raw (bool) – If
True
, disable TTY control code interpretation. - aslr (bool) – See
pwnlib.tubes.process.process
for more information. - setuid (bool) – See
pwnlib.tubes.process.process
for more information. - shell (bool) – Pass the command-line arguments to the shell.
Returns: A new SSH channel, or a path to a script if
run=False
.Notes
Requires Python on the remote server.
Examples
>>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> sh = s.process('/bin/sh', env={'PS1':''}) >>> sh.sendline('echo Hello; exit') >>> sh.recvall() 'Hello\n' >>> s.process(['/bin/echo', '\xff']).recvall() '\xff\n' >>> s.process(['readlink', '/proc/self/exe']).recvall() '/bin/readlink\n' >>> s.process(['LOLOLOL', '/proc/self/exe'], executable='readlink').recvall() '/bin/readlink\n' >>> s.process(['LOLOLOL\x00', '/proc/self/cmdline'], executable='cat').recvall() 'LOLOLOL\x00/proc/self/cmdline\x00' >>> sh = s.process(executable='/bin/sh') >>> sh.pid in pidof('sh') True >>> s.process(['pwd'], cwd='/tmp').recvall() '/tmp\n' >>> p = s.process(['python','-c','import os; print os.read(2, 1024)'], stderr=0) >>> p.send('hello') >>> p.recv() 'hello\n' >>> s.process(['/bin/echo', 'hello']).recvall() 'hello\n' >>> s.process(['/bin/echo', 'hello'], stdout='/dev/null').recvall() '' >>> s.process(['/usr/bin/env'], env={}).recvall() '' >>> s.process('/usr/bin/env', env={'A':'B'}).recvall() 'A=B\n'
>>> s.process('false', preexec_fn=1234) Traceback (most recent call last): ... PwnlibException: preexec_fn must be a function
>>> s.process('false', preexec_fn=lambda: 1234) Traceback (most recent call last): ... PwnlibException: preexec_fn cannot be a lambda
>>> def uses_globals(): ... foo = bar >>> print s.process('false', preexec_fn=uses_globals).recvall().strip() Traceback (most recent call last): ... NameError: global name 'bar' is not defined
>>> s.process('echo hello', shell=True).recvall() 'hello\n'
-
put
(file_or_directory, remote=None)[source]¶ upload(file_or_directory, remote=None)
Upload a file or directory to the remote host.
Parameters:
-
read
(path)[source]¶ Wrapper around download_data to match
pwnlib.util.misc.read()
-
remote
(host, port, timeout=pwnlib.timeout.Timeout.default)[source]¶ connect_remote(host, port, timeout = Timeout.default) -> ssh_connecter
Connects to a host through an SSH connection. This is equivalent to using the
-L
flag onssh
.Returns a
pwnlib.tubes.ssh.ssh_connecter
object.Examples
>>> from pwn import * >>> l = listen() >>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> a = s.connect_remote(s.host, l.lport) >>> b = l.wait_for_connection() >>> a.sendline('Hello') >>> print repr(b.recvline()) 'Hello\n'
-
run
(process, tty=True, wd=None, env=None, timeout=None, raw=True)[source]¶ Backward compatibility. Use
system()
-
run_to_end
(process, tty = False, timeout = Timeout.default, env = None) → str[source]¶ Run a command on the remote server and return a tuple with (data, exit_status). If tty is True, then the command is run inside a TTY on the remote server.
Examples
>>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> print s.run_to_end('echo Hello; exit 17') ('Hello\n', 17)
-
set_working_directory
(wd=None, symlink=False)[source]¶ Sets the working directory in which future commands will be run (via ssh.run) and to which files will be uploaded/downloaded from if no path is provided
Note
This uses
mktemp -d
under the covers, sets permissions on the directory to0700
. This means that setuid binaries will not be able to access files created in this directory.In order to work around this, we also
chmod +x
the directory.Parameters: - wd (string) – Working directory. Default is to auto-generate a directory based on the result of running ‘mktemp -d’ on the remote machine.
- symlink (bool,str) –
Create symlinks in the new directory.
The default value,
False
, implies that no symlinks should be created.A string value is treated as a path that should be symlinked. It is passed directly to the shell on the remote end for expansion, so wildcards work.
Any other value is treated as a boolean, where
True
indicates that all files in the “old” working directory should be symlinked.
Examples
>>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> cwd = s.set_working_directory() >>> s.ls() '' >>> s.pwd() == cwd True
>>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> homedir = s.pwd() >>> _=s.touch('foo')
>>> _=s.set_working_directory() >>> assert s.ls() == ''
>>> _=s.set_working_directory(homedir) >>> assert 'foo' in s.ls().split()
>>> _=s.set_working_directory(symlink=True) >>> assert 'foo' in s.ls().split() >>> assert homedir != s.pwd()
>>> symlink=os.path.join(homedir,'*') >>> _=s.set_working_directory(symlink=symlink) >>> assert 'foo' in s.ls().split() >>> assert homedir != s.pwd()
-
sftp
[source]¶ Paramiko SFTPClient object which is used for file transfers. Set to
None
to disablesftp
.
-
shell
(shell = None, tty = True, timeout = Timeout.default) → ssh_channel[source]¶ Open a new channel with a shell inside.
Parameters: Returns: Return a
pwnlib.tubes.ssh.ssh_channel
object.Examples
>>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> sh = s.shell('/bin/sh') >>> sh.sendline('echo Hello; exit') >>> print 'Hello' in sh.recvall() True
-
system
(process, tty = True, wd = None, env = None, timeout = Timeout.default, raw = True) → ssh_channel[source]¶ Open a new channel with a specific process inside. If tty is True, then a TTY is requested on the remote server.
If raw is True, terminal control codes are ignored and input is not echoed back.
Return a
pwnlib.tubes.ssh.ssh_channel
object.Examples
>>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> py = s.run('python -i') >>> _ = py.recvuntil('>>> ') >>> py.sendline('print 2+2') >>> py.sendline('exit') >>> print repr(py.recvline()) '4\n'
-
upload
(file_or_directory, remote=None)[source]¶ Upload a file or directory to the remote host.
Parameters:
-
upload_data
(data, remote)[source]¶ Uploads some data into a file on the remote server.
Parameters: Example
>>> s = ssh(host='example.pwnme', ... user='travis', ... password='demopass') >>> s.upload_data('Hello, world', '/tmp/upload_foo') >>> print file('/tmp/upload_foo').read() Hello, world >>> s._sftp = False >>> s._tried_sftp = True >>> s.upload_data('Hello, world', '/tmp/upload_bar') >>> print file('/tmp/upload_bar').read() Hello, world
-
upload_dir
(local, remote=None)[source]¶ Recursively uploads a directory onto the remote server
Parameters: - local – Local directory
- remote – Remote directory
-
upload_file
(filename, remote=None)[source]¶ Uploads a file to the remote server. Returns the remote filename.
Arguments: filename(str): The local filename to download remote(str): The remote filename to save it to. Default is to infer it from the local filename.
-
which
(program) → str[source]¶ Minor modification to just directly invoking
which
on the remote system which adds the current working directory to the end of$PATH
.
-
write
(path, data)[source]¶ Wrapper around upload_data to match
pwnlib.util.misc.write()
-
-
class
pwnlib.tubes.ssh.
ssh_channel
[source]¶ Bases:
pwnlib.tubes.sock.sock
-
interactive
(prompt = pwnlib.term.text.bold_red('$') + ' ')[source]¶ If not in TTY-mode, this does exactly the same as meth:pwnlib.tubes.tube.tube.interactive, otherwise it does mostly the same.
An SSH connection in TTY-mode will typically supply its own prompt, thus the prompt argument is ignored in this case. We also have a few SSH-specific hacks that will ideally be removed once the
pwnlib.term
is more mature.
-
-
class
pwnlib.tubes.ssh.
ssh_connecter
[source]¶ Bases:
pwnlib.tubes.sock.sock
-
class
pwnlib.tubes.ssh.
ssh_listener
[source]¶ Bases:
pwnlib.tubes.sock.sock
pwnlib.tubes.tube
— Common Functionality¶
-
class
pwnlib.tubes.tube.
tube
[source]¶ Container of all the tube functions common to sockets, TTYs and SSH connetions.
-
can_recv
(timeout = 0) → bool[source]¶ Returns True, if there is data available within timeout seconds.
Examples
>>> import time >>> t = tube() >>> t.can_recv_raw = lambda *a: False >>> t.can_recv() False >>> _=t.unrecv('data') >>> t.can_recv() True >>> _=t.recv() >>> t.can_recv() False
-
clean
(timeout = 0.05)[source]¶ Removes all the buffered data from a tube by calling
pwnlib.tubes.tube.tube.recv()
with a low timeout until it fails.If
timeout
is zero, only cached data will be cleared.Note: If timeout is set to zero, the underlying network is not actually polled; only the internal buffer is cleared.
Returns: All data received Examples
>>> t = tube() >>> t.unrecv('clean me up') >>> t.clean(0) 'clean me up' >>> len(t.buffer) 0
-
clean_and_log
(timeout = 0.05)[source]¶ Works exactly as
pwnlib.tubes.tube.tube.clean()
, but logs received data withpwnlib.self.info()
.Returns: All data received Examples
>>> def recv(n, data=['', 'hooray_data']): ... while data: return data.pop() >>> t = tube() >>> t.recv_raw = recv >>> t.connected_raw = lambda d: True >>> t.fileno = lambda: 1234 >>> with context.local(log_level='info'): ... data = t.clean_and_log() [DEBUG] Received 0xb bytes: 'hooray_data' >>> data 'hooray_data' >>> context.clear()
-
connect_input
(other)[source]¶ Connects the input of this tube to the output of another tube object.
Examples
>>> def p(x): print x >>> def recvone(n, data=['data']): ... while data: return data.pop() ... raise EOFError >>> a = tube() >>> b = tube() >>> a.recv_raw = recvone >>> b.send_raw = p >>> a.connected_raw = lambda d: True >>> b.connected_raw = lambda d: True >>> a.shutdown = lambda d: True >>> b.shutdown = lambda d: True >>> import time >>> _=(b.connect_input(a), time.sleep(0.1)) data
-
connect_output
(other)[source]¶ Connects the output of this tube to the input of another tube object.
Examples
>>> def p(x): print x >>> def recvone(n, data=['data']): ... while data: return data.pop() ... raise EOFError >>> a = tube() >>> b = tube() >>> a.recv_raw = recvone >>> b.send_raw = p >>> a.connected_raw = lambda d: True >>> b.connected_raw = lambda d: True >>> a.shutdown = lambda d: True >>> b.shutdown = lambda d: True >>> _=(a.connect_output(b), time.sleep(0.1)) data
-
connected
(direction = 'any') → bool[source]¶ Returns True if the tube is connected in the specified direction.
Parameters: direction (str) – Can be the string ‘any’, ‘in’, ‘read’, ‘recv’, ‘out’, ‘write’, ‘send’. Doctest:
>>> def p(x): print x >>> t = tube() >>> t.connected_raw = p >>> _=map(t.connected, ('any', 'in', 'read', 'recv', 'out', 'write', 'send')) any recv recv recv send send send >>> t.connected('bad_value') Traceback (most recent call last): ... KeyError: "direction must be in ['any', 'in', 'out', 'read', 'recv', 'send', 'write']"
-
connected_raw
(direction)[source]¶ connected(direction = ‘any’) -> bool
Should not be called directly. Returns True iff the tube is connected in the given direction.
-
interactive
(prompt = pwnlib.term.text.bold_red('$') + ' ')[source]¶ Does simultaneous reading and writing to the tube. In principle this just connects the tube to standard in and standard out, but in practice this is much more usable, since we are using
pwnlib.term
to print a floating prompt.Thus it only works in while in
pwnlib.term.term_mode
.
-
newline
= '\n'[source]¶ Delimiter to use for
sendline()
,recvline()
, and related functions.
-
recv
(numb = 4096, timeout = default) → str[source]¶ Receives up to numb bytes of data from the tube, and returns as soon as any quantity of data is available.
If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.Raises: exceptions.EOFError
– The connection is closedReturns: A string containing bytes received from the socket, or ''
if a timeout occurred while waiting.Examples
>>> t = tube() >>> # Fake a data source >>> t.recv_raw = lambda n: 'Hello, world' >>> t.recv() == 'Hello, world' True >>> t.unrecv('Woohoo') >>> t.recv() == 'Woohoo' True >>> with context.local(log_level='debug'): ... _ = t.recv() [...] Received 0xc bytes: 'Hello, world'
-
recvline
(keepends = True) → str[source]¶ Receive a single line from the tube.
A “line” is any sequence of bytes terminated by the byte sequence set in
newline
, which defaults to'\n'
.If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.Parameters: Returns: All bytes received over the tube until the first newline
'\n'
is received. Optionally retains the ending.Examples
>>> t = tube() >>> t.recv_raw = lambda n: 'Foo\nBar\r\nBaz\n' >>> t.recvline() 'Foo\n' >>> t.recvline() 'Bar\r\n' >>> t.recvline(keepends = False) 'Baz' >>> t.newline = '\r\n' >>> t.recvline(keepends = False) 'Foo\nBar'
-
recvline_contains
(items, keepends=False, timeout=pwnlib.timeout.Timeout.default)[source]¶ Receive lines until one line is found which contains at least one of items.
Parameters: Examples
>>> t = tube() >>> t.recv_raw = lambda n: "Hello\nWorld\nXylophone\n" >>> t.recvline_contains('r') 'World' >>> f = lambda n: "cat dog bird\napple pear orange\nbicycle car train\n" >>> t = tube() >>> t.recv_raw = f >>> t.recvline_contains('pear') 'apple pear orange' >>> t = tube() >>> t.recv_raw = f >>> t.recvline_contains(('car', 'train')) 'bicycle car train'
-
recvline_endswith
(delims, keepends = False, timeout = default) → str[source]¶ Keep receiving lines until one is found that starts with one of delims. Returns the last line received.
If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.See
recvline_startswith()
for more details.Examples
>>> t = tube() >>> t.recv_raw = lambda n: 'Foo\nBar\nBaz\nKaboodle\n' >>> t.recvline_endswith('r') 'Bar' >>> t.recvline_endswith(tuple('abcde'), True) 'Kaboodle\n' >>> t.recvline_endswith('oodle') 'Kaboodle'
-
recvline_pred
(pred, keepends = False) → str[source]¶ Receive data until
pred(line)
returns a truthy value. Drop all other data.If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.Parameters: pred (callable) – Function to call. Returns the line for which this function returns True
.Examples
>>> t = tube() >>> t.recv_raw = lambda n: "Foo\nBar\nBaz\n" >>> t.recvline_pred(lambda line: line == "Bar\n") 'Bar' >>> t.recvline_pred(lambda line: line == "Bar\n", keepends=True) 'Bar\n' >>> t.recvline_pred(lambda line: line == 'Nope!', timeout=0.1) ''
-
recvline_regex
(regex, exact=False, keepends=False, timeout=pwnlib.timeout.Timeout.default)[source]¶ recvregex(regex, exact = False, keepends = False, timeout = default) -> str
Wrapper around
recvline_pred()
, which will return when a regex matches a line.By default
re.RegexObject.search()
is used, but if exact is set to True, thenre.RegexObject.match()
will be used instead.If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.
-
recvline_startswith
(delims, keepends = False, timeout = default) → str[source]¶ Keep receiving lines until one is found that starts with one of delims. Returns the last line received.
If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.Parameters: Returns: The first line received which starts with a delimiter in
delims
.Examples
>>> t = tube() >>> t.recv_raw = lambda n: "Hello\nWorld\nXylophone\n" >>> t.recvline_startswith(tuple('WXYZ')) 'World' >>> t.recvline_startswith(tuple('WXYZ'), True) 'Xylophone\n' >>> t.recvline_startswith('Wo') 'World'
-
recvlines
(numlines, keepends = False, timeout = default) → str list[source]¶ Receive up to
numlines
lines.A “line” is any sequence of bytes terminated by the byte sequence set by
newline
, which defaults to'\n'
.If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.Parameters: Raises: exceptions.EOFError
– The connection closed before the request could be satisfiedReturns: A string containing bytes received from the socket, or
''
if a timeout occurred while waiting.Examples
>>> t = tube() >>> t.recv_raw = lambda n: '\n' >>> t.recvlines(3) ['', '', ''] >>> t.recv_raw = lambda n: 'Foo\nBar\nBaz\n' >>> t.recvlines(3) ['Foo', 'Bar', 'Baz'] >>> t.recvlines(3, True) ['Foo\n', 'Bar\n', 'Baz\n']
-
recvn
(numb, timeout = default) → str[source]¶ Receives exactly n bytes.
If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.Raises: exceptions.EOFError
– The connection closed before the request could be satisfiedReturns: A string containing bytes received from the socket, or ''
if a timeout occurred while waiting.Examples
>>> t = tube() >>> data = 'hello world' >>> t.recv_raw = lambda *a: data >>> t.recvn(len(data)) == data True >>> t.recvn(len(data)+1) == data + data[0] True >>> t.recv_raw = lambda *a: None >>> # The remaining data is buffered >>> t.recv() == data[1:] True >>> t.recv_raw = lambda *a: time.sleep(0.01) or 'a' >>> t.recvn(10, timeout=0.05) '' >>> t.recvn(10, timeout=0.06) 'aaaaaa...'
-
recvpred
(pred, timeout = default) → str[source]¶ Receives one byte at a time from the tube, until
pred(bytes)
evaluates to True.If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.Parameters: Raises: exceptions.EOFError
– The connection is closedReturns: A string containing bytes received from the socket, or
''
if a timeout occurred while waiting.
-
recvregex
(regex, exact = False, timeout = default) → str[source]¶ Wrapper around
recvpred()
, which will return when a regex matches the string in the buffer.By default
re.RegexObject.search()
is used, but if exact is set to True, thenre.RegexObject.match()
will be used instead.If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.
-
recvrepeat
()[source]¶ Receives data until a timeout or EOF is reached.
Examples
>>> data = [ ... 'd', ... '', # simulate timeout ... 'c', ... 'b', ... 'a', ... ] >>> def delayrecv(n, data=data): ... return data.pop() >>> t = tube() >>> t.recv_raw = delayrecv >>> t.recvrepeat(0.2) 'abc' >>> t.recv() 'd'
-
recvuntil
(delims, timeout = default) → str[source]¶ Receive data until one of delims is encountered.
If the request is not satisfied before
timeout
seconds pass, all data is buffered and an empty string (''
) is returned.Parameters: Raises: exceptions.EOFError
– The connection closed before the request could be satisfiedReturns: A string containing bytes received from the socket, or
''
if a timeout occurred while waiting.Examples
>>> t = tube() >>> t.recv_raw = lambda n: "Hello World!" >>> t.recvuntil(' ') 'Hello ' >>> _=t.clean(0) >>> # Matches on 'o' in 'Hello' >>> t.recvuntil(tuple(' Wor')) 'Hello' >>> _=t.clean(0) >>> # Matches expressly full string >>> t.recvuntil(' Wor') 'Hello Wor' >>> _=t.clean(0) >>> # Matches on full string, drops match >>> t.recvuntil(' Wor', drop=True) 'Hello'
>>> # Try with regex special characters >>> t = tube() >>> t.recv_raw = lambda n: "Hello|World" >>> t.recvuntil('|', drop=True) 'Hello'
-
send
(data)[source]¶ Sends data.
If log level
DEBUG
is enabled, also prints out the data received.If it is not possible to send anymore because of a closed connection, it raises
exceptions.EOFError
Examples
>>> def p(x): print repr(x) >>> t = tube() >>> t.send_raw = p >>> t.send('hello') 'hello'
-
sendafter
(delim, data, timeout = default) → str[source]¶ A combination of
recvuntil(delim, timeout)
andsend(data)
.
-
sendline
(data)[source]¶ Shorthand for
t.send(data + t.newline)
.Examples
>>> def p(x): print repr(x) >>> t = tube() >>> t.send_raw = p >>> t.sendline('hello') 'hello\n' >>> t.newline = '\r\n' >>> t.sendline('hello') 'hello\r\n'
-
sendlineafter
(delim, data, timeout = default) → str[source]¶ A combination of
recvuntil(delim, timeout)
andsendline(data)
.
-
sendlinethen
(delim, data, timeout = default) → str[source]¶ A combination of
sendline(data)
andrecvuntil(delim, timeout)
.
-
sendthen
(delim, data, timeout = default) → str[source]¶ A combination of
send(data)
andrecvuntil(delim, timeout)
.
-
settimeout
(timeout)[source]¶ Set the timeout for receiving operations. If the string “default” is given, then
context.timeout
will be used. If None is given, then there will be no timeout.Examples
>>> t = tube() >>> t.settimeout_raw = lambda t: None >>> t.settimeout(3) >>> t.timeout == 3 True
-
shutdown
(direction = "send")[source]¶ Closes the tube for futher reading or writing depending on direction.
Parameters: direction (str) – Which direction to close; “in”, “read” or “recv” closes the tube in the ingoing direction, “out”, “write” or “send” closes it in the outgoing direction. Returns: None
Examples
>>> def p(x): print x >>> t = tube() >>> t.shutdown_raw = p >>> _=map(t.shutdown, ('in', 'read', 'recv', 'out', 'write', 'send')) recv recv recv send send send >>> t.shutdown('bad_value') Traceback (most recent call last): ... KeyError: "direction must be in ['in', 'out', 'read', 'recv', 'send', 'write']"
-
shutdown_raw
(direction)[source]¶ Should not be called directly. Closes the tube for further reading or writing.
-
spawn_process
(*args, **kwargs)[source]¶ Spawns a new process having this tube as stdin, stdout and stderr.
Takes the same arguments as
subprocess.Popen
.
-
stream
()[source]¶ Receive data until the tube exits, and print it to stdout.
Similar to
interactive()
, except that no input is sent.Similar to
print tube.recvall()
except that data is printed as it is received, rather than after all data is received.Parameters: line_mode (bool) – Whether to receive line-by-line or raw data. Returns: All data printed.
-
timeout_change
()[source]¶ Informs the raw layer of the tube that the timeout has changed.
Should not be called directly.
Inherited from
Timeout
.
-
pwnlib.ui
— Functions for user interaction¶
-
pwnlib.ui.
more
(text)[source]¶ Shows text like the command line tool
more
.It not in term_mode, just prints the data to the screen.
Parameters: text (str) – The text to show. Returns: None
pwnlib.update
— Updating Pwntools¶
# Pwntools Update
In order to ensure that Pwntools users always have the latest and greatest version, Pwntools automatically checks for updates.
Since this update check takes a moment, it is only performed once every week. It can be permanently disabled via:
$ echo never > ~/.pwntools-cache/update
-
pwnlib.update.
available_on_pypi
(prerelease=False)[source]¶ Return True if an update is available on PyPI.
>>> available_on_pypi() <Version('...')> >>> available_on_pypi(prerelease=False).is_prerelease False
-
pwnlib.update.
cache_file
()[source]¶ Returns the path of the file used to cache update data, and ensures that it exists.
-
pwnlib.update.
perform_check
(prerelease=False)[source]¶ Perform the update check, and report to the user.
Parameters: prerelease (bool) – Whether or not to include pre-release versions. Returns: A list of arguments to the update command. >>> from packaging.version import Version >>> pwnlib.update.current_version = Version("999.0.0") >>> print perform_check() None >>> pwnlib.update.current_version = Version("0.0.0") >>> perform_check() ['pip', 'install', '-U', ...]
>>> def bail(*a): raise Exception() >>> pypi = pwnlib.update.available_on_pypi
>>> perform_check(prerelease=False) ['pip', 'install', '-U', 'pwntools'] >>> perform_check(prerelease=True) ['pip', 'install', '-U', 'pwntools...']
pwnlib.useragents
— A database of useragent strings¶
Database of >22,000 user agent strings
-
pwnlib.useragents.
getall
() → str set[source]¶ Get all the user agents that we know about.
Parameters: None – Returns: A set of user agent strings. Examples
>>> 'libcurl-agent/1.0' in getall() True >>> 'wget' in getall() True
-
pwnlib.useragents.
random
() → str[source]¶ Get a random user agent string.
Parameters: None – Returns: A random user agent string selected from getall()
.>>> import random as randommod >>> randommod.seed(1) >>> random() 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; FunWebProducts; FunWebProducts-MyTotalSearch; iebar)'
pwnlib.util.crc
— Calculating CRC-sums¶
Module for calculating CRC-sums.
Contains all crc implementations know on the interwebz. For most implementations it contains only the core crc algorithm and not e.g. padding schemes.
It is horribly slow, as implements a naive algorithm working direclty on bit polynomials. This class is exposed as BitPolynom.
The current algorithm is super-linear and takes about 4 seconds to calculate
the crc32-sum of 'A'*40000
.
An obvious optimization would be to actually generate some lookup-tables.
-
class
pwnlib.util.crc.
BitPolynom
(n)[source]¶ Class for representing GF(2)[X], i.e. the field of polynomials over GF(2).
In practice the polynomials are represented as numbers such that x**n corresponds to 1 << n. In this representation calculations are easy: Just do everything as normal, but forget about everything the carries.
Addition becomes xor and multiplication becomes carry-less multiplication.
Examples
>>> p1 = BitPolynom("x**3 + x + 1") >>> p1 BitPolynom('x**3 + x + 1') >>> int(p1) 11 >>> p1 == BitPolynom(11) True >>> p2 = BitPolynom("x**2 + x + 1") >>> p1 + p2 BitPolynom('x**3 + x**2') >>> p1 * p2 BitPolynom('x**5 + x**4 + 1') >>> p1 / p2 BitPolynom('x + 1') >>> p1 % p2 BitPolynom('x') >>> d, r = divmod(p1, p2) >>> d * p2 + r == p1 True >>> BitPolynom(-1) Traceback (most recent call last): ... ValueError: Polynomials cannot be negative: -1 >>> BitPolynom('y') Traceback (most recent call last): ... ValueError: Not a valid polynomial: y
-
pwnlib.util.crc.
generic_crc
(data, polynom, width, init, refin, refout, xorout)[source]¶ A generic CRC-sum function.
This is suitable to use with: http://reveng.sourceforge.net/crc-catalogue/all.htm
The “check” value in the document is the CRC-sum of the string “123456789”.
Parameters: - data (str) – The data to calculate the CRC-sum of. This should either be a string or a list of bits.
- polynom (int) – The polynomial to use.
- init (int) – If the CRC-sum was calculated in hardware, then this would b the initial value of the checksum register.
- refin (bool) – Should the input bytes be reflected?
- refout (bool) – Should the checksum be reflected?
- xorout (int) – The value to xor the checksum with before outputting
-
pwnlib.util.crc.
cksum
(data) → int[source]¶ Calculates the same checksum as returned by the UNIX-tool
cksum
.Parameters: data (str) – The data to checksum. Example
>>> print cksum('123456789') 930766865
-
pwnlib.util.crc.
find_crc_function
(data, checksum)[source]¶ Finds all known CRC functions that hashes a piece of data into a specific checksum. It does this by trying all known CRC functions one after the other.
Parameters: data (str) – Data for which the checksum is known. Example
>>> find_crc_function('test', 46197) [<function crc_crc_16_dnp at ...>]
-
pwnlib.util.crc.
arc
(data) → int[source]¶ Calculates the arc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x8005
- width = 16
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.16
Parameters: data (str) – The data to checksum. Example
>>> print arc('123456789') 47933
-
pwnlib.util.crc.
crc_10
(data) → int[source]¶ Calculates the crc_10 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x233
- width = 10
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.10
Parameters: data (str) – The data to checksum. Example
>>> print crc_10('123456789') 409
-
pwnlib.util.crc.
crc_10_cdma2000
(data) → int[source]¶ Calculates the crc_10_cdma2000 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x3d9
- width = 10
- init = 0x3ff
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-10-cdma2000
Parameters: data (str) – The data to checksum. Example
>>> print crc_10_cdma2000('123456789') 563
-
pwnlib.util.crc.
crc_11
(data) → int[source]¶ Calculates the crc_11 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x385
- width = 11
- init = 0x1a
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.11
Parameters: data (str) – The data to checksum. Example
>>> print crc_11('123456789') 1443
-
pwnlib.util.crc.
crc_12_3gpp
(data) → int[source]¶ Calculates the crc_12_3gpp checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x80f
- width = 12
- init = 0x0
- refin = False
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.12
Parameters: data (str) – The data to checksum. Example
>>> print crc_12_3gpp('123456789') 3503
-
pwnlib.util.crc.
crc_12_cdma2000
(data) → int[source]¶ Calculates the crc_12_cdma2000 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0xf13
- width = 12
- init = 0xfff
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-12-cdma2000
Parameters: data (str) – The data to checksum. Example
>>> print crc_12_cdma2000('123456789') 3405
-
pwnlib.util.crc.
crc_12_dect
(data) → int[source]¶ Calculates the crc_12_dect checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x80f
- width = 12
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-12-dect
Parameters: data (str) – The data to checksum. Example
>>> print crc_12_dect('123456789') 3931
-
pwnlib.util.crc.
crc_13_bbc
(data) → int[source]¶ Calculates the crc_13_bbc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1cf5
- width = 13
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.13
Parameters: data (str) – The data to checksum. Example
>>> print crc_13_bbc('123456789') 1274
-
pwnlib.util.crc.
crc_14_darc
(data) → int[source]¶ Calculates the crc_14_darc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x805
- width = 14
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.14
Parameters: data (str) – The data to checksum. Example
>>> print crc_14_darc('123456789') 2093
-
pwnlib.util.crc.
crc_15
(data) → int[source]¶ Calculates the crc_15 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x4599
- width = 15
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.15
Parameters: data (str) – The data to checksum. Example
>>> print crc_15('123456789') 1438
-
pwnlib.util.crc.
crc_15_mpt1327
(data) → int[source]¶ Calculates the crc_15_mpt1327 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x6815
- width = 15
- init = 0x0
- refin = False
- refout = False
- xorout = 0x1
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-15-mpt1327
Parameters: data (str) – The data to checksum. Example
>>> print crc_15_mpt1327('123456789') 9574
-
pwnlib.util.crc.
crc_16_aug_ccitt
(data) → int[source]¶ Calculates the crc_16_aug_ccitt checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0x1d0f
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-aug-ccitt
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_aug_ccitt('123456789') 58828
-
pwnlib.util.crc.
crc_16_buypass
(data) → int[source]¶ Calculates the crc_16_buypass checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x8005
- width = 16
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-buypass
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_buypass('123456789') 65256
-
pwnlib.util.crc.
crc_16_ccitt_false
(data) → int[source]¶ Calculates the crc_16_ccitt_false checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0xffff
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-ccitt-false
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_ccitt_false('123456789') 10673
-
pwnlib.util.crc.
crc_16_cdma2000
(data) → int[source]¶ Calculates the crc_16_cdma2000 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0xc867
- width = 16
- init = 0xffff
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-cdma2000
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_cdma2000('123456789') 19462
-
pwnlib.util.crc.
crc_16_dds_110
(data) → int[source]¶ Calculates the crc_16_dds_110 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x8005
- width = 16
- init = 0x800d
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-dds-110
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_dds_110('123456789') 40655
-
pwnlib.util.crc.
crc_16_dect_r
(data) → int[source]¶ Calculates the crc_16_dect_r checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x589
- width = 16
- init = 0x0
- refin = False
- refout = False
- xorout = 0x1
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-dect-r
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_dect_r('123456789') 126
-
pwnlib.util.crc.
crc_16_dect_x
(data) → int[source]¶ Calculates the crc_16_dect_x checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x589
- width = 16
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-dect-x
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_dect_x('123456789') 127
-
pwnlib.util.crc.
crc_16_dnp
(data) → int[source]¶ Calculates the crc_16_dnp checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x3d65
- width = 16
- init = 0x0
- refin = True
- refout = True
- xorout = 0xffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-dnp
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_dnp('123456789') 60034
-
pwnlib.util.crc.
crc_16_en_13757
(data) → int[source]¶ Calculates the crc_16_en_13757 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x3d65
- width = 16
- init = 0x0
- refin = False
- refout = False
- xorout = 0xffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-en-13757
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_en_13757('123456789') 49847
-
pwnlib.util.crc.
crc_16_genibus
(data) → int[source]¶ Calculates the crc_16_genibus checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0xffff
- refin = False
- refout = False
- xorout = 0xffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-genibus
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_genibus('123456789') 54862
-
pwnlib.util.crc.
crc_16_maxim
(data) → int[source]¶ Calculates the crc_16_maxim checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x8005
- width = 16
- init = 0x0
- refin = True
- refout = True
- xorout = 0xffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-maxim
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_maxim('123456789') 17602
-
pwnlib.util.crc.
crc_16_mcrf4xx
(data) → int[source]¶ Calculates the crc_16_mcrf4xx checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0xffff
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-mcrf4xx
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_mcrf4xx('123456789') 28561
-
pwnlib.util.crc.
crc_16_riello
(data) → int[source]¶ Calculates the crc_16_riello checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0xb2aa
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-riello
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_riello('123456789') 25552
-
pwnlib.util.crc.
crc_16_t10_dif
(data) → int[source]¶ Calculates the crc_16_t10_dif checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x8bb7
- width = 16
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-t10-dif
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_t10_dif('123456789') 53467
-
pwnlib.util.crc.
crc_16_teledisk
(data) → int[source]¶ Calculates the crc_16_teledisk checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0xa097
- width = 16
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-teledisk
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_teledisk('123456789') 4019
-
pwnlib.util.crc.
crc_16_tms37157
(data) → int[source]¶ Calculates the crc_16_tms37157 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0x89ec
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-tms37157
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_tms37157('123456789') 9905
-
pwnlib.util.crc.
crc_16_usb
(data) → int[source]¶ Calculates the crc_16_usb checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x8005
- width = 16
- init = 0xffff
- refin = True
- refout = True
- xorout = 0xffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-16-usb
Parameters: data (str) – The data to checksum. Example
>>> print crc_16_usb('123456789') 46280
-
pwnlib.util.crc.
crc_24
(data) → int[source]¶ Calculates the crc_24 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x864cfb
- width = 24
- init = 0xb704ce
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.24
Parameters: data (str) – The data to checksum. Example
>>> print crc_24('123456789') 2215682
-
pwnlib.util.crc.
crc_24_flexray_a
(data) → int[source]¶ Calculates the crc_24_flexray_a checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x5d6dcb
- width = 24
- init = 0xfedcba
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-24-flexray-a
Parameters: data (str) – The data to checksum. Example
>>> print crc_24_flexray_a('123456789') 7961021
-
pwnlib.util.crc.
crc_24_flexray_b
(data) → int[source]¶ Calculates the crc_24_flexray_b checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x5d6dcb
- width = 24
- init = 0xabcdef
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-24-flexray-b
Parameters: data (str) – The data to checksum. Example
>>> print crc_24_flexray_b('123456789') 2040760
-
pwnlib.util.crc.
crc_31_philips
(data) → int[source]¶ Calculates the crc_31_philips checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x4c11db7
- width = 31
- init = 0x7fffffff
- refin = False
- refout = False
- xorout = 0x7fffffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.31
Parameters: data (str) – The data to checksum. Example
>>> print crc_31_philips('123456789') 216654956
-
pwnlib.util.crc.
crc_32
(data) → int[source]¶ Calculates the crc_32 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x4c11db7
- width = 32
- init = 0xffffffff
- refin = True
- refout = True
- xorout = 0xffffffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.32
Parameters: data (str) – The data to checksum. Example
>>> print crc_32('123456789') 3421780262
-
pwnlib.util.crc.
crc_32_bzip2
(data) → int[source]¶ Calculates the crc_32_bzip2 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x4c11db7
- width = 32
- init = 0xffffffff
- refin = False
- refout = False
- xorout = 0xffffffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32-bzip2
Parameters: data (str) – The data to checksum. Example
>>> print crc_32_bzip2('123456789') 4236843288
-
pwnlib.util.crc.
crc_32_mpeg_2
(data) → int[source]¶ Calculates the crc_32_mpeg_2 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x4c11db7
- width = 32
- init = 0xffffffff
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32-mpeg-2
Parameters: data (str) – The data to checksum. Example
>>> print crc_32_mpeg_2('123456789') 58124007
-
pwnlib.util.crc.
crc_32_posix
(data) → int[source]¶ Calculates the crc_32_posix checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x4c11db7
- width = 32
- init = 0x0
- refin = False
- refout = False
- xorout = 0xffffffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32-posix
Parameters: data (str) – The data to checksum. Example
>>> print crc_32_posix('123456789') 1985902208
-
pwnlib.util.crc.
crc_32c
(data) → int[source]¶ Calculates the crc_32c checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1edc6f41
- width = 32
- init = 0xffffffff
- refin = True
- refout = True
- xorout = 0xffffffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32c
Parameters: data (str) – The data to checksum. Example
>>> print crc_32c('123456789') 3808858755
-
pwnlib.util.crc.
crc_32d
(data) → int[source]¶ Calculates the crc_32d checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0xa833982b
- width = 32
- init = 0xffffffff
- refin = True
- refout = True
- xorout = 0xffffffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32d
Parameters: data (str) – The data to checksum. Example
>>> print crc_32d('123456789') 2268157302
-
pwnlib.util.crc.
crc_32q
(data) → int[source]¶ Calculates the crc_32q checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x814141ab
- width = 32
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-32q
Parameters: data (str) – The data to checksum. Example
>>> print crc_32q('123456789') 806403967
-
pwnlib.util.crc.
crc_3_rohc
(data) → int[source]¶ Calculates the crc_3_rohc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x3
- width = 3
- init = 0x7
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.3
Parameters: data (str) – The data to checksum. Example
>>> print crc_3_rohc('123456789') 6
-
pwnlib.util.crc.
crc_40_gsm
(data) → int[source]¶ Calculates the crc_40_gsm checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x4820009
- width = 40
- init = 0x0
- refin = False
- refout = False
- xorout = 0xffffffffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.40
Parameters: data (str) – The data to checksum. Example
>>> print crc_40_gsm('123456789') 910907393606
-
pwnlib.util.crc.
crc_4_itu
(data) → int[source]¶ Calculates the crc_4_itu checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x3
- width = 4
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.4
Parameters: data (str) – The data to checksum. Example
>>> print crc_4_itu('123456789') 7
-
pwnlib.util.crc.
crc_5_epc
(data) → int[source]¶ Calculates the crc_5_epc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x9
- width = 5
- init = 0x9
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.5
Parameters: data (str) – The data to checksum. Example
>>> print crc_5_epc('123456789') 0
-
pwnlib.util.crc.
crc_5_itu
(data) → int[source]¶ Calculates the crc_5_itu checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x15
- width = 5
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-5-itu
Parameters: data (str) – The data to checksum. Example
>>> print crc_5_itu('123456789') 7
-
pwnlib.util.crc.
crc_5_usb
(data) → int[source]¶ Calculates the crc_5_usb checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x5
- width = 5
- init = 0x1f
- refin = True
- refout = True
- xorout = 0x1f
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-5-usb
Parameters: data (str) – The data to checksum. Example
>>> print crc_5_usb('123456789') 25
-
pwnlib.util.crc.
crc_64
(data) → int[source]¶ Calculates the crc_64 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x42f0e1eba9ea3693
- width = 64
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.64
Parameters: data (str) – The data to checksum. Example
>>> print crc_64('123456789') 7800480153909949255
-
pwnlib.util.crc.
crc_64_we
(data) → int[source]¶ Calculates the crc_64_we checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x42f0e1eba9ea3693
- width = 64
- init = 0xffffffffffffffff
- refin = False
- refout = False
- xorout = 0xffffffffffffffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-64-we
Parameters: data (str) – The data to checksum. Example
>>> print crc_64_we('123456789') 7128171145767219210
-
pwnlib.util.crc.
crc_64_xz
(data) → int[source]¶ Calculates the crc_64_xz checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x42f0e1eba9ea3693
- width = 64
- init = 0xffffffffffffffff
- refin = True
- refout = True
- xorout = 0xffffffffffffffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-64-xz
Parameters: data (str) – The data to checksum. Example
>>> print crc_64_xz('123456789') 11051210869376104954
-
pwnlib.util.crc.
crc_6_cdma2000_a
(data) → int[source]¶ Calculates the crc_6_cdma2000_a checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x27
- width = 6
- init = 0x3f
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.6
Parameters: data (str) – The data to checksum. Example
>>> print crc_6_cdma2000_a('123456789') 13
-
pwnlib.util.crc.
crc_6_cdma2000_b
(data) → int[source]¶ Calculates the crc_6_cdma2000_b checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x7
- width = 6
- init = 0x3f
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-6-cdma2000-b
Parameters: data (str) – The data to checksum. Example
>>> print crc_6_cdma2000_b('123456789') 59
-
pwnlib.util.crc.
crc_6_darc
(data) → int[source]¶ Calculates the crc_6_darc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x19
- width = 6
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-6-darc
Parameters: data (str) – The data to checksum. Example
>>> print crc_6_darc('123456789') 38
-
pwnlib.util.crc.
crc_6_itu
(data) → int[source]¶ Calculates the crc_6_itu checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x3
- width = 6
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-6-itu
Parameters: data (str) – The data to checksum. Example
>>> print crc_6_itu('123456789') 6
-
pwnlib.util.crc.
crc_7
(data) → int[source]¶ Calculates the crc_7 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x9
- width = 7
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.7
Parameters: data (str) – The data to checksum. Example
>>> print crc_7('123456789') 117
-
pwnlib.util.crc.
crc_7_rohc
(data) → int[source]¶ Calculates the crc_7_rohc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x4f
- width = 7
- init = 0x7f
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-7-rohc
Parameters: data (str) – The data to checksum. Example
>>> print crc_7_rohc('123456789') 83
-
pwnlib.util.crc.
crc_8
(data) → int[source]¶ Calculates the crc_8 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x7
- width = 8
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.8
Parameters: data (str) – The data to checksum. Example
>>> print crc_8('123456789') 244
-
pwnlib.util.crc.
crc_82_darc
(data) → int[source]¶ Calculates the crc_82_darc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x308c0111011401440411
- width = 82
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat-bits.82
Parameters: data (str) – The data to checksum. Example
>>> print crc_82_darc('123456789') 749237524598872659187218
-
pwnlib.util.crc.
crc_8_cdma2000
(data) → int[source]¶ Calculates the crc_8_cdma2000 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x9b
- width = 8
- init = 0xff
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-8-cdma2000
Parameters: data (str) – The data to checksum. Example
>>> print crc_8_cdma2000('123456789') 218
-
pwnlib.util.crc.
crc_8_darc
(data) → int[source]¶ Calculates the crc_8_darc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x39
- width = 8
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-8-darc
Parameters: data (str) – The data to checksum. Example
>>> print crc_8_darc('123456789') 21
-
pwnlib.util.crc.
crc_8_dvb_s2
(data) → int[source]¶ Calculates the crc_8_dvb_s2 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0xd5
- width = 8
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-8-dvb-s2
Parameters: data (str) – The data to checksum. Example
>>> print crc_8_dvb_s2('123456789') 188
-
pwnlib.util.crc.
crc_8_ebu
(data) → int[source]¶ Calculates the crc_8_ebu checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1d
- width = 8
- init = 0xff
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-8-ebu
Parameters: data (str) – The data to checksum. Example
>>> print crc_8_ebu('123456789') 151
-
pwnlib.util.crc.
crc_8_i_code
(data) → int[source]¶ Calculates the crc_8_i_code checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1d
- width = 8
- init = 0xfd
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-8-i-code
Parameters: data (str) – The data to checksum. Example
>>> print crc_8_i_code('123456789') 126
-
pwnlib.util.crc.
crc_8_itu
(data) → int[source]¶ Calculates the crc_8_itu checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x7
- width = 8
- init = 0x0
- refin = False
- refout = False
- xorout = 0x55
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-8-itu
Parameters: data (str) – The data to checksum. Example
>>> print crc_8_itu('123456789') 161
-
pwnlib.util.crc.
crc_8_maxim
(data) → int[source]¶ Calculates the crc_8_maxim checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x31
- width = 8
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-8-maxim
Parameters: data (str) – The data to checksum. Example
>>> print crc_8_maxim('123456789') 161
-
pwnlib.util.crc.
crc_8_rohc
(data) → int[source]¶ Calculates the crc_8_rohc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x7
- width = 8
- init = 0xff
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-8-rohc
Parameters: data (str) – The data to checksum. Example
>>> print crc_8_rohc('123456789') 208
-
pwnlib.util.crc.
crc_8_wcdma
(data) → int[source]¶ Calculates the crc_8_wcdma checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x9b
- width = 8
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-8-wdcma
Parameters: data (str) – The data to checksum. Example
>>> print crc_8_wcdma('123456789') 37
-
pwnlib.util.crc.
crc_a
(data) → int[source]¶ Calculates the crc_a checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0xc6c6
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.crc-a
Parameters: data (str) – The data to checksum. Example
>>> print crc_a('123456789') 48901
-
pwnlib.util.crc.
jamcrc
(data) → int[source]¶ Calculates the jamcrc checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x4c11db7
- width = 32
- init = 0xffffffff
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.jamcrc
Parameters: data (str) – The data to checksum. Example
>>> print jamcrc('123456789') 873187033
-
pwnlib.util.crc.
kermit
(data) → int[source]¶ Calculates the kermit checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0x0
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.kermit
Parameters: data (str) – The data to checksum. Example
>>> print kermit('123456789') 8585
-
pwnlib.util.crc.
modbus
(data) → int[source]¶ Calculates the modbus checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x8005
- width = 16
- init = 0xffff
- refin = True
- refout = True
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.modbus
Parameters: data (str) – The data to checksum. Example
>>> print modbus('123456789') 19255
-
pwnlib.util.crc.
x_25
(data) → int[source]¶ Calculates the x_25 checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0xffff
- refin = True
- refout = True
- xorout = 0xffff
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.x-25
Parameters: data (str) – The data to checksum. Example
>>> print x_25('123456789') 36974
-
pwnlib.util.crc.
xfer
(data) → int[source]¶ Calculates the xfer checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0xaf
- width = 32
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.xfer
Parameters: data (str) – The data to checksum. Example
>>> print xfer('123456789') 3171672888
-
pwnlib.util.crc.
xmodem
(data) → int[source]¶ Calculates the xmodem checksum.
This is simply the
generic_crc()
with these frozen arguments:- polynom = 0x1021
- width = 16
- init = 0x0
- refin = False
- refout = False
- xorout = 0x0
See also: http://reveng.sourceforge.net/crc-catalogue/all.htm#crc.cat.xmodem
Parameters: data (str) – The data to checksum. Example
>>> print xmodem('123456789') 12739
pwnlib.util.cyclic
— Generation of unique sequences¶
-
pwnlib.util.cyclic.
cyclic
(length = None, alphabet = string.ascii_lowercase, n = 4) → list/str[source]¶ A simple wrapper over
de_bruijn()
. This function returns at most length elements.If the given alphabet is a string, a string is returned from this function. Otherwise a list is returned.
Parameters: - length – The desired length of the list or None if the entire sequence is desired.
- alphabet – List or string to generate the sequence over.
- n (int) – The length of subsequences that should be unique.
Example
>>> cyclic(alphabet = "ABC", n = 3) 'AAABAACABBABCACBACCBBBCBCCC' >>> cyclic(20) 'aaaabaaacaaadaaaeaaa' >>> alphabet, n = range(30), 3 >>> len(alphabet)**n, len(cyclic(alphabet = alphabet, n = n)) (27000, 27000)
-
pwnlib.util.cyclic.
cyclic_find
(subseq, alphabet = string.ascii_lowercase, n = None) → int[source]¶ Calculates the position of a substring into a De Bruijn sequence.
Parameters: - subseq – The subsequence to look for. This can be a string, a list or an integer. If an integer is provided it will be packed as a little endian integer.
- alphabet – List or string to generate the sequence over.
- n (int) – The length of subsequences that should be unique.
Examples
>>> cyclic_find(cyclic(1000)[514:518]) 514 >>> cyclic_find(0x61616162) 4
-
pwnlib.util.cyclic.
cyclic_metasploit
(length = None, sets = [ string.ascii_uppercase, string.ascii_lowercase, string.digits ]) → str[source]¶ A simple wrapper over
metasploit_pattern()
. This function returns a string of length length.Parameters: - length – The desired length of the string or None if the entire sequence is desired.
- sets – List of strings to generate the sequence over.
Example
>>> cyclic_metasploit(32) 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab' >>> cyclic_metasploit(sets = ["AB","ab","12"]) 'Aa1Aa2Ab1Ab2Ba1Ba2Bb1Bb2' >>> cyclic_metasploit()[1337:1341] '5Bs6' >>> len(cyclic_metasploit()) 20280
-
pwnlib.util.cyclic.
cyclic_metasploit_find
(subseq, sets = [ string.ascii_uppercase, string.ascii_lowercase, string.digits ]) → int[source]¶ Calculates the position of a substring into a Metasploit Pattern sequence.
Parameters: - subseq – The subsequence to look for. This can be a string or an integer. If an integer is provided it will be packed as a little endian integer.
- sets – List of strings to generate the sequence over.
Examples
>>> cyclic_metasploit_find(cyclic_metasploit(1000)[514:518]) 514 >>> cyclic_metasploit_find(0x61413161) 4
-
pwnlib.util.cyclic.
de_bruijn
(alphabet = string.ascii_lowercase, n = 4) → generator[source]¶ Generator for a sequence of unique substrings of length n. This is implemented using a De Bruijn Sequence over the given alphabet.
The returned generator will yield up to
len(alphabet)**n
elements.Parameters: - alphabet – List or string to generate the sequence over.
- n (int) – The length of subsequences that should be unique.
-
pwnlib.util.cyclic.
metasploit_pattern
(sets = [ string.ascii_uppercase, string.ascii_lowercase, string.digits ]) → generator[source]¶ Generator for a sequence of characters as per Metasploit Framework’s Rex::Text.pattern_create (aka pattern_create.rb).
The returned generator will yield up to
len(sets) * reduce(lambda x,y: x*y, map(len, sets))
elements.Parameters: sets – List of strings to generate the sequence over.
pwnlib.util.fiddling
— Utilities bit fiddling¶
-
pwnlib.util.fiddling.
b64d
(s) → str[source]¶ Base64 decodes a string
Example
>>> b64d('dGVzdA==') 'test'
-
pwnlib.util.fiddling.
b64e
(s) → str[source]¶ Base64 encodes a string
Example
>>> b64e("test") 'dGVzdA=='
-
pwnlib.util.fiddling.
bits
(s, endian = 'big', zero = 0, one = 1) → list[source]¶ Converts the argument a list of bits.
Parameters: - s – A string or number to be converted into bits.
- endian (str) – The binary endian, default ‘big’.
- zero – The representing a 0-bit.
- one – The representing a 1-bit.
Returns: A list consisting of the values specified in zero and one.
Examples
>>> bits(511, zero = "+", one = "-") ['+', '+', '+', '+', '+', '+', '+', '-', '-', '-', '-', '-', '-', '-', '-', '-'] >>> sum(bits("test")) 17 >>> bits(0) [0, 0, 0, 0, 0, 0, 0, 0]
-
pwnlib.util.fiddling.
bits_str
(s, endian = 'big', zero = '0', one = '1') → str[source]¶ A wrapper around
bits()
, which converts the output into a string.Examples
>>> bits_str(511) '0000000111111111' >>> bits_str("bits_str", endian = "little") '0100011010010110001011101100111011111010110011100010111001001110'
-
pwnlib.util.fiddling.
bitswap
(s) → str[source]¶ Reverses the bits in every byte of a given string.
Example
>>> bitswap("1234") '\x8cL\xcc,'
-
pwnlib.util.fiddling.
bitswap_int
(n) → int[source]¶ Reverses the bits of a numbers and returns the result as a new number.
Parameters: Examples
>>> hex(bitswap_int(0x1234, 8)) '0x2c' >>> hex(bitswap_int(0x1234, 16)) '0x2c48' >>> hex(bitswap_int(0x1234, 24)) '0x2c4800' >>> hex(bitswap_int(0x1234, 25)) '0x589000'
-
pwnlib.util.fiddling.
enhex
(x) → str[source]¶ Hex-encodes a string.
Example
>>> enhex("test") '74657374'
-
pwnlib.util.fiddling.
hexdump
(s, width=16, skip=True, hexii=False, begin=0, style=None, highlight=None, cyclic=False)[source]¶ - hexdump(s, width = 16, skip = True, hexii = False, begin = 0,
- style = None, highlight = None, cyclic = False) -> str generator
Return a hexdump-dump of a string.
Parameters: - s (str) – The data to hexdump.
- width (int) – The number of characters per line
- skip (bool) – Set to True, if repeated lines should be replaced by a “*”
- hexii (bool) – Set to True, if a hexii-dump should be returned instead of a hexdump.
- begin (int) – Offset of the first byte to print in the left column
- style (dict) – Color scheme to use.
- highlight (iterable) – Byte values to highlight.
- cyclic (bool) – Attempt to skip consecutive, unmodified cyclic lines
Returns: A hexdump-dump in the form of a string.
Examples
>>> print hexdump("abc") 00000000 61 62 63 │abc│ 00000003
>>> print hexdump('A'*32) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│ * 00000020
>>> print hexdump('A'*32, width=8) 00000000 41 41 41 41 41 41 41 41 │AAAA│AAAA│ * 00000020
>>> print hexdump(cyclic(32), width=8, begin=0xdead0000, hexii=True) dead0000 .a .a .a .a .b .a .a .a │ dead0008 .c .a .a .a .d .a .a .a │ dead0010 .e .a .a .a .f .a .a .a │ dead0018 .g .a .a .a .h .a .a .a │ dead0020
>>> print hexdump(list(map(chr, range(256)))) 00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f │····│····│····│····│ 00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f │····│····│····│····│ 00000020 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f │ !"#│$%&'│()*+│,-./│ 00000030 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f │0123│4567│89:;│<=>?│ 00000040 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f │@ABC│DEFG│HIJK│LMNO│ 00000050 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f │PQRS│TUVW│XYZ[│\]^_│ 00000060 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f │`abc│defg│hijk│lmno│ 00000070 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f │pqrs│tuvw│xyz{│|}~·│ 00000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f │····│····│····│····│ 00000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f │····│····│····│····│ 000000a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af │····│····│····│····│ 000000b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf │····│····│····│····│ 000000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf │····│····│····│····│ 000000d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df │····│····│····│····│ 000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef │····│····│····│····│ 000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff │····│····│····│····│ 00000100
>>> print hexdump(list(map(chr, range(256))), hexii=True) 00000000 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f │ 00000010 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f │ 00000020 20 .! ." .# .$ .% .& .' .( .) .* .+ ., .- .. ./ │ 00000030 .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .: .; .< .= .> .? │ 00000040 .@ .A .B .C .D .E .F .G .H .I .J .K .L .M .N .O │ 00000050 .P .Q .R .S .T .U .V .W .X .Y .Z .[ .\ .] .^ ._ │ 00000060 .` .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o │ 00000070 .p .q .r .s .t .u .v .w .x .y .z .{ .| .} .~ 7f │ 00000080 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f │ 00000090 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f │ 000000a0 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af │ 000000b0 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf │ 000000c0 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf │ 000000d0 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df │ 000000e0 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef │ 000000f0 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ## │ 00000100
>>> print hexdump('X' * 64) 00000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ * 00000040
>>> print hexdump('X' * 64, skip=False) 00000000 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ 00000010 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ 00000020 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ 00000030 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ 00000040
>>> print hexdump(fit({0x10: 'X'*0x20, 0x50-1: '\xff'*20}, length=0xc0) + '\x00'*32) 00000000 61 61 61 61 62 61 61 61 63 61 61 61 64 61 61 61 │aaaa│baaa│caaa│daaa│ 00000010 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ * 00000030 6d 61 61 61 6e 61 61 61 6f 61 61 61 70 61 61 61 │maaa│naaa│oaaa│paaa│ 00000040 71 61 61 61 72 61 61 61 73 61 61 61 74 61 61 ff │qaaa│raaa│saaa│taa·│ 00000050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff │····│····│····│····│ 00000060 ff ff ff 61 7a 61 61 62 62 61 61 62 63 61 61 62 │···a│zaab│baab│caab│ 00000070 64 61 61 62 65 61 61 62 66 61 61 62 67 61 61 62 │daab│eaab│faab│gaab│ 00000080 68 61 61 62 69 61 61 62 6a 61 61 62 6b 61 61 62 │haab│iaab│jaab│kaab│ 00000090 6c 61 61 62 6d 61 61 62 6e 61 61 62 6f 61 61 62 │laab│maab│naab│oaab│ 000000a0 70 61 61 62 71 61 61 62 72 61 61 62 73 61 61 62 │paab│qaab│raab│saab│ 000000b0 74 61 61 62 75 61 61 62 76 61 61 62 77 61 61 62 │taab│uaab│vaab│waab│ 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│ * 000000e0
>>> print hexdump(fit({0x10: 'X'*0x20, 0x50-1: '\xff'*20}, length=0xc0) + '\x00'*32, cyclic=1) 00000000 61 61 61 61 62 61 61 61 63 61 61 61 64 61 61 61 │aaaa│baaa│caaa│daaa│ 00000010 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 │XXXX│XXXX│XXXX│XXXX│ * 00000030 6d 61 61 61 6e 61 61 61 6f 61 61 61 70 61 61 61 │maaa│naaa│oaaa│paaa│ 00000040 71 61 61 61 72 61 61 61 73 61 61 61 74 61 61 ff │qaaa│raaa│saaa│taa·│ 00000050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff │····│····│····│····│ 00000060 ff ff ff 61 7a 61 61 62 62 61 61 62 63 61 61 62 │···a│zaab│baab│caab│ 00000070 64 61 61 62 65 61 61 62 66 61 61 62 67 61 61 62 │daab│eaab│faab│gaab│ * 000000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│ * 000000e0
>>> print hexdump(fit({0x10: 'X'*0x20, 0x50-1: '\xff'*20}, length=0xc0) + '\x00'*32, cyclic=1, hexii=1) 00000000 .a .a .a .a .b .a .a .a .c .a .a .a .d .a .a .a │ 00000010 .X .X .X .X .X .X .X .X .X .X .X .X .X .X .X .X │ * 00000030 .m .a .a .a .n .a .a .a .o .a .a .a .p .a .a .a │ 00000040 .q .a .a .a .r .a .a .a .s .a .a .a .t .a .a ## │ 00000050 ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## │ 00000060 ## ## ## .a .z .a .a .b .b .a .a .b .c .a .a .b │ 00000070 .d .a .a .b .e .a .a .b .f .a .a .b .g .a .a .b │ * 000000c0 │ * 000000e0
>>> print hexdump('A'*16, width=9) 00000000 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│A│ 00000009 41 41 41 41 41 41 41 │AAAA│AAA│ 00000010 >>> print hexdump('A'*16, width=10) 00000000 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AA│ 0000000a 41 41 41 41 41 41 │AAAA│AA│ 00000010 >>> print hexdump('A'*16, width=11) 00000000 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAA│ 0000000b 41 41 41 41 41 │AAAA│A│ 00000010 >>> print hexdump('A'*16, width=12) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│ 0000000c 41 41 41 41 │AAAA││ 00000010 >>> print hexdump('A'*16, width=13) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│A│ 0000000d 41 41 41 │AAA│ 00000010 >>> print hexdump('A'*16, width=14) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AA│ 0000000e 41 41 │AA│ 00000010 >>> print hexdump('A'*16, width=15) 00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAA│ 0000000f 41 │A│ 00000010
-
pwnlib.util.fiddling.
hexdump_iter
(fd, width=16, skip=True, hexii=False, begin=0, style=None, highlight=None, cyclic=False)[source]¶ - hexdump_iter(s, width = 16, skip = True, hexii = False, begin = 0,
- style = None, highlight = None, cyclic = False) -> str generator
Return a hexdump-dump of a string as a generator of lines. Unless you have massive amounts of data you probably want to use
hexdump()
.Parameters: - fd (file) – File object to dump. Use
StringIO.StringIO()
orhexdump()
to dump a string. - width (int) – The number of characters per line
- skip (bool) – Set to True, if repeated lines should be replaced by a “*”
- hexii (bool) – Set to True, if a hexii-dump should be returned instead of a hexdump.
- begin (int) – Offset of the first byte to print in the left column
- style (dict) – Color scheme to use.
- highlight (iterable) – Byte values to highlight.
- cyclic (bool) – Attempt to skip consecutive, unmodified cyclic lines
Returns: A generator producing the hexdump-dump one line at a time.
Example
>>> tmp = tempfile.NamedTemporaryFile() >>> tmp.write('XXXXHELLO, WORLD') >>> tmp.flush() >>> tmp.seek(4) >>> print '\n'.join(hexdump_iter(tmp)) 00000000 48 45 4c 4c 4f 2c 20 57 4f 52 4c 44 │HELL│O, W│ORLD││ 0000000c
>>> t = tube() >>> t.unrecv('I know kung fu') >>> print '\n'.join(hexdump_iter(t)) 00000000 49 20 6b 6e 6f 77 20 6b 75 6e 67 20 66 75 │I kn│ow k│ung │fu│ 0000000e
-
pwnlib.util.fiddling.
hexii
(s, width = 16, skip = True) → str[source]¶ Return a HEXII-dump of a string.
Parameters: Returns: A HEXII-dump in the form of a string.
-
pwnlib.util.fiddling.
naf
(int) → int generator[source]¶ Returns a generator for the non-adjacent form (NAF[1]) of a number, n. If naf(n) generates z_0, z_1, ..., then n == z_0 + z_1 * 2 + z_2 * 2**2, ....
[1] https://en.wikipedia.org/wiki/Non-adjacent_form
Example
>>> n = 45 >>> m = 0 >>> x = 1 >>> for z in naf(n): ... m += x * z ... x *= 2 >>> n == m True
-
pwnlib.util.fiddling.
randoms
(count, alphabet = string.lowercase) → str[source]¶ Returns a random string of a given length using only the specified alphabet.
Parameters: - count (int) – The length of the desired string.
- alphabet – The alphabet of allowed characters. Defaults to all lowercase characters.
Returns: A random string.
Example
>>> randoms(10) 'evafjilupm'
-
pwnlib.util.fiddling.
rol
(n, k, word_size=None)[source]¶ Returns a rotation by k of n.
When n is a number, then means
((n << k) | (n >> (word_size - k)))
truncated to word_size bits.When n is a list, tuple or string, this is
n[k % len(n):] + n[:k % len(n)]
.Parameters: Example
>>> rol('abcdefg', 2) 'cdefgab' >>> rol('abcdefg', -2) 'fgabcde' >>> hex(rol(0x86, 3, 8)) '0x34' >>> hex(rol(0x86, -3, 8)) '0xd0'
-
pwnlib.util.fiddling.
ror
(n, k, word_size=None)[source]¶ A simple wrapper around
rol()
, which negates the values of k.
-
pwnlib.util.fiddling.
unbits
(s, endian = 'big') → str[source]¶ Converts an iterable of bits into a string.
Parameters: - s – Iterable of bits
- endian (str) – The string “little” or “big”, which specifies the bits endianness.
Returns: A string of the decoded bits.
Example
>>> unbits([1]) '\x80' >>> unbits([1], endian = 'little') '\x01' >>> unbits(bits('hello'), endian = 'little') '\x16\xa666\xf6'
-
pwnlib.util.fiddling.
unhex
(s) → str[source]¶ Hex-decodes a string.
Example
>>> unhex("74657374") 'test' >>> unhex("F\n") '\x0f'
-
pwnlib.util.fiddling.
urldecode
(s, ignore_invalid = False) → str[source]¶ URL-decodes a string.
Example
>>> urldecode("test%20%41") 'test A' >>> urldecode("%qq") Traceback (most recent call last): ... ValueError: Invalid input to urldecode >>> urldecode("%qq", ignore_invalid = True) '%qq'
-
pwnlib.util.fiddling.
urlencode
(s) → str[source]¶ URL-encodes a string.
Example
>>> urlencode("test") '%74%65%73%74'
-
pwnlib.util.fiddling.
xor
(*args, cut = 'max') → str[source]¶ Flattens its arguments using
pwnlib.util.packing.flat()
and then xors them together. If the end of a string is reached, it wraps around in the string.Parameters: - args – The arguments to be xor’ed together.
- cut – How long a string should be returned. Can be either ‘min’/’max’/’left’/’right’ or a number.
Returns: The string of the arguments xor’ed together.
Example
>>> xor('lol', 'hello', 42) '. ***'
-
pwnlib.util.fiddling.
xor_key
(data, size=None, avoid='x00n') -> None or (int, str)[source]¶ Finds a
size
-width value that can be XORed with a string to producedata
, while neither the XOR value or XOR string contain any bytes inavoid
.Parameters: Returns: A tuple containing two strings; the XOR key and the XOR string. If no such pair exists, None is returned.
Example
>>> xor_key("Hello, world") ('\x01\x01\x01\x01', 'Idmmn-!vnsme')
-
pwnlib.util.fiddling.
xor_pair
(data, avoid = 'x00n') -> None or (str, str)[source]¶ Finds two strings that will xor into a given string, while only using a given alphabet.
Parameters: - data (str) – The desired string.
- avoid – The list of disallowed characters. Defaults to nulls and newlines.
Returns: Two strings which will xor to the given string. If no such two strings exist, then None is returned.
Example
>>> xor_pair("test") ('\x01\x01\x01\x01', 'udru')
pwnlib.util.hashes
— Hashing functions¶
Functions for computing various hashes of files and strings.
-
pwnlib.util.hashes.
sha224filehex
(x)[source]¶ Calculates the sha224 sum of a file; returns hex-encoded
-
pwnlib.util.hashes.
sha224sumhex
(x)[source]¶ Calculates the sha224 sum of a string; returns hex-encoded
-
pwnlib.util.hashes.
sha256filehex
(x)[source]¶ Calculates the sha256 sum of a file; returns hex-encoded
-
pwnlib.util.hashes.
sha256sumhex
(x)[source]¶ Calculates the sha256 sum of a string; returns hex-encoded
-
pwnlib.util.hashes.
sha384filehex
(x)[source]¶ Calculates the sha384 sum of a file; returns hex-encoded
-
pwnlib.util.hashes.
sha384sumhex
(x)[source]¶ Calculates the sha384 sum of a string; returns hex-encoded
pwnlib.util.iters
— Extension of standard module itertools
¶
This module includes and extends the standard module itertools
.
-
pwnlib.util.iters.
bruteforce
(func, alphabet, length, method = 'upto', start = None)[source]¶ Bruteforce func to return
True
. func should take a string input and return abool()
. func will be called with strings from alphabet until it returnsTrue
or the search space has been exhausted.The argument start can be used to split the search space, which is useful if multiple CPU cores are available.
Parameters: - func (function) – The function to bruteforce.
- alphabet – The alphabet to draw symbols from.
- length – Longest string to try.
- method – If ‘upto’ try strings of length
1 .. length
, if ‘fixed’ only try strings of lengthlength
and if ‘downfrom’ try strings of lengthlength .. 1
. - start – a tuple
(i, N)
which splits the search space up into N pieces and starts at piece i (1..N).None
is equivalent to(1, 1)
.
Returns: A string s such that
func(s)
returnsTrue
orNone
if the search space was exhausted.Example
>>> bruteforce(lambda x: x == 'hello', string.lowercase, length = 10) 'hello' >>> bruteforce(lambda x: x == 'hello', 'hllo', 5) is None True
-
pwnlib.util.iters.
mbruteforce
(func, alphabet, length, method = 'upto', start = None, threads = None)[source]¶ Same functionality as bruteforce(), but multithreaded.
Parameters: - alphabet, length, method, start (func,) – same as for bruteforce()
- threads – Amount of threads to spawn, default is the amount of cores.
-
pwnlib.util.iters.
chained
(func)[source]¶ A decorator chaining the results of func. Useful for generators.
Parameters: func (function) – The function being decorated. Returns: A generator function whoose elements are the concatenation of the return values from func(*args, **kwargs)
.Example
>>> @chained ... def g(): ... for x in count(): ... yield (x, -x) >>> take(6, g()) [0, 0, 1, -1, 2, -2]
-
pwnlib.util.iters.
consume
(n, iterator)[source]¶ Advance the iterator n steps ahead. If n is :const:`None, consume everything.
Parameters: - n (int) – Number of elements to consume.
- iterator (iterator) – An iterator.
Returns: None
.Examples
>>> i = count() >>> consume(5, i) >>> i.next() 5 >>> i = iter([1, 2, 3, 4, 5]) >>> consume(2, i) >>> list(i) [3, 4, 5]
-
pwnlib.util.iters.
cyclen
(n, iterable) → iterator[source]¶ Repeats the elements of iterable n times.
Parameters: - n (int) – The number of times to repeat iterable.
- iterable – An iterable.
Returns: An iterator whoose elements are the elements of iterator repeated n times.
Examples
>>> take(4, cyclen(2, [1, 2])) [1, 2, 1, 2] >>> list(cyclen(10, [])) []
-
pwnlib.util.iters.
dotproduct
(x, y) → int[source]¶ Computes the dot product of x and y.
Parameters: - x (iterable) – An iterable.
- x – An iterable.
Returns: x[0] * y[0] + x[1] * y[1] + ...
.Return type: The dot product of x and y, i.e.
Example
>>> dotproduct([1, 2, 3], [4, 5, 6]) ... # 1 * 4 + 2 * 5 + 3 * 6 == 32 32
-
pwnlib.util.iters.
flatten
(xss) → iterator[source]¶ Flattens one level of nesting; when xss is an iterable of iterables, returns an iterator whoose elements is the concatenation of the elements of xss.
Parameters: xss – An iterable of iterables. Returns: An iterator whoose elements are the concatenation of the iterables in xss. Examples
>>> list(flatten([[1, 2], [3, 4]])) [1, 2, 3, 4] >>> take(6, flatten([[43, 42], [41, 40], count()])) [43, 42, 41, 40, 0, 1]
-
pwnlib.util.iters.
group
(n, iterable, fill_value = None) → iterator[source]¶ Similar to
pwnlib.util.lists.group()
, but returns an iterator and usesitertools
fast build-in functions.Parameters: - n (int) – The group size.
- iterable – An iterable.
- fill_value – The value to fill into the remaining slots of the last group if the n does not divide the number of elements in iterable.
Returns: An iterator whoose elements are n-tuples of the elements of iterable.
Examples
>>> list(group(2, range(5))) [(0, 1), (2, 3), (4, None)] >>> take(3, group(2, count())) [(0, 1), (2, 3), (4, 5)] >>> [''.join(x) for x in group(3, 'ABCDEFG', 'x')] ['ABC', 'DEF', 'Gxx']
-
pwnlib.util.iters.
iter_except
(func, exception)[source]¶ Calls func repeatedly until an exception is raised. Works like the build-in
iter()
but uses an exception instead of a sentinel to signal the end.Parameters: - func – The function to call.
- exception (exception) – The exception that signals the end. Other exceptions will not be caught.
Returns: An iterator whoose elements are the results of calling
func()
until an exception matching exception is raised.Examples
>>> s = {1, 2, 3} >>> i = iter_except(s.pop, KeyError) >>> i.next() 1 >>> i.next() 2 >>> i.next() 3 >>> i.next() Traceback (most recent call last): ... StopIteration
-
pwnlib.util.iters.
lexicographic
(alphabet) → iterator[source]¶ The words with symbols in alphabet, in lexicographic order (determined by the order of alphabet).
Parameters: alphabet – The alphabet to draw symbols from. Returns: An iterator of the words with symbols in alphabet, in lexicographic order. Example
>>> take(8, imap(lambda x: ''.join(x), lexicographic('01'))) ['', '0', '1', '00', '01', '10', '11', '000']
-
pwnlib.util.iters.
lookahead
(n, iterable) → object[source]¶ Inspects the upcoming element at index n without advancing the iterator. Raises
IndexError
if iterable has too few elements.Parameters: - n (int) – Index of the element to return.
- iterable – An iterable.
Returns: The element in iterable at index n.
Examples
>>> i = count() >>> lookahead(4, i) 4 >>> i.next() 0 >>> i = count() >>> nth(4, i) 4 >>> i.next() 5 >>> lookahead(4, i) 10
-
pwnlib.util.iters.
nth
(n, iterable, default = None) → object[source]¶ Returns the element at index n in iterable. If iterable is a iterator it will be advanced.
Parameters: - n (int) – Index of the element to return.
- iterable – An iterable.
- default (objext) – A default value.
Returns: The element at index n in iterable or default if iterable has too few elements.
Examples
>>> nth(2, [0, 1, 2, 3]) 2 >>> nth(2, [0, 1], 42) 42 >>> i = count() >>> nth(42, i) 42 >>> nth(42, i) 85
-
pwnlib.util.iters.
pad
(iterable, value = None) → iterator[source]¶ Pad an iterable with value, i.e. returns an iterator whoose elements are first the elements of iterable then value indefinitely.
Parameters: - iterable – An iterable.
- value – The value to pad with.
Returns: An iterator whoose elements are first the elements of iterable then value indefinitely.
Examples
>>> take(3, pad([1, 2])) [1, 2, None] >>> i = pad(iter([1, 2, 3]), 42) >>> take(2, i) [1, 2] >>> take(2, i) [3, 42] >>> take(2, i) [42, 42]
-
pwnlib.util.iters.
pairwise
(iterable) → iterator[source]¶ Parameters: iterable – An iterable. Returns: An iterator whoose elements are pairs of neighbouring elements of iterable. Examples
>>> list(pairwise([1, 2, 3, 4])) [(1, 2), (2, 3), (3, 4)] >>> i = starmap(operator.add, pairwise(count())) >>> take(5, i) [1, 3, 5, 7, 9]
-
pwnlib.util.iters.
powerset
(iterable, include_empty = True) → iterator[source]¶ The powerset of an iterable.
Parameters: - iterable – An iterable.
- include_empty (bool) – Whether to include the empty set.
Returns: The powerset of iterable as an interator of tuples.
Examples
>>> list(powerset(range(3))) [(), (0,), (1,), (2,), (0, 1), (0, 2), (1, 2), (0, 1, 2)] >>> list(powerset(range(2), include_empty = False)) [(0,), (1,), (0, 1)]
-
pwnlib.util.iters.
quantify
(iterable, pred = bool) → int[source]¶ Count how many times the predicate pred is
True
.Parameters: - iterable – An iterable.
- pred – A function that given an element from iterable returns either
True
orFalse
.
Returns: The number of elements in iterable for which pred returns
True
.Examples
>>> quantify([1, 2, 3, 4], lambda x: x % 2 == 0) 2 >>> quantify(['1', 'two', '3', '42'], str.isdigit) 3
-
pwnlib.util.iters.
random_combination
(iterable, r) → tuple[source]¶ Parameters: - iterable – An iterable.
- r (int) – Size of the combination.
Returns: A random element from
itertools.combinations(iterable, r = r)
.Examples
>>> random_combination(range(2), 2) (0, 1) >>> random_combination(range(10), r = 2) in combinations(range(10), r = 2) True
-
pwnlib.util.iters.
random_combination_with_replacement
(iterable, r)[source]¶ random_combination(iterable, r) -> tuple
Parameters: - iterable – An iterable.
- r (int) – Size of the combination.
Returns: A random element from
itertools.combinations_with_replacement(iterable, r = r)
.Examples
>>> cs = {(0, 0), (0, 1), (1, 1)} >>> random_combination_with_replacement(range(2), 2) in cs True >>> i = combinations_with_replacement(range(10), r = 2) >>> random_combination_with_replacement(range(10), r = 2) in i True
-
pwnlib.util.iters.
random_permutation
(iterable, r=None)[source]¶ random_product(iterable, r = None) -> tuple
Parameters: - iterable – An iterable.
- r (int) – Size of the permutation. If
None
select all elements in iterable.
Returns: A random element from
itertools.permutations(iterable, r = r)
.Examples
>>> random_permutation(range(2)) in {(0, 1), (1, 0)} True >>> random_permutation(range(10), r = 2) in permutations(range(10), r = 2) True
-
pwnlib.util.iters.
random_product
(*args, repeat = 1) → tuple[source]¶ Parameters: - args – One or more iterables
- repeat (int) – Number of times to repeat args.
Returns: A random element from
itertools.product(*args, repeat = repeat)
.Examples
>>> args = (range(2), range(2)) >>> random_product(*args) in {(0, 0), (0, 1), (1, 0), (1, 1)} True >>> args = (range(3), range(3), range(3)) >>> random_product(*args, repeat = 2) in product(*args, repeat = 2) True
-
pwnlib.util.iters.
repeat_func
(func, *args, **kwargs) → iterator[source]¶ Repeatedly calls func with positional arguments args and keyword arguments kwargs. If no keyword arguments is given the resulting iterator will be computed using only functions from
itertools
which are very fast.Parameters: - func (function) – The function to call.
- args – Positional arguments.
- kwargs – Keyword arguments.
Returns: An iterator whoose elements are the results of calling
func(*args, **kwargs)
repeatedly.Examples
>>> def f(x): ... x[0] += 1 ... return x[0] >>> i = repeat_func(f, [0]) >>> take(2, i) [1, 2] >>> take(2, i) [3, 4] >>> def f(**kwargs): ... return kwargs.get('x', 43) >>> i = repeat_func(f, x = 42) >>> take(2, i) [42, 42] >>> i = repeat_func(f, 42) >>> take(2, i) Traceback (most recent call last): ... TypeError: f() takes exactly 0 arguments (1 given)
-
pwnlib.util.iters.
roundrobin
(*iterables)[source]¶ Take elements from iterables in a round-robin fashion.
Parameters: *iterables – One or more iterables. Returns: An iterator whoose elements are taken from iterables in a round-robin fashion. Examples
>>> ''.join(roundrobin('ABC', 'D', 'EF')) 'ADEBFC' >>> ''.join(take(10, roundrobin('ABC', 'DE', repeat('x')))) 'ADxBExCxxx'
-
pwnlib.util.iters.
tabulate
(func, start = 0) → iterator[source]¶ Parameters: Returns: An iterator with the elements
func(start), func(start + 1), ...
.Examples
>>> take(2, tabulate(str)) ['0', '1'] >>> take(5, tabulate(lambda x: x**2, start = 1)) [1, 4, 9, 16, 25]
-
pwnlib.util.iters.
take
(n, iterable) → list[source]¶ Returns first n elements of iterable. If iterable is a iterator it will be advanced.
Parameters: - n (int) – Number of elements to take.
- iterable – An iterable.
Returns: A list of the first n elements of iterable. If there are fewer than n elements in iterable they will all be returned.
Examples
>>> take(2, range(10)) [0, 1] >>> i = count() >>> take(2, i) [0, 1] >>> take(2, i) [2, 3] >>> take(9001, [1, 2, 3]) [1, 2, 3]
-
pwnlib.util.iters.
unique_everseen
(iterable, key = None) → iterator[source]¶ Get unique elements, preserving order. Remember all elements ever seen. If key is not
None
then for each elementelm
in iterable the element that will be rememberes iskey(elm)
. Otherwiseelm
is remembered.Parameters: - iterable – An iterable.
- key – A function to map over each element in iterable before remembering
it. Setting to
None
is equivalent to the identity function.
Returns: An iterator of the unique elements in iterable.
Examples
>>> ''.join(unique_everseen('AAAABBBCCDAABBB')) 'ABCD' >>> ''.join(unique_everseen('ABBCcAD', str.lower)) 'ABCD'
-
pwnlib.util.iters.
unique_justseen
(iterable, key=None)[source]¶ unique_everseen(iterable, key = None) -> iterator
Get unique elements, preserving order. Remember only the elements just seen. If key is not
None
then for each elementelm
in iterable the element that will be rememberes iskey(elm)
. Otherwiseelm
is remembered.Parameters: - iterable – An iterable.
- key – A function to map over each element in iterable before remembering
it. Setting to
None
is equivalent to the identity function.
Returns: An iterator of the unique elements in iterable.
Examples
>>> ''.join(unique_justseen('AAAABBBCCDAABBB')) 'ABCDAB' >>> ''.join(unique_justseen('ABBCcAD', str.lower)) 'ABCAD'
-
pwnlib.util.iters.
unique_window
(iterable, window, key=None)[source]¶ unique_everseen(iterable, window, key = None) -> iterator
Get unique elements, preserving order. Remember only the last window elements seen. If key is not
None
then for each elementelm
in iterable the element that will be rememberes iskey(elm)
. Otherwiseelm
is remembered.Parameters: - iterable – An iterable.
- window (int) – The number of elements to remember.
- key – A function to map over each element in iterable before remembering
it. Setting to
None
is equivalent to the identity function.
Returns: An iterator of the unique elements in iterable.
Examples
>>> ''.join(unique_window('AAAABBBCCDAABBB', 6)) 'ABCDA' >>> ''.join(unique_window('ABBCcAD', 5, str.lower)) 'ABCD' >>> ''.join(unique_window('ABBCcAD', 4, str.lower)) 'ABCAD'
-
pwnlib.util.iters.
chain
()[source]¶ Alias for
itertools.chain()
.
-
pwnlib.util.iters.
combinations
()[source]¶ Alias for
itertools.combinations()
-
pwnlib.util.iters.
compress
()[source]¶ Alias for
itertools.compress()
-
pwnlib.util.iters.
count
()[source]¶ Alias for
itertools.count()
-
pwnlib.util.iters.
cycle
()[source]¶ Alias for
itertools.cycle()
-
pwnlib.util.iters.
dropwhile
()[source]¶ Alias for
itertools.dropwhile()
-
pwnlib.util.iters.
groupby
()[source]¶ Alias for
itertools.groupby()
-
pwnlib.util.iters.
ifilter
()[source]¶ Alias for
itertools.ifilter()
-
pwnlib.util.iters.
ifilterfalse
()[source]¶ Alias for
itertools.ifilterfalse()
-
pwnlib.util.iters.
imap
()[source]¶ Alias for
itertools.imap()
-
pwnlib.util.iters.
islice
()[source]¶ Alias for
itertools.islice()
-
pwnlib.util.iters.
izip
()[source]¶ Alias for
itertools.izip()
-
pwnlib.util.iters.
izip_longest
()[source]¶ Alias for
itertools.izip_longest()
-
pwnlib.util.iters.
permutations
()[source]¶ Alias for
itertools.permutations()
-
pwnlib.util.iters.
product
()[source]¶ Alias for
itertools.product()
-
pwnlib.util.iters.
repeat
()[source]¶ Alias for
itertools.repeat()
-
pwnlib.util.iters.
starmap
()[source]¶ Alias for
itertools.starmap()
-
pwnlib.util.iters.
takewhile
()[source]¶ Alias for
itertools.takewhile()
-
pwnlib.util.iters.
tee
()[source]¶ Alias for
itertools.tee()
pwnlib.util.lists
— Operations on lists¶
-
pwnlib.util.lists.
concat
(l) → list[source]¶ Concats a list of lists into a list.
Example
>>> concat([[1, 2], [3]]) [1, 2, 3]
-
pwnlib.util.lists.
concat_all
(*args) → list[source]¶ Concats all the arguments together.
Example
>>> concat_all(0, [1, (2, 3)], [([[4, 5, 6]])]) [0, 1, 2, 3, 4, 5, 6]
-
pwnlib.util.lists.
findall
(l, e) → l[source]¶ Generate all indices of needle in haystack, using the Knuth-Morris-Pratt algorithm.
Example
>>> foo = findall([1,2,3,4,4,3,4,2,1], 4) >>> foo.next() 3 >>> foo.next() 4 >>> foo.next() 6
-
pwnlib.util.lists.
group
(n, lst, underfull_action = 'ignore', fill_value = None) → list[source]¶ Split sequence into subsequences of given size. If the values cannot be evenly distributed among into groups, then the last group will either be returned as is, thrown out or padded with the value specified in fill_value.
Parameters: Returns: A list containing the grouped values.
Example
>>> group(3, "ABCDEFG") ['ABC', 'DEF', 'G'] >>> group(3, 'ABCDEFG', 'drop') ['ABC', 'DEF'] >>> group(3, 'ABCDEFG', 'fill', 'Z') ['ABC', 'DEF', 'GZZ'] >>> group(3, list('ABCDEFG'), 'fill') [['A', 'B', 'C'], ['D', 'E', 'F'], ['G', None, None]]
-
pwnlib.util.lists.
ordlist
(s) → list[source]¶ Turns a string into a list of the corresponding ascii values.
Example
>>> ordlist("hello") [104, 101, 108, 108, 111]
-
pwnlib.util.lists.
partition
(lst, f, save_keys = False) → list[source]¶ Partitions an iterable into sublists using a function to specify which group they belong to.
It works by calling f on every element and saving the results into an
collections.OrderedDict
.Parameters: Example
>>> partition([1,2,3,4,5], lambda x: x&1) [[1, 3, 5], [2, 4]]
pwnlib.util.misc
— We could not fit it any other place¶
-
pwnlib.util.misc.
align
(alignment, x) → int[source]¶ Rounds x up to nearest multiple of the alignment.
Example
>>> [align(5, n) for n in range(15)] [0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10, 15, 15, 15, 15]
-
pwnlib.util.misc.
align_down
(alignment, x) → int[source]¶ Rounds x down to nearest multiple of the alignment.
Example
>>> [align_down(5, n) for n in range(15)] [0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10]
-
pwnlib.util.misc.
binary_ip
(host) → str[source]¶ Resolve host and return IP as four byte string.
Example
>>> binary_ip("127.0.0.1") '\x7f\x00\x00\x01'
-
pwnlib.util.misc.
parse_ldd_output
(output)[source]¶ Parses the output from a run of ‘ldd’ on a binary. Returns a dictionary of {path: address} for each library required by the specified binary.
Parameters: output (str) – The output to parse Example
>>> sorted(parse_ldd_output(''' ... linux-vdso.so.1 => (0x00007fffbf5fe000) ... libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fe28117f000) ... libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe280f7b000) ... libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe280bb4000) ... /lib64/ld-linux-x86-64.so.2 (0x00007fe2813dd000) ... ''').keys()) ['/lib/x86_64-linux-gnu/libc.so.6', '/lib/x86_64-linux-gnu/libdl.so.2', '/lib/x86_64-linux-gnu/libtinfo.so.5', '/lib64/ld-linux-x86-64.so.2']
-
pwnlib.util.misc.
read
(path, count=-1, skip=0) → str[source]¶ Open file, return content.
Examples
>>> read('/proc/self/exe')[:4] '\x7fELF'
-
pwnlib.util.misc.
register_sizes
(regs, in_sizes)[source]¶ Create dictionaries over register sizes and relations
Given a list of lists of overlapping register names (e.g. [‘eax’,’ax’,’al’,’ah’]) and a list of input sizes, it returns the following:
- all_regs : list of all valid registers
- sizes[reg] : the size of reg in bits
- bigger[reg] : list of overlapping registers bigger than reg
- smaller[reg]: list of overlapping registers smaller than reg
Used in i386/AMD64 shellcode, e.g. the mov-shellcode.
Example
>>> regs = [['eax', 'ax', 'al', 'ah'],['ebx', 'bx', 'bl', 'bh'], ... ['ecx', 'cx', 'cl', 'ch'], ... ['edx', 'dx', 'dl', 'dh'], ... ['edi', 'di'], ... ['esi', 'si'], ... ['ebp', 'bp'], ... ['esp', 'sp'], ... ] >>> all_regs, sizes, bigger, smaller = register_sizes(regs, [32, 16, 8, 8]) >>> all_regs ['eax', 'ax', 'al', 'ah', 'ebx', 'bx', 'bl', 'bh', 'ecx', 'cx', 'cl', 'ch', 'edx', 'dx', 'dl', 'dh', 'edi', 'di', 'esi', 'si', 'ebp', 'bp', 'esp', 'sp'] >>> sizes {'ch': 8, 'cl': 8, 'ah': 8, 'edi': 32, 'al': 8, 'cx': 16, 'ebp': 32, 'ax': 16, 'edx': 32, 'ebx': 32, 'esp': 32, 'esi': 32, 'dl': 8, 'dh': 8, 'di': 16, 'bl': 8, 'bh': 8, 'eax': 32, 'bp': 16, 'dx': 16, 'bx': 16, 'ecx': 32, 'sp': 16, 'si': 16} >>> bigger {'ch': ['ecx', 'cx', 'ch'], 'cl': ['ecx', 'cx', 'cl'], 'ah': ['eax', 'ax', 'ah'], 'edi': ['edi'], 'al': ['eax', 'ax', 'al'], 'cx': ['ecx', 'cx'], 'ebp': ['ebp'], 'ax': ['eax', 'ax'], 'edx': ['edx'], 'ebx': ['ebx'], 'esp': ['esp'], 'esi': ['esi'], 'dl': ['edx', 'dx', 'dl'], 'dh': ['edx', 'dx', 'dh'], 'di': ['edi', 'di'], 'bl': ['ebx', 'bx', 'bl'], 'bh': ['ebx', 'bx', 'bh'], 'eax': ['eax'], 'bp': ['ebp', 'bp'], 'dx': ['edx', 'dx'], 'bx': ['ebx', 'bx'], 'ecx': ['ecx'], 'sp': ['esp', 'sp'], 'si': ['esi', 'si']} >>> smaller {'ch': [], 'cl': [], 'ah': [], 'edi': ['di'], 'al': [], 'cx': ['cl', 'ch'], 'ebp': ['bp'], 'ax': ['al', 'ah'], 'edx': ['dx', 'dl', 'dh'], 'ebx': ['bx', 'bl', 'bh'], 'esp': ['sp'], 'esi': ['si'], 'dl': [], 'dh': [], 'di': [], 'bl': [], 'bh': [], 'eax': ['ax', 'al', 'ah'], 'bp': [], 'dx': ['dl', 'dh'], 'bx': ['bl', 'bh'], 'ecx': ['cx', 'cl', 'ch'], 'sp': [], 'si': []}
-
pwnlib.util.misc.
run_in_new_terminal
(command, terminal = None) → None[source]¶ Run a command in a new terminal.
- When
terminal
is not set: - If
context.terminal
is set it will be used. If it is an iterable thencontext.terminal[1:]
are default arguments. - If a
pwntools-terminal
command exists in$PATH
, it is used - If
$TERM_PROGRAM
is set, that is used. - If X11 is detected (by the presence of the
$DISPLAY
environment variable),x-terminal-emulator
is used. - If tmux is detected (by the presence of the
$TMUX
environment variable), a new pane will be opened.
- If
Parameters: Note
The command is opened with
/dev/null
for stdin, stdout, stderr.Returns: PID of the new terminal process - When
-
pwnlib.util.misc.
size
(n, abbrev = 'B', si = False) → str[source]¶ Convert the length of a bytestream to human readable form.
Parameters: Example
>>> size(451) '451B' >>> size(1000) '1000B' >>> size(1024) '1.00KB' >>> size(1024, ' bytes') '1.00K bytes' >>> size(1024, si = True) '1.02KB' >>> [size(1024 ** n) for n in range(7)] ['1B', '1.00KB', '1.00MB', '1.00GB', '1.00TB', '1.00PB', '1024.00PB'] >>> size([]) '0B' >>> size([1,2,3]) '3B'
-
pwnlib.util.misc.
which
(name, flags = os.X_OK, all = False) → str or str set[source]¶ Works as the system command
which
; searches $PATH forname
and returns a full path if found.If all is
True
the set of all found locations is returned, else the first occurence orNone
is returned.Parameters: Returns: If all is
True
the set of all locations where name was found, else the first location orNone
if not found.Example
>>> which('sh') '/bin/sh'
pwnlib.util.net
— Networking interfaces¶
-
pwnlib.util.net.
getifaddrs
() → dict list[source]¶ A wrapper for libc’s
getifaddrs
.Parameters: None – Returns: list of dictionaries each representing a struct ifaddrs. The dictionaries have the fields name, flags, family, addr and netmask. Refer to getifaddrs(3) for details. The fields addr and netmask are themselves dictionaries. Their structure depend on family. If family is not socket.AF_INET
orsocket.AF_INET6
they will be empty.
-
pwnlib.util.net.
interfaces
(all = False) → dict[source]¶ Parameters: - all (bool) – Whether to include interfaces with not associated address.
- Default –
False
.
Returns: A dictionary mapping each of the hosts interfaces to a list of it’s addresses. Each entry in the list is a tuple
(family, addr)
, and family is eithersocket.AF_INET
orsocket.AF_INET6
.
-
pwnlib.util.net.
interfaces4
(all = False) → dict[source]¶ As
interfaces()
but only includes IPv4 addresses and the lists in the dictionary only contains the addresses not the family.Parameters: - all (bool) – Whether to include interfaces with not associated address.
- Default –
False
.
Returns: A dictionary mapping each of the hosts interfaces to a list of it’s IPv4 addresses.
-
pwnlib.util.net.
interfaces6
(all = False) → dict[source]¶ As
interfaces()
but only includes IPv6 addresses and the lists in the dictionary only contains the addresses not the family.Parameters: - all (bool) – Whether to include interfaces with not associated address.
- Default –
False
.
Returns: A dictionary mapping each of the hosts interfaces to a list of it’s IPv6 addresses.
pwnlib.util.packing
— Packing and unpacking of strings¶
Module for packing and unpacking integers.
Simplifies access to the standard struct.pack
and struct.unpack
functions, and also adds support for packing/unpacking arbitrary-width
integers.
The packers are all context-aware for endian
and signed
arguments,
though they can be overridden in the parameters.
Examples
>>> p8(0)
'\x00'
>>> p32(0xdeadbeef)
'\xef\xbe\xad\xde'
>>> p32(0xdeadbeef, endian='big')
'\xde\xad\xbe\xef'
>>> with context.local(endian='big'): p32(0xdeadbeef)
'\xde\xad\xbe\xef'
Make a frozen packer, which does not change with context.
>>> p=make_packer('all')
>>> p(0xff)
'\xff'
>>> p(0x1ff)
'\xff\x01'
>>> with context.local(endian='big'): print repr(p(0x1ff))
'\xff\x01'
-
pwnlib.util.packing.
dd
(dst, src, count = 0, skip = 0, seek = 0, truncate = False) → dst[source]¶ Inspired by the command line tool
dd
, this function copies count byte values from offset seek in src to offset skip in dst. If count is 0, all ofsrc[seek:]
is copied.If dst is a mutable type it will be updated. Otherwise a new instance of the same type will be created. In either case the result is returned.
src can be an iterable of characters or integers, a unicode string or a file object. If it is an iterable of integers, each integer must be in the range [0;255]. If it is a unicode string, its UTF-8 encoding will be used.
The seek offset of file objects will be preserved.
Parameters: - dst – Supported types are :class:file, :class:list, :class:tuple, :class:str, :class:bytearray and :class:unicode.
- src – An iterable of byte values (characters or integers), a unicode string or a file object.
- count (int) – How many bytes to copy. If count is 0 or larger than
len(src[seek:])
, all bytes until the end of src are copied. - skip (int) – Offset in dst to copy to.
- seek (int) – Offset in src to copy from.
- truncate (bool) – If :const:True, dst is truncated at the last copied byte.
Returns: A modified version of dst. If dst is a mutable type it will be modified in-place.
Examples: >>> dd(tuple(‘Hello!’), ‘?’, skip = 5) (‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘?’) >>> dd(list(‘Hello!’), (63,), skip = 5) [‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘?’] >>> write(‘/tmp/foo’, ‘A’ * 10) ... dd(file(‘/tmp/foo’), file(‘/dev/zero’), skip = 3, count = 4) ... read(‘/tmp/foo’) ‘AAAAAA’ >>> write(‘/tmp/foo’, ‘A’ * 10) ... dd(file(‘/tmp/foo’), file(‘/dev/zero’), skip = 3, count = 4, truncate = True) ... read(‘/tmp/foo’) ‘AAA’
-
pwnlib.util.packing.
fit
(pieces, filler = de_bruijn(), length = None, preprocessor = None) → str[source]¶ Generates a string from a dictionary mapping offsets to data to place at that offset.
For each key-value pair in pieces, the key is either an offset or a byte sequence. In the latter case, the offset will be the lowest index at which the sequence occurs in filler. See examples below.
Each piece of data is passed to
flat()
along with the keyword arguments word_size, endianness and sign.Space between pieces of data is filled out using the iterable filler. The n‘th byte in the output will be byte at index
n % len(iterable)
byte in filler if it has finite length or the byte at index n otherwise.If length is given, the output will padded with bytes from filler to be this size. If the output is longer than length, a
ValueError
exception is raised.If entries in pieces overlap, a
ValueError
exception is raised.Parameters: - pieces – Offsets and values to output.
- length – The length of the output.
- filler – Iterable to use for padding.
- preprocessor (function) – Gets called on every element to optionally
transform the element before flattening. If
None
is returned, then the original value is used. - word_size (int) – Word size of the converted integer.
- endianness (str) – Endianness of the converted integer (“little”/”big”).
- sign (str) – Signedness of the converted integer (False/True)
Examples
>>> fit({12: 0x41414141, ... 24: 'Hello', ... }) 'aaaabaaacaaaAAAAeaaafaaaHello' >>> fit({'caaa': ''}) 'aaaabaaa' >>> fit({12: 'XXXX'}, filler = 'AB', length = 20) 'ABABABABABABXXXXABAB' >>> fit({ 8: [0x41414141, 0x42424242], ... 20: 'CCCC'}) 'aaaabaaaAAAABBBBeaaaCCCC' >>> fit({ 0x61616162: 'X'}) 'aaaaX'
-
pwnlib.util.packing.
flat
(*args, preprocessor = None, word_size = None, endianness = None, sign = None)[source]¶ Flattens the arguments into a string.
This function takes an arbitrary number of arbitrarily nested lists and tuples. It will then find every string and number inside those and flatten them out. Strings are inserted directly while numbers are packed using the
pack()
function.The three kwargs word_size, endianness and sign will default to using values in
pwnlib.context
if not specified as an argument.Parameters: - args – Values to flatten
- preprocessor (function) – Gets called on every element to optionally
transform the element before flattening. If
None
is returned, then the original value is uded. - word_size (int) – Word size of the converted integer.
- endianness (str) – Endianness of the converted integer (“little”/”big”).
- sign (str) – Signedness of the converted integer (False/True)
Examples
>>> flat(1, "test", [[["AB"]*2]*3], endianness = 'little', word_size = 16, sign = False) '\x01\x00testABABABABABAB' >>> flat([1, [2, 3]], preprocessor = lambda x: str(x+1)) '234'
-
pwnlib.util.packing.
make_packer
(word_size = None, endianness = None, sign = None) → number → str[source]¶ Creates a packer by “freezing” the given arguments.
Semantically calling
make_packer(w, e, s)(data)
is equivalent to callingpack(data, w, e, s)
. If word_size is one of 8, 16, 32 or 64, it is however faster to call this function, since it will then use a specialized version.Parameters: - word_size (int) – The word size to be baked into the returned packer or the string all.
- endianness (str) – The endianness to be baked into the returned packer. (“little”/”big”)
- sign (str) – The signness to be baked into the returned packer. (“unsigned”/”signed”)
- kwargs – Additional context flags, for setting by alias (e.g.
endian=
rather than index)
Returns: A function, which takes a single argument in the form of a number and returns a string of that number in a packed form.
Examples
>>> p = make_packer(32, endian='little', sign='unsigned') >>> p <function _p32lu at 0x...> >>> p(42) '*\x00\x00\x00' >>> p(-1) Traceback (most recent call last): ... error: integer out of range for 'I' format code >>> make_packer(33, endian='little', sign='unsigned') <function <lambda> at 0x...>
-
pwnlib.util.packing.
make_unpacker
(word_size = None, endianness = None, sign = None, **kwargs) → str → number[source]¶ Creates a unpacker by “freezing” the given arguments.
Semantically calling
make_unpacker(w, e, s)(data)
is equivalent to callingunpack(data, w, e, s)
. If word_size is one of 8, 16, 32 or 64, it is however faster to call this function, since it will then use a specialized version.Parameters: - word_size (int) – The word size to be baked into the returned packer.
- endianness (str) – The endianness to be baked into the returned packer. (“little”/”big”)
- sign (str) – The signness to be baked into the returned packer. (“unsigned”/”signed”)
- kwargs – Additional context flags, for setting by alias (e.g.
endian=
rather than index)
Returns: A function, which takes a single argument in the form of a string and returns a number of that string in an unpacked form.
Examples
>>> u = make_unpacker(32, endian='little', sign='unsigned') >>> u <function _u32lu at 0x...> >>> hex(u('/bin')) '0x6e69622f' >>> u('abcde') Traceback (most recent call last): ... error: unpack requires a string argument of length 4 >>> make_unpacker(33, endian='little', sign='unsigned') <function <lambda> at 0x...>
-
pwnlib.util.packing.
p16
(number, sign, endian, ...) → str[source]¶ Packs an 16-bit integer
Parameters: Returns: The packed number as a string
-
pwnlib.util.packing.
p32
(number, sign, endian, ...) → str[source]¶ Packs an 32-bit integer
Parameters: Returns: The packed number as a string
-
pwnlib.util.packing.
p64
(number, sign, endian, ...) → str[source]¶ Packs an 64-bit integer
Parameters: Returns: The packed number as a string
-
pwnlib.util.packing.
p8
(number, sign, endian, ...) → str[source]¶ Packs an 8-bit integer
Parameters: Returns: The packed number as a string
-
pwnlib.util.packing.
pack
(number, word_size = None, endianness = None, sign = None, **kwargs) → str[source]¶ Packs arbitrary-sized integer.
Word-size, endianness and signedness is done according to context.
word_size can be any positive number or the string “all”. Choosing the string “all” will output a string long enough to contain all the significant bits and thus be decodable by
unpack()
.word_size can be any positive number. The output will contain word_size/8 rounded up number of bytes. If word_size is not a multiple of 8, it will be padded with zeroes up to a byte boundary.
Parameters: Returns: The packed number as a string.
Examples
>>> pack(0x414243, 24, 'big', True) 'ABC' >>> pack(0x414243, 24, 'little', True) 'CBA' >>> pack(0x814243, 24, 'big', False) '\x81BC' >>> pack(0x814243, 24, 'big', True) Traceback (most recent call last): ... ValueError: pack(): number does not fit within word_size >>> pack(0x814243, 25, 'big', True) '\x00\x81BC' >>> pack(-1, 'all', 'little', True) '\xff' >>> pack(-256, 'all', 'big', True) '\xff\x00' >>> pack(0x0102030405, 'all', 'little', True) '\x05\x04\x03\x02\x01' >>> pack(-1) '\xff\xff\xff\xff' >>> pack(0x80000000, 'all', 'big', True) '\x00\x80\x00\x00\x00'
-
pwnlib.util.packing.
routine
(*a, **kw)[source]¶ u32(number, sign, endian, ...) -> int
Unpacks an 32-bit integer
Parameters: Returns: The unpacked number
-
pwnlib.util.packing.
u16
(number, sign, endian, ...) → int[source]¶ Unpacks an 16-bit integer
Parameters: Returns: The unpacked number
-
pwnlib.util.packing.
u32
(number, sign, endian, ...) → int[source]¶ Unpacks an 32-bit integer
Parameters: Returns: The unpacked number
-
pwnlib.util.packing.
u64
(number, sign, endian, ...) → int[source]¶ Unpacks an 64-bit integer
Parameters: Returns: The unpacked number
-
pwnlib.util.packing.
u8
(number, sign, endian, ...) → int[source]¶ Unpacks an 8-bit integer
Parameters: Returns: The unpacked number
-
pwnlib.util.packing.
unpack
(data, word_size = None, endianness = None, sign = None, **kwargs) → int[source]¶ Packs arbitrary-sized integer.
Word-size, endianness and signedness is done according to context.
word_size can be any positive number or the string “all”. Choosing the string “all” is equivalent to
len(data)*8
.If word_size is not a multiple of 8, then the bits used for padding are discarded.
Parameters: Returns: The unpacked number.
Examples
>>> hex(unpack('\xaa\x55', 16, endian='little', sign=False)) '0x55aa' >>> hex(unpack('\xaa\x55', 16, endian='big', sign=False)) '0xaa55' >>> hex(unpack('\xaa\x55', 16, endian='big', sign=True)) '-0x55ab' >>> hex(unpack('\xaa\x55', 15, endian='big', sign=True)) '0x2a55' >>> hex(unpack('\xff\x02\x03', 'all', endian='little', sign=True)) '0x302ff' >>> hex(unpack('\xff\x02\x03', 'all', endian='big', sign=True)) '-0xfdfd'
-
pwnlib.util.packing.
unpack_many
(*a, **kw)[source]¶ unpack(data, word_size = None, endianness = None, sign = None) -> int list
Splits data into groups of
word_size//8
bytes and callsunpack()
on each group. Returns a list of the results.word_size must be a multiple of 8 or the string “all”. In the latter case a singleton list will always be returned.
- Args
- number (int): String to convert word_size (int): Word size of the converted integers or the string “all”. endianness (str): Endianness of the converted integer (“little”/”big”) sign (str): Signedness of the converted integer (False/True) kwargs: Anything that can be passed to context.local
Returns: The unpacked numbers. Examples
>>> map(hex, unpack_many('\xaa\x55\xcc\x33', 16, endian='little', sign=False)) ['0x55aa', '0x33cc'] >>> map(hex, unpack_many('\xaa\x55\xcc\x33', 16, endian='big', sign=False)) ['0xaa55', '0xcc33'] >>> map(hex, unpack_many('\xaa\x55\xcc\x33', 16, endian='big', sign=True)) ['-0x55ab', '-0x33cd'] >>> map(hex, unpack_many('\xff\x02\x03', 'all', endian='little', sign=True)) ['0x302ff'] >>> map(hex, unpack_many('\xff\x02\x03', 'all', endian='big', sign=True)) ['-0xfdfd']
pwnlib.util.proc
— Working with /proc/
¶
-
pwnlib.util.proc.
ancestors
(pid) → int list[source]¶ Parameters: pid (int) – PID of the process. Returns: List of PIDs of whose parent process is pid or an ancestor of pid.
-
pwnlib.util.proc.
children
(ppid) → int list[source]¶ Parameters: pid (int) – PID of the process. Returns: List of PIDs of whose parent process is pid.
-
pwnlib.util.proc.
cmdline
(pid) → str list[source]¶ Parameters: pid (int) – PID of the process. Returns: A list of the fields in /proc/<pid>/cmdline
.
-
pwnlib.util.proc.
cwd
(pid) → str[source]¶ Parameters: pid (int) – PID of the process. Returns: The path of the process’s current working directory. I.e. what /proc/<pid>/cwd
points to.
-
pwnlib.util.proc.
descendants
(pid) → dict[source]¶ Parameters: pid (int) – PID of the process. Returns: Dictionary mapping the PID of each child of pid to it’s descendants.
-
pwnlib.util.proc.
exe
(pid) → str[source]¶ Parameters: pid (int) – PID of the process. Returns: The path of the binary of the process. I.e. what /proc/<pid>/exe
points to.
-
pwnlib.util.proc.
name
(pid) → str[source]¶ Parameters: pid (int) – PID of the process. Returns: Name of process as listed in /proc/<pid>/status
.Example
>>> pid = pidof('init')[0] >>> name(pid) == 'init' True
-
pwnlib.util.proc.
parent
(pid) → int[source]¶ Parameters: pid (int) – PID of the process. Returns: Parent PID as listed in /proc/<pid>/status
underPPid
, or 0 if there is not parent.
-
pwnlib.util.proc.
pid_by_name
(name) → int list[source]¶ Parameters: name (str) – Name of program. Returns: List of PIDs matching name sorted by lifetime, youngest to oldest. Example
>>> os.getpid() in pid_by_name(name(os.getpid())) True
-
pwnlib.util.proc.
pidof
(target) → int list[source]¶ Get PID(s) of target. The returned PID(s) depends on the type of target:
str
: PIDs of all processes with a name matching target.pwnlib.tubes.process.process
: singleton list of the PID of target.pwnlib.tubes.sock.sock
: singleton list of the PID at the remote end of target if it is running on the host. Otherwise an empty list.
Parameters: target (object) – The target whose PID(s) to find. Returns: A list of found PIDs.
-
pwnlib.util.proc.
starttime
(pid) → float[source]¶ Parameters: pid (int) – PID of the process. Returns: The time (in seconds) the process started after system boot
-
pwnlib.util.proc.
stat
(pid) → str list[source]¶ Parameters: pid (int) – PID of the process. Returns: A list of the values in /proc/<pid>/stat
, with the exception that(
and)
has been removed from around the process name.
-
pwnlib.util.proc.
state
(pid) → str[source]¶ Parameters: pid (int) – PID of the process. Returns: State of the process as listed in /proc/<pid>/status
. See proc(5) for details.Example
>>> state(os.getpid()) 'R (running)'
-
pwnlib.util.proc.
status
(pid) → dict[source]¶ Get the status of a process.
Parameters: pid (int) – PID of the process. Returns: The contents of /proc/<pid>/status
as a dictionary.
pwnlib.util.safeeval
— Safe evaluation of python code¶
-
pwnlib.util.safeeval.
const
(expression) → value[source]¶ Safe Python constant evaluation
Evaluates a string that contains an expression describing a Python constant. Strings that are not valid Python expressions or that contain other code besides the constant raise ValueError.
Examples
>>> const("10") 10 >>> const("[1,2, (3,4), {'foo':'bar'}]") [1, 2, (3, 4), {'foo': 'bar'}] >>> const("[1]+[2]") Traceback (most recent call last): ... ValueError: opcode BINARY_ADD not allowed
-
pwnlib.util.safeeval.
expr
(expression) → value[source]¶ Safe Python expression evaluation
Evaluates a string that contains an expression that only uses Python constants. This can be used to e.g. evaluate a numerical expression from an untrusted source.
Examples
>>> expr("1+2") 3 >>> expr("[1,2]*2") [1, 2, 1, 2] >>> expr("__import__('sys').modules") Traceback (most recent call last): ... ValueError: opcode LOAD_NAME not allowed
-
pwnlib.util.safeeval.
test_expr
(expr, allowed_codes) → codeobj[source]¶ Test that the expression contains only the listed opcodes. If the expression is valid and contains only allowed codes, return the compiled code object. Otherwise raise a ValueError
-
pwnlib.util.safeeval.
values
(expression, dict) → value[source]¶ Safe Python expression evaluation
Evaluates a string that contains an expression that only uses Python constants and values from a supplied dictionary. This can be used to e.g. evaluate e.g. an argument to a syscall.
- Note: This is potentially unsafe if e.g. the __add__ method has side
- effects.
Examples
>>> values("A + 4", {'A': 6}) 10 >>> class Foo: ... def __add__(self, other): ... print "Firing the missiles" >>> values("A + 1", {'A': Foo()}) Firing the missiles >>> values("A.x", {'A': Foo()}) Traceback (most recent call last): ... ValueError: opcode LOAD_ATTR not allowed
pwnlib.util.sh_string
— Shell Expansion is Hard¶
Routines here are for getting any NULL-terminated sequence of bytes evaluated intact by any shell. This includes all variants of quotes, whitespace, and non-printable characters.
Supported Shells¶
The following shells have been evaluated:
- Ubuntu (dash/sh)
- MacOS (GNU Bash)
- Zsh
- FreeBSD (sh)
- OpenBSD (sh)
- NetBSD (sh)
Debian Almquist shell (Dash)¶
Ubuntu 14.04 and 16.04 use the Dash shell, and /bin/sh is actually just a symlink to /bin/dash. The feature set supported when invoked as “sh” instead of “dash” is different, and we focus exclusively on the “/bin/sh” implementation.
From the Ubuntu Man Pages, every character except for single-quote can be wrapped in single-quotes, and a backslash can be used to escape unquoted single-quotes.
Quoting
Quoting is used to remove the special meaning of certain characters or
words to the shell, such as operators, whitespace, or keywords. There
are three types of quoting: matched single quotes, matched double quotes,
and backslash.
Backslash
A backslash preserves the literal meaning of the following character,
with the exception of ⟨newline⟩. A backslash preceding a ⟨newline⟩ is
treated as a line continuation.
Single Quotes
Enclosing characters in single quotes preserves the literal meaning of
all the characters (except single quotes, making it impossible to put
single-quotes in a single-quoted string).
Double Quotes
Enclosing characters within double quotes preserves the literal meaning
of all characters except dollarsign ($), backquote (`), and backslash
(\). The backslash inside double quotes is historically weird, and
serves to quote only the following characters:
$ ` " \ <newline>.
Otherwise it remains literal.
GNU Bash¶
The Bash shell is default on many systems, though it is not generally the default system-wide shell (i.e., the system syscall does not generally invoke it).
That said, its prevalence suggests that it also be addressed.
From the GNU Bash Manual, every character except for single-quote can be wrapped in single-quotes, and a backslash can be used to escape unquoted single-quotes.
3.1.2.1 Escape Character
A non-quoted backslash ‘\’ is the Bash escape character. It preserves the
literal value of the next character that follows, with the exception of
newline. If a ``\newline`` pair appears, and the backslash itself is not
quoted, the ``\newline`` is treated as a line continuation (that is, it
is removed from the input stream and effectively ignored).
3.1.2.2 Single Quotes
Enclosing characters in single quotes (‘'’) preserves the literal value of
each character within the quotes. A single quote may not occur between single
uotes, even when preceded by a backslash.
3.1.2.3 Double Quotes
Enclosing characters in double quotes (‘"’) preserves the literal value of a
ll characters within the quotes, with the exception of ‘$’, ‘`’, ‘\’, and,
when history expansion is enabled, ‘!’. The characters ‘$’ and ‘`’ retain their
pecial meaning within double quotes (see Shell Expansions). The backslash retains
its special meaning only when followed by one of the following characters:
‘$’, ‘`’, ‘"’, ‘\’, or newline. Within double quotes, backslashes that are
followed by one of these characters are removed. Backslashes preceding
characters without a special meaning are left unmodified. A double quote may
be quoted within double quotes by preceding it with a backslash. If enabled,
history expansion will be performed unless an ‘!’ appearing in double quotes
is escaped using a backslash. The backslash preceding the ‘!’ is not removed.
The special parameters ‘*’ and ‘@’ have special meaning when in double quotes
see Shell Parameter Expansion).
Z Shell¶
The Z shell is also a relatively common user shell, even though it’s not generally the default system-wide shell.
From the Z Shell Manual, every character except for single-quote can be wrapped in single-quotes, and a backslash can be used to escape unquoted single-quotes.
A character may be quoted (that is, made to stand for itself) by preceding
it with a ‘\’. ‘\’ followed by a newline is ignored.
A string enclosed between ‘$'’ and ‘'’ is processed the same way as the
string arguments of the print builtin, and the resulting string is considered
o be entirely quoted. A literal ‘'’ character can be included in the string
by using the ‘\'’ escape.
All characters enclosed between a pair of single quotes ('') that is not
preceded by a ‘$’ are quoted. A single quote cannot appear within single
quotes unless the option RC_QUOTES is set, in which case a pair of single
quotes are turned into a single quote. For example,
print ''''
outputs nothing apart from a newline if RC_QUOTES is not set, but one single
quote if it is set.
Inside double quotes (""), parameter and command substitution occur, and
‘\’ quotes the characters ‘\’, ‘`’, ‘"’, and ‘$’.
FreeBSD Shell¶
Compatibility with the FreeBSD shell is included for completeness.
From the FreeBSD man pages, every character except for single-quote can be wrapped in single-quotes, and a backslash can be used to escape unquoted single-quotes.
Quoting is used to remove the special meaning of certain characters or
words to the shell, such as operators, whitespace, keywords, or alias
names.
There are four types of quoting: matched single quotes, dollar-single
quotes, matched double quotes, and backslash.
Single Quotes
Enclosing characters in single quotes preserves the literal mean-
ing of all the characters (except single quotes, making it impos-
sible to put single-quotes in a single-quoted string).
Dollar-Single Quotes
Enclosing characters between $' and ' preserves the literal mean-
ing of all characters except backslashes and single quotes. A
backslash introduces a C-style escape sequence:
...
Double Quotes
Enclosing characters within double quotes preserves the literal
meaning of all characters except dollar sign (`$'), backquote
(``'), and backslash (`\'). The backslash inside double quotes
is historically weird. It remains literal unless it precedes the
following characters, which it serves to quote:
$ ` " \ \n
Backslash
A backslash preserves the literal meaning of the following char-
acter, with the exception of the newline character (`\n'). A
backslash preceding a newline is treated as a line continuation.
OpenBSD Shell¶
From the OpenBSD Man Pages, every character except for single-quote can be wrapped in single-quotes, and a backslash can be used to escape unquoted single-quotes.
A backslash (\) can be used to quote any character except a newline.
If a newline follows a backslash the shell removes them both, effectively
making the following line part of the current one.
A group of characters can be enclosed within single quotes (') to quote
every character within the quotes.
A group of characters can be enclosed within double quotes (") to quote
every character within the quotes except a backquote (`) or a dollar
sign ($), both of which retain their special meaning. A backslash (\)
within double quotes retains its special meaning, but only when followed
by a backquote, dollar sign, double quote, or another backslash.
An at sign (@) within double quotes has a special meaning
(see SPECIAL PARAMETERS, below).
NetBSD Shell¶
The NetBSD shell’s documentation is identical to the Dash documentation.
Android Shells¶
Android has gone through some number of shells.
- Mksh, a Korn shell, was used with Toolbox releases (5.0 and prior)
- Toybox, also derived from the Almquist Shell (6.0 and newer)
Notably, the Toolbox implementation is not POSIX compliant as it lacks a “printf” builtin (e.g. Android 5.0 emulator images).
Toybox Shell¶
Android 6.0 (and possibly other versions) use a shell based on toybox
.
While it does not include a printf
builtin, toybox
itself includes
a POSIX-compliant printf
binary.
The Ash shells should be feature-compatible with dash
.
BusyBox Shell¶
BusyBox’s Wikipedia page claims to use an ash
-compliant shell,
and should therefore be compatible with dash
.
-
pwnlib.util.sh_string.
sh_command_with
(f, arg0, ..., argN) → command[source]¶ Returns a command create by evaluating f(new_arg0, ..., new_argN) whenever f is a function and f % (new_arg0, ..., new_argN) otherwise.
If the arguments are purely alphanumeric, then they are simply passed to function. If they are simple to escape, they will be escaped and passed to the function.
If the arguments contain trailing newlines, then it is hard to use them directly because of a limitation in the posix shell. In this case the output from f is prepended with a bit of code to create the variables.
Examples
>>> sh_command_with(lambda: "echo hello") 'echo hello' >>> sh_command_with(lambda x: "echo " + x, "hello") 'echo hello' >>> sh_command_with(lambda x: "/bin/echo " + x, "\\x01") "/bin/echo '\\x01'" >>> sh_command_with(lambda x: "/bin/echo " + x, "\\x01\\n") "/bin/echo '\\x01\\n'" >>> sh_command_with("/bin/echo %s", "\\x01\\n") "/bin/echo '\\x01\\n'"
-
pwnlib.util.sh_string.
sh_prepare
(variables, export=False)[source]¶ Outputs a posix compliant shell command that will put the data specified by the dictionary into the environment.
It is assumed that the keys in the dictionary are valid variable names that does not need any escaping.
Parameters: It is assumed that var is a valid name for a variable in the shell.
Examples
>>> sh_prepare({'X': 'foobar'}) 'X=foobar' >>> r = sh_prepare({'X': 'foobar', 'Y': 'cookies'}) >>> r == 'X=foobar;Y=cookies' or r == 'Y=cookies;X=foobar' True >>> sh_prepare({'X': 'foo bar'}) "X='foo bar'" >>> sh_prepare({'X': "foo'bar"}) "X='foo'\\''bar'" >>> sh_prepare({'X': "foo\\\\bar"}) "X='foo\\\\bar'" >>> sh_prepare({'X': "foo\\\\'bar"}) "X='foo\\\\'\\''bar'" >>> sh_prepare({'X': "foo\\x01'bar"}) "X='foo\\x01'\\''bar'" >>> sh_prepare({'X': "foo\\x01'bar"}, export = True) "export X='foo\\x01'\\''bar'" >>> sh_prepare({'X': "foo\\x01'bar\\n"}) "X='foo\\x01'\\''bar\\n'" >>> sh_prepare({'X': "foo\\x01'bar\\n"}) "X='foo\\x01'\\''bar\\n'" >>> sh_prepare({'X': "foo\\x01'bar\\n"}, export = True) "export X='foo\\x01'\\''bar\\n'"
-
pwnlib.util.sh_string.
sh_string
(s)[source]¶ Outputs a string in a format that will be understood by /bin/sh.
If the string does not contain any bad characters, it will simply be returned, possibly with quotes. If it contains bad characters, it will be escaped in a way which is compatible with most known systems.
Warning
This does not play along well with the shell’s built-in “echo”. It works exactly as expected to set environment variables and arguments, unless it’s the shell-builtin echo.
- Argument:
- s(str): String to escape.
Examples
>>> sh_string('foobar') 'foobar' >>> sh_string('foo bar') "'foo bar'" >>> sh_string("foo'bar") "'foo'\\''bar'" >>> sh_string("foo\\\\bar") "'foo\\\\bar'" >>> sh_string("foo\\\\'bar") "'foo\\\\'\\''bar'" >>> sh_string("foo\\x01'bar") "'foo\\x01'\\''bar'"
-
pwnlib.util.sh_string.
test
(original)[source]¶ Tests the output provided by a shell interpreting a string
>>> test('foobar') >>> test('foo bar') >>> test('foo bar\n') >>> test("foo'bar") >>> test("foo\\\\bar") >>> test("foo\\\\'bar") >>> test("foo\\x01'bar") >>> test('\n') >>> test('\xff') >>> test(os.urandom(16 * 1024).replace('\x00', ''))
pwnlib.util.web
— Utilities for working with the WWW¶
-
pwnlib.util.web.
wget
(url, save=None, timeout=5) → str[source]¶ Downloads a file via HTTP/HTTPS.
Parameters: Example
>>> url = 'https://httpbin.org/robots.txt' >>> result = wget(url, timeout=60) >>> result 'User-agent: *\nDisallow: /deny\n' >>> result2 = wget(url, True, timeout=60) >>> result == file('robots.txt').read() True
pwnlib.testexample
— Example Test Module¶
Module-level documentation would go here, along with a general description of the functionality. You can also add module-level doctests.
You can see what the documentation for this module will look like here: https://docs.pwntools.com/en/stable/testexample.html
The tests for this module are run when the documentation is automatically-generated
by Sphinx. This particular module is invoked by an “automodule” directive, which
imports everything in the module, or everything listed in __all__
in the module.
The doctests are automatically picked up by the >>>
symbol, like from
the Python prompt. For more on doctests, see the Python documentation.
All of the syntax in this file is ReStructuredText. You can find a nice cheat sheet here.
Here’s an example of a module-level doctest:
>>> add(3, add(2, add(1, 0)))
6
If doctests are wrong / broken, you can disable them temporarily.
>>> add(2, 2)
5
Some things in Python are non-deterministic, like dict
or set
ordering. There are a lot of ways to work around this, but the
accepted way of doing this is to test for equality.
>>> a = {a:a+1 for a in range(3)}
>>> a == {0:1, 1:2, 2:3}
True
In order to use other modules, they need to be imported from the RST which documents the module.
>>> os.path.basename('foo/bar')
'bar'