CTF-2

Preliminaries

CTF-2 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-2 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 any support in such cases. If you are connecting remotely, use ssh(1) and follow the instructions provided by tstaff.

Copy ctf-2.tar.gz to your home directory and extract it; you should get ctf-2/, which, in turn, should contain the following files: Makefile, README, exp2.c, exp3.c, vcat2, vcat3, mget, and magic.txt. Make sure that no one else has access to ctf-2/ (e.g., chmod go-rx ctf-2), type cd ctf-2, and start hacking!

vcat2

vcat is back! vcat2 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 vcat2.

Similarly to CTF-1, you may run vcat2 by typing make vcat2_run. This make(1) directive wraps the execution of vcat2 with setarch i686 -R -3, which emulates a 32-bit x86 environment (i686), without support for address space layout randomization (-R), and with a proper 3GB user space (-3). Recall that the department machines are 64-bit; hence, do not invoke vcat2 directly, like ./vcat2, because you will end up solving a different assignment :-). Similarly, if you need to execute vcat2 under gdb(1), type make vcat2_dbg. To aid the exploitation process, we provide exp2 (exp2.c). This binary dumps in stdout(3) the contents of a particular payload (i.e., variable unsigned char payload[] in exp2.c). By running make vcat2_exp, make(1) will effectively execute ./exp2 | ./vcat2, under setarch i686 -R -3, thereby allowing you to feed vcat2 with the exact contents of unsigned char payload[]. Lastly, if you wish to execute ./exp2 | ./vcat2 under gdb(1), and attach the debugger to vcat2, run make vcat2_dbg and commence execution as follows: r < <(./exp2).

vcat2 contains a stack-based buffer overflow, and exp2 already exploits this vulnerability using the jmp *%esp technique. In particular, exp2 smashes the stack of vcat2, overwrites a (saved) return address with the address of a jmp *%esp gadget (located in the .text section of vcat2), and effectively transfers the control right above the overwritten return address on the stack. The payload variable (unsigned char payload[] in exp2.c) contains a template that transfers control to a “dummy” shellcode that consists of a single trap instruction (int 3), thereby raising a SIGTRAP signal and terminating the execution of vcat2.

  1. Flag 1 (20 points)
    • Replace int 3 (0xcc) with a proper shellcode for invoking the following (chain of) system calls: kill(getpid(), SIGUSR1). More specifically, first invoke getpid(), to get the process identifier (pid) of vcat2, and then proceed to call kill(), with pid and SIGUSR1 as first and second argument, respectively. What should be the value of payload (i.e., variable unsigned char payload[] in exp2.c) for getting the flag?
  2. Flag 2 (30 points)
    • Replace int 3 (0xcc) with a proper shellcode for invoking the following (chains of) system calls: write(open("magic.txt", O_WRONLY, 0), "xyzzy", 5); kill(getpid(), SIGUSR2). Start by invoking open(), for opening the file magic.txt, in write-only mode, and getting the respective file descriptor (fd). Next, proceed to call write(), using the fd you got from the previous call to open(), for writing the word “xyzzy” in magic.txt. Lastly, repeat the chain of system calls for flag 1 (kill(getpid(), SIGUSR2)), but this time invoke kill() with SIGUSR2. What should be the value of payload (i.e., variable unsigned char payload[] in exp2.c) for getting the flag?

vcat3

Similarly to vcat2, vcat3 is a vulnerable program that reads from stdin(3) and writes to stdout(3). Again, you are not given the source code of vcat3.

You may run vcat3 by typing make vcat3_run. Also, if you need to execute vcat3 under gdb(1), type make vcat3_dbg. To aid the exploitation process, we provide exp3 (exp3.c), which dumps in stdout(3) the contents of a particular payload (i.e., variable unsigned char payload[] in exp3.c). By running make vcat3_exp, make(1) will effectively execute ./exp3 | ./vcat3, allowing you to feed vcat3 with the exact contents of unsigned char payload[]. Lastly, if you wish to execute ./exp3 | ./vcat3 under gdb(1), and attach the debugger to vcat3, run make vcat3_dbg and commence execution as follows: r < <(./exp3).

vcat3 contains a stack-based buffer overflow, but it is hardened against code injection with executable space protection. exp3 contains a template payload (unsigned char payload[] in exp3.c) that smashes the stack of vcat3 and invokes exit(EXIT_SUCCESS) (i.e., the exit(3) routine of libc, not the exit system call), using the return-to-lib(c) technique, gracefully terminating the execution of vcat3.

  1. Flag 3 (10 points)
    • Modify the payload and invoke raise(SIGUSR1), instead of exit(EXIT_SUCCESS), using the return-to-libc (ret2libc) technique. What should be the value of payload (i.e., variable unsigned char payload[] in exp3.c) for getting the flag?
  2. Flag 4 (30 points)
    • Modify the payload and invoke the following sequence of libc routines: system("echo xyzzy > magic.txt"); raise(SIGUSR2); for this flag you have to leverage the ret2libc chaining technique. What should be the value of payload (i.e., variable unsigned char payload[] in exp3.c) for getting the flag?
  3. Flag 4+ (or 5) (10 points)
    • Modify the payload and invoke the following sequence of libc routines: open("magic.txt", O_WRONLY, 0); write(3, "xyzzy", 5); raise(SIGUSR2); for this flag you have to leverage both the ret2libc chaining and %esp lifting techniques. What should be the value of payload (i.e., variable unsigned char payload[] in exp3.c) for getting the flag?
  • Hints
    • SIGUSR1 = 0x0a, SIGUSR2 = 0x0c, and O_WRONLY = 0x01.
    • Address 0xb7f36946 (libc) contains the following gadget: add $0xc, %esp; ret; you may find it useful for %esp lifting.

Handin Instructions

  1. Run make mget_run and make mget_dbg (commence execution by typing r), and record the two (2) hexadecimal numbers printed in stdout(3).
  2. Your write-up template is README. First, edit section 0xf (whoami), and fill ‘Name’, ‘mget_run’, and ‘mget_dbg’, with your name and the two hexadecimal numbers your got by running the corresponding make(1) directives (step 1 above). Next, fill every other section (0x0 -- 0x5) with the respective 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 value(s), 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/cs1951h/bin/cs1951h_handin 0x2 from within ctf-2/ to submit your write-up -- you may want to alias that command for multiple submissions (or future write-ups). 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 1951H 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 write-up must be entirely your own work.