第二个lab,bomb lab,一个"legendary lab"(原话就是这样),通过看C的源码可以看出共有6个phase,每个phase其实就是一个拆弹的过程:
每一个phase里要求输入一个字符串,如果正确,这个phase的bomb就会被解除,并进入下一个phase。
很显然,phase的难度是逐步增加的,到后面单独一个phase的分析都快赶上lab1的工作量了... 分区写吧,一个一个来。
首先C的源码只是一个空壳,能看出调用phase的过程,但并不能帮助我们了解字符串应该是什么。
- /***************************************************************************
- * Dr. Evil's Insidious Bomb, Version 1.1
- * Copyright 2011, 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 <stdlib.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;
- }
C源码告诉我们在每次调用phase函数之前,会先调用read_line()读取字符串
在这门课程的handout材料里,除了C源码外,还有一个可执行文件bomb,这个文件是解除炸弹的关键。
首先用objdump命令获得bomb的汇编代码,可以重定向进入一个txt文件存起来,方便查看
作为小白大量地不了解某汇编操作的作用... 所以备一个x86-64 Intel汇编指令集随时查找也是必要的(所以我的上传资源里多了这么个东西...
首先,phase_1:
- 0000000000400ee0 <phase_1>:
- 400ee0: 48 83 ec 08 sub $0x8,%rsp
- 400ee4: be 00 24 40 00 mov $0x402400,%esi
- 400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal>
- 400eee: 85 c0 test %eax,%eax
- 400ef0: 74 05 je 400ef7 <phase_1+0x17>
- 400ef2: e8 43 05 00 00 callq 40143a <explode_bomb>
- 400ef7: 48 83 c4 08 add $0x8,%rsp
- 400efb: c3 retq
rsi的低16位被赋予0x402400的值,接着调用一个strings_not_equal函数,从名字上能看出这个函数的作用是比较字符串的
返回值rax被按位做合取运算(test),查阅手册知道test操作会在两个操作数都为0时将Zero Flag设为0,这样才能满足下面的je语句的条件跳过400ef2这个引爆炸弹的函数
看下面strings_not_equal函数的汇编码,发现也确实在字符串相等时返回rax为0,那么我们只要找到在400ee9调用它时能返回0的字符串就好了
参见main函数的汇编码
- 400e32: e8 67 06 00 00 callq 40149e <read_line>
- 400e37: 48 89 c7 mov %rax,%rdi
- 400e3a: e8 a1 00 00 00 callq 400ee0 <phase_1> #phase_1
在调用phase_1前,一条第一个参数rdi已经保存了rax,而rax在调用read_line后已经保存了我们输入的字符串地址
第二个参数rsi保存了0x402400这个地址,用x/s命令读取这个地址,发现那里确实存有一个字符串:Border relations with Canada have never been better.
gdb里执行bomb(当然首先给explode_bomb设好断点),输入这个字符串,第一个phase就通过了。
- 0000000000401338 <strings_not_equal>:
- 401338: 41 54 push %r12
- 40133a: 55 push %rbp
- 40133b: 53 push %rbx
- 40133c: 48 89 fb mov %rdi,%rbx
- 40133f: 48 89 f5 mov %rsi,%rbp
- 401342: e8 d4 ff ff ff callq 40131b <string_length>
- 401347: 41 89 c4 mov %eax,%r12d
- 40134a: 48 89 ef mov %rbp,%rdi
- 40134d: e8 c9 ff ff ff callq 40131b <string_length>
- 401352: ba 01 00 00 00 mov $0x1,%edx
- 401357: 41 39 c4 cmp %eax,%r12d
- 40135a: 75 3f jne 40139b <strings_not_equal+0x63>
- 40135c: 0f b6 03 movzbl (%rbx),%eax
- 40135f: 84 c0 test %al,%al
- 401361: 74 25 je 401388 <strings_not_equal+0x50>
- 401363: 3a 45 00 cmp 0x0(%rbp),%al
- 401366: 74 0a je 401372 <strings_not_equal+0x3a>
- 401368: eb 25 jmp 40138f <strings_not_equal+0x57>
- 40136a: 3a 45 00 cmp 0x0(%rbp),%al
- 40136d: 0f 1f 00 nopl (%rax)
- 401370: 75 24 jne 401396 <strings_not_equal+0x5e>
- 401372: 48 83 c3 01 add $0x1,%rbx
- 401376: 48 83 c5 01 add $0x1,%rbp
- 40137a: 0f b6 03 movzbl (%rbx),%eax
- 40137d: 84 c0 test %al,%al
- 40137f: 75 e9 jne 40136a <strings_not_equal+0x32>
- 401381: ba 00 00 00 00 mov $0x0,%edx
- 401386: eb 13 jmp 40139b <strings_not_equal+0x63>
- 401388: ba 00 00 00 00 mov $0x0,%edx
- 40138d: eb 0c jmp 40139b <strings_not_equal+0x63>
- 40138f: ba 01 00 00 00 mov $0x1,%edx
- 401394: eb 05 jmp 40139b <strings_not_equal+0x63>
- 401396: ba 01 00 00 00 mov $0x1,%edx
- 40139b: 89 d0 mov %edx,%eax
- 40139d: 5b pop %rbx
- 40139e: 5d pop %rbp
- 40139f: 41 5c pop %r12
- 4013a1: c3 retq
- 000000000040149e <read_line>:
- 40149e: 48 83 ec 08 sub $0x8,%rsp
- 4014a2: b8 00 00 00 00 mov $0x0,%eax
- 4014a7: e8 4d ff ff ff callq 4013f9 <skip>
- 4014ac: 48 85 c0 test %rax,%rax
- 4014af: 75 6e jne 40151f <read_line+0x81>
- 4014b1: 48 8b 05 90 22 20 00 mov 0x202290(%rip),%rax # 603748 <stdin@@GLIBC_2.2.5>
- 4014b8: 48 39 05 a9 22 20 00 cmp %rax,0x2022a9(%rip) # 603768 <infile>
- 4014bf: 75 14 jne 4014d5 <read_line+0x37>
- 4014c1: bf d5 25 40 00 mov $0x4025d5,%edi
- 4014c6: e8 45 f6 ff ff callq 400b10 <puts@plt>
- 4014cb: bf 08 00 00 00 mov $0x8,%edi
- 4014d0: e8 4b f7 ff ff callq 400c20 <exit@plt>
- 4014d5: bf f3 25 40 00 mov $0x4025f3,%edi
- 4014da: e8 01 f6 ff ff callq 400ae0 <getenv@plt>
- 4014df: 48 85 c0 test %rax,%rax
- 4014e2: 74 0a je 4014ee <read_line+0x50>
- 4014e4: bf 00 00 00 00 mov $0x0,%edi
- 4014e9: e8 32 f7 ff ff callq 400c20 <exit@plt>
- 4014ee: 48 8b 05 53 22 20 00 mov 0x202253(%rip),%rax # 603748 <stdin@@GLIBC_2.2.5>
- 4014f5: 48 89 05 6c 22 20 00 mov %rax,0x20226c(%rip) # 603768 <infile>
- 4014fc: b8 00 00 00 00 mov $0x0,%eax
- 401501: e8 f3 fe ff ff callq 4013f9 <skip>
- 401506: 48 85 c0 test %rax,%rax
- 401509: 75 14 jne 40151f <read_line+0x81>
- 40150b: bf d5 25 40 00 mov $0x4025d5,%edi
- 401510: e8 fb f5 ff ff callq 400b10 <puts@plt>
- 401515: bf 00 00 00 00 mov $0x0,%edi
- 40151a: e8 01 f7 ff ff callq 400c20 <exit@plt>
- 40151f: 8b 15 3b 22 20 00 mov 0x20223b(%rip),%edx # 603760 <num_input_strings>
- 401525: 48 63 c2 movslq %edx,%rax
- 401528: 48 8d 34 80 lea (%rax,%rax,4),%rsi
- 40152c: 48 c1 e6 04 shl $0x4,%rsi
- 401530: 48 81 c6 80 37 60 00 add $0x603780,%rsi
- 401537: 48 89 f7 mov %rsi,%rdi
- 40153a: b8 00 00 00 00 mov $0x0,%eax
- 40153f: 48 c7 c1 ff ff ff ff mov $0xffffffffffffffff,%rcx
- 401546: f2 ae repnz scas %es:(%rdi),%al
- 401548: 48 f7 d1 not %rcx
- 40154b: 48 83 e9 01 sub $0x1,%rcx
- 40154f: 83 f9 4e cmp $0x4e,%ecx
- 401552: 7e 46 jle 40159a <read_line+0xfc>
- 401554: bf fe 25 40 00 mov $0x4025fe,%edi
- 401559: e8 b2 f5 ff ff callq 400b10 <puts@plt>
- 40155e: 8b 05 fc 21 20 00 mov 0x2021fc(%rip),%eax # 603760 <num_input_strings>
- 401564: 8d 50 01 lea 0x1(%rax),%edx
- 401567: 89 15 f3 21 20 00 mov %edx,0x2021f3(%rip) # 603760 <num_input_strings>
- 40156d: 48 98 cltq
- 40156f: 48 6b c0 50 imul $0x50,%rax,%rax
- 401573: 48 bf 2a 2a 2a 74 72 movabs $0x636e7572742a2a2a,%rdi
- 40157a: 75 6e 63
- 40157d: 48 89 b8 80 37 60 00 mov %rdi,0x603780(%rax)
- 401584: 48 bf 61 74 65 64 2a movabs $0x2a2a2a64657461,%rdi
- 40158b: 2a 2a 00
- 40158e: 48 89 b8 88 37 60 00 mov %rdi,0x603788(%rax)
- 401595: e8 a0 fe ff ff callq 40143a <explode_bomb>
- 40159a: 83 e9 01 sub $0x1,%ecx
- 40159d: 48 63 c9 movslq %ecx,%rcx
- 4015a0: 48 63 c2 movslq %edx,%rax
- 4015a3: 48 8d 04 80 lea (%rax,%rax,4),%rax
- 4015a7: 48 c1 e0 04 shl $0x4,%rax
- 4015ab: c6 84 01 80 37 60 00 movb $0x0,0x603780(%rcx,%rax,1)
- 4015b2: 00
- 4015b3: 83 c2 01 add $0x1,%edx
- 4015b6: 89 15 a4 21 20 00 mov %edx,0x2021a4(%rip) # 603760 <num_input_strings>
- 4015bc: 48 89 f0 mov %rsi,%rax
- 4015bf: 48 83 c4 08 add $0x8,%rsp
- 4015c3: c3 retq