Pwntools分为两个模块,一个是pwn,简单地使用“from pwn import *”即可将所有子模块和一些常用的系统库导入当前命名空间中,是专门针对CTF比赛优化的;而另一个模块是pwnlib,它更适合根据需要导入子模块,常用于基于Pwntools的二次开发。
下面是Pwntools的一些常用子模块。
? pwnlib.adb:安卓调试桥;
? pwnlib.asm:汇编和反汇编,支持i386/i686/amd64/thumb等;
? pwnlib.constants:包含各种体系结构和操作系统中的常量(来自头文件),如constants.linux.i386.SYS_stat;
? pwnlib.context:设置运行时变量;
? pwnlib.dynelf:利用信息泄露远程解析函数;
? pwnlib.encoders:对shellcode进行编码,如encoders.encoder.null('xxxx');
? pwnlib.elf:操作ELF可执行文件和共享库;
? pwnlib.fmtstr:格式化字符串利用工具;
? pwnlib.gdb:调试,与GDB配合使用;
? pwnlib.libcdb:libc数据库,如libcdb.search_by_build_id('xxxx');
? pwnlib.log:日志记录管理,如log.info('hello');
? pwnlib.memleak:内存泄露工具,将泄露的内存缓存起来,作为装饰器使用;
? pwnlib.qume:QEMU相关;
? pwnlib.rop:ROP利用工具,包括rop、srop等;
? pwnlib.runner:运行shellcode,例如run_assembly('mov eax, SYS_exit; int 0x80;');
? pwnlib.shellcraft:shellcode生成器;
? pwnlib.tubes:与sockets、processes、ssh等进行连接;
? pwnlib.util:一些实用小工具。
pwnlib.tubes
在漏洞利用中,首先需要与目标文件或者目标服务器进行交互,这就要用到tubes模块。
主要函数在pwnlib.tubes.tube中实现,子模块则只负责某个管道特殊的地方。4种管道及其对应的子模块如下所示。
? pwnlib.tubes.process:进程
○ p = process('/bin/sh')
? pwnlib.tubes.serialtube:串口
? pwnlib.tubes.sock:套接字
○ r = remote('127.0.0.1', 1080)
○ l = listen(1080)
? pwnlib.tubes.ssh:SSH
○ s = ssh(host='example.com, user='name', password='passwd')`
pwnlib.tubes.tube中的主要函数如下。
? interactive():交互模式,能够同时读写管道,通常在获得shell之后调用;
? recv(numb=1096, timeout=default):接收最多numb字节的数据;
? recvn(numb, timeout = default):接收numb字节的数据;
? recvall():接收数据直到EOF;
? recvline(keepends=True):接收一行,可选择是否保留行尾的“ ”;
? recvrepeat(timeout=default):接收数据直到EOF或timeout;
? recvuntil(delims, timeout=default):接收数据直到delims出现;
? send(data):发送数据;
? sendafter(delim, data,timeout=default):相当于recvuntil(delim, timeout)和send(data)的组合;
? sendline(data):发送一行,默认在行尾加“ ”;
? sendlineafter(delim, data, timeout=default):相当于recvuntil(delim, timeout)和sendline(data)的组合;
? close():关闭管道。
下面的例子先使用listen()开启一个本地的监听端口,然后使用remote()开启一个套接字管道与之交互。
下面则是一个与进程交互的例子。
pwnlib.context
该模块用于设置运行时变量,例如目标系统、目标体系结构、端序、日志等。
pwnlib.elf
该模块用于操作ELF文件,包括符号查找、虚拟内存、文件偏移,以及修改和保存二进制文件等功能。
上面的代码分别获得了ELF文件装载的基地址、符号地址、GOT地址和PLT地址。在CTF中,我们还常常用它加载一个libc,从而得到system()等所需函数的位置。
我们甚至可以修改ELF文件的代码:
下面列出一些常用函数。
? asm(address, assembly):汇编指令assemnbly并将其插入ELF的address地址处,需要使用ELF.save()函数来保存;
? bss(offset):返回.bss段加上offset后的地址;
? checksec():查看文件开启的安全保护;
? disable_nx():关闭NX;
? disasm(address, n_bytes):返回对地址address反汇编n字节的字符串;
? offset_to_vaddr(offset):将偏移offset转换为虚拟地址;
? vaddr_to_offset(address):将虚拟地址address转换为文件偏移;
? read(address, count):从虚拟地址address读取count个字节的数据;
? write(address, data):在虚拟地址address写入data;
? section(name):获取name段的数据;
? debug():使用gdb.debug()进行调试。
最后还要注意一下pwnlib.elf.corefile,它用于处理核心转储文件(Core Dump),当我们在写利用代码时,核心转储文件是非常有用的。
pwnlib.asm
该模块用于汇编和反汇编代码,请确保已安装对应体系结构的binutils。虽然体系结构、端序和字长可以作为asm()和disasm()的参数,但为了避免重复,运行时变量最好通过pwnlib.context来设置。汇编模块(pwnlib.asm.asm)如下。
反汇编模块(pwnlib.asm.disasm)如下。
构建具有指定二进制数据的ELF文件(pwnlib.asm.make_elf)。这里我们生成了amd64架构的shellcode,配合asm()函数,即可通过make_elf()函数得到ELF文件。
另一个函数pwnlib.asm.make_elf_from_assembly()则允许构建具有指定汇编代码的ELF文件,与make_elf()不同的是,make_elf_from_assembly()直接从汇编生成ELF文件,并且保留了所有的符号,例如标签和局部变量等。
pwnlib.shellcraft
使用shellcraft模块可以生成各种体系结构(aarch64、amd64、arm、i386、mips、thumb等)的shellcode代码。
pwnlib.gdb
在编写漏洞利用的时候,常常需要使用GDB动态调试,该模块就提供了这方面的支持。两个常用函数如下所示。
? gdb.attach(target, gdbscript=None):在一个新终端打开GDB并attach到指定PID的进程,或者一个pwnlib.tubes对象;
? gdb.debug(args, gdbscript=None):在新终端中使用GDB加载一个二进制文件。
这两种方法都可以传递一个脚本到GDB,很方便地做一些操作,例如设置断点:
pwnlib.dynelf
该模块(pwnlib.dynelf.DynELF)是专门用来应对无libc情况下的漏洞利用。它首先找到libc的基地址,然后使用符号表和字符串表对所有符号进行解析,直到找到我们需要的函数的符号。
pwnlib.fmtstr
该模块用于格式化字符串漏洞的利用,格式化字符串漏洞是CTF中一种常见的题型。
pwnlib.rop
rop模块分为两个子模块:pwnlib.rop.rop和pwnlib.rop.srop。前者是普通的rop模块,可以帮助我们构建ROP链;后者则提供了针对SROP的利用能力。
pwnlib.util
util其实是模块的集合,包含了一些实用的小工具。这里主要介绍两个,packing(pwnlib.util.packing)和 cyclic(pwnlib.util.cyclic)。
packing模块用于将整数打包和解包,是标准库中的struct.pack()和struct.unpack()函数的改造,同时增加了对任意宽度整数的支持。
使用p32()、p64()、u32()和u64()函数可以分别对32位和64位整数打包和解包,也可以使用pack()函数自己定义长度,添加参数endian和signed设置端序及是否带符号。
cyclic模块在缓冲区溢出中用于帮助生成模式字符串(de Bruijn序列),然后还可以查找偏移,以确定返回地址。
命令行工具
除了上面介绍的一系列模块,Pwntools还提供了一些有用的命令行工具,如下所示。
留言与评论(共有 0 条评论) “” |