CS 6264-OCY Overview Welcome to your new job as a penetration tester at TotallySafe Inc.! As a new member of the team, your manager comes to your cubicle and begins to talk about your first assignment. "...and you won't be able to use a debugger as they have compiled it using anti-debugging techniques." "Wait. What?" You should have been listening to your new boss from the beginning. "As I said, we want you to find THREE binary exploits in this application without needing a debugger. I expect this to be done in 3 weeks." "How..." "Just get it done!" Your boss cut you off before you could finish. "The exploit would most likely be a buffer overflow, so start there." This is going to be a looong career... you think to yourself as you pore over documentation on fuzzing tools and ROP-chain generators. Assignment The purpose of this assignment is to assess your ability to find tools that can help you create a binary exploit involving Buffer-Overflow, ROP chain, Use-After-Free. Note that you will not be able to use a debugger such as GDB in order to investigate a crash. We have also compiled it without debugging symbols to make reversing the binary more non-trivial (although not impossible) for you to encourage you to use the open-source tools. Furthermore, we have enabled DEP, meaning that any shellcode will be non-executable on the stack. If you do wish to debug, you will need topatch the binary yourselfLinks to an external site. . Lastly, we have $ checksec ./target Deliverables • The exploit: this should be a script you use to send some payload to the binary. We should be able to directly run the exploit to see the content of the file. Save your exploit as a Python file called exploit.py o Task1 - 20 pts o Task2 - 50 pts o Task3 - 10 pts (Bonus in Writeup) • A writeup: Save your writeup as a PDF file called writeup.pdf. This is worth 40 pts (10pts for task1, 20pts for task2, 10pts bonus for task3). This should include: o Detail the steps you took to find the exploit o Detail the steps you took to exploit the vulnerability o For example(task2): ▪ List the syscall functions you chose to execute to read the contents of the file and why those were selected ▪ List the gadgets you used for your ROP-chain and why those gadgets were selected • Bundle all files in a tarball in the following format: [GT Username]_cs6264_lab1.tar.gz. For example, a submission would be dzhang377_cs6264_lab1.tar.gz. • NOTE: If your submitted exploit does not work, include the approach you took to exploit the vulnerability in the write-up, as well as why you think it did not work, so partial credit can be given. Partial credit will also be given for the exploit code, so make sure to submit whatever you have.
● Basics of Binary Exploitation ○ Fuzzing ○ Finding overflow location ○ Leveraging overflow ● Binary Exploitation Defenses and Bypasses ● Further Reading Basics of Binary Exploitation Fuzzing ● Sending unexpected or invalid inputs to program to see if it crashes > ./program1 aaaaaaaaaaaaaaaa (no crash) > ./program1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa (no crash) > ./program1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Finding overflow location ● After an overflow is found, you will want to gain execution by controlling the value of the instruction pointer register (EIP) ● If an overflow exists in the stack, you are able to control the value of the EIP as the return address is popped off the stack upon a function return ● Location (offset) of return address can be found by having a unique string (i.e. Aa0Aa1Aa2Aa3…), then checking the value of EIP after the crash to find the location of that substring in the fuzzing string Fuzzing (cont.) ● Both processes can be automated with Angr: ○ Initialize an Angr project that will execute the binary ○ Initialize a simulation manager based on the project ○ Create a stash in the manager to put dumps of runs in which the memory is corrupt (i.e. sm.stashes['mem_corrupt'] = []) ○ Let the manager step through the program until it reaches an unconstrained state (i.e. a crash) ○ Check if the program can let the PC register point to a specific value while in the unconstrained state ○ If so, you have a memory corruption! If you print the input that allowed the simulation manager to reach this state and count the number of bytes until your specific value, you now know the offset at which you overwrite the return address!
Leveraging Overflow ● 2 main methods for program execution ● Shellcode ○ Directly execute shellcode from the stack after injecting a POP-RET gadget into the return address ○ After program POP-RETs, the EIP will be pointing to the top of the stack where the rest of the shellcode resides and will execute the shellcode ○ Can be generated with shellcraft module in pwntool Leveraging Overflow (cont.) ● Return-Oriented-Programming (ROP) ○ Usually used when you can’t execute code (i.e. instructions) on the stack (i.e. DEP is enabled in the binary) ○ Instead of actual instructions being on the stack, addresses to those instructions are inserted on the stack instead (called gadgets, must end with a RET instruction to get back to stack) ○ For example, you can execute some syscalls ■ Normally, an OS doesn’t allow the user/program to perform certain actions (i.e. opening a file, allocating memory, cleaning up a program after it exits, etc.) ■ If a user/program wishes to perform these actions, you will need to use a system call ■ Basically acts as an API to the underlying OS to execute those restricted actions Example: Setting up an OPEN syscall to open ‘flag’
Binary Defenses and Bypasses Binary Defenses and Bypasses ● Traditional Defenses - discussed in lectures ○ DEP - bypassed with ROP ○ ASLR - bypassed if you can leak an address like libc base or stack address ○ Canary - bypassed if canary is static and found by reversing binary ● Custom Defenses ○ Seccomp: limit the types of syscalls that you can make ■ Thus, if you wanted to make an exec() syscall, the program will exit with a SIGKILL or SIGSYS ○ Anti-debugging: prevent someone from attaching a debugger to the binary for reversing Binary Defenses and Bypasses (cont.) ● How to bypass custom defenses? ○ Seccomp ■ Can’t really bypass, so you will have to work within the limitations set by the binary ■ However, you can check what syscalls are allowed with Seccomp-tools ○ Anti-debugging ■ Find where the check for anti-debugging software happens in disassembler ■ Patch out the check in the binary so that you can attach a debugger ■ For example, maybe it checks a specific string value that will always be true when a program is run in with a debugger (hint, hint) ■ Then, you can either edit the bytecode to have a different test (i.e. changing JNZ to JZ) or edit the string it compares to to a different string Further Reading Automated Fuzzing Resources Uncover buffer overflow example (check #piecing-it-together for a full walkthrough) https://breakingbits.gitbook.io/breaking-bits/vulnerability-discovery/automated-exploit-development/ buffer-overflows angr solver example (while loop at line 67 is another example of finding the offset to overwrite the PC) https://github.com/angr/angr-doc/blob/master/examples/insomnihack_aeg/solve.py Seccomp Resources (secure computing mode) linux kernel security facility (first paragraph is a good overview) https://en.wikipedia.org/wiki/Seccomp Seccomp-bpf (third paragraph of the Wikipedia article is a helpful overview) an extension to seccomp that allows filtering of system calls seccomp-tools: tools for seccomp analysis AKA check what syscalls are allowed (check #command-line-interface for instructions for how to run) https://github.com/david942j/seccomptools Binary Patching Resources Patching with Ghidra at 3:35 https://www.youtube.com/watch?v=8U6JOQnOOkg with vim, Binary Ninja, Ghidra and radare2 https://www.youtube.com/watch?v=LyNyf3UM9Yc