10/08/2025, 11:59PM AoE (soft deadline) 10/14/2025, 11:59PM AoE (hard deadline)
CTF-1 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-1 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-1.tar.gz to your home directory and
extract it; you should get ctf-1/, which, in turn,
should contain the following files: Makefile,
exp0.c, exp1.c, vcat0.o,
vcat1.o, hlp.o, trnd,
magic.so, and README. Make sure that
(1) no one else has access to ctf-1/
(e.g., chmod go-rx ctf-1) and
(2) trnd can be executed
(e.g., chmod u+x trnd). Type
cd ctf-1 and start hacking!
vcat0 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 -. Note that you are
not given the source code of vcat0.
You may execute vcat0 by typing
make vcat0_run. This make(1) directive
wraps the execution of vcat0 with
setarch i686 -3 -R, which emulates a 32-bit x86
environment (i686), with a proper 3GB user space
(-3) and without support for address space layout randomization
(-R). Recall that the department machines are
64-bit; hence, do not invoke vcat0 directly, like
./vcat0, because you will end up solving a different
assignment :-). Similarly, if you need to execute
vcat0 under gdb(1), type
make vcat0_dbg. More importantly, to aid the
exploitation process, we provide exp0
(exp0.c). This binary dumps in
stdout(3) the contents of a particular payload
(i.e., variable unsigned char payload[]
in exp0.c). By running make vcat0_exp,
make(1) will effectively execute
./exp0 | ./vcat0, under
setarch i686 -3 -R, thereby allowing you to feed
vcat0 with the exact contents of
unsigned char payload[]. Lastly, if you wish to
execute ./exp0 | ./vcat0 under gdb(1),
and attach the debugger to vcat0, run
make vcat0_dbg and commence execution as follows:
r < <(./exp0).
vcat0 contains a stack-based buffer overflow.
vcat0 and
redirect execution to function
flag1(void). What should be the
value of payload (i.e., variable
unsigned char payload[] in
exp0.c) for getting the flag?vcat0 and
redirect execution to function
flag2(int). Note that this function
takes as argument an integer, and you need to
invoke is as follows:
flag2(0xdeadbeef). What should be
the value of payload (i.e., variable
unsigned char payload[] in
exp0.c) for getting the flag?vcat0 and
redirect execution to function
flag3(char *). Note that this
function takes as argument a string, and you
need to invoke is as follows:
flag3("pwn3d"). What should be the
value of payload (i.e., variable
unsigned char payload[] in
exp0.c) for getting the flag?
Similarly to vcat0, vcat1 is a
vulnerable program that reads from
stdin(3) and writes to stdout(3).
Again, you are not given the source code of
vcat1.
You may run vcat1 by typing
make vcat1_run. Also, if you need to execute
vcat1 under gdb(1), type
make vcat1_dbg. To aid the exploitation process, we
provide exp1 (exp1.c), which dumps in
stdout(3) the contents of a particular payload
(i.e., variable unsigned char payload[]
in exp1.c). By running make vcat1_exp,
make(1) will effectively execute
./exp1 | ./vcat1, allowing you to feed
vcat1 with the exact contents of
unsigned char payload[]. Lastly, if you wish to
execute ./exp1 | ./vcat1 under gdb(1),
and attach the debugger to vcat1, run
make vcat1_dbg and commence execution as follows:
r < <(./exp1).
vcat1 contains a stack-based buffer overflow.
unsigned char payload[] in
exp1.c) already contains a proper
shellcode. Smash the stack of vcat1
and redirect execution to the given
shellcode. What should be the value of payload
(i.e., variable
unsigned char payload[] in
exp1.c) for getting the flag?jmp *%esp gadget.unsigned char payload[] in
exp1.c) contains the shellcode at
its beginning. Smash the stack of
vcat1 and redirect execution to the
given shellcode using the
NOP sled technique.
Specifically, move the shellcode closer to the
saved return address (preferably right below
it), and replace the beginning of the payload
with NOP instructions (up to the
shellcode). Lastly, transfer control to the
shellcode by jumping in the middleof the payload. What should be the value of payload (i.e., variable
unsigned char payload[] in
exp1.c) for getting the flag?unsigned char payload[] in
exp1.c) contains a shellcode at its
beginning. Smash the stack of vcat1
and redirect execution to the given shellcode
using the
jmp *%esp technique. That is,
move the shellcode right above the saved return
address, and overwrite the return address with
the address of a jmp *%esp gadget.
What should be the value of payload
(i.e., variable
unsigned char payload[] in
exp1.c) for getting the flag?add $0x40, %esp instruction of the
shellcode to get this flag.unsigned char payload[] in
exp1.c) contains a shellcode that
includes NULL bytes
(0x00). Construct an
equivalent shellcode that does not have
NULL bytes in it. What is the value
of this NULL-free payload
(i.e., variable
unsigned char payload[] in
exp1.c)?flag7 file should contain
only shellcode; not an end-to-end
payload that captures a particular flag.flag1, flag2, etc.
You can double-check that you have correctly dumped a
functioning payload (e.g., you have not
accidentally corrupted it, or overwritten it, with
something else) by running
make vcat#_run < flag#
(or cat flag# | make vcat#_run), where
# is the respective flag number. Note that
for flag 7, the payload file flag7 should
only contain the NULL-free
shellcode; not an end-to-end payload that captures
flag 4, flag 5, or flag 6. If a payload file is
missing, we will assume that your exploit does not work
properly and read your README file (see
below) for partial credit. You do not need to
submit separate payloads for the extra credit; if the
respective payload is stack-independent you will get
the extra points automatically.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
(0x1 – 0x7) 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-1/ to submit
your hand-in—you may want to
alias
that command for multiple submissions (or future
hand-ins). 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-1 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.