实验资源下载地址:csapp.cs.cmu.edu/3e/labs.html 请先查看writeup
解压后
当我们运行bomb时,发现该程序要求我们输入行,如果输入错误,程序就会返回BOOM!!!提示我们失败了.
所以我们的目标是输入正确的行.以解开bomb程序.
实验前先详细阅读bomb.c
//bomb.c
/**************************************************************************** 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.***************************************************************************/
/****************************************************************************邪恶博士的阴险炸弹,1.1版*版权所有2011,邪恶博士公司。保留所有权利。**许可证:*邪恶博士公司(肇事者)特此授予您(受害者)使用此炸弹(炸弹)的明确许可。这是一个有时间限制的许可证,在受害者死亡时到期。肇事者对受害者的伤害、沮丧、精神错乱、bug、腕管综合征、睡眠不足或其他伤害不承担任何责任。除非肇事者想邀功,也就是说。受害者不得将此炸弹源码分发给肇事者的任何敌人。任何受害者不得调试、逆向工程、运行“字符串”、反编译、解密或使用任何其他技术来获得炸弹的知识并拆除炸弹。 处理本程序时不得穿着防爆服。肇事者不会为肇事者的幽默感差道歉。在法律禁止使用炸弹的情况下,本许可证无效。***************************************************************************/#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. *//*自我提醒:记得把这个炸弹移植到Windows上,并在上面放一个很棒的GUI。*//* 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. *//*当使用一个参数<file>运行时,炸弹从<file>读取直到EOF,然后切换到标准输入。因此,当您拆除每个阶段时,您可以将其拆除字符串添加到<file>并避免重新键入它。*/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. *//*您不能使用超过1个命令行参数调用炸弹。*/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! *//*哇,他们明白了!但是不是有什么东西……丢失了吗?也许他们忽略了什么?mua哈哈哈哈哈!*/return 0;
}
bomb文件是一个bomb.c编译后的程序,我们由于缺失一些头文件,所以无法编译bomb.c
让我们反编译bomb,以理清程序的具体实现,从而分析出我们要输入的行:
objdump -d bomb > bomb.txt
阶段一函数,我们可以看到在call strings_not_equal之前传入了一个参数 0x402400我们不知道这是什么,接着看.
call strings_not_equal之后 传入的%esi和%rsi是同一个寄存器,所以参数 0x402400被传到%rbp了,下面我们又看到(%rbp)很明显了,加载了0x402400,也就是0x402400是一个地址,此时我们希望在运行bomb的时候看一下0x402400地址上是什么东西.这里自然就想到书中和实验网页writeup中提到的gdb调试器了.
gdb bomb
加个断点,只需要断在%esi接收到参数0x402400之后即可
(gdb)b strings_not_equal
以字符串形式输出地址上的数据:
(gdb)x/s 0x402400
关于gdb的命令,自己在网上查着,每个用一用就会了.
不查不知道一查吓一跳,原来是个字符串啊.我们再联想一下这个函数的名字strings_not_equal.不难猜到这是一个比较字符串的函数.我们把查到的字符串保存在a.txt文件中,然后传入bomb,这里先按ctrl+d退出gdb在运行bomb方便一些.
./bomb a.txt
解开阶段一.