CTF-1

Preliminaries

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, vcat1, and README. Make sure that no one else has access to ctf-1/ (e.g., chmod go-rx ctf-1), type cd ctf-1 and start hacking!

vcat0

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.

  1. Warm-up (5 points)
    • Disassemble vcat0 and provide a list of all its executable functions, along with their addresses. For example: 0xdeadbeef main, 0xdeadc0de foo, 0x0defaced bar, 0x0badf00d xyzzy, etc.
    • Replace the payload (i.e., variable unsigned char payload[] in exp0.c) with 'X'...'X', until you get a segfault on vcat0. (In other words, try "X", "XX", ..., until vcat0 crashes). What is the maximum size of the payload (in bytes) that does not crash vcat0? (That specific payload plus a single 'X' should trigger a segfault.)
    • Hint You may find readelf(1), objdump(1), nm(1), or even gdb(1) useful for this task.
  1. Flag 1 (10 points)
    • Smash the stack of 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?
  2. Flag 2 (10 points)
    • Smash the stack of 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?
  3. Flag 3 (15 points)
    • Smash the stack of 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?
  • Extra Credit (5 points)
    • Make the payload for flag 3 stack-independent. (The payload should not include absolute stack references.)

vcat1

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.

  1. Flag 4 (10 points)
    • The payload variable (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?
  • Extra Credit (15 points)
    • Make the payload for flag 4 stack-independent. (The payload should not include absolute stack references.) Furthermore, you may not use a jmp *%esp gadget.
  1. Flag 4+ (or 5) (20 points)
    • The payload variable (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 middle of the payload. What should be the value of payload (i.e., variable unsigned char payload[] in exp1.c) for getting the flag?
  2. Flag 4++ (or 6) (20 points)
    • The payload variable (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, located in the .text section of vcat1. What should be the value of payload (i.e., variable unsigned char payload[] in exp1.c) for getting the flag?
    • Hint You need to remove the first instruction of the shellcode (add $0x40, %esp) to get this flag. Why?
  3. Flag 7 (10 points)
    • The payload (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)?

Handin Instructions

  1. Save the payload(s) of your functioning exploit(s) by executing ./exp0 > flag# or ./exp1 > flag#, where # is the respective flag number (e.g., to dump the payload for flag 5, run ./exp1 > flag5, once make vcat1_exp succeeds). Dump all the seven functioning payloads in separate files, named flag1, flag2, etc. 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.
  2. Your write-up template is README. First, edit section 0xf (whoami), and fill ‘Name’ and ‘Login’, with your (full) name and CS login, respectively. Next, fill every other section (0x00x7) 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.
  3. Run /course/cs1650/bin/cs1650_handin 0x1 from within 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.

Collaboration Policy

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.