安全矩阵

 找回密码
 立即注册
搜索
查看: 4493|回复: 0

pwntools学习

[复制链接]

991

主题

1063

帖子

4315

积分

论坛元老

Rank: 8Rank: 8

积分
4315
发表于 2020-3-25 12:51:24 | 显示全部楼层 |阅读模式
本帖最后由 gclome 于 2020-3-25 12:52 编辑

本文转自 左岸风息 的博客

大致框架
官网的一个简单样例
  1. from pwn import *
  2. context(arch = 'i386', os = 'linux')
  3. r = remote('exploitme.example.com', 31337)
  4. EXPLOIT CODE GOES HERE
  5. r.send(asm(shellcraft.sh()))
  6. r.interactive()
复制代码
基本上仿造这个格式就可以写exp了。

  1. from pwn import *
复制代码
用来导入pwntools的模块

  1. context(arch = 'i386', os = 'linux')
复制代码
设置目标机的信息

  1. r = remote('exploitme.example.com', 31337)
复制代码
用来建立一个远程连接,url或者ip作为地址,然后指明端口这里也可以仅仅使用本地文件,调试时方便:
  1. r = process("./test")
复制代码
test即为文件名,这使得改变远程和本地十分方便.

  1. asm(shellcraft.sh())
复制代码
asm()函数接收一个字符串作为参数,得到汇编码的机器代码。 比如:
  1. >>> asm('mov eax, 0')
  2. '\xb8\x00\x00\x00\x00'
复制代码
shellcraft模块是shellcode的模块,包含一些生成shellcode的函数。其中的子模块声明架构,比如shellcraft.arm 是ARM架构的,shellcraft.amd64是AMD64架构,shellcraft.i386是Intel 80386架构的,以及有一个shellcraft.common是所有架构通用的。
而这里的shellcraft.sh()则是执行/bin/sh的shellcode了
r.send()将shellcode发送到远程连接
最后,
  1. r.interactive()
复制代码

将控制权交给用户,这样就可以使用打开的shell了

Context设置

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


数据打包

数据打包,即将整数值转换为32位或者64位地址一样的表示方式,比如0x400010表示为\x10\x00\x40一样,这使得我们构造payload变得很方便
用法:
* p32/p64: 打包一个整数,分别打包为32或64位
* u32/u64: 解包一个字符串,得到整数

p对应pack,打包,u对应unpack,解包,简单好记


  1. payload = p32(0xdeadbeef) # pack 32 bits number
复制代码

数据输出

如果需要输出一些信息,最好使用pwntools自带的,因为和pwntools本来的格式吻合,看起来也比较舒服,用法:
  1. some_str = "hello, world"
  2. log.info(some_str)
复制代码
其中的info代表是log等级,也可以使用其他log等级。


Cyclic Pattern

Cyclic pattern是一个很强大的功能,大概意思就是,使用pwntools生成一个pattern,pattern就是指一个字符串,可以通过其中的一部分数据去定位到他在一个字符串中的位置。
在我们完成栈溢出题目的时候,使用pattern可以大大的减少计算溢出点的时间。
用法:

  1. cyclic(0x100) # 生成一个0x100大小的pattern,即一个特殊的字符串
  2. cyclic_find(0x61616161) # 找到该数据在pattern中的位置
  3. cyclic_find('aaaa') # 查找位置也可以使用字符串去定位
复制代码
比如,我们在栈溢出的时候,首先构造cyclic(0x100),或者更长长度的pattern,进行输入,输入后pc的值变味了0x61616161,那么我们通过cyclic_find(0x61616161)就可以得到从哪一个字节开始会控制PC寄存器了,避免了很多没必要的计算。

汇编与shellcode

有的时候我们需要在写exp的时候用到简单的shellcode,pwntools提供了对简单的shellcode的支持。
首先,常用的,也是最简单的shellcode。shellcraft : shellcode的生成器。即调用/bin/sh可以通过shellcraft得到:
注意,由于各个平台,特别是32位和64位的shellcode不一样,所以最好先设置context。
  1. print(shellcraft.sh()) # 打印出shellcode
复制代码
不过,现在我们看到的shellcode还是汇编代码,不是能用的机器码,所以还需要进行一次汇编
  1. print(asm(shellcraft.sh())) # 打印出汇编后的shellcode
复制代码

asm可以对汇编代码进行汇编,不过pwntools目前的asm实现还有一些缺陷,比如不能支持相对跳转等等,只可以进行简单的汇编操作。如果需要更复杂一些的汇编功能,可以使用keystone-engine项目,这里就不再赘述了。asm也是架构相关,所以一定要先设置context,避免一些意想不到的错误。
asm也是架构相关,所以一定要先设置context,避免一些意想不到的错误。

ELF文件操作
  1. >>> e = ELF('/bin/cat')
  2. >>> print hex(e.address)  # 文件装载的基地址
  3. 0x400000
  4. >>> print hex(e.symbols['write']) # 函数地址
  5. 0x401680
  6. >>> print hex(e.got['write']) # GOT表的地址
  7. 0x60b070
  8. >>> print hex(e.plt['write']) # PLT的地址
  9. 0x401680
  10. >>> print hex(e.search('/bin/sh').next())# 字符串/bin/sh的地址
复制代码


原文见:https://www.cnblogs.com/liuyimin/
参考:http://brieflyx.me/2015/python-module/pwntools-intro/
https://www.dazhuanlan.com/2019/08/21/5d5c1d0106fcc/





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-27 22:26 , Processed in 0.014485 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表