Skip to content

CMU Binary Bomb Lab: Phase 1

The binary bomb lab from CMU is a legendary learning exercise as part of the Computer Systems course at Cargenie Melon University.

A “binary bomb” is a program provided to students as an object code file. When run, it prompts the user to type in 6 different strings. If any of these is incorrect, the bomb “explodes,” printing an error message and logging the event on a grading server. Students must “defuse” their own unique bomb by disassembling and reverse engineering the program to determine what the 6 strings should be. The lab teaches students to understand assembly language, and also forces them to learn how to use a debugger.

Dealing with the bomb involves defusing 6 phases, I’ll be covering one phase per article.

Tools (across all 6 phases)

$ ./cmubomb 
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
> test phrase
BOOM!!!
The bomb has blown up.

Standard cracking techniques will work here, and with phase 1 there’s very little protection in place. A quick look at the disassembled source suggests that the code for each phase is contained within a function named phase_[number]. Radare2’s output is very useful once you get used to looking at it.

The phase_1 function is fairly simple. Using the PDF (print disassembled file) command along with sym.function_name allows viewing the function in isolation. Here’s an annotation of what it’s doing:

  push ebp
  mov ebp, esp
  sub esp, 0x8

This is the standard way of entering a function, putting EBP on the stack and swapping EBP with ESP, and then making space on the stack for local variables. If you’re unfamiliar with this sort of thing, be sure to read up on how stack frames work.

 mov eax, [ebp+0x8]

When you see numbers along with EBP, an easy way to translate what’s being handled is the following:

| [ebp + 16] (3rd function argument)
| [ebp + 12] (2nd argument)
| [ebp + 8]  (1st argument)
| [ebp + 4]  (return address)
| [ebp]      (old ebp value)
| [ebp - 4]  (1st local variable)

So the first argument to the phase_1 function (likely the string we entered) is being passed along in the next function call.

push str.Publicspeakingisveryeasy. ; 0x080497c0 
  push eax

Two arguments are being put on the stack in preparation for a function call. One is the function argument that was kept in eax, the other is a string of some sort.

call fcn.08049030 (sym.strings_not_equal)

So we’re calling strings_not_equal with two strings, in a piece of code that checks passwords.

 
  add esp, 0x10
  test eax, eax
  jz 0x8048b43

The strings_not_equal function puts its result in eax. Since the `test eax, eax` instruction is simply a fast way of checking if the value is zero, it’s quite probably that strings_not_equal returns zero if the strings are equal, much like strcmp.

call sym.explode_bomb

If the result of the strings_not_equal function is zero, the explode_bomb call would’ve been avoided.

  mov esp, ebp
  pop ebp
  ret

This does the opposite of what the intro to the function did, in prep for returning from the called function. Putting all this together it should be fairly clear what the phase_1 function does:

phase_1(password) {
  if (strings_not_equal(password, stored_password) > 0) {
    explode_bomb()
  } else {
    return
  }
}

Since radare2 gave us the location of the password string in memory, it’s very simple to grab it:

[0x080488e0]> psz n @ 0x080497c0 
Public speaking is very easy.

`psz` prints the null-terminated string at the location specified, and that’s our password for Phase 1!

Published inReverse EngineeringWalkthroughs

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *