CSAPP实验二:二进制炸弹(Bomb Lab)

Posted CNFINIT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSAPP实验二:二进制炸弹(Bomb Lab)相关的知识,希望对你有一定的参考价值。

       本系列文章为中国科学技术大学计算机专业学科基础课《计算机系统》布置的实验,上课所用教材和内容为黑书CSAPP,当时花费很大精力和弯路,现来总结下各个实验,本文章为第二个实验——二进制炸弹(Bomb Lab)。

一、实验名称:二进制炸弹

二、实验学时: 3

三、实验内容和目的

       1.二进制炸弹包含若干个阶段,每个阶段需要输入特定的字符串,所有输入正确则炸弹被排除,否则…..

       任务是找出这些字符串

       字符串记录到文件中,可按下列方式验证:

       ./bomb  solution.txt

       用换行区别不同阶段的字符串

       实验完成后上传solution.txt的打包文件

       2.从教辅系统上下载压缩包、组队表格

       压缩包包含48个bomb代码包

       在组队表格中找到自己的组号

       根据“学号%48 + 1”领取自己的代码

       学号191,领取bomb48

       解压后有如下文件

       bomb     二进制可执行文件,任务目标文件

       bomb.c   bomb的源文件,辅助理解bomb代码

       3.GDB参考

       课本3.12(第二版3.11)节,“现实生活:使用GDB调试器”

       更详细一些的资料:

       http://heather.cs.ucdavis.edu/~matloff/UnixAndC/CLanguage/Debug.html

       官方网站

       http://www.gnu.org/software/gdb/

四、实验原理

       查看bomb.c可知程序利用phase_*函数(*为1~6) 检查输入字符串是否合法,不合法就引爆炸弹。我们的任务就是逆向出每个phase的检查规则,构造出合法字符串。

       当然,bomb.c没有给出phase_*的源码

       逆向方法:gdb,直接反汇编

五、汇编复习

       想要完成拆弹任务,不但需要理解不同寄存器的常用方法,也要弄明白具体的操作符是什么意思:

类型

语法

例子

备注

常量

符号$开头

$-42$0x15213

一定要注意十进制还是十六进制

寄存器

符号%开头

%esi%rax

可能存的是值或者地址

内存地址

括号括起来

(%rbx),0x1c(%rax),0x4(%rcx,%rdi,0x1)

括号实际上是去寻址的意思

        一些汇编语句与实际命令的转换:

指令

效果

mov %rbx, %rdx

rdx = rbx

add (%rdx), %r8

r8 += value at rdx

mul $3, %r8

r8 *= 3

sub $1, %r8

r8--

lea (%rdx, %rbx, 2), %rdx

rdx = rdx + rbx*2

       比较与跳转是拆弹的关键,基本所有的字符判断就是通过比较来实现的,比方说cmp b,a会计算a-b的值,test b, a会计算a&b,注意运算符的顺序。例如

cmpl %r9, %r10
jg   8675309

等同于

if %r10 > %r9, jump to 8675309

       各种不同的跳转:

指令

效果

指令

效果

jmp

Always jump

ja

Jump if above(unsigned >)

je/jz

Jump if eq / zero

jae

Jump if above / equal

jne/jnz

Jump if !eq / !zero

jb

Jump if below(unsigned <)

jg

Jump if greater

jbe

Jump if below / equal

jge

Jump if greater / eq

js

Jump if sign bits is 1(neg)

jl

Jump if less

jns

Jump if sign bit is 0 (pos)

jle

Jump if less / eq

x

x

       举几个例子

cmp $0x15213, 
%r12jge deadbeef

       若%r12 >= 0x15213,则跳转到 0xdeadeef

cmp %rax, %rdi
jae 15213b

       如果%rdi的无符号值大于等于%rax,则跳转到0x15213b

test %r8, 
%r8jnz (%rsi)

       如果%r8 & %r8不为零,那么跳转到%rsi存着的地址中。

# 检查符号表
# 然后可以寻找跟 bomb 有关的内容
objdump -t bomb | less

# 反编译
# 搜索 explode_bomb
objdump -d bomb > bomb.txt

# 显示所有字符
strings bomb | less

        GDB 介绍

gdb bomb

# 获取帮助
help

# 设置断点
break explode_bomb
break phase_1

# 开始运行
run

# 检查汇编 会给出对应的代码的汇编
disas 

# 查看寄存器内容
info registers

# 打印指定寄存器
print $rsp

# 每步执行
stepi

# 检查寄存器或某个地址
x/4wd $rsp

六、实验步骤及结果:

     1.准备工作

        首先反汇编

        首先反汇编代码,objdump –d bomb > bomb.txt,对bomb进行反汇编并将汇编代码输出到bomb.txt中。

        bomb.txt文件已经生成,为后面的分析做准备

        开始GDB调试break进入调试窗口

      2. Phase1

        调试函数1

        设置断点break phase_1   

         接着运行run,就会在断点处停下,这里会先让我们输入第一关的密码,随便输入一个抵达断点再说。

          我们现在到断点了,可以利用 disas 来看看对应的汇编代码,其实就和我们之前反汇编出来的一致。  

08048b80 <phase_1>:

   0x08048b80 <+0>: push   %ebp

   0x08048b81 <+1>: mov    %esp,%ebp

   0x08048b83 <+3>: sub    $0x8,%esp

=> 0x08048b86 <+6>: movl   $0x80499d8,0x4(%esp)

   0x08048b8e <+14>: mov    0x8(%ebp),%eax

   0x08048b91 <+17>: mov    %eax,(%esp)

   0x08048b94 <+20>: call   0x8049113 <strings_not_equal>

   0x08048b99 <+25>: test   %eax,%eax

   0x08048b9b <+27>: je     0x8048ba2 <phase_1+34>

   0x08048b9d <+29>: call   0x80496da <explode_bomb>

   0x08048ba2 <+34>: leave  

   0x08048ba3 <+35>: ret  

        第一步先压栈,ebp为栈底指针,esp为栈顶指针

        第二步把esp赋值给ebp

        第三步把0x18赋值给esp

        第四步把内存中地址为$0x80499d8的内容赋值给*(esp+4)

        第五步输入的字符*(ebp+8)->eax即为所求,理由如后续。

        后续比较两字符串是否相等,如果相等令eax为0 否则为1。

        再往后,如果eax=0 则进入phase2 否则爆炸

        最后为第二个炸弹做准备。返回。

        用(gdb) x/s 0x80499d8 查看位于该地址处的内容,可以看到出现

        Why make trillions when we could make... billions?

        读出数据后使用RUN命令测试成功,上面字符串即为所求。

        然后输入 quit 退出 gdb,新建一个文本文件 touch solution.txt,方便以后输入答案。

        下面的phase步骤都是先打断点,再分析

     3. Phase2

         调试函数2

0x8048baa<phase_2>:

   0x08048ba4 <+0>: push   %ebp

   0x08048ba5 <+1>: mov    %esp,%ebp

   0x08048ba7 <+3>: sub    $0x28,%esp

=> 0x08048baa <+6>: movl   $0x0,-0x4(%ebp)

   0x08048bb1 <+13>: lea    -0x20(%ebp),%eax

   0x08048bb4 <+16>: mov    %eax,0x4(%esp)

   0x08048bb8 <+20>: mov    0x8(%ebp),%eax

   0x08048bbb <+23>: mov    %eax,(%esp)

   0x08048bbe <+26>: call   0x8049080 <read_six_numbers>

   0x08048bc3 <+31>: movl   $0x0,-0x8(%ebp)

   0x08048bca <+38>: jmp    0x8048bf3 <phase_2+79>

   0x08048bcc <+40>: mov    -0x8(%ebp),%eax

   0x08048bcf <+43>: mov    -0x20(%ebp,%eax,4),%edx

   0x08048bd3 <+47>: mov    -0x8(%ebp),%eax

   0x08048bd6 <+50>: add    $0x3,%eax

   0x08048bd9 <+53>: mov    -0x20(%ebp,%eax,4),%eax

   0x08048bdd <+57>: cmp    %eax,%edx

   0x08048bdf <+59>: je     0x8048be6 <phase_2+66>

   0x08048be1 <+61>: call   0x80496da <explode_bomb>

   0x08048be6 <+66>: mov    -0x8(%ebp),%eax

   0x08048be9 <+69>: mov    -0x20(%ebp,%eax,4),%eax

   0x08048bed <+73>: add    %eax,-0x4(%ebp)

   0x08048bf0 <+76>: incl   -0x8(%ebp)

   0x08048bf3 <+79>: cmpl   $0x2,-0x8(%ebp)

   0x08048bf7 <+83>: jle    0x8048bcc <phase_2+40>

   0x08048bf9 <+85>: cmpl   $0x0,-0x4(%ebp)

   0x08048bfd <+89>: jne    0x8048c04 <phase_2+96>

   0x08048bff <+91>: call   0x80496da <explode_bomb>

   0x08048c04 <+96>: leave  

   0x08048c05 <+97>: ret 

         生成的txt文件中代码如上所示。

         由这句话0x08048bc3 <+31>: movl   $0x0,-0x8(%ebp) 表明-0x8(%ebp)里的值一开始是0

         然后根据0x08048bf3 <+79>: cmpl   $0x2,-0x8(%ebp)知道循环三次

         再根据以下  

   0x08048bcc <+40>: mov    -0x8(%ebp),%eax

   0x08048bcf <+43>: mov    -0x20(%ebp,%eax,4),%edx

   0x08048bd3 <+47>: mov    -0x8(%ebp),%eax

   0x08048bd6 <+50>: add    $0x3,%eax

   0x08048bd9 <+53>: mov    -0x20(%ebp,%eax,4),%eax

   0x08048bdd <+57>: cmp    %eax,%edx

   0x08048bdf <+59>: je     0x8048be6 <phase_2+66>

         这段可知每隔三个数比较数组元素是否相等,不相等则跳转炸弹爆炸,故输入4 5 6 4 5 6即可通过。

      4. Phase3

         调试函数3

08048c06 <phase_3>:

   0x08048c06 <+0>: push   %ebp

   0x08048c07 <+1>: mov    %esp,%ebp

   0x08048c09 <+3>: sub    $0x38,%esp

   0x08048c0c <+6>: movl   $0x0,-0x8(%ebp)

   0x08048c13 <+13>: lea    -0x10(%ebp),%eax

   0x08048c16 <+16>: mov    %eax,0x10(%esp)

   0x08048c1a <+20>: lea    -0x11(%ebp),%eax

   0x08048c1d <+23>: mov    %eax,0xc(%esp)

   0x08048c21 <+27>: lea    -0xc(%ebp),%eax

   0x08048c24 <+30>: mov    %eax,0x8(%esp)

   0x08048c28 <+34>: movl   $0x8049a0b,0x4(%esp)

   0x08048c30 <+42>: mov    0x8(%ebp),%eax

=> 0x08048c33 <+45>: mov    %eax,(%esp)

   0x08048c36 <+48>: call   0x8048868 <sscanf@plt>

   0x08048c3b <+53>: mov    %eax,-0x8(%ebp)

   0x08048c3e <+56>: cmpl   $0x2,-0x8(%ebp)

   0x08048c42 <+60>: jg     0x8048c49 <phase_3+67>

   0x08048c44 <+62>: call   0x80496da <explode_bomb>

   0x08048c49 <+67>: mov    -0xc(%ebp),%eax

   0x08048c4c <+70>: mov    %eax,-0x24(%ebp)

   0x08048c4f <+73>: cmpl   $0x7,-0x24(%ebp)

   0x08048c53 <+77>: ja     0x8048d19 <phase_3+275>

   0x08048c59 <+83>: mov    -0x24(%ebp),%edx

   0x08048c5c <+86>: mov    0x8049a14(,%edx,4),%eax

   0x08048c63 <+93>: jmp    *%eax

   0x08048c65 <+95>: movb   $0x79,-0x1(%ebp)

   0x08048c69 <+99>: mov    -0x10(%ebp),%eax

   0x08048c6c <+102>: cmp    $0x346,%eax

   0x08048c71 <+107>: je     0x8048d22 <phase_3+284>

   0x08048c77 <+113>: call   0x80496da <explode_bomb>

   0x08048c7c <+118>: jmp    0x8048d22 <phase_3+284>

   0x08048c81 <+123>: movb   $0x69,-0x1(%ebp)

   0x08048c85 <+127>: mov    -0x10(%ebp),%eax

   0x08048c88 <+130>: cmp    $0x36f,%eax

   0x08048c8d <+135>: je     0x8048d22 <phase_3+284>

   0x08048c93 <+141>: call   0x80496da <explode_bomb>

   0x08048c98 <+146>: jmp    0x8048d22 <phase_3+284>

   0x08048c9d <+151>: movb   $0x68,-0x1(%ebp)

   0x08048ca1 <+155>: mov    -0x10(%ebp),%eax

   0x08048ca4 <+158>: cmp    $0x274,%eax

   0x08048ca9 <+163>: je     0x8048d22 <phase_3+284>

   0x08048cab <+165>: call   0x80496da <explode_bomb>

   0x08048cb0 <+170>: jmp    0x8048d22 <phase_3+284>

   0x08048cb2 <+172>: movb   $0x6e,-0x1(%ebp)

   0x08048cb6 <+176>: mov    -0x10(%ebp),%eax

   0x08048cb9 <+179>: cmp    $0x46,%eax

   0x08048cbc <+182>: je     0x8048d22 <phase_3+284>

   0x08048cbe <+184>: call   0x80496da <explode_bomb>

   0x08048cc3 <+189>: jmp    0x8048d22 <phase_3+284>

   0x08048cc5 <+191>: movb   $0x64,-0x1(%ebp)

   0x08048cc9 <+195>: mov    -0x10(%ebp),%eax

   0x08048ccc <+198>: cmp    $0x15b,%eax

   0x08048cd1 <+203>: je     0x8048d22 <phase_3+284>

   0x08048cd3 <+205>: call   0x80496da <explode_bomb>

   0x08048cd8 <+210>: jmp    0x8048d22 <phase_3+284>

---Type <return> to continue, or q <return> to quit---

   0x08048cda <+212>: movb   $0x6b,-0x1(%ebp)

   0x08048cde <+216>: mov    -0x10(%ebp),%eax

   0x08048ce1 <+219>: cmp    $0x35c,%eax

   0x08048ce6 <+224>: je     0x8048d22 <phase_3+284>

   0x08048ce8 <+226>: call   0x80496da <explode_bomb>

   0x08048ced <+231>: jmp    0x8048d22 <phase_3+284>

   0x08048cef <+233>: movb   $0x65,-0x1(%ebp)

   0x08048cf3 <+237>: mov    -0x10(%ebp),%eax

   0x08048cf6 <+240>: cmp    $0x29c,%eax

   0x08048cfb <+245>: je     0x8048d22 <phase_3+284>

   0x08048cfd <+247>: call   0x80496da <explode_bomb>

   0x08048d02 <+252>: jmp    0x8048d22 <phase_3+284>

   0x08048d04 <+254>: movb   $0x63,-0x1(%ebp)

   0x08048d08 <+258>: mov    -0x10(%ebp),%eax

   0x08048d0b <+261>: cmp    $0xeb,%eax

   0x08048d10 <+266>: je     0x8048d22 <phase_3+284>

   0x08048d12 <+268>: call   0x80496da <explode_bomb>

   0x08048d17 <+273>: jmp    0x8048d22 <phase_3+284>

   0x08048d19 <+275>: movb   $0x63,-0x1(%ebp)

   0x08048d1d <+279>: call   0x80496da <explode_bomb>

   0x08048d22 <+284>: movzbl -0x11(%ebp),%eax

   0x08048d26 <+288>: cmp    %al,-0x1(%ebp)

   0x08048d29 <+291>: je     0x8048d30 <phase_3+298>

   0x08048d2b <+293>: call   0x80496da <explode_bomb>

   0x08048d30 <+298>: leave  

   0x08048d31 <+299>: ret   

         总体汇编代码如上所示,具体分析如下:

         本题代码整体太长,一点一点解读既费时间,又可能找不到头绪。所幸我们找到了里面一直出现的cmp je语句,这提示我们一个重要信息,即附近有个switch循环,仔细寻找后如下

   0x08048c13 <+13>: lea    -0x10(%ebp),%eax

   0x08048c16 <+16>: mov    %eax,0x10(%esp)

   0x08048c1a <+20>: lea    -0x11(%ebp),%eax

   0x08048c1d <+23>: mov    %eax,0xc(%esp)
   
   0x08048c21 <+27>: lea    -0xc(%ebp),%eax

   0x08048c24 <+30>: mov    %eax,0x8(%esp)

   0x08048c28 <+34>: movl   $0x8049a0b,0x4(%esp)

         分析上面几个lea和mov语句可知,该操作获取了三个参数,

         x/sb 0x8049a0b,得0x8049a0b: "%d %c %d"。依次是int,char,int

         再根据如下

   0x08048c49 <+67>: mov    -0xc(%ebp),%eax

   0x08048c4c <+70>: mov    %eax,-0x24(%ebp)

   0x08048c4f <+73>: cmpl   $0x7,-0x24(%ebp)

         由上三行可知,比较第一个参数在不在0到7之间,然后后面根据第一个输入的参数进行跳转。

         如果输入 0,那么就直接执行下一条 mov 语句,然后0x08048c6c <+102>: cmp $0x346,%eax是比较第三个参数是否和 0x346 相等,所以我们知道第三个参数是 838(如果第一个参数是 0)的话。如果一切正常,那么就会跳转到 +284 的位置,也就是: 

   0x08048d22 <+284>: movzbl -0x11(%ebp),%eax

   0x08048d26 <+288>: cmp    %al,-0x1(%ebp)

   0x08048d29 <+291>: je     0x8048d30 <phase_3+298>

   0x08048d2b <+293>: call   0x80496da <explode_bomb>

   0x08048d30 <+298>: leave  

   0x08048d31 <+299>: ret

         我们只要搞清楚 %al 里面的值是什么就好(会和第二个参数进行比较),具体的值,其实就是前面 mov 语句0x08048c65 <+95>: movb   $0x79,-0x1(%ebp),读入的 0x79(121),对应的字符是 y。

         所以答案是 0 y 838,当然选择不同的分支就有不同的答案,其他分支的分析也都是类似的。运行一下,就可以发现这一关又过了。

      5. Phase4

        调试函数4

08048d72 <phase_4>:

   0x08048d72 <+0>: push   %ebp

   0x08048d73 <+1>: mov    %esp,%ebp

   0x08048d75 <+3>: sub    $0x28,%esp

=> 0x08048d78 <+6>: lea    -0xc(%ebp),%eax

   0x08048d7b <+9>: mov    %eax,0x8(%esp)

   0x08048d7f <+13>: movl   $0x8049a34,0x4(%esp)

   0x08048d87 <+21>: mov    0x8(%ebp),%eax

   0x08048d8a <+24>: mov    %eax,(%esp)

   0x08048d8d <+27>: call   0x8048868 <sscanf@plt>

   0x08048d92 <+32>: mov    %eax,-0x4(%ebp)

   0x08048d95 <+35>: cmpl   $0x1,-0x4(%ebp)

   0x08048d99 <+39>: jne    0x8048da2 <phase_4+48>

   0x08048d9b <+41>: mov    -0xc(%ebp),%eax

   0x08048d9e <+44>: test   %eax,%eax

   0x08048da0 <+46>: jg     0x8048da7 <phase_4+53>

   0x08048da2 <+48>: call   0x80496da <explode_bomb>

   0x08048da7 <+53>: mov    -0xc(%ebp),%eax

   0x08048daa <+56>: mov    %eax,(%esp)

   0x08048dad <+59>: call   0x8048d32 <func4>

   0x08048db2 <+64>: mov    %eax,-0x8(%ebp)

   0x08048db5 <+67>: cmpl   $0x262,-0x8(%ebp)

   0x08048dbc <+74>: je     0x8048dc3 <phase_4+81>

   0x08048dbe <+76>: call   0x80496da <explode_bomb>

   0x08048dc3 <+81>: leave  

   0x08048dc4 <+82>: ret

        0x08048d7f <+13>: movl   $0x8049a34,0x4(%esp) 可看出时刻获取了某个参数打个断点看一下x/s 0x8049a340x8049a34: "%d"

        说明此刻输入一个整数

        再由

   0x08048db5 <+67>: cmpl   $0x262,-0x8(%ebp)

   0x08048dbc <+74>: je     0x8048dc3 <phase_4+81>

   0x08048dbe <+76>: call   0x80496da <explode_bomb>

   0x08048dc3 <+81>: leave  

        得即从斐波那契函数等于0x0x262时是第几个数,即为输入,

        F(x) = F(x-1)+F(x-2), F(1)=1,F(2)=1,F(3)=2......F(15)=610即0x262但是然后看func4里面有减的,所以要找14。

     6. Phase5

       调试函数5

08048dc5 <phase_5>:

   0x08048dc5 <+0>: push   %ebp //压栈 ebp为栈指针 esp为栈指针

   0x08048dc6 <+1>: mov    %esp,%ebp //把esp赋值给ebp

   0x08048dc8 <+3>: sub    $0x18,%esp //0x18赋值给esp

=> 0x08048dcb <+6>: mov    0x8(%ebp),%eax //*(esp+8)->eax 就是输入的字符串

   0x08048dce <+9>: mov    %eax,(%esp) //eax的值赋值给*esp

   0x08048dd1 <+12>: call   0x80490e9 <string_length>

   0x08048dd6 <+17>: mov    %eax,-0x4(%ebp)

   0x08048dd9 <+20>: cmpl   $0x6,-0x4(%ebp)//输入字符串长6

   0x08048ddd <+24>: je     0x8048de4 <phase_5+31>

   0x08048ddf <+26>: call   0x80496da <explode_bomb>

   0x08048de4 <+31>: movl   $0x0,-0x8(%ebp)

   0x08048deb <+38>: jmp    0x8048e0d <phase_5+72>

   0x08048ded <+40>: mov    -0x8(%ebp),%edx

   0x08048df0 <+43>: mov    -0x8(%ebp),%eax

   0x08048df3 <+46>: add    0x8(%ebp),%eax

   0x08048df6 <+49>: movzbl (%eax),%eax

   0x08048df9 <+52>: movsbl %al,%eax

   0x08048dfc <+55>: and    $0xf,%eax //取后4位

   0x08048dff <+58>: movzbl 0x804a5c0(%eax),%eax

   0x08048e06 <+65>: mov    %al,-0xf(%ebp,%edx,1)

   0x08048e0a <+69>: incl   -0x8(%ebp)

   0x08048e0d <+72>: cmpl   $0x5,-0x8(%ebp)

   0x08048e11 <+76>: jle    0x8048ded <phase_5+40>

   0x08048e13 <+78>: movb   $0x0,-0x9(%ebp)

   0x08048e17 <+82>: movl   $0x8049a37,0x4(%esp)

   0x08048e1f <+90>: lea    -0xf(%ebp),%eax

   0x08048e22 <+93>: mov    %eax,(%esp)

   0x08048e25 <+96>: call   0x8049113 <strings_not_equal>

   0x08048e2a <+101>: test   %eax,%eax

   0x08048e2c <+103>: je     0x8048e33 <phase_5+110> //如果eax=0 则进入phase6 否则爆炸

   0x08048e2e <+105>: call   0x80496da <explode_bomb>

   0x08048e33 <+110>: leave  //为结束函数做准备

   0x08048e34 <+111>: ret

       1.调用string_length测长度3,若不为6则爆炸

  8048dd1:e8 13 03 00 00        call   80490e9 <string_length>
 
  8048dd6:89 45 fc              mov    %eax,-0x4(%ebp)

  8048dd9:83 7d fc 06           cmpl   $0x6,-0x4(%ebp)//输入字符串长6

  8048ddd:74 05                 je     8048de4 <phase_5+0x1f>

  8048ddf: e8 f6 08 00 00        call   80496da <explode_bomb>

        2.循环6次,取出字符,截取低四位

  8048df6: 0f b6 00              movzbl (%eax),%eax

  8048df9: 0f be c0              movsbl %al,%eax

  8048dfc: 83 e0 0f              and    $0xf,%eax//取后4位

  8048dff: 0f b6 80 c0 a5 04 08  movzbl 0x804a5c0(%eax),%eax

  8048e06: 88 44 15 f1           mov    %al,-0xf(%ebp,%edx,1)

        3.根据输入字符ASCII码低四位与索引比较,不同则爆炸。

       我们得到的作为参考用,也就是索引表功能的字符串为isrveawhobpnutf,而我们的目的字符串为saints,分别为1位,5位,0位,11位,13位和1位,所以只要我们输入的六个字符的相应的低4位的二进制表示为1,5,0,11,13,1 即可。所以这一关我选取的密码是150km1。

     7. Phase6

      调试函数6   

0x8048e3b <fun6>:

 8048e35: 55                    push   %ebp

 8048e36: 89 e5                 mov    %esp,%ebp

 8048e38: 83 ec 10              sub    $0x10,%esp # esp-0x10

 8048e3b: 8b 45 08              mov 0x8(%ebp),%eax 

# eax=arg=local2=0x804a66c

 8048e3e: 89 45 f0              mov    %eax,-0x10(%ebp) # local4=arg

 8048e41: 8b 45 08              mov    0x8(%ebp),%eax

 8048e44: 89 45 f0              mov    %eax,-0x10(%ebp)

 8048e47: 8b 45 08              mov    0x8(%ebp),%eax # eax=arg

 # eax=*(arg+8)=*(0x804a66c)

8048e4a: 8b 40 08              mov    0x8(%eax),%eax 

# local3=eax=*(0x804a66c)

8048e4d: 89 45 f4              mov    %eax,-0xc(%ebp) 

# eax=local4=0x804a66c

8048e50: 8b 45 f0              mov    -0x10(%ebp),%eax

# *(0x804a66c)=0

 8048e53: c7 40 08 00 00 00 00 movl   $0x0,0x8(%eax)

 8048e5a: eb 62                 jmp    8048ebe <fun6+0x89>

#loop

 8048e5c: 8b 45 f0              mov    -0x10(%ebp),%eax # eax=local4

 # local1=local4

8048e5f: 89 45 fc              mov    %eax,-0x4(%ebp) 

8048e62: 8b 45 f0              mov    -0x10(%ebp),%eax

# local2=local4

 8048e65: 89 45 f8              mov    %eax,-0x8(%ebp)

 8048e68: eb 0f                 jmp    8048e79 <fun6+0x44>



 8048e6a: 8b 45 fc              mov    -0x4(%ebp),%eax

 8048e6d: 89 45 f8              mov    %eax,-0x8(%ebp)

 8048e70: 8b 45 fc              mov    -0x4(%ebp),%eax

 8048e73: 8b 40 08              mov    0x8(%eax),%eax

 8048e76: 89 45 fc              mov    %eax,-0x4(%ebp)

 8048e79: 83 7d fc 00           cmpl   $0x0,-0x4(%ebp)

# if(local1==0)

 8048e7d: 74 0e                 je     8048e8d <fun6+0x58>



 8048e7f: 8b 45 fc              mov    -0x4(%ebp),%eax

 8048e82: 8b 10                 mov    (%eax),%edx

 8048e84: 8b 45 f4              mov    -0xc(%ebp),%eax

 8048e87: 8b 00                 mov    (%eax),%eax

 8048e89: 39 c2                 cmp    %eax,%edx

 8048e8b: 7f dd                 jg     8048e6a <fun6+0x35>



 8048e8d: 8b 45 f8              mov    -0x8(%ebp),%eax

 8048e90: 3b 45 fc              cmp    -0x4(%ebp),%eax

 8048e93: 74 0b                 je     8048ea0 <fun6+0x6b>



 8048e95: 8b 55 f8              mov    -0x8(%ebp),%edx

 8048e98: 8b 45 f4              mov    -0xc(%ebp),%eax

 8048e9b: 89 42 08              mov    %eax,0x8(%edx)

 8048e9e: eb 06                 jmp    8048ea6 <fun6+0x71>



 8048ea0: 8b 45 f4              mov    -0xc(%ebp),%eax

 8048ea3: 89 45 f0              mov    %eax,-0x10(%ebp)

 8048ea6: 8b 45 f4              mov    -0xc(%ebp),%eax

 8048ea9: 8b 40 08              mov    0x8(%eax),%eax

 8048eac: 89 45 f8              mov    %eax,-0x8(%ebp)

 8048eaf: 8b 55 f4              mov    -0xc(%ebp),%edx

 8048eb2: 8b 45 fc              mov    -0x4(%ebp),%eax

 8048eb5: 89 42 08              mov    %eax,0x8(%edx)

 8048eb8: 8b 45 f8              mov    -0x8(%ebp),%eax

 8048ebb: 89 45 f4              mov    %eax,-0xc(%ebp)



 8048ebe: 83 7d f4 00           cmpl   $0x0,-0xc(%ebp) #是否为0

#if(local3!=0) jump 39;

 8048ec2: 75 98                 jne    8048e5c <fun6+0x27>

 8048ec4: 8b 45 f0              mov    -0x10(%ebp),%eax

 8048ec7: c9                    leave  

 8048ec8: c3                    ret 
0x8048ecf <phase_6>:

   0x08048ec9 <+0>: push   %ebp

   0x08048eca <+1>: mov    %esp,%ebp

   0x08048ecc <+3>: sub    $0x18,%esp

=> 0x08048ecf <+6>: movl   $0x804a63c,-0x8(%ebp)

   0x08048ed6 <+13>: mov    0x8(%ebp),%eax

   0x08048ed9 <+16>: mov    %eax,(%esp)

   0x08048edc <+19>: call   0x8048858 <atoi@plt>

   0x08048ee1 <+24>: mov    %eax,%edx

   0x08048ee3 <+26>: mov    -0x8(%ebp),%eax

   0x08048ee6 <+29>: mov    %edx,(%eax)

   0x08048ee8 <+31>: mov    -0x8(%ebp),%eax

   0x08048eeb <+34>: mov    %eax,(%esp)

   0x08048eee <+37>: call   0x8048e35 <fun6>

   0x08048ef3 <+42>: mov    %eax,-0x8(%ebp)

   0x08048ef6 <+45>: mov    -0x8(%ebp),%eax

   0x08048ef9 <+48>: mov    %eax,-0x4(%ebp)

   0x08048efc <+51>: movl   $0x1,-0xc(%ebp)

   0x08048f03 <+58>: jmp    0x8048f11 <phase_6+72>

   0x08048f05 <+60>: mov    -0x4(%ebp),%eax

   0x08048f08 <+63>: mov    0x8(%eax),%eax

   0x08048f0b <+66>: mov    %eax,-0x4(%ebp)

   0x08048f0e <+69>: incl   -0xc(%ebp)

   0x08048f11 <+72>: cmpl   $0x7,-0xc(%ebp)

   0x08048f15 <+76>: jle    0x8048f05 <phase_6+60>

   0x08048f17 <+78>: mov    -0x4(%ebp),%eax

   0x08048f1a <+81>: mov    (%eax),%edx

   0x08048f1c <+83>: mov    0x804a63c,%eax

   #在这设置一个断点 break *0x8048f21

   0x08048f21 <+88>: cmp    %eax,%edx

   0x08048f23 <+90>: je     0x8048f2a <phase_6+97>

   0x08048f25 <+92>: call   0x80496da <explode_bomb>

   0x08048f2a <+97>: leave  

   0x08048f2b <+98>: ret

      看到phase_6的<+88>行是和输入的数做比较,只要在这里设置断点直接查看edx中的值即可

      0xf8=248,即为答案。

    8.实验总结

     所以每个关卡的答案为:

Why make trillions when we could make... billions?

4 5 6 4 5 6

0 y 838

14

150km1

248

        一开始接触这个实验的时候什么都不懂或者说是什么都不敢动。查阅一些料后并学习了一些gdb 的使用方法后,开始着手研究反编译代码,并一步一步她开始拆除炸弹。本次实验后,对涌过gdb 调试工具来调试程序有了一些了解。整个二进制炸弹的程序分别用到了直接她址寻址、循环语句、跳转、递归函数、字符串switch码转换和链表等知识,涉及内容多覆盖面广,破解炸弹的过程是一次重要的巩固和提高的过程。

以上是关于CSAPP实验二:二进制炸弹(Bomb Lab)的主要内容,如果未能解决你的问题,请参考以下文章

CSAPP实验二:二进制炸弹(Bomb Lab)

CMU-CSAPP-Lab2拆解二进制炸弹

CSAPP Bomb Lab记录

CSAPP-Bomb Lab

CSAPP Bomb Lab

CSAPP Bomb Lab