Explosive-Code

The Infamous Bomb Lab

Taken from an old assignment I found lying around on a thumb drive...

Our next assignment, the "Bomb Lab," was developed by Bryant and O`Hallaron and is presented in their text. Students are given an x86 executable, compiled for Linux. When run, the program reads in a line of text from stdin. The line of text must match what the program is expecting; otherwise, the executable triggers an "explosion" (i.e., it sends a message to a server and then quits).

Six lines of input must be fed to the program to defuse it; each stage is progressively more complex and exercises different aspects of C-language control and data structures. Furthermore, every student gets his or her own personalized bomb, in which each of the six stages is built from a choice of several related but different possibilities. We use GDB (the command line version) to single-step and debug the bomb executables; this is typically students' first use of this tool.

Lectures that accompany this lab introduce the Pentium/x86 architecture and how the C language is translated into x86 machine code. The C-to-assembly topics include function calls (including stack frames and argument passing), how arrays are implemented, and various control structures. In our Computer Organization class, students have encountered a lot of these same assembly language topics, but have not specifically seen C-to-assembly translation.

Students absolutely love the Bomb Lab, it's positively addicting. More than a few students have reported to me "I should have been doing something else, but I kept working on my bomb."

Ahh - I'm sure for most people, this is their first (and probably their last) attempt to reverse a program. Though I'm sure it gave a few people the bug for reversing, it's just a big puzzle! Arguably, aside from the heavily layden anti-debug tricks, one of the best written linux crackmes I've ever done. There are plenty of "harder" ones, though this one have a very simplistic approach to wanting to make you solve it - so it forces you to learn how to reverse.

Now that we've found this, "gem" of a linux crackme - lets re-examine it! If I remember correctly there was a secret stage that I never was able to get into, and some nasty and annoying little feature that would not let you run it on a non-university machine. At the time I would rather have not patched the program, for the sake of my grade - but heck, what do I care now? I'm going to hack this thing to peices... Though I might as well try to analyse it using the only tools we where allowed to back in the day. Let's start from there, then we will move on to bigger and much, much badder tools.

Bomb.c

/***************************************************************************
 * Dr. Evil's Insidious Bomb, Version 1.0
 * Copyright 2002, Dr. Evil Incorporated. All rights reserved.
 *
 * LICENSE:
 *
 * Dr. Evil Incorporated (the PERPETRATOR) hereby grants you (the
 * VICTIM) explicit permission to use this bomb (the BOMB).  This is a
 * time limited license, which expires on the death of the VICTIM.
 * The PERPETRATOR takes no responsibility for damage, frustration,
 * insanity, bug-eyes, carpal-tunnel syndrome, loss of sleep, or other
 * harm to the VICTIM.  Unless the PERPETRATOR wants to take credit,
 * that is.  The VICTIM may not distribute this bomb source code to
 * any enemies of the PERPETRATOR.  No VICTIM may debug,
 * reverse-engineer, run "strings" on, decompile, decrypt, or use any
 * other technique to gain knowledge of and defuse the BOMB.  BOMB
 * proof clothing may not be worn when handling this program.  The
 * PERPETRATOR will not apologize for the PERPETRATOR's poor sense of
 * humor.  This license is null and void where the BOMB is prohibited
 * by law.
 ***************************************************************************/

#include <stdio.h>

#include "support.h"
#include "phases.h"

/* 
 * Note to self: Remember to erase this file so my victims will have no
 * idea what is going on, and so they will all blow up in a
 * spectaculary fiendish explosion. -- Dr. Evil 
 */

FILE *infile;

int main(int argc, char *argv[])
{

    char *input;

    /* Note to self: remember to port this bomb to Windows and put a 
     * fantastic GUI on it. */

    /* When run with no arguments, the bomb reads its input lines 
     * from standard input. */
    if (argc == 1) {  
	infile = stdin;
    } 

    /* When run with one argument <file>, the bomb reads from <file> 
     * until EOF, and then switches to standard input. Thus, as you 
     * defuse each phase, you can add its defusing string to <file> and
     * avoid having to retype it. */

    else if (argc == 2) {
	if (!(infile = fopen(argv[1], "r"))) {

	    printf("%s: Error: Couldn't open %s\n", argv[0], argv[1]);
	    exit(8);
	}
    }

    /* You can't call the bomb with more than 1 command line argument. */
    else {
	printf("Usage: %s [<input_file>]\n", argv[0]);

	exit(8);
    }

    /* Do all sorts of secret stuff that makes the bomb harder to defuse. */
    initialize_bomb();

    printf("Welcome to my fiendish little bomb. You have 6 phases with\n");

    printf("which to blow yourself up. Have a nice day!\n");

    /* Hmm...  Six phases must be more secure than one phase! */
    input = read_line();             /* Get input                   */

    phase_1(input);                  /* Run the phase               */
    phase_defused();                 /* Drat!  They figured it out!
				      * Let me know how they did it. */
    printf("Phase 1 defused. How about the next one?\n");

    /* The second phase is harder.  No one will ever figure out
     * how to defuse this... */
    input = read_line();
    phase_2(input);

    phase_defused();
    printf("That's number 2.  Keep going!\n");

    /* I guess this is too easy so far.  Some more complex code will
     * confuse people. */
    input = read_line();

    phase_3(input);
    phase_defused();
    printf("Halfway there!\n");

    /* Oh yeah?  Well, how good is your math?  Try on this saucy problem! */
    input = read_line();
    phase_4(input);

    phase_defused();
    printf("So you got that one.  Try this one.\n");
    
    /* Round and 'round in memory we go, where we stop, the bomb blows! */
    input = read_line();

    phase_5(input);
    phase_defused();
    printf("Good work!  On to the next...\n");

    /* This phase will never be used, since no one will get past the
     * earlier ones.  But just in case, make this one extra hard. */
    input = read_line();
    phase_6(input);

    phase_defused();

    /* Wow, they got it!  But isn't something... missing?  Perhaps
     * something they overlooked?  Mua ha ha ha ha! */
    
    return 0;
}

The above is the "stolen" source code that you receive with your bomb lab.

Patching to run

A quick google for this "Bomb lab" (or "Binary Bomb" as it is called in some places) reveals someone who went to the Swiss Federal Insitute of Technology Zurich had a similar idea as me. His page can be found here:

http://www.mauchle.name/binarybomb.htm

A interesting work around, but I don't like it that much. Since we're going to be reversing this bomb, lets patch it a little. Against the rules, yes, but heck - I'm not getting graded on this anyway! We need to find out what is not allowing us to run the program...

Bad Host (4)

A quick debug will show us that it's complaining about having a bad host - this seems to be coming from "Initialize_Bomb". [insert strace to prove this] If we dump out this function we can see that it is checking for a valid "host", or lab computer. Then it attempts to connect to a site (university site normally) and will fail with a "Bad Host (5)" if this cannot be found. Instead of patching inside this function, which would require a few well place patches - lets make out lives as easy as possible. Since "Initialize_Bomb" doesn't seem to do anything but hinder us right now, we're going to NOP out it's function call.

From the "stolen" source code listed above, we know that the "Initialize_Bomb" is called right before we receive a welcome message. So if we look at a dump of the main function [include dump] we can see the call we want to NOP out is as follows;

dump of code

So start up whatever hex editor you would like, and we're going to NOP out the jump. So change E811070000 to 9090909090. There, that was easy! Now the bomb should run on any machine you'd like.

More to come as I have time to update this - until then, I'll let google index the page :D