11/22/2025, 11:59PM AoE (soft deadline) 12/01/2025, 11:59PM AoE (hard deadline)
CTF-4 is specifically designed
to run on the department machines. You are expected to do
all the development on that particular environment,
which is also what we will be using for grading. Do not run
CTF-4 on your personal desktop, laptop, VM, or any
other non-standard setting—you are free to do so, if you
insist or know what you are doing, but we are not going to
provide support in such cases. If you are connecting remotely,
use ssh(1) and follow the instructions
provided by tstaff.
Copy ctf-4.tar.gz to your home directory and
extract it; you should get ctf-4/, which, in turn,
should contain the following files: Makefile,
exp6.c, vcat6, and
README. Make sure that no one else has access to
ctf-4/ (e.g.,
chmod go-rx ctf-4), type cd ctf-4 and
start hacking!
Yes, it's the usual “suspect”:
vcat
:-). vcat6 is a vulnerable
program that reads from stdin(3) (standard input)
and writes to stdout(3) (standard output)—it
is roughly equivalent to executing cat -. As always,
you are not given the source code of
vcat6.
Similarly to CTF-1, CTF-2, and
CTF-3, you may run vcat6 by typing
make vcat6_run. This make(1) directive
wraps the execution of vcat6 with
setarch i686 -3, which emulates a 32-bit x86
environment (i686) with a proper 3GB user space
(-3). Recall that the department machines are
64-bit; hence, do not invoke vcat6 directly, like
./vcat6, because you will end up solving a different
assignment :-). Also, if you need to execute
vcat6 under gdb(1), type
make vcat6_dbg. To aid the exploitation process, we
provide exp6 (exp6.c), which: (a)
dumps in stdout(3) the value of macro
FMT_STR and the contents of variable
unsigned char payload[]; and (b) reads from
stdin(3) two hexadecimal values as two separate,
consecutive string literals (e.g.,
"0x4100feeb""0xb700cafe"). By running
make vcat6_exp, make(1) will effectively
execute ./exp6 < fifo | ./vcat6 > fifo,
allowing you to feed vcat6 with the exact
contents of FMT_STR and
unsigned char payload[], and exp6 with
the output of vcat6. Lastly, if you wish to execute
./exp6 | ./vcat6 under gdb(1), and
attach the debugger to vcat6, run
make vcat6_dbg and commence execution as follows:
r < <(sleep 1; ./exp6).
vcat6 contains both a stack-based buffer
overflow and a format string vulnerability. However, it is
hardened, against both code injection and code reuse,
with executable space protection
and full address space layout randomization;
vcat6 is a position-independent
executable (PIE). exp6 contains: (1) a format
string template (FMT_STR) for leaking two 4-byte
hexadecimal values from the stack of vcat6; and (2)
a template payload (unsigned char payload[]) that
overwrites a function pointer in the stack of
vcat6 and transfers control to address
0xdeadbeef. (Note that the stack-based buffer
overflow in vcat6 is bounded; you can only
corrupt/overwrite a function pointer adjacent to the vulnerable
buffer.)
mgk1, mgk2,
rnd1, and rnd2.vcat6: (1)
an address belonging to the .text
section of vcat6 (e.g., a
saved return address); and (b) an address
belonging to the .text section of
libc.so. The leaked output
should consist of two separate, consecutive
string literals: i.e.,
"0x4100feeb""0xb700cafe". What
should be the value of the format string
template (i.e.,
macro FMT_STR in
exp6.c) to achieve that?flag1(void). What should be the
value of payload (i.e., variable
unsigned char payload[] in
exp6.c) for getting the flag?
(You must modify exp6.c
in order to dynamically compose the required
payload.)0x0defaced (4 bytes) to
mgk1; and (b) invokes
flag2(void). What should be the
value of payload (i.e., variable
unsigned char payload[] in
exp6.c) for getting the flag?
(You must modify exp6.c
in order to dynamically compose the required
payload.)rnd1 and rnd2
(4 bytes each); (b) sets
mgk2 = rnd1 + rnd2; and (c)
invokes flag3(void). What
should be the value of payload (i.e.,
variable unsigned char payload[] in
exp6.c) for getting the flag?
(You must modify exp6.c
in order to dynamically compose the required
payload.)rnd1 and rnd2
(4 bytes each); (b) sets
mgk2 = rnd1 + rnd2 - 1; and (c)
restores the execution of
vcat6 right after the control-flow
hijacking point (i.e., right after the
dereference of the controlled function pointer).
What should be the value of payload
(i.e., variable
unsigned char payload[] in
exp6.c) for getting the flag?
(You must modify exp6.c
in order to dynamically compose the required
payload.)vcat6 under gdb(1),
but without feeding exp6
with the output of vcat6.
Therefore, the leaked addresses from the stack
of vcat6 will be printed in
stdout(3), allowing you to
experiment with different format string
templates until you complete
Warm-up. Once you have
successfully leaked the addresses belonging to
the .text section of
vcat6 and
libc.so, you can manually feed
them to exp6, by typing them in
stdin(3), which, in turn, will
compute the base address of vcat6
and libc.so (see variables
unsigned long baddr,
unsigned long laddr, and the
macros BIN_BASE_OFF and
LIBC_BASE_OFF in
exp6.c). Armed with that
information, you can then dynamically compute
the absolute address of each gadget, or symbol,
in vcat6 or
libc.so, and attempt the
respective flags.vcat6 and
libc.so, you have to
set BIN_BASE_OFF and
LIBC_BASE_OFF accordingly.vcat6 and
libc.so to successfully
capture flag 2, flag 3, and flag 4.mgk2 = rnd1 + rnd2 - 1, and then
un-pivot it for reliably continuing
the execution of vcat6.vcat6 and
libc.so.
vcat6 as follows:
exp6-flag1.c, ...,
exp6-flag4.c. If an exploit file is
missing, we will assume that your exploit does not work
properly and read your README file (see
below) for partial credit.
README.
First, edit section
0x0 (whoami), and fill
‘Name’,
‘Login’, and
‘Hostname’, with your (full)
name, CS login, and hostname(1) of the
machine that you tested all your exploits.
Next, fill every other section
(0x0 – 0x4) with the
corresponding answer(s) if you cannot capture
a flag: you can still get partial credit by
providing a brief description of your attack plan
(e.g., what exactly you plan on corrupting,
with what values, and why; or what you plan on
injecting, where, and why), the actions you took for
implementing it (i.e., partial or incomplete
payload values, memory dumps, and gdb(1)
excerpts), as well as your findings.ctf-4/ to submit
your hand-in—you may want to
alias
that command for multiple submissions. You can resubmit
as many times as you like, prior to the deadline, but
note that your old submission(s) will be
overwritten by the latest one.You should not discuss CTF-4 with anyone except the CSCI 1650 course staff. You may consult “outside sources of information”, but you must cite them; and you may rely on such sources only for concepts, not for solutions to problems—the hand-in must be entirely your own work.