The bomb lab is most easily completed if you understand the following tools and commands. Also, if I am describing a program, assume that you run it from command line.
In case you have never used strings before it basically just tells you all the
strings in an executable. If I were to run it on the bomb I would simply run
"strings bomb" and it will output all the strings contained in that executable
to console, each on its own line. If you aren't in some sort of utility that will
let you scroll around through output (such as tmux, which is awesome) I recommend either sending
the output to a file or piping it through less.
to file: strings bomb > strings.txt
to less: strings bomb | less
Strings should come standard with any Linux distribution.
objdump is a utitity that can be used to dump the assembly code of an executable. This can be useful if you like looking at print outs or prefer to see the whole picture rather than snippets that GDB gives you. objdump comes standard on any Linux distribution as well. To run it use the following:
objdump -d bomb > dump
This will output the assembly code to a file called dump. When I did this lab I actually mostly used a print out of the assembly to figure out what was going on.
GDB is a must for this lab, or if you prefer graphical stuff there's DDD. I don't know how to use DDD so everything this explains will relate to GDB specifically. If you want a GUI you'll have to figure it out on your own.
If you are using a lab machine it is already there. If you have your own Linux VM or whatnot then just install it in the normal way. apt-get install gdb or yum install gdb.
Just run "gdb bomb" and it will load your bomb into GDB. To actually start it you use the run command (or r if you're lazy like me). If there are options you would like to specify on the commandline then just list them out after run. This lab allows you to specify a file for the bomb to read your discovered solutions from at run time. So if my solutions I have found for different phases are in a file called solutions.txt I would run "run solutions.txt" and it would run my bomb with that argument.
Note: the solutions in your solutions file need to be in order of phases. So if you have solved phase 2 but not phase 1 you should keep track of phase 2's answer but not put it into the file. Otherwise it will assume that is the answer for phase 1.
There are a lot of commands you can use in GDB. Google is pretty helpful at showing what you may need to use. Here is a list of some quick reference sheets:
Following is a list of ones I think you will definitely need.
Use either b or break to issue a breakpoint. When you do this you have to specify where the breakpoint will be. For this lab we don't have line numbers since the executable was not compiled with debugging support, but you can still provide function names or addresses. If I want a breakpoint at address 0x0804ee32 then I run "b 0x0804ee32". If I want a breakpoint at a specific function then I run "b function_name". For this lab you should only need to set break points at function names. The source file provided with the bomb should give you an idea of which functions you will want to break at.
When you provide an incorrect answer to a phase the bomb sends a message to the server saying that you did something wrong and points are taken away because of it. There is a sneaky way of getting around this using breakpoints.
Throughout the lab you may find it useful to examine the memory. You can look at the
hex values in memory, and if it contains a string you can look at memory as a string!
If there is a decimal value in a register you need to examine you can also print that
out in decimal! So cool! This is all done using the x command.
For strings: x/s address. So if I think there is a string at the address 0x476890
then I can specify that as the address parameter to x/s. The /s tells examine to print
what it finds out as a string.
For hex: x/x address. Same as above except it will print out whatever is at the
specified address in hex.
For words: x/w address. This is the same as /x except it shows you a word of memory.
For decimal: x/d address. This works the same as the prior two commands except that
it prints out the value in memory in decimal.
NOTE: you can specify a number before the command to say you want to see a certain
number of the things you're looking for. For example if I want to see 32 bytes with the
hex command I use x/32x. Or if I want to see two strings I use x/2s. This is very useful.
You may also want to see what values are in the processor's registers. You can use the x command for this as well. Registers are the standard x86 or x86_64 registers and to view their contents you simply put a $ before the name. So x/w $eax will show me the contents of the eax register in hex as a word. If you want to see all of them at once you can use info reg.
There is also a print command. Use it with "p". It is kinda the same as x. I prefer x since p has funkiness that I don't like and x gets down into the nitty gritty which is what you need for this lab.
When in GDB it is EXTREMELY useful to dump the assembly a function you want to look at. This is done using the disas command. If I want to look at the assembly of the main function I simply run "disas main" and it outputs the assembly of main. If the function is too long to fit onto your screen GDB will give it to you in groupings of how much output will fit on screen. You need this.
When you run your function and hit a breakpoint it will stop you at that line of assembly, just like a normal debugger (since GDB is a normal debugger). When you disassemble the function you have stopped at you will notice a tiny little pointer that looks like => off to the left of the assembly code. This is where you are at in execution. Sometimes it disappears, and I'm not really sure why, but don't freak out if it does. It reappears eventually.
When you are in a function you may want to step through it and see what the function does to any parameters passed to it, or anything else internal. You can advance through the function using ni or si. They both advance you one instruction, but ni skips over any other function calls whereas si goes into those functions (just like stepping over and stepping into). If you want to advance more than one instruction at a time you can specify the number using "si N" or "ni N" where N is the number of instructions you want to execute.
If you hit a breakpoint and want to advance to the next breakpoint, or if there isn't one run to conclusion, use "c". This is short for continue. Also, note that if you get to a spot in your program you don't want to be in or have execute, you can restart the program by running the "r" command again. It will say that the current process is running, are you sure you want to restart from the beginning, so you say yes and it runs the program from the start. This is also useful and necessary.
You will need to know some x86 and x86-64 to complete this lab. Dig in your memory banks back to CS 124 and that should help you some. Although 124 doesn't cover x86, x86 is similar to what you learned. If you need some help feel free to come in and ask us TAs. Also feel free to counsel with the greatest TA of all. Here are some references that hopefully will help get you started on learning/remembering x86:
People tend to ask questions about x86 instructions on stackoverflow, so Googling for the instruction is also helpful typically.
You also need to know about the different x86 registers. Here is a reference for those, although it isn't amazingly readable. Ask TAs for more help with registers.
If you know how to use IDA then use it. It will probably make some of this stuff easier. I find it large and hard to manage, but if you would prefer to use that you can. Just know that I can't help you with it at all.