pwntools的使用

November 16, 2018 PWN 访问: 30 次

pwntools

  • pwntools是一个二进制利用框架。官方文档提供了详细的api规范。然而目前并没有一个很好的新手教程。因此我用了我过去的几篇writeup。由于本文只是用来介绍pwntools使用方法,我不会过于详细的讲解各种二进制漏洞攻击技术。

使用方法

引入pwntools模块

from pwn import *

连接到我们指定的地址及端口,然后该函数会返回remote对象。

 remote("一个域名或者ip地址", 端口)

remote对象主要用来进行对远程主机的输入输出,它有如下几个方法:

  • send(payload)发送payload
  • sendline(payload)发送payload,并进行换行(末尾\n)
  • sendafter(some_string, payload)接收到 some_string 后,发送你的 payload
  • recvn(N) 接受 N(数字) 字符;
  • recvline() 接收一行输出;
  • recvlines(N)接收 N(数字) 行输出;
  • recvuntil(some_string)接收到 some_string 为止。
  • recvuntil(some_string,drop=True)接受到some_string为止前面的字符串
  • r.interactive() 获取到shell,进行交互

p32()、u32()

  • p**()可以让我们转换整数到小端序格式,p32转换4字节,p64和p16 则分别转换 8 bit 和 2 bit 数字
  • u**()可以将字符串转化为数字

debug调试输出

  • context.log_level="debug"脚本在执行时就会输出debug的信息,你可以通过观察这些信息查找哪步出错了

在pwntools写脚本的时候与GDB交互

  • pwnlib.gdb.attach(p)在发送payload前加入这条语句,同时加上pause() 时脚本暂停

  • 然后就会弹出来一个开启着gdb的终端,你先在gdb中设置好断点

  • 然后再运行脚本的那个终端按一下回车继续运行脚本,程序就会运行到断点,你就可以查看相应的寄存器,或者是栈的信息

ELF():用来操作elf的工具

  • 既可以操作ELF可执行文件,
e = ELF("./pwn") #用来加载一个文件
e.plt["funcname"] # 找出funcname在plt段中的地址
e.got["funcname"] # 找出funcname在got段中的地址
e.symbols["funcname"] #找出funcname在.text段中中的地址
e.search("/bin/sh").next() #找出“/bin/sh”在文件中的位置
e.bss() #返回该文件中bss段的首地址
  • 可以用来操作libc.so文件
libc = ELF("libc.so.6")
libc.address = function_real_addr - function_got   #libc.address赋值过之后再用libc.symbols查找函数时,地址是自动计算好的

DynELF

  • 通过信息泄露 获得远程函数地址
def leak(address):
    #函数体
d = DynELF(leak, main) # 创建一个没有程序的DynELF对象
d = DynELF(leak, main, elf=ELF('./pwnme')) # 创建一个有程序的DynELF对象
d.lookup('system', 'libc') # 显示system在内存中的地址

汇编与反汇编

  • asm('mov eax, 0')
  • disasm('\xb8\x0b\x00\x00\x00')

生成shellcode

context.arch = 'amd64'
shellcode = asm(shellcraft.amd64.sh())

一些小工具

#base64加密解密
b64e("test")
b64d('dGVzdA==')
#字符串与ASCII码的转换
enhex("test")
unhex("74657374")
#随机生成n个字符的字符串
randoms(n)

2019-9-14 总结

pwnlib.args:用于接收命令行传进的参数

#coding:utf-8
from pwn import *
print args
print "远程端口 : "+ args['IP']
print "远程地址 : "+ args['PORT']

out:

 一筐萝卜➜ test  python  study.py IP=127.0.0.1 PORT=12345
defaultdict(<type 'str'>, {'PLT_DEBUG': '', 'PORT': '12345', 'IP': '127.0.0.1'})
远程端口 : 127.0.0.1
远程地址 : 12345
 一筐萝卜➜ test

在python中直接运行字节码

#coding:utf-8
from pwn import *
binsh_code = asm(shellcraft.i386.sh())
filename = make_elf(binsh_code,extract=False)
p = process(filename)
p.sendline("ls")
print "-"*40
print p.recvline()
print "-"*40

out:

 一筐萝卜➜ test  python study.py
[+] Starting local process '/tmp/pwn-asm-L1xcN5/step3-elf': pid 16587
----------------------------------------
easy_heap  exp.py  study.py  test.py
----------------------------------------
[*] Stopped process '/tmp/pwn-asm-L1xcN5/step3-elf' (pid 16587)
 一筐萝卜➜ test

pwn.context:设置运行时的变量

使用context.binary自动设置所有适当的值
from pwn import *
context.binary='./pwn_file'

context.update:改写变量

context.update(os='linux',arch='amd64')

添加新评论