Foundations of Computer Systems
|Assigned:||Wednesday, March 17|
|Checkpoint 1:||Friday, March 26, 11:59 pm. Phase 1 should be defused by this checkpoint.|
|Checkpoint 2:||Thursday, April 1, 11:59 pm. Phases 2 and 3 should be defused by this checkpoint.|
|Due Date:||Thursday, April 8, 11:59 pm. All phases should be defused.|
|Collaboration Policy:||Level 1|
This lab will give you experience with x86-64 machine code and reverse-engineering, in addition to extensive practice with the debugger. Your task is to defuse a BitBomb planted on the class server by reverse-engineering it to discover its defusal codes!
Safety Notice: Read through the full writeup before tackling your bitbomb; do not immediately (and blindly) execute it!
Agents of the nefarious organization BitBombs Inc. have infiltrated the CSCI 2330 server and planted a set of BitBombs on our machine. A BitBomb is a compiled executable program that consists of a sequence of six phases, each wired to explode and wreak havoc on our bits. The bitbombs are on timers and are set to detonate at midnight on April 7. Luckily, each bitbomb contains a failsafe mechanism - each phase of the bitbomb can be bypassed if a specific defusal code is entered. However, if an incorrect defusal code is entered for any phase, the bitbomb will immediately explode.
There are too many bitbombs for one person to handle, so each of you will be provided with your own bitbomb to defuse. Your task is to safely defuse your bitbomb before it detonates. Good luck - our bits are counting on you!
Once you accept the lab repository on GitHub, I will place your personal BitBomb (and associated files) in your repository. Once this is done, do a
git pull to fetch them. Once you have done this, there will be several key files in your lab directory:
bitbomb: Your unique bitbomb executable.
bitbomb.c: Some code that BitBombs Inc. left lying around (we think it might be useful).
codes.txt: File in which you will write your defusal codes.
descriptions.txt: File in which you will describe your defusal solutions.
ID: File containing your unique BitBomb ID.
Safety Notice: You should ONLY execute the bitbomb on the class server. Attempting to execute your bitbomb on any other machine will detonate it immediately!
Execute the bitbomb to begin the defusal process:
When executed, the bitbomb will wait for you to enter a defusal code, which will be passed to the current phase. If the code is correct, the phase will be bypassed and you will be prompted to enter the code for the next phase. If the code is incorrect, the bitbomb will explode. If you enter all six correct defusal codes, the bitbomb will be defused. Note that pressing enter without typing anything still constitutes submitting a defusal code!
Safety Notice: Our server has been outfitted with a bitbomb monitoring system, which will automatically detect and record bitbomb explosions. Practice safe bitbomb handling and don't blindly execute your bitbomb!
The bitbomb will start from phase 1 each time you execute it. To avoid having to re-enter earlier defusal codes each time you run the bitbomb, you should enter your codes in
codes.txt as you discover them, one phase per line. Then, you can pass this file to your bitbomb when you execute it to automatically feed it your codes:
$ ./bitbomb codes.txt
Once all the codes from
codes.txt have been given to the bitbomb, it will switch over to prompting for manual defusal codes as normal.
To discover the defusal codes and avoid accidentally setting off the bitbomb, you will need to use a debugger (GDB) to set breakpoints, step through the bitbomb, and inspect its state. However, this will be substantially more challenging than in the previous lab, because you will (mostly) not have any source code to reference! Instead, you will need to reverse-engineer your bitbomb by inspecting its assembly instructions.
To run the bitbomb using the debugger
gdb and pass it a codes file, you can run the following:
$ gdb bitbomb ... startup messages from gdb ... (gdb) run codes.txt
To run your bitbomb in
gdb without passing it any initial codes, you can simply type
run at the initial
See the tools and advice sections below for more tips on defusing your bitbomb.
You are responsible for two tasks:
You should organize your descriptions by phase (i.e., each phase should have a code and a corresponding description). Each description should be a short paragraph or two describing what the phase is doing with your input (to the best of your understanding), and how you determined the correct input.
The objective of your descriptions should not be a line-by-line explanation of what each individual assembly command is doing (though you'll largely need to understand that regardless), but rather to show that you understand how the entire phase fits together at a higher level. Ideally, your documentation should describe the behavior of the phase at the level of comments you might write for a regular C program (e.g., "searches for the largest value in an array"). You may not understand every aspect of what each phase is doing (and that's okay) but your descriptions should explain what insights you've learned and how they led you to discovering your defusal codes.
Note that a description like "I tried a bunch of random codes and this one worked" is not (by itself) a good description! Even if you happen to stumble across a working defusal code, you should still try to understand what the phase is actually doing.
There are many approaches you can take to defusing your bitbomb. You can examine your bitbomb in great detail without ever executing it to figure out how it works. You can also execute the bitbomb using a debugger to run it step by step and examine the state of the machine along the way (while also giving you a chance to bail out before it explodes!). A mix of these two approaches is probably most efficient.
First, you should not use brute force to defuse your bitbomb! While you could theoretically write a program to try many defusal codes on your bitbomb, this is a bad idea for several reasons. One, the number of possibilities is so large that you are unlucky to solve your bitbomb using this approach. Two, a brute force approach will not allow you to write a very good description of your reverse engineering approach. Three, a brute force approach is likely to result in repeatedly detonating your bitbomb!
There are many tools that are designed to help you figure out how programs work and what is wrong when they do not work. You are likely to find the following tools helpful in particular:
gdbwill allow you to trace through the bitbomb instruction by instruction, examine the contents of memory and registers, look at the assembly code (and the source code if available...which it mostly isn't in this case), set breakpoints, and more. Refer to the GDB Reference Sheet for useful
objdumpis a program that can output various types of information about compiled (aka 'object') files. The two uses of
objdumpthat you will likely find most useful are
objdump -t bitbomband
objdump -d bitbomb. The former (
-t) will print out the bitbomb's symbol table, which includes the names of all functions and global variables in the program, as well as their addresses. These names may be useful! The latter (
-d) will dump a complete assembly instruction listing of the program (i.e., it will disassemble the entire program). You may note, however, that certain things in this assembly instruction listing are cryptic, particularly the names of system library functions that are called. Some of this information is presented more usefully when the code is disassembled from within
gdb(i.e., while the program is running) - the reason for this has to do with linking and loading, some of which happens at runtime. You can disassemble within
disascommand, which will usually give you the most information about the assembly instructions.
stringsis a utility that will output all the printable, literal strings contained in a program. A useful way to run it is as follows:
strings -t x bitbombThe above will output all the strings and their hex offsets in the program.
stringsfor later reference. You can easily do this using output redirection, like so:
progname arg1 > output.txtThe above will run
progname arg1and dump the output into a file called
output.txt(of course, substitute whatever program, argument(s), and filename you actually want).
If you encounter x86-64 assembly instructions with which you are not familiar, you can consult the textbook, Google, or go right to the source and check the the official Intel architecture manuals. Remember when consulting references that we're using x86-64, not the 32-bit x86 (aka IA32).
Lastly, it may be helpful to refer to this quick reference sheet of common x86-64 register names as you get used to the conventions (note that this sheet only shows 32-bit and 64-bit register names).
The following pieces of advice are well worth heeding as you tackle your bitbomb:
gdbsuch that the bitbomb will be interrupted before it explodes, giving you a chance to exit out and try again if you enter a wrong code. Make a habit of setting this breakpoint to give yourself an insurance policy!
Control-Cto interrupt execution of a program that you're executing directly (i.e., outside of
gdb). BitBombs Inc. was rumored to be working on a mechanism to defeat attempts to interrupt the bitbomb, so let's hope that feature doesn't work yet...
descriptions.txt. You will be looking at a lot of instructions, register names, symbols, and memory addresses in the course of reverse engineering, and keeping everything in your head is likely to be difficult. Jot down notes along the way so you don't have to do the process all over again to remember how it worked!
gdbis quite useful - it allows you to print expressions automatically (registers, memory contents, etc) every time execution stops. More generally, review all of the commands listed on the GDB reference sheet to get a sense of what's possible (and potentially useful; the commands shown were selected because of their likelihood to be useful).
Your final submission will consist of your committed files at the time of the due date, as well as the automatically submitted results of executing your bitbomb.
You will be evaluated both on determining the correct defusal codes for each phase as well as clearly documenting your methods and insights during reverse-engineering in
descriptions.txt. Points for each phase are given below (of which roughly half will be from your solution and half from your description):
Partial credit is possible on unsolved phases for clear documentation that demonstrates effort and some understanding of the phase. Full credit requires both correct defusal codes and high-quality descriptions!
To assist us in tracking the server-wide defusal effort, we have created an online Disarmament Status Report page (active for the duration of the lab). The status report page will show your progress towards defusing your bomb as well as the progress made by your classmates. You can also see your total number of bitbomb explosions on this page. Entries are identified by bitbomb ID, which is contained in your
The status report page is automatically updated as you work with your bitbomb and requires no action on your part.