CS 304, Fall 2015
Lab Assignment L2: Defusing a
Binary Bomb
Assigned: 9/22, 2015
Due: 23:59PM, 10/4 (Sunday), 2015
The nefarious Dr. Evil has created a slew of “binary bombs” for our class. A binary bomb is a program that consists of a sequence of six phases. Each phase expects you to type a particular string on stdin. If you type the correct string, then the phase is defused and the bomb proceeds to the next phase. Otherwise, the bomb explodes by printing "BOOM!!!" and then terminating. The bomb is defused when every phase has been defused.
Each student in the class will be supplied with
a bomb to defuse. The assignment is to defuse your bomb before the
due date. Good luck, and welcome to the bomb squad!
The bombs will be numbered from bomb1 to bombn, where n is the number of students in
the class. Each bomb is constructed with a random choice of
phases, and the bomb numbers are assigned in a random order
relative to the class roll (that is, the alphabetically first
student on the roll will most probably not be assigned bomb1).
Please visit http://th001-8.cs.wm.edu:
mkdir lab2
cd lab2
cp
downloaded_file
tar xvf
bomb.tar
Once you have received your bomb, save it in a secure directory. Your job is to defuse the bomb.
You can use many tools to help you with this; please look at the hints section for some tips and ideas. The best way is to use your favorite debugger to step through the disassembled binary.
Each time your bomb explodes it notifies the project logfile, and you lose 1/2 point (up to a max of 20 points) in the final score for the lab. So there are consequences to exploding the bomb. However, as you learn about setting breakpoints in gdb, you will realize that you can protect yourself by setting a breakpoint in explode_bomb.
Phase one is worth 10 points, and phases 2 through 6 are worth 14 points each, for a lab total of 80 points.
There is also a challenging, extra-credit (4 points) “secret” phase that only appears if a student appends a certain string to the solution of one of the earlier phases.
The phases get progressively harder to defuse, but the expertise you gain as you move from phase to phase should offset this difficulty. However, the last phase will challenge even the best students, so please don’t wait until the last minute to start.
The bomb ignores blank input lines. If you run the bomb with a command line argument such as psol.txt (a name chosen arbitrarily), the bomb will read the input lines from psol.txt until it reaches EOF, and then switch over to stdin. In a moment of weakness, Dr. Evil added this feature so you don’t have to keep retyping the solutions to phases you have already defused.
To avoid accidentally detonating the bomb, you will need to learn how to single-step through the assembly code and how to set breakpoints. You will also need to learn how to inspect both the registers and the memory states. One of the nice side-effects of doing the lab is that you will get very good at using a debugger. This is a crucial skill that will pay big dividends the rest of your career.
Any clarifications and revisions to the assignment will be posted on the Web page for this lab.
You must complete the assignment on the machines in M-S 121 (you can also ssh to a machine in 121 to finish this lab). In fact, there is a rumor that Dr. Evil really is evil, and the bomb will always blow up if run elsewhere. There are several other tamper-proofing devices built into the bomb as well, or so they say.
There is no explicit hand-in. The bomb will notify your instructor automatically after you have successfully defused it. You can keep track of how you (and the other students) are doing by following the link on the lab web page to the page summarizing the current status of the bomb tests. This web page is updated continuously to show the progress of being made on each bomb. Results are displayed by bomb number. Note: If the update timestamp stops changing, then please send email to liqun@cs.---- to let me know. This means that the autograder daemon has died and needs to be restarted. Successfully debugged phases won’t show up until the autograder daemon is running.
There are many ways of defusing your bomb. You can examine a disassembly of it in great detail without ever running the program, and figure out exactly what it does. This is a useful technique, but it may not give you enough information about what the bomb is doing.
You can also run the bomb with a debugger, inspect its memory locations, watch what it does step by step, and use this information to defuse it. This is probably the fastest way of defusing the bomb. Combining this technique with the hard copy of the disassembly of the bomb is probably the strongest combination you can use.
We do make one request, please do not use brute force! You could write a program that will try every possible key to find the right one. But this is no good for two reasons:
There are many tools that are designed to help you figure out both how programs work, and what is wrong when they don’t work. Here is a list of some of the tools you may find useful in analyzing your bomb, and hints on how to use them.
There is a graphical front-end to gdb called ddd. Type “info ddd” for more information. You will find the GDB summary and GDB reference card useful. Or try tutorial1, tutorial 2, tutorial 3,
You can also use the disas command in gdb to disassemble a given subroutine, but it gives you slightly different information than objdump does. For example, here is the output produced by the disas command for the read_six_numbers routine:
For 64 bits:
(gdb) disas read_six_numbers
Dump of
assembler code for function read_six_numbers:
0x0000000000401750
<+0>: sub
$0x18,%rsp
0x0000000000401754
<+4>: mov
%rsi,%rdx
0x0000000000401757
<+7>: lea
0x4(%rsi),%rcx
0x000000000040175b
<+11>: lea
0x14(%rsi),%rax
0x000000000040175f
<+15>: mov
%rax,0x8(%rsp)
0x0000000000401764
<+20>: lea
0x10(%rsi),%rax
0x0000000000401768
<+24>: mov %rax,(%rsp)
0x000000000040176c
<+28>: lea 0xc(%rsi),%r9
0x0000000000401770
<+32>: lea 0x8(%rsi),%r8
0x0000000000401774
<+36>: mov
$0x402875,%esi
0x0000000000401779 <+41>:
mov $0x0,%eax
0x000000000040177e <+46>: callq
0x400c70 <__isoc99_sscanf@plt>
0x0000000000401783 <+51>:
cmp $0x5,%eax
0x0000000000401786 <+54>:
jg 0x40178d <read_six_numbers+61>
0x0000000000401788
<+56>: callq 0x4015ef
<explode_bomb>
0x000000000040178d
<+61>: add $0x18,%rsp
0x0000000000401791 <+65>: retq
End of assembler dump.
and here is the corresponding output from the
objdump command:
For 64 bits
0000000000401750
<read_six_numbers>:
401750: 48 83 ec
18
sub $0x18,%rsp
401754: 48 89
f2
mov %rsi,%rdx
401757: 48 8d 4e
04
lea 0x4(%rsi),%rcx
40175b: 48 8d 46
14
lea 0x14(%rsi),%rax
40175f: 48 89 44 24
08
mov %rax,0x8(%rsp)
401764: 48 8d 46
10
lea 0x10(%rsi),%rax
401768: 48 89 04
24
mov %rax,(%rsp)
40176c: 4c 8d 4e
0c
lea 0xc(%rsi),%r9
401770: 4c 8d 46
08
lea 0x8(%rsi),%r8
401774: be 75 28 40
00
mov $0x402875,%esi
401779: b8 00 00 00
00
mov $0x0,%eax
40177e: e8 ed f4 ff
ff
callq 400c70 <__isoc99_sscanf@plt>
401783: 83 f8
05
cmp $0x5,%eax
401786: 7f
05
jg 40178d
<read_six_numbers+0x3d>
401788: e8 62 fe ff
ff
callq 4015ef <explode_bomb>
40178d: 48 83 c4
18
add $0x18,%rsp
401791:
c3
retq
Notice that objdump
correctly identifies the sscanf
C library call, but the disas
command of gdb simply lists
the call location as _init+392 in the
bomb
executable. The disas
command of gdb is more
convenient to use if you’re already in gdb,
but you may occasionally find it necessary to refer to the objdump output
to track down any mysterious C library calls.
I don’t mean to over-emphasize the read_six_numbers routine here. I am simply pointing out the differences between objdump -d and the disas command of gdb. By the name of this procedure and by a glance at its construction, you can see that the procedure uses sscanf to parse the input string fed to it and place six int values in an array whose address is supplied as one of its parameters. That’s about all you need to know about read_six_numbers.
Looking for a particular tool? How about
documentation? Don’t forget, the commands apropos and man are your friends. In
particular, man ascii might
come in useful. Also, the web may also be a treasure trove of
information. If you get stumped, feel free to ask me for help.
Try the following to start:
objdump -t bomb
objdump -t bomb > bomb_sym.txt
#save the symbol table in bomb_sym.txt
objdump -d bomb
objdump -d bomb > bomb_dump.txt
#save the dump file in bomb_dump.txt
string -t x bomb
string -t x bomb > bomb_string.txt
#save the strings in bomb_string.txt
gdb bomb
#use gdb to run bomb
(gdb)b explode_bomb
#set breakpoint at explode_bomb
(gdb)b main
#set breakpoint at main
(gdb)disp /i $rip
(gdb)r
(gdb)r psol.txt
(gdb)c
(gdb)si
(gdb)i r
(gdb)x/10wx $rsp
(gdb)x/10wx $rsp-0x20
It is important to set a breakpoint are
explode_bomb: (gdb)b explode_bomb
If you do not, you may unintentionally explode the bomb. If the
breakpoint is set, when you are about to explode the bomb, the
program will breakpoint at the beginning of the procedure
explode_bomb. This way you know you will explode the bomb if you
continue. Simply type r (or r psol.txt if you saved your solution
in psol.txt) to rerun the progra from the beginning.