信息安全专业知识黑客

pwntools ---前六节

2019-07-03  本文已影响18人  Black_Sun
l = listen()

使用listen来开启一个本地的监听端口

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进行远程连接进行交互

>>> context.arch      = 'i386'
>>> context.os        = 'linux'
>>> context.endian    = 'little'
>>> context.word_size = 32

可以使用context来指定cpu类型以及操作系统,设定系统的指定参数。对比如下:

>>> asm ('nop' )
'\ x90' 
>>> context (arch = 'arm' , os = 'linux' , endian = 'big' , word_size = 32 )
>>> asm ('nop' )
' \ xe3 \ xf0 \ x00'

/////////////
设置记录详情
日志记录的详情:
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'

下面是一些可用的函数:
asm(address, assembly) : 在指定地址进行汇编
bss(offset) : 返回bss段的位置,offset是偏移值
checksec() : 对elf进行一些安全保护检查,例如NX, PIE等。
disasm(address, n_bytes) : 在指定位置进行n_bytes个字节的反汇编
offset_to_vaddr(offset) : 将文件中的偏移offset转换成虚拟地址VMA
vaddr_to_offset(address) : 与上面的函数作用相反
read(address, count) : 在address(VMA)位置读取count个字节
write(address, data) : 在address(VMA)位置写入data
section(name) : dump出指定section的数据

Context设置:

context是pwntools用来设置环境的功能。在很多时候,由于二进制文件的情况不同,我们可能需要进行一些环境设置才能够正常运行exp,比如有一些需要进行汇编,但是32的汇编和64的汇编不同,如果不设置context会导致一些问题。
一般来说我们设置context只需要简单的一句话:

context(os='linux', arch='amd64', log_level='debug')

这句话的意思是:

  1. os设置系统为linux系统,在完成ctf题目的时候,大多数pwn题目的系统都是linux
  2. arch设置架构为amd64,可以简单的认为设置为64位的模式,对应的32位模式是’i386’
  3. log_level设置日志输出的等级为debug,这句话在调试的时候一般会设置,这样pwntools会将完整的io过程都打印下来,使得调试更加方便,可以避免在完成CTF题目时出现一些和IO相关的错误。
    ////////////////////////////////////
    DynELF
    DynELF是leak信息的神器。前提条件是要提供一个输入地址,输出此地址最少1byte数的函数。官网给出的说明是: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启动程序,并弹出新窗口与其交互
2 附加到一个程序上,pid/pwnlibs.tubes/socket都可以

gdb.attach(proc.pidof(p)[0])

//////////////////////////
args 快速访问所有的命令行参数

python foo.py REMOTE=1
args['REMOTE'] == '1'

/////////////////
一些实用工具

Default

b64d('dGVzdA==')

b64e("test")

bits(511, zero = "+", one = "-") 把参数转换为位

bits_str(511) 得到'0000000111111111'

enhex("test") 得到'74657374'

isprint(c) 判断一个字符是否可打印

randoms(10) 返回'evafjilupm'

rol('abcdefg', 2) 得到'cdefgab'

unhex("74657374") 得到'test'

urldecode("test%20%41")

net 查询网络借口
proc 查询进程
pause
safeeval 执行python代码,但不会产生副作用
其他

Default

hexdump
read and write
enhex and unhex
more
group
align and align_down
urlencode and urldecode
which
wget
urlencode

常用模块

asm 汇编与反汇编
dynelf 用于远程符号泄露,需要提供leak方法
elf 对elf文件进行操作
gdb 配合gdb进行调试
memleak 用于内存泄漏
shellcraft shellcode的生成器
tubes 包括tubes.sock,tubes.process,tubes.ssh,tubes.serialtube,分别适用于不同场景的PIPE
utils 一些实用的小功能,例如CRC计算,cyclic pattern等

asm

把shellcode汇编成字节形式:
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
链接到汇编,如果没有提供,就使用标准输入
-v <avoid>, --avoid <avoid>
避免出现不需要的字符(比如0x00)
-z, --zero
编码shellcode避免NULL字节出现
-d, --debug
使用gdb调试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
使用正则表达式匹配你要查找的内容

constant
需要寻找的常数
-e <<constant name>>, --exact <<constant name>>
Do an exact match for a constant instead of searching for a regex
做一个精确匹配,(这里说的并不是搜索一个正则表达式)
-i, --case-insensitive
搜索不区分大小写
-m, --mask-mode
进行模糊匹配,不要求严格匹配,可以比匹配的字符少。
-c <<opt>>, --context <<opt>>
程序运行在什么样的架构之上(默认:linux/i386)
elfdiff
比较两个对象的不同
cyclic
count:打印多少
-a <alphabet>, --alphabet <alphabet>
有什么符号代替字母表
-n
排列变化的,子字符串长度
-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
将文件按十六进制输出
-w <width>, --width <width>
每一行输出的十六进制个数
-l <highlight>, --highlight <highlight>
高亮显示要查找的字节(参数放在程序的后面)
-s <skip>, --skip <skip>
跳过指定字节数开始显示
-c <count>, --count <count>
仅展示多少字节
-o <offset>, --offset <offset>
从左边你需要的地址开始执行
--color {always,never,auto}
Colorize the output. When ‘auto’ output is colorized exactly when stdout is a TTY. Default is ‘auto’.
pwn pwnstrip
Strip binaries for CTF usage
-b, --build-id
Strip build ID

-p <function>, --patch <function>
Patch function
加载一个函数的功能 ,测试一堆二进制文件

pwn scramble
Shellcode encoder
-f {raw,hex,string,elf}, --format {raw,hex,string,elf}
Output format (defaults to hex for ttys, otherwise raw)

不会用
pwn shellcraft
微软的shellcode生成器
相关参数看如下网站:
http://pwntoolsdocinzh-cn.readthedocs.io/en/master/commandline.html#
pwn unhex
hex
把16进制数转化为标准输入

pwnlib.adb — Android Debug Bridge

通过使用Android调试桥接器与Android设备进行交互的程序。
Using Android Devices with Pwntools

获得第一个有效的设备
context.device = adb.wait_for_device()
 给设备添加一个编号
context.device = 'ZX1G22LH8S'
给设备设置名称
for device in adb.devices():
    if device.product == 'shamu':
        break
else:
    error("Could not find any shamus!")

pwnlib.adb
通过此模块你可以调用此设备的所有功能。

获取一个进程列表
print adb.process(['ps']).recvall()

获取属性
print adb.properties.ro.build.fingerprint

读或者写入一个文档
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)
系统的基本信息

例如:

>>> 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
设备的启动时间,采用四舍五入。

pwnlib.adb.adb.build(* a,** kw )
返回设备的Build ID

pwnlib.adb.adb.compile(source)
使用 Android NDK的源文件和项目

pwnlib.adb.adb.current_device(any=False)
返回context.device选中的adbDevice的实例
例子:

>>> 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)
返回连接设备相对应的Device对象的列表

pwnlib.adb.adb.disable_verity(*a, **kw)
禁用设备上的dm-verity

pwnlib.adb.adb.exists(* a,** kw )
返回目标设备上路径是否存在。

例子:

>>> adb.exists('/')
True
>>> adb.exists('/init')
True
>>> adb.exists('/does/not/exist')
False

wnlib.adb.adb.fastboot(*a, **kw)
执行快速启动命令
返回:命令输出结果

pwnlib.adb.adb.find_ndk_project_root(source)
给定一个目录路径,找到最顶层的项目根目录
tl;dr “foo/bar/jni/baz.cpp” ==> “foo/bar”

pwnlib.adb.adb.fingerprint(*a, **kw)
返回设备的构建的指纹信息

pwnlib.adb.adb.forward(*a, **kw)
设置端口已经转发的设备

pwnlib.adb.adb.getprop(*a, **kw)
从系统属性存储中读取一个属性。
参数: name(str)-选项,读取一个属性
返回:如果name没有指定,将返回所有属性的dict值,否则将返回name的属性值。

pwnlib.adb.adb.install(apk, *arguments)
在设备上安装一个APK

pwnlib.adb.adb.install(apk, *arguments)
这是一个'pm install'封装包,她支持'adb install'
参数:
apk (str) 安装路径
arguments – 补充 参数 ‘pm install’, e.g. '-l', '-g'.

pwnlib.adb.adb.interactive(* a,** kw )
产生一个交互式的shell

pwnlib.adb.adb.isdir(* a,** kw )
返回目标设备的路径是否存在。
例子:

>>> adb.isdir('/')
True
>>> adb.isdir('/init')
False
>>> adb.isdir('/does/not/exist')
False

pwnlib.adb.adb.listdir(*a, **kw)
返回一个进入设备目录的的列表
注意:
在adbd SELinux环境中,使用运行的SYNC LIST功能。如果adbd在su域('adb root')中运行,则其行为与预期相同。
否则,由于adbd上的限制了SELinux策略,可能会返回更少的文件。

pwnlib.adb.adb.logcat(*a, **kw)
读取系统日志文件
默认情况下,读取文件后导致日志退出。
参数:
stream:如果是true,是流形式,不是读取形式,默认是False
返回: 如果stream是False,返回包含日志数据的字符串,否则,返回 pwnlib.tubes.tube.tube的连接到日志输出。

pwnlib.adb.adb.makedirs(* a,** kw )
在目标设备上创建一个目录和所有父目录。
注意:
如果目录存在,它什么也不做。

例子:

>>> 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)
在目标设备上建立目录
注意:
如果目录存在,它什么也不做。
参数: path(str):目标的路径

例子:

>>> 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)
返回系统上安装的软件包列表

pwnlib.adb.adb.pidof(* a,** kw )
返回指定进程的PID列表。

pwnlib.adb.adb.proc_exe(* a,** kw )
返回,提供的PID的可执行文件的完整路径

pwnlib.adb.adb.process(* a,** kw )
在设备上执行一个进程
请参阅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)
返回设备产品标识符

pwnlib.adb.adb.pull(* a,** kw )
从设备下载文件
参数:
remote_path(str) - 设备上文件的路径或目录
local_path(str) 保存文件的路径。在默认情况下使用文件的名称。
返回:文件的内容

例子:

>>> _=adb.pull('/proc/version', './proc-version')
>>> print read('./proc-version') 
Linux version ...

pwnlib.adb.adb.push(* a,** kw )
上传文件到设备
参数:
local_path(str) 要推送的本地文件的路径
remote_path(str) 将文件存储在设备上的路径或目录
Returns:文件的远程路径

例子:

>>> 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)
从设备下载文件,并提取其内容
参数:
path(str)设备上的文件路径
target(str)可选,存储文件的位置。默认使用临时文件
callback(callable)详细文档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 )
重新启动设备

pwnlib.adb.adb.reboot_bootloader(* a,** kw )
从引导模式里重新启动

pwnlib.adb.adb.remount(* a,** kw )
将文件系统重新设置为可写

pwnlib.adb.adb.root(* a,** kw )
以root身份重新启动 adbd

>>> adb.root()

pwnlib.adb.adb.setprop(*a, **kw)
将属性写入系统属性存储区

pwnlib.adb.adb.shell(* a,** kw )
返回交互式shell。

pwnlib.adb.adb.uninstall(package, *arguments)
从设备上卸载APK。
这是'pm卸载',它支持'adb'卸载。

参数:
package(str)要卸载的包的名称 (例 'com.foo.MyPackage')
arguments 补充参数,例如 'pm install''-k'

pwnlib.adb.adb.unlink(* a,** kw )
取消链接目标设备上的文件或目录

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 )
解锁设备的引导程序
注意:
这需要与设备进行物理交互

pwnlib.adb.adb.unroot(* a,** kw )
将adbd重新启动为AID_SHELL

pwnlib.adb.adb.uptime() →float
Returns:设备的正常运行时间,以秒为单位

pwnlib.adb.adb.wait_for_device(* a,** kw )
等待设备连接
默认情况下,等待当前选择的设备(通过context.device)。要等待特定的设备,请设置context.device。要等待其它任何设备,必循清除context.device
Returns:AdbDevice设备的实例

例子:

>>> device = adb.wait_for_device()

pwnlib.adb.adb.which(*a, **kw)
检索$PATH设备上二进制文件的完整路径
Parameters:
name (str) 二进制名称
all(bool)返回所有路径,还是只返回第一个
*a 其它参数 adb.process()
**kw 其它参数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 )
用提供的内容在设备上创建一个文件
参数:
path (str) 设备上文件的路径
data(str) 存储在文件中的内容

例子

>>> adb.write('/dev/null', 'data')
>>> adb.write('/data/local/tmp/')

相关链接网站:
https://binjitsu.readthedocs.io/commandline.html#asm

pwntools学习网站:
http://pwntoolsdocinzh-cn.readthedocs.io/en/master/intro.html(中文网站)
https://etenal.me/archives/972
https://www.cnblogs.com/liuyimin/p/7512252.html(详细清楚)
http://cheesehack.tistory.com/category/Etc/Pwntools%20reference(有些新的参数介绍)

上一篇下一篇

猜你喜欢

热点阅读