l = listen()
使用listen來(lái)開(kāi)啟一個(gè)本地的監(jiān)聽(tīng)端口
r = process("./test")
shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0')
pwn_ssh=ssh(host='pwnable.kr',user='fd',password='guest',port=2222)
使用ssh進(jìn)行遠(yuǎn)程連接進(jìn)行交互
>>> context.arch = 'i386'
>>> context.os = 'linux'
>>> context.endian = 'little'
>>> context.word_size = 32
可以使用context來(lái)指定cpu類(lèi)型以及操作系統(tǒng)伤靠,設(shè)定系統(tǒng)的指定參數(shù)峦树。對(duì)比如下:
>>> asm ('nop' )
'\ x90'
>>> context (arch = 'arm' , os = 'linux' , endian = 'big' , word_size = 32 )
>>> asm ('nop' )
' \ xe3 \ xf0 \ x00'
/////////////
設(shè)置記錄詳情
日志記錄的詳情:
Can also control logging verbosity and terminal fancyness
NOTERM
SILENT
DEBUG
>>> context.log_level = 'debug'
匯編和反匯編:
>>> 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
///////////////////////////////////////////////////////////
http://blog.csdn.net/gyhgx/article/details/53439417
http://www.91ri.org/14382.html
>>> 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'
下面是一些可用的函數(shù):
asm(address, assembly) : 在指定地址進(jìn)行匯編
bss(offset) : 返回bss段的位置峭判,offset是偏移值
checksec() : 對(duì)elf進(jìn)行一些安全保護(hù)檢查,例如NX, PIE等棕叫。
disasm(address, n_bytes) : 在指定位置進(jìn)行n_bytes個(gè)字節(jié)的反匯編
offset_to_vaddr(offset) : 將文件中的偏移offset轉(zhuǎn)換成虛擬地址VMA
vaddr_to_offset(address) : 與上面的函數(shù)作用相反
read(address, count) : 在address(VMA)位置讀取count個(gè)字節(jié)
write(address, data) : 在address(VMA)位置寫(xiě)入data
section(name) : dump出指定section的數(shù)據(jù)
Context設(shè)置:
context是pwntools用來(lái)設(shè)置環(huán)境的功能林螃。在很多時(shí)候,由于二進(jìn)制文件的情況不同俺泣,我們可能需要進(jìn)行一些環(huán)境設(shè)置才能夠正常運(yùn)行exp夸赫,比如有一些需要進(jìn)行匯編微峰,但是32的匯編和64的匯編不同,如果不設(shè)置context會(huì)導(dǎo)致一些問(wèn)題。
一般來(lái)說(shuō)我們?cè)O(shè)置context只需要簡(jiǎn)單的一句話:
context(os='linux', arch='amd64', log_level='debug')
這句話的意思是:
- os設(shè)置系統(tǒng)為linux系統(tǒng)禀综,在完成ctf題目的時(shí)候幽勒,大多數(shù)pwn題目的系統(tǒng)都是linux
- arch設(shè)置架構(gòu)為amd64桨昙,可以簡(jiǎn)單的認(rèn)為設(shè)置為64位的模式骡楼,對(duì)應(yīng)的32位模式是’i386’
- log_level設(shè)置日志輸出的等級(jí)為debug,這句話在調(diào)試的時(shí)候一般會(huì)設(shè)置赴肚,這樣pwntools會(huì)將完整的io過(guò)程都打印下來(lái)素跺,使得調(diào)試更加方便二蓝,可以避免在完成CTF題目時(shí)出現(xiàn)一些和IO相關(guān)的錯(cuò)誤。
////////////////////////////////////
DynELF
DynELF是leak信息的神器指厌。前提條件是要提供一個(gè)輸入地址刊愚,輸出此地址最少1byte數(shù)的函數(shù)。官網(wǎng)給出的說(shuō)明是:Given a function which can leak data at an arbitrary address, any symbol in any loaded library can be resolved
d = DynELF(leak, elf=ELF("./xxx")) #初始化DynELF模塊
///////////////////////////
gdb.debug 和 gdb.attach
1 用gdb啟動(dòng)程序,并彈出新窗口與其交互
2 附加到一個(gè)程序上,pid/pwnlibs.tubes/socket都可以
gdb.attach(proc.pidof(p)[0])
//////////////////////////
args 快速訪問(wèn)所有的命令行參數(shù)
python foo.py REMOTE=1
args['REMOTE'] == '1'
/////////////////
一些實(shí)用工具
Default
b64d('dGVzdA==')
b64e("test")
bits(511, zero = "+", one = "-") 把參數(shù)轉(zhuǎn)換為位
bits_str(511) 得到'0000000111111111'
enhex("test") 得到'74657374'
isprint(c) 判斷一個(gè)字符是否可打印
randoms(10) 返回'evafjilupm'
rol('abcdefg', 2) 得到'cdefgab'
unhex("74657374") 得到'test'
urldecode("test%20%41")
net 查詢(xún)網(wǎng)絡(luò)借口
proc 查詢(xún)進(jìn)程
pause
safeeval 執(zhí)行python代碼,但不會(huì)產(chǎn)生副作用
其他
Default
hexdump
read and write
enhex and unhex
more
group
align and align_down
urlencode and urldecode
which
wget
urlencode
常用模塊
asm 匯編與反匯編
dynelf 用于遠(yuǎn)程符號(hào)泄露踩验,需要提供leak方法
elf 對(duì)elf文件進(jìn)行操作
gdb 配合gdb進(jìn)行調(diào)試
memleak 用于內(nèi)存泄漏
shellcraft shellcode的生成器
tubes 包括tubes.sock鸥诽,tubes.process,tubes.ssh箕憾,tubes.serialtube衙传,分別適用于不同場(chǎng)景的PIPE
utils 一些實(shí)用的小功能,例如CRC計(jì)算厕九,cyclic pattern等
asm
把shellcode匯編成字節(jié)形式:
usage: asm [-h] [-f {raw,hex,string,elf}] [-o file] [-c context] [-v AVOID] [-n] [-z] [-d] [-e ENCODER] [-i INFILE] [-r] [line [line ...]]
line
Lines to assemble. If none are supplied, use stdin
鏈接到匯編,如果沒(méi)有提供地回,就使用標(biāo)準(zhǔn)輸入
-v <avoid>, --avoid <avoid>
避免出現(xiàn)不需要的字符(比如0x00)
-z, --zero
編碼shellcode避免NULL字節(jié)出現(xiàn)
-d, --debug
使用gdb調(diào)試shellcode
-e <encoder>, --encoder <encoder>
使用需要的編碼器
-i <infile>, --infile <infile>
需要指定的輸入文件
-r, --run
Run output
/////////////////////////////////////////
checksec
Check binary security settings
//////////////////////////////////////////////
constgrep
查找文件頭部的常量:
例如:
constgrep -c freebsd -m ^PROT_ ‘3 + 4’
regex
使用正則表達(dá)式匹配你要查找的內(nèi)容
constant
需要尋找的常數(shù)
-e <<constant name>>, --exact <<constant name>>
Do an exact match for a constant instead of searching for a regex
做一個(gè)精確匹配扁远,(這里說(shuō)的并不是搜索一個(gè)正則表達(dá)式)
-i, --case-insensitive
搜索不區(qū)分大小寫(xiě)
-m, --mask-mode
進(jìn)行模糊匹配,不要求嚴(yán)格匹配刻像,可以比匹配的字符少畅买。
-c <<opt>>, --context <<opt>>
程序運(yùn)行在什么樣的架構(gòu)之上(默認(rèn):linux/i386)
elfdiff
比較兩個(gè)對(duì)象的不同
cyclic
count:打印多少
-a <alphabet>, --alphabet <alphabet>
有什么符號(hào)代替字母表
-n
排列變化的,子字符串長(zhǎng)度
-l <lookup_value>, -o <lookup_value>, --offset <lookup_value>, --lookup <lookup_value>
Do a lookup instead printing the alphabet
pwn elfpatch
Patch an ELF file
usage: pwn [-h]
{asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update}
pwn phd
將文件按十六進(jìn)制輸出
-w <width>, --width <width>
每一行輸出的十六進(jìn)制個(gè)數(shù)
-l <highlight>, --highlight <highlight>
高亮顯示要查找的字節(jié)(參數(shù)放在程序的后面)
-s <skip>, --skip <skip>
跳過(guò)指定字節(jié)數(shù)開(kāi)始顯示
-c <count>, --count <count>
僅展示多少字節(jié)
-o <offset>, --offset <offset>
從左邊你需要的地址開(kāi)始執(zhí)行
--color {always,never,auto}
Colorize the output. When ‘a(chǎn)uto’ output is colorized exactly when stdout is a TTY. Default is ‘a(chǎn)uto’.
pwn pwnstrip
Strip binaries for CTF usage
-b, --build-id
Strip build ID
-p <function>, --patch <function>
Patch function
加載一個(gè)函數(shù)的功能 细睡,測(cè)試一堆二進(jìn)制文件
pwn scramble
Shellcode encoder
-f {raw,hex,string,elf}, --format {raw,hex,string,elf}
Output format (defaults to hex for ttys, otherwise raw)
不會(huì)用
pwn shellcraft
微軟的shellcode生成器
相關(guān)參數(shù)看如下網(wǎng)站:
http://pwntoolsdocinzh-cn.readthedocs.io/en/master/commandline.html#
pwn unhex
hex
把16進(jìn)制數(shù)轉(zhuǎn)化為標(biāo)準(zhǔn)輸入
pwnlib.adb — Android Debug Bridge
通過(guò)使用Android調(diào)試橋接器與Android設(shè)備進(jìn)行交互的程序谷羞。
Using Android Devices with Pwntools
- 1.最重要的就是context.device
- 在任意一個(gè)范圍內(nèi)選擇一個(gè)驅(qū)動(dòng)
- 手工的填寫(xiě)一個(gè)編號(hào)
- 添加一個(gè)設(shè)備的實(shí)例
獲得第一個(gè)有效的設(shè)備
context.device = adb.wait_for_device()
給設(shè)備添加一個(gè)編號(hào)
context.device = 'ZX1G22LH8S'
給設(shè)備設(shè)置名稱(chēng)
for device in adb.devices():
if device.product == 'shamu':
break
else:
error("Could not find any shamus!")
pwnlib.adb
通過(guò)此模塊你可以調(diào)用此設(shè)備的所有功能。
獲取一個(gè)進(jìn)程列表
print adb.process(['ps']).recvall()
獲取屬性
print adb.properties.ro.build.fingerprint
讀或者寫(xiě)入一個(gè)文檔
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)
系統(tǒng)的基本信息
例如:
>>> 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)
返回ABD子命令的輸出:
>>> adb.adb(['get-serialno'])
'emulator-5554\n'
pwnlib.adb.adb.boot_time() → int
設(shè)備的啟動(dòng)時(shí)間溜徙,采用四舍五入湃缎。
pwnlib.adb.adb.build(* a,** kw )
返回設(shè)備的Build ID
pwnlib.adb.adb.compile(source)
使用 Android NDK的源文件和項(xiàng)目
pwnlib.adb.adb.current_device(any=False)
返回context.device選中的adbDevice的實(shí)例
例子:
>>> 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)
返回連接設(shè)備相對(duì)應(yīng)的Device對(duì)象的列表
pwnlib.adb.adb.disable_verity(*a, **kw)
禁用設(shè)備上的dm-verity
pwnlib.adb.adb.exists(* a蠢壹,** kw )
返回目標(biāo)設(shè)備上路徑是否存在嗓违。
例子:
>>> adb.exists('/')
True
>>> adb.exists('/init')
True
>>> adb.exists('/does/not/exist')
False
wnlib.adb.adb.fastboot(*a, **kw)
執(zhí)行快速啟動(dòng)命令
返回:命令輸出結(jié)果
pwnlib.adb.adb.find_ndk_project_root(source)
給定一個(gè)目錄路徑,找到最頂層的項(xiàng)目根目錄
tl;dr “foo/bar/jni/baz.cpp” ==> “foo/bar”
pwnlib.adb.adb.fingerprint(*a, **kw)
返回設(shè)備的構(gòu)建的指紋信息
pwnlib.adb.adb.forward(*a, **kw)
設(shè)置端口已經(jīng)轉(zhuǎn)發(fā)的設(shè)備
pwnlib.adb.adb.getprop(*a, **kw)
從系統(tǒng)屬性存儲(chǔ)中讀取一個(gè)屬性图贸。
參數(shù): name(str)-選項(xiàng)蹂季,讀取一個(gè)屬性
返回:如果name沒(méi)有指定,將返回所有屬性的dict值疏日,否則將返回name的屬性值偿洁。
pwnlib.adb.adb.install(apk, *arguments)
在設(shè)備上安裝一個(gè)APK
pwnlib.adb.adb.install(apk, *arguments)
這是一個(gè)'pm install'封裝包,她支持'adb install'
參數(shù):
apk (str) 安裝路徑
arguments – 補(bǔ)充 參數(shù) ‘pm install’, e.g. '-l', '-g'.
pwnlib.adb.adb.interactive(* a沟优,** kw )
產(chǎn)生一個(gè)交互式的shell
pwnlib.adb.adb.isdir(* a涕滋,** kw )
返回目標(biāo)設(shè)備的路徑是否存在。
例子:
>>> adb.isdir('/')
True
>>> adb.isdir('/init')
False
>>> adb.isdir('/does/not/exist')
False
pwnlib.adb.adb.listdir(*a, **kw)
返回一個(gè)進(jìn)入設(shè)備目錄的的列表
注意:
在adbd SELinux環(huán)境中净神,使用運(yùn)行的SYNC LIST功能何吝。如果adbd在su域('adb root')中運(yùn)行溉委,則其行為與預(yù)期相同。
否則爱榕,由于adbd上的限制了SELinux策略瓣喊,可能會(huì)返回更少的文件。
pwnlib.adb.adb.logcat(*a, **kw)
讀取系統(tǒng)日志文件
默認(rèn)情況下黔酥,讀取文件后導(dǎo)致日志退出藻三。
參數(shù):
stream:如果是true,是流形式跪者,不是讀取形式棵帽,默認(rèn)是False
返回: 如果stream是False,返回包含日志數(shù)據(jù)的字符串渣玲,否則逗概,返回 pwnlib.tubes.tube.tube的連接到日志輸出。
pwnlib.adb.adb.makedirs(* a忘衍,** kw )
在目標(biāo)設(shè)備上創(chuàng)建一個(gè)目錄和所有父目錄逾苫。
注意:
如果目錄存在,它什么也不做枚钓。
例子:
>>> 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)
在目標(biāo)設(shè)備上建立目錄
注意:
如果目錄存在铅搓,它什么也不做。
參數(shù): path(str):目標(biāo)的路徑
例子:
>>> 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.packages(*a, **kw)
返回系統(tǒng)上安裝的軟件包列表
pwnlib.adb.adb.pidof(* a搀捷,** kw )
返回指定進(jìn)程的PID列表星掰。
pwnlib.adb.adb.proc_exe(* a,** kw )
返回,提供的PID的可執(zhí)行文件的完整路徑
pwnlib.adb.adb.process(* a嫩舟,** kw )
在設(shè)備上執(zhí)行一個(gè)進(jìn)程
請(qǐng)參閱pwnlib.tubes.process.process文檔了解更多信息氢烘。
Returns: A pwnlib.tubes.process.process tube.
例子:
>>> adb.root()
>>> print adb.process(['cat','/proc/version']).recvall()
Linux version ...
pwnlib.adb.adb.product(*a, **kw)
返回設(shè)備產(chǎn)品標(biāo)識(shí)符
pwnlib.adb.adb.pull(* a,** kw )
從設(shè)備下載文件
參數(shù):
remote_path(str) - 設(shè)備上文件的路徑或目錄
local_path(str) 保存文件的路徑至壤。在默認(rèn)情況下使用文件的名稱(chēng)威始。
返回:文件的內(nèi)容
例子:
>>> _=adb.pull('/proc/version', './proc-version')
>>> print read('./proc-version')
Linux version ...
pwnlib.adb.adb.push(* a,** kw )
上傳文件到設(shè)備
參數(shù):
local_path(str) 要推送的本地文件的路徑
remote_path(str) 將文件存儲(chǔ)在設(shè)備上的路徑或目錄
Returns:文件的遠(yuǎn)程路徑
例子:
>>> 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)
從設(shè)備下載文件像街,并提取其內(nèi)容
參數(shù):
path(str)設(shè)備上的文件路徑
target(str)可選黎棠,存儲(chǔ)文件的位置。默認(rèn)使用臨時(shí)文件
callback(callable)詳細(xì)文檔adb.protocol.AdbClient.read
例子:
>>> 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.reboot(* a镰绎,** kw )
重新啟動(dòng)設(shè)備
pwnlib.adb.adb.reboot_bootloader(* a脓斩,** kw )
從引導(dǎo)模式里重新啟動(dòng)
pwnlib.adb.adb.remount(* a,** kw )
將文件系統(tǒng)重新設(shè)置為可寫(xiě)
pwnlib.adb.adb.root(* a畴栖,** kw )
以root身份重新啟動(dòng) adbd
>>> adb.root()
pwnlib.adb.adb.setprop(*a, **kw)
將屬性寫(xiě)入系統(tǒng)屬性存儲(chǔ)區(qū)
pwnlib.adb.adb.shell(* a随静,** kw )
返回交互式shell。
pwnlib.adb.adb.uninstall(package, *arguments)
從設(shè)備上卸載APK。
這是'pm卸載'燎猛,它支持'adb'卸載恋捆。
參數(shù):
package(str)要卸載的包的名稱(chēng) (例 'com.foo.MyPackage')
arguments 補(bǔ)充參數(shù),例如 'pm install''-k'
pwnlib.adb.adb.unlink(* a重绷,** kw )
取消鏈接目標(biāo)設(shè)備上的文件或目錄
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 )
解鎖設(shè)備的引導(dǎo)程序
注意:
這需要與設(shè)備進(jìn)行物理交互
pwnlib.adb.adb.unroot(* a,** kw )
將adbd重新啟動(dòng)為AID_SHELL
pwnlib.adb.adb.uptime() →float
Returns:設(shè)備的正常運(yùn)行時(shí)間昭卓,以秒為單位
pwnlib.adb.adb.wait_for_device(* a愤钾,** kw )
等待設(shè)備連接
默認(rèn)情況下,等待當(dāng)前選擇的設(shè)備(通過(guò)context.device)候醒。要等待特定的設(shè)備能颁,請(qǐng)?jiān)O(shè)置context.device。要等待其它任何設(shè)備倒淫,必循清除context.device
Returns:AdbDevice設(shè)備的實(shí)例
例子:
>>> device = adb.wait_for_device()
pwnlib.adb.adb.which(*a, **kw)
檢索$PATH設(shè)備上二進(jìn)制文件的完整路徑
Parameters:
name (str) 二進(jìn)制名稱(chēng)
all(bool)返回所有路徑伙菊,還是只返回第一個(gè)
*a 其它參數(shù) adb.process()
**kw 其它參數(shù)adb.process()
Returns:
路徑或路徑列表
例子:
>>> 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)
[]
pwnlib.adb.adb.write(* a,** kw )
用提供的內(nèi)容在設(shè)備上創(chuàng)建一個(gè)文件
參數(shù):
path (str) 設(shè)備上文件的路徑
data(str) 存儲(chǔ)在文件中的內(nèi)容
例子
>>> adb.write('/dev/null', 'data')
>>> adb.write('/data/local/tmp/')
相關(guān)鏈接網(wǎng)站:
https://binjitsu.readthedocs.io/commandline.html#asm
pwntools學(xué)習(xí)網(wǎng)站:
http://pwntoolsdocinzh-cn.readthedocs.io/en/master/intro.html(中文網(wǎng)站)
https://etenal.me/archives/972
https://www.cnblogs.com/liuyimin/p/7512252.html(詳細(xì)清楚)
http://cheesehack.tistory.com/category/Etc/Pwntools%20reference(有些新的參數(shù)介紹)