Programming lesson
Defusing the Binary Bomb: A Step-by-Step Guide to CSCI 247 Project 2
Learn how to defuse your binary bomb in CSCI 247 using GDB, reverse engineering, and assembly analysis. This guide covers phases 1-6 with practical tips and debugging strategies.
Introduction to the Binary Bomb Lab
The Binary Bomb Lab in CSCI 247 is a classic reverse engineering project where you must defuse a series of phases by finding the correct input strings. Each phase expects a specific string; if you provide the wrong one, the bomb explodes and you lose points. The goal is to analyze the binary using tools like GDB, objdump, and strings to determine the hidden passwords. This project builds essential skills in assembly language, debugging, and problem-solving—skills that are directly applicable to cybersecurity, game hacking, and even optimizing AI models.
Setting Up Your Environment
First, obtain your bomb by running the curl command provided in the assignment. This downloads a tar file containing your unique bomb executable, source code (bomb.c), and a README. Extract it with tar -xvf bomb.tar. You'll get a directory named bombk where k is your bomb number. Make sure you're on a CS machine, as the bomb communicates with a server to track progress. Use ssh to connect if working remotely.
Essential Tools for Defusing
GDB: The GNU Debugger
GDB is your primary tool. Start your bomb under GDB: gdb ./bomb. Set breakpoints before each phase, e.g., break phase_1. Run the bomb with run (or provide a solution file: run solutions.txt). Use stepi to step through instructions, info registers to view register states, and x/s $rdi to examine strings. For example, if you suspect a string comparison, break at strings_not_equal and inspect the arguments.
Objdump and Strings
Disassemble the bomb with objdump -d bomb > bomb.asm. This gives you the assembly code. Look for functions like phase_1, phase_2, etc. Use strings bomb to extract printable strings—sometimes the password is hidden in plain sight! For instance, phase 1 might compare your input to a hardcoded string like "Public speaking is very easy."
Phase-by-Phase Analysis
Phase 1: Simple String Comparison
Phase 1 typically calls strings_not_equal. Examine the assembly: it loads an address into %rdi (your input) and another into %rsi (the target). Use GDB to print the target string: print (char*) $rsi. Or look at the disassembly: the target is often a static string in the .rodata section. Example solution: "I am not evil."
Phase 2: Loop with Sum
Phase 2 often reads six numbers separated by spaces. The assembly might loop and compute a sum or check a sequence. For instance, it could require numbers that form a specific pattern like 1, 2, 3, 4, 5, 6. Use GDB to set a breakpoint after read_six_numbers and examine the array: x/6wd $rdi. Then step through the loop to see the condition.
Phase 3: Switch Statement
Phase 3 involves a switch-like structure. The input might be two integers (e.g., "1 123"). The first number selects a case, and the second must match a computed value. Disassemble the switch block: look for jmp *0x...(%rax). Each case loads a specific value; compare it to your second number. For example, if first input is 1, the required second number might be 321.
Phase 4: Recursive Function
Phase 4 often calls a recursive function like func4. The input is two integers. The first must be in a range (e.g., 0-14). The recursive function computes something like a Fibonacci variant. Analyze func4 in assembly: it typically uses lea to compute midpoint and recurses. Use GDB to trace the recursion with breakpoints. Example: input "7 0" might work if func4(7) returns 0.
Phase 5: Pointer Array
Phase 5 expects a string of length 6 (or 5). It uses each character's low nibble as an index into an array of characters. The array might spell out a word like "giants". Disassemble the array: look for a static data section with 16 characters. For example, if the array is "isrveawhobpnutfg", then inputting "5 1 2 3 4 5" (ASCII values) yields indices. Use GDB to print the array: p (char*) 0x... . Then compute the required input: e.g., "opekma" produces "giants".
Phase 6: Linked List Sorting
Phase 6 is the hardest. It reads six numbers, then uses them to traverse a linked list. The list nodes contain values; you must order the nodes by value (e.g., decreasing). Disassemble the list: look for node1, node2 labels. Each node has a value and a next pointer. Use GDB to print node values: p node1.value. Then determine the order of nodes from highest to lowest. Input the node indices in that order (e.g., "4 2 1 6 3 5").
Advanced Tips and Common Pitfalls
- Use breakpoints wisely: Set breakpoints at
explode_bombto catch explosions early. Also break atphase_defusedto confirm success. - Inspect memory: Use
x/sfor strings,x/dfor integers, andx/gxfor pointers. - Single-step through loops: Use
stepirepeatedly, but be patient. Usedisplayto auto-show registers. - Don't brute force: Each explosion costs points and may lock you out. Instead, reverse engineer the logic.
- Work in pairs: Discussing the assembly with a partner helps. You can share insights on tricky phases.
Real-World Relevance: From Bombs to AI
Reverse engineering binaries is not just an academic exercise. Cybersecurity experts use these skills to analyze malware, find vulnerabilities, and patch software. For example, when a new ransomware hits, analysts disassemble it to understand its encryption algorithm. Similarly, game modders reverse engineer game binaries to create cheats or mods. Even in AI, understanding low-level computation helps optimize neural network inference on edge devices. The binary bomb lab is your first step into this exciting field.
Conclusion
Defusing your binary bomb requires patience, attention to detail, and a methodical approach. Start early, use GDB extensively, and don't be afraid to ask for help. By the end, you'll have a solid grasp of assembly, debugging, and reverse engineering—skills that will serve you well in future projects and careers. Good luck, and remember: the bomb squad is counting on you!