NOTE: From now on, we’ll assume that you start lab by connecting to the CS portal and that you are familiar with the command line environment. If you have not been practicing with the terminal, we strongly encourage reviewing Lab 1.
We will also assume that you ran the setup script from that lab and have all modules (including clang and git) by default.
A Mad Programmer created a slew of “escape rooms”. Each binary escape room is a program, containing a sequence of puzzles. Each puzzle expects you to type a particular string. If you type the correct string, then the puzzle is solved and the escape room proceeds on to the next puzzle. Otherwise, the escape room flags the attempt, prints a message, tells us it did so, and then terminates.
In lab, we strongly encourage you to work with one another. Reading binary is much more fun and effective with someone else to talk to.
You should not work together on puzzle 2 and beyond, that is HOMEWORK.
You’ll use the same escape room for this lab and for the following homework.
For lab, you need to either (a) have a TA record that you were part of a team that solved the first puzzle or (b) solve the first puzzle in your escape room.
For the homework, you’ll need to solve the additional puzzles on your own.
Each time your escape room flags an attempt, it notifies the escape room server. If we’re notified of 20 flags we’ll start removing points each time your room is flagged.
Run our script to get a unique escape room in your home directory:
#is your room number).
- Read the
- You are welcome to look at
room.c– it isn’t very interesting, though
- Do whatever you need to understand what the escape room and puzzles are doing
- Only run the escape room
./roomonce you are confident you can solve a puzzle (or at least avoid a flag being sent)
- Once you solve a puzzle visit the scoreboard to verify that we saw your success.
If you run your escape room with a command line argument, for example,
./room psol.txt, then it will read the input lines from
psol.txt until it reaches EOF (end of file), and then switch over to the command line. This will keep you from having re-type solutions.
Because you want to avoid flags on incorrect puzzle solutions, you’ll want to set a breakpoint before you run the program so that you can stop the program before it gets to a the function that does the flagging.
You might find it useful to run,
objdump --syms room to get a list of all symbols in the escape room file, including all function names, as a starting point on where you want your breakpoint.
The best way is to use your favorite debugger to step through the disassembled binary. Almost no students succeed without using a debugger like lldb or gdb. We recommend using
lldb. On the department machines, if you did not run the script from Lab 1, you can enable
lldb buy running
module load clang-llvm.
To avoid accidentally submitting an incorrect solution to a puzzle in the room, 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.
It may be helpful to use various utilities for examining the escape room program outside a debugger, as described in “examining the executable” below.
The escape room ignores blank input lines.
If you run your escape room with a command line argument, for example,
then it will read the input lines from
psol.txtuntil it reaches EOF (end of file), and then switch over to
stdin. This will keep you from having re-type solutions.
objdump -twill print out the escape room’s symbol table. The symbol table includes the names of all functions and global variables in the room, the names of all the functions the room calls, and their addresses. You may learn something by looking at the function names!
objdump -dwill disassemble all of the code in the escape room. You can also just look at individual functions. Reading the assembler code can tell you how the room and puzzles work.
If you prefer to get Intel syntax disassembly from
objdump, you can use
objdump -M intel -d.
stringsis a utility which will display the printable strings in your escape room.
If you are on a department Unix machine, and did not run the script from Lab 1,
module load clang-llvmfirst (this needs to be done once per terminal), so
Run the excape room
roomfrom a debugger like
lldbinstead of running it directly. The debugger will allow you to stop the escape room before it flags a bad solution.
For example, if I ran
lldb room (lldb) b methodName (lldb) run (lldb) kill
this will start
lldb, set a breakpoint at
methodName, and run the code. The code will halt before it runs
killwill stop the escape room and exit the current debugging session without
Walk through code using one of
nextigoes one assembly instruction at a time, skipping over function calls
stepigoes one assembly instruction at a time, entering function calls
lldb room (lldb) b lineNumberForPuzzle1Call (lldb) run
input test passphrase here
(lldb) register read (lldb) fame variable
Generally some parameters are local variables and some are stored in registers and others on the stack; if none are on the stack,
frame variablesprints nothing. Strings are stored as pointers so you’ll need to “examine” what they point to. Try looking at several as if they are strings:
(lldb) x/s anAddressDisplayedByRegisterReadOrFrameVariable
You can also look at the assembly directly
And walk through it instruction by instruction
nextiing until you see
strings_not_equalmethod (a suspicious name that might be checking your passphrase)
(lldb) register read (lldb) frame variable
Which one holds your passphrase? Try “examining” that and others…
(lldb) frame variable
prints out the name and value of local variables in scope at your current place in the code, if any.
(lldb) register read
prints the values of all registers except floating-point and vector registers
(lldb) x/20bx 0x...
examine the values of the 20 bytes of memory stored at the specified memory address (0x…). Displays it in hexadecimal bytes.
(lldb) x/20bd 0x...
examine the values of the 20 bytes of memory stored at the specified memory address (0x…). Displays it in decimal bytes.
(lldb) x/gx 0x...
examine the value of the 8-byte integer stored at the specified memory address.
(lldb) x/s 0x...
examines the value stored at the specified memory address. Displays the value as a string.
(lldb) x/s $someRegister
examines the value at register someRegister. Displays the value as a string (assuming the register contains a pointer).
Note it is
x/s $rdiin lldb, not
%rdilike it would be in assembly.
(lldb) print expr
evaluates and prints the value of the given expression
call (void) puts (0x...)
calls the built-in output method
putswith the given
char *(as a memory address). See
man putsfor more.
(lldb) disas methodName
get the machine instruction translation of the method
get the machine instruction translation of the currently executing method.
(lldb) x/6i 0x...
try to disassemble 6 instructions in memory starting at the memory address 0x…
(lldb) b *0x...
set a breakpoint at the specified memory address (0x…).
(lldb) b function_name.
set a breakpoint at the beginning of the specified function.
step forward by one instruction, skipping any called function.
step forward by one instruction, entering any called function.
termiante the program immediately
brings up lldb’s built-in help menu
Reviewing the x86-64 calling convention may be helpful.
The C standard library function
__isoc99_sscanfin the executable. Try
man sscanffor more information about this library function.
%fs:0x1234refers to a value in a “thread-local storage” region at offset
0x1234. The escape room only has one thread (using multiple threads would allow the room to do multiple things at once, but that is not something the room needs), so this is effectively a region for extra global variables. In the escape room, this appears mostly to implement stack canaries, a security feature designed to cause out-of-bounds accesses to arrays on the stack to more consistently trigger a crash.
Pay attention to the names of functions being called.
Disassembling a standard library function instead of reading the documentation for the function is probably a waste of time.
Some of the things later escape room puzzles might be using include:
- calls to
scanf(which is a formatted read; try
man scanfor Wikipedia for more)
- linked data structure traversal
- string literals
- calls to