Lab2 Defusing a Binary Bomb

Introduction

The nefarious Dr. Evil has planted a slew of “binary bombs” on our machines. A binary bomb is a program that consists of a sequence of 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.
There are too many bombs for us to deal with, so we are giving each student a bomb to defuse. Your mission, whom you have no choice but to accept, is to defuse your bomb before the due date. Good luck, and welcome to the bomb squad!

Get Your Bomb

通过SVN获得,之前已经进行了连接,所以只需$ svn update即可获得lab2文件夹,包含以下三个文件:

  • README: 主要是用于判断这个Bomb是不是你的,里面包含bomb的编号和你的学号
  • bomb: 就是一个可执行文件,但是可以通过反汇编objdump -d bomb > <object_file>得到汇编文件
  • bomb.c: bomb主线的源文件,其实没什么东西,但是看着挺有趣的,有一些作者自言自语的话,自带萌点(嘤)。主要的提示就是不要直接双击运行bomb文件,因为这样相当于什么参数都不给,所以它就会一直爆炸(T^T)。代码贴在下面:
/***************************************************************************
 * 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;
}

Defuse Your Bomb

  • 一共有6个phase(各10分)加一个secret_phase(5分),从第四次爆炸开始一次bomb扣一分,所以可以白炸三次2333(为了少扣分,先把explode_bomb和phase_defused两个函数加上断点,发现即将爆炸就kill调试进程)
  • 可以将已经知道的答案写在文档里面,在命令行运行bomb直接读取,例如:
    $./bomb psol.txt //psol.txt的每一行分别为一个phase的答案
    

Tools

  1. gdb
    The GNU debugger, this is a command line debugger tool available on virtually every platform. You can trace through a program line by line, examine memory and registers, look at both the source code and assembly code (we are not giving you the source code for most of your bomb), set breakpoints, set memory watch points, and write scripts. Here are some tips for using gdb.
    • To keep the bomb from blowing up every time you type in a wrong input, you’ll want to learn how to set breakpoints.
    • For other documentation, type helpat the gdb command prompt, or type man gdb, or info gdbat a Unix prompt. Some people also like to run gdb under gdb-mode in emacs.
    • http://ipads.se.sjtu.edu.cn/courses/ics/tutorials/gdb-ref.txt
  2. objdump -t
    This will print out the bomb’s symbol table. The symbol table includes the
    names of all functions and global variables in the bomb, the names of all the functions the bomb calls, and their addresses. You may learn something by looking at the function names!
  3. objdump -d
    Use this to disassemble all of the code in the bomb. You can also just look at individual functions. Reading the assembler code can tell you how the bomb works. Although objdump -dgives you a lot of information, it doesn’t tell you the whole story. Calls to system-level functions are displayed in a cryptic form. For example, a call to printfmight appear as:
    171d: e8 6e f8 ff ff callq f90 <printf@plt>
    
    To determine that the call was to printf, you would need to disassemble within gdb.
  4. strings
    This utility will display the printable strings in your bomb.

Special

objdump -d之后的地址并不一定是真的地址,但是相对偏移量是对的。所以可以先gdb bomb,在main函数这里设一个断点break main,然后运行程序run,程序会在断点处停止并显示main的真正地址,计算真正地址与反汇编后的地址之间的偏移量,将反汇编文件中的地址加上偏移量可以得到真正的地址,之后就可以进行正常的设置断点和调试了

Phase 1

  1. 代码如下:
    00000000000013b0 <phase_1>:
    13b0:	48 83 ec 08          	sub    $0x8,%rsp
    13b4:	48 8d 35 55 10 00 00 	lea    0x1055(%rip),%rsi        # 2410 <_IO_stdin_used+0x150>
    13bb:	e8 43 04 00 00       	callq  1803 <strings_not_equal>
    13c0:	85 c0                	test   %eax,%eax
    13c2:	75 05                	jne    13c9 <phase_1+0x19>
    13c4:	48 83 c4 08          	add    $0x8,%rsp
    13c8:	c3                   	retq   
    13c9:	e8 45 0c 00 00       	callq  2013 <explode_bomb>
    13ce:	eb f4                	jmp    13c4 <phase_1+0x14>
    
  2. 分析:
    这个bomb比较简单,首先联网拿到对应的string
    lea    0x1055(%rip),%rsi  # 2410 <_IO_stdin_used+0x150>
    
    然后调用函数,从名字上来看是判断两个字符串是否相等
    13bb:	e8 43 04 00 00       	callq  1803 <strings_not_equal>
    
    test判断返回值是否为0
    13c0:	85 c0                	test   %eax,%eax
    
    不为0就爆炸
    13c2:	75 05                	jne    13c9 <phase_1+0x19>
    13c9:	e8 45 0c 00 00       	callq  2013 <explode_bomb>
    
    所以这个时候猜都能猜到是要输入%rsi中的字符串,直接x $rsi或者一个字符一个字符的print出来也行。如果不放心,可以到<strings_not_equal>函数里面再去看一看,代码如下:
    0000000000001803 <strings_not_equal>:
    1803:	41 54                	push   %r12
    1805:	55                   	push   %rbp
    1806:	53                   	push   %rbx
    1807:	48 89 fb             	mov    %rdi,%rbx
    180a:	48 89 f5             	mov    %rsi,%rbp
    180d:	e8 d3 ff ff ff       	callq  17e5 <string_length>
    1812:	41 89 c4             	mov    %eax,%r12d
    1815:	48 89 ef             	mov    %rbp,%rdi
    1818:	e8 c8 ff ff ff       	callq  17e5 <string_length>
    181d:	ba 01 00 00 00       	mov    $0x1,%edx
    1822:	41 39 c4             	cmp    %eax,%r12d
    1825:	74 07                	je     182e <strings_not_equal+0x2b>
    1827:	89 d0                	mov    %edx,%eax
    1829:	5b                   	pop    %rbx
    182a:	5d                   	pop    %rbp
    182b:	41 5c                	pop    %r12
    182d:	c3                   	retq   
    182e:	0f b6 03             	movzbl (%rbx),%eax
    1831:	84 c0                	test   %al,%al
    1833:	74 27                	je     185c <strings_not_equal+0x59>
    1835:	3a 45 00             	cmp    0x0(%rbp),%al
    1838:	75 29                	jne    1863 <strings_not_equal+0x60>
    183a:	48 83 c3 01          	add    $0x1,%rbx
    183e:	48 83 c5 01          	add    $0x1,%rbp
    1842:	0f b6 03             	movzbl (%rbx),%eax
    1845:	84 c0                	test   %al,%al
    1847:	74 0c                	je     1855 <strings_not_equal+0x52>
    1849:	3a 45 00             	cmp    0x0(%rbp),%al
    184c:	74 ec                	je     183a <strings_not_equal+0x37>
    184e:	ba 01 00 00 00       	mov    $0x1,%edx
    1853:	eb d2                	jmp    1827 <strings_not_equal+0x24>
    1855:	ba 00 00 00 00       	mov    $0x0,%edx
    185a:	eb cb                	jmp    1827 <strings_not_equal+0x24>
    185c:	ba 00 00 00 00       	mov    $0x0,%edx
    1861:	eb c4                	jmp    1827 <strings_not_equal+0x24>
    1863:	ba 01 00 00 00       	mov    $0x1,%edx
    1868:	eb bd                	jmp    1827 <strings_not_equal+0x24>
    
    发现就是先比较两个字符串的长度,如果相等再逐个比较字符,并没有什么用
  3. 结果:
    When I get angry, Mr. Bigglesworth gets upset.
    

Phase 2

  1. 代码如下:
    00000000000013d0 <phase_2>:
    13d0:	55                   	push   %rbp
    13d1:	53                   	push   %rbx
    13d2:	48 83 ec 28          	sub    $0x28,%rsp
    13d6:	48 89 e6             	mov    %rsp,%rsi
    13d9:	e8 71 0c 00 00       	callq  204f <read_six_numbers>
    13de:	83 3c 24 01          	cmpl   $0x1,(%rsp)
    13e2:	74 05                	je     13e9 <phase_2+0x19>
    13e4:	e8 2a 0c 00 00       	callq  2013 <explode_bomb>
    13e9:	48 89 e5             	mov    %rsp,%rbp
    13ec:	bb 01 00 00 00       	mov    $0x1,%ebx
    13f1:	eb 09                	jmp    13fc <phase_2+0x2c>
    13f3:	48 83 c5 04          	add    $0x4,%rbp
    13f7:	83 fb 06             	cmp    $0x6,%ebx
    13fa
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值