cmu-csapp-lab2-bomb解题过程

  这个题的本质是让通过gdb和objdump的工具的使用,以及对汇编代码的理解找到程序在栈中已存在的数据或者汇编代码本身的代码逻辑。从而根据固有信息确定输入,使得炸弹得以解除。这个实验有6道关卡和一道隐藏关卡。由于时间原因,我并没有想方法找出隐藏关,只是把固有的6道关卡做完了。下面说一下解题步骤。

  由于炸弹爆炸是要扣分的,所以最开始需要做的任务是在炸弹爆炸函数的入口设置一个断点。这样一来当发现运行到这个断点之后就可以重新开始gdb的运行,使得爆炸函数得不到运行。由于是只有通过前一关后才能做后一关所以当做到后面几关的时候,要把前几关的答案放在一个文档里,然后运行gdb时指定这个文件,就会自动通过前几关。

  关于gdb的使用可以看我的另一篇文章。

第一道关卡:phase1

  上代码:

08048b90 <phase_1>:
 8048b90:       55                      push   %ebp
 8048b91:       89 e5                   mov    %esp,%ebp
 8048b93:       83 ec 18                sub    $0x18,%esp
 8048b96:       c7 44 24 04 e4 a2 04    movl   $0x804a2e4,0x4(%esp)
 8048b9d:       08
 8048b9e:       8b 45 08                mov    0x8(%ebp),%eax
 8048ba1:       89 04 24                mov    %eax,(%esp)
 8048ba4:       e8 a2 04 00 00          call   804904b <strings_not_equal>
 8048ba9:       85 c0                   test   %eax,%eax
 8048bab:       74 05                   je     8048bb2 <phase_1+0x22>
 8048bad:       e8 86 07 00 00          call   8049338 <explode_bomb>
 8048bb2:       c9                      leave
 8048bb3:       c3                      ret

  以上是通过用objdump工具反汇编bomb可执行程序后得到的汇编代码文件中第一关的代码。这个代码的意义非常简单。通读下来发现首先确定栈的大小。然后为函数strings_not_equal准备参数。参数总共有两个一个是用户自己输入的字符串。由于是字符串,肯定不是直接把字符串本身放在运行占空间里的,所以通过ebp寄存器可以找到存放字符串的内存地址。同理,很自然的可以知道0x804a2e4即是程序本身的一段字符串。通过匹配字符串,便可以把炸弹解开。因此此题的目的便是把字符串找出来,因此便用到了gdb工具。

  首先,用p/x *(int *)0x804a2e4便可以得到一个地址。假设地址为ooxx,那么要想查看这段地址存放的字符串内容便可以通过x/s ooxx既可以得到字符串的内容。我的答案是:There are rumors on the internets.每个人的答案都不一样。哈哈。下面来看第二题。

第二道关卡:phase2

  上代码:

08048bb4 <phase_2>:
 8048bb4:       55                      push   %ebp
 8048bb5:       89 e5                   mov    %esp,%ebp
 8048bb7:       56                      push   %esi
 8048bb8:       53                      push   %ebx
 8048bb9:       83 ec 30                sub    $0x30,%esp
 8048bbc:       8d 45 e0                lea    -0x20(%ebp),%eax
 8048bbf:       89 44 24 04             mov    %eax,0x4(%esp)
 8048bc3:       8b 45 08                mov    0x8(%ebp),%eax
 8048bc6:       89 04 24                mov    %eax,(%esp)
 8048bc9:       e8 d2 08 00 00          call   80494a0 <read_six_numbers>
 8048bce:       83 7d e0 01             cmpl   $0x1,-0x20(%ebp)
 8048bd2:       74 05                   je     8048bd9 <phase_2+0x25>
 8048bd4:       e8 5f 07 00 00          call   8049338 <explode_bomb>
 8048bd9:       8d 5d e4                lea    -0x1c(%ebp),%ebx
 8048bdc:       8d 75 f8                lea    -0x8(%ebp),%esi
 8048bdf:       8b 43 fc                mov    -0x4(%ebx),%eax
 8048be2:       01 c0                   add    %eax,%eax
 8048be4:       39 03                   cmp    %eax,(%ebx)
 8048be6:       74 05                   je     8048bed <phase_2+0x39>
 8048be8:       e8 4b 07 00 00          call   8049338 <explode_bomb>
 8048bed:       83 c3 04                add    $0x4,%ebx
 8048bf0:       39 f3                   cmp    %esi,%ebx
 8048bf2:       75 eb                   jne    8048bdf <phase_2+0x2b>
 8048bf4:       83 c4 30                add    $0x30,%esp
 8048bf7:       5b                      pop    %ebx
 8048bf8:       5e                      pop    %esi
 8048bf9:       5d                      pop    %ebp
 8048bfa:       c3                      ret

  首先可以看到这道题调用一个函数。函数名叫输入6个数。很明显,这六个书会以次放在ebp-0x20到ebp-0x8的空间内。然后再从以下的代码逻辑可以看出这6个数得满足一种关系:等比为2的等比数列。并且首元素为1.因此答案就明了了为:1 2 4 8 16 32.下面来看第三关。

第三道关卡:phase3

上代码:

08048bfb <phase_3>:
 8048bfb:       55                      push   %ebp
 8048bfc:       89 e5                   mov    %esp,%ebp
 8048bfe:       83 ec 28                sub    $0x28,%esp
 8048c01:       8d 45 f0                lea    -0x10(%ebp),%eax
 8048c04:       89 44 24 0c             mov    %eax,0xc(%esp)
 8048c08:       8d 45 f4                lea    -0xc(%ebp),%eax
 8048c0b:       89 44 24 08             mov    %eax,0x8(%esp)
 8048c0f:       c7 44 24 04 25 a6 04    movl   $0x804a625,0x4(%esp)
 8048c16:       08
 8048c17:       8b 45 08                mov    0x8(%ebp),%eax
 8048c1a:       89 04 24                mov    %eax,(%esp)
 8048c1d:       e8 be fb ff ff          call   80487e0 <__isoc99_sscanf@plt>
 8048c22:       83 f8 01                cmp    $0x1,%eax
 8048c25:       7f 05                   jg     8048c2c <phase_3+0x31>
 8048c27:       e8 0c 07 00 00          call   8049338 <explode_bomb>
 8048c2c:       83 7d f4 07             cmpl   $0x7,-0xc(%ebp)
 8048c30:       77 65                   ja     8048c97 <phase_3+0x9c>
 8048c32:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048c35:       ff 24 85 40 a3 04 08    jmp    *0x804a340(,%eax,4)
 8048c3c:       b8 00 00 00 00          mov    $0x0,%eax
 8048c41:       eb 05                   jmp    8048c48 <phase_3+0x4d>
 8048c43:       b8 56 00 00 00          mov    $0x56,%eax
 8048c48:       2d 0f 02 00 00          sub    $0x20f,%eax
 8048c4d:       eb 05                   jmp    8048c54 <phase_3+0x59>
 8048c4f:       b8 00 00 00 00          mov    $0x0,%eax
 8048c54:       05 a9 03 00 00          add    $0x3a9,%eax
 8048c59:       eb 05                   jmp    8048c60 <phase_3+0x65>
 8048c5b:       b8 00 00 00 00          mov    $0x0,%eax
 8048c60:       2d e5 00 00 00          sub    $0xe5,%eax
 8048c65:       eb 05                   jmp    8048c6c <phase_3+0x71>
 8048c67:       b8 00 00 00 00          mov    $0x0,%eax
 8048c6c:       05 e5 00 00 00          add    $0xe5,%eax
 8048c71:       eb 05                   jmp    8048c78 <phase_3+0x7d>
 8048c73:       b8 00 00 00 00          mov    $0x0,%eax
 8048c78:       2d e5 00 00 00          sub    $0xe5,%eax
 8048c7d:       eb 05                   jmp    8048c84 <phase_3+0x89>
 8048c7f:       b8 00 00 00 00          mov    $0x0,%eax
 8048c84:       05 e5 00 00 00          add    $0xe5,%eax
 8048c89:       eb 05                   jmp    8048c90 <phase_3+0x95>
 8048c8b:       b8 00 00 00 00          mov    $0x0,%eax
 8048c90:       2d e5 00 00 00          sub    $0xe5,%eax
 8048c95:       eb 0a                   jmp    8048ca1 <phase_3+0xa6>
 8048c97:       e8 9c 06 00 00          call   8049338 <explode_bomb>
 8048c9c:       b8 00 00 00 00          mov    $0x0,%eax
 8048ca1:       83 7d f4 05             cmpl   $0x5,-0xc(%ebp)
 8048ca5:       7f 05                   jg     8048cac <phase_3+0xb1>
 8048ca7:       3b 45 f0                cmp    -0x10(%ebp),%eax
 8048caa:       74 05                   je     8048cb1 <phase_3+0xb6>
 8048cac:       e8 87 06 00 00          call   8049338 <explode_bomb>
 8048cb1:       c9                      leave
 8048cb2:       c3                      ret

  有没有被这段代码吓到?确实有点长。依然可以看到这个题会调用一个函数,这个函数是sscanf,如果对这个函数有所了解的话,可以从它下面的一个比较看出这个函数要求输入两个变量,那么这两个变量是什么类型的呢?可以从movl   $0x804a625,0x4(%esp)这句里找到信息。很明显这是个非常突兀的地址,那么这个地址是干嘛的,首先可以肯定它是sscanf函数的参数,联想到sscanf的参数,可以这段地址的内容便是变量的类型。通过x/s 0x804a625便可以得到"%d %d"这个字符串。同样从开始代码的调动,仍然可以清晰的确定这是有接受两个参数。从后面的代码逻辑可以看出,要根据第一个参数的具体值跳到不同的地址,来执行命令。而且第一个参数要小于7.可以分别假设第一个参数等于0到6,然后可以看出根据这个分支选择可以确定eax的大小,然后第二个参数等eax的值即可。而且又可以从后面的代码看出第一个参数要小于5所以只有0到4可以选择,然后假设第一个参数为4那么eax在运算后为0,因此第二个参数为0便是一个解。(可以看出这题没有唯一解)

第四道关卡:phase_4

  上代码:

08048d19 <phase_4>:
 8048d19:       55                      push   %ebp
 8048d1a:       89 e5                   mov    %esp,%ebp
 8048d1c:       83 ec 28                sub    $0x28,%esp
 8048d1f:       8d 45 f0                lea    -0x10(%ebp),%eax
 8048d22:       89 44 24 0c             mov    %eax,0xc(%esp)
 8048d26:       8d 45 f4                lea    -0xc(%ebp),%eax
 8048d29:       89 44 24 08             mov    %eax,0x8(%esp)
 8048d2d:       c7 44 24 04 25 a6 04    movl   $0x804a625,0x4(%esp)
 8048d34:       08
 8048d35:       8b 45 08                mov    0x8(%ebp),%eax
 8048d38:       89 04 24                mov    %eax,(%esp)
 8048d3b:       e8 a0 fa ff ff          call   80487e0 <__isoc99_sscanf@plt>
 8048d40:       83 f8 02                cmp    $0x2,%eax
 8048d43:       75 0c                   jne    8048d51 <phase_4+0x38>
 8048d45:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048d48:       85 c0                   test   %eax,%eax
 8048d4a:       78 05                   js     8048d51 <phase_4+0x38>
 8048d4c:       83 f8 0e                cmp    $0xe,%eax
 8048d4f:       7e 05                   jle    8048d56 <phase_4+0x3d>
 8048d51:       e8 e2 05 00 00          call   8049338 <explode_bomb>
 8048d56:       c7 44 24 08 0e 00 00    movl   $0xe,0x8(%esp)
 8048d5d:       00
 8048d5e:       c7 44 24 04 00 00 00    movl   $0x0,0x4(%esp)
 8048d65:       00
 8048d66:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048d69:       89 04 24                mov    %eax,(%esp)
 8048d6c:       e8 42 ff ff ff          call   8048cb3 <func4>
 8048d71:       83 f8 25                cmp    $0x25,%eax
 8048d74:       75 06                   jne    8048d7c <phase_4+0x63>
 8048d76:       83 7d f0 25             cmpl   $0x25,-0x10(%ebp)
 8048d7a:       74 05                   je     8048d81 <phase_4+0x68>
 8048d7c:       e8 b7 05 00 00          call   8049338 <explode_bomb>
 8048d81:       c9                      leave
 8048d82:       c3                      ret

 看到代码里的 

call   80487e0 __isoc99_sscanf@plt
cmp    $0x2,%eax

 就明白了要输入两个数,然后拿出输入的第一个数(mov    -0xc(%ebp),%eax)首先看看其是不是负数,如果是负数,bomb!!然后将其与14进行比较,如果它比14大,则bomb!!然后将第一个参数,0,和14分别作为第1,2,3个参数传递给func4,然后调用func4.这个函数的返回值是37.因此我们要做的就是,使得输入的值传递给func4,然后让其返回37即可。下面来看看func4函数。依然上代码:

08048cb3 <func4>:
 8048cb3:       55                      push   %ebp
 8048cb4:       89 e5                   mov    %esp,%ebp
 8048cb6:       83 ec 18                sub    $0x18,%esp
 8048cb9:       89 5d f8                mov    %ebx,-0x8(%ebp)
 8048cbc:       89 75 fc                mov    %esi,-0x4(%ebp)
 8048cbf:       8b 45 08                mov    0x8(%ebp),%eax
 8048cc2:       8b 55 0c                mov    0xc(%ebp),%edx
 8048cc5:       8b 75 10                mov    0x10(%ebp),%esi
 8048cc8:       89 f1                   mov    %esi,%ecx
 8048cca:       29 d1                   sub    %edx,%ecx
 8048ccc:       89 cb                   mov    %ecx,%ebx
 8048cce:       c1 eb 1f                shr    $0x1f,%ebx
 8048cd1:       8d 0c 0b                lea    (%ebx,%ecx,1),%ecx
 8048cd4:       d1 f9                   sar    %ecx
 8048cd6:       8d 1c 11                lea    (%ecx,%edx,1),%ebx
 8048cd9:       39 c3                   cmp    %eax,%ebx
 8048cdb:       7e 17                   jle    8048cf4 <func4+0x41>
 8048cdd:       8d 4b ff                lea    -0x1(%ebx),%ecx
 8048ce0:       89 4c 24 08             mov    %ecx,0x8(%esp)
 8048ce4:       89 54 24 04             mov    %edx,0x4(%esp)
 8048ce8:       89 04 24                mov    %eax,(%esp)
 8048ceb:       e8 c3 ff ff ff          call   8048cb3 <func4>
 8048cf0:       01 c3                   add    %eax,%ebx
 8048cf2:       eb 19                   jmp    8048d0d <func4+0x5a>
 8048cf4:       39 c3                   cmp    %eax,%ebx
 8048cf6:       7d 15                   jge    8048d0d <func4+0x5a>
 8048cf8:       89 74 24 08             mov    %esi,0x8(%esp)
 8048cfc:       8d 53 01                lea    0x1(%ebx),%edx
 8048cff:       89 54 24 04             mov    %edx,0x4(%esp)
 8048d03:       89 04 24                mov    %eax,(%esp)
 8048d06:       e8 a8 ff ff ff          call   8048cb3 <func4>
 8048d0b:       01 c3                   add    %eax,%ebx
 8048d0d:       89 d8                   mov    %ebx,%eax
 8048d0f:       8b 5d f8                mov    -0x8(%ebp),%ebx
 8048d12:       8b 75 fc                mov    -0x4(%ebp),%esi
 8048d15:       89 ec                   mov    %ebp,%esp
 8048d17:       5d                      pop    %ebp
 8048d18:       c3                      ret

  一看到这个函数里面有func4,心理就紧张了,这是要递归啊。对于这部分,有的同学是用c写了一段代码,模拟这个逻辑,把题给结出来的,我是拿笔算加推理得出的。对于此,不管你认为怎么样,我反正认为是没有必要,这个递归逻辑不复杂。

  下面就来剖析func4,这个函数在确定栈之后,首先取出来传递给它的参数,依次放在eax,edx,esi.中,从一个jle和一个jge可以看出,这个递归函数跳出的条件根据func4的第二个参数和第二个参数进过种种运算的结果等于第一个参数即可。注意在递归过程中第一个参数是不变的,最后返回值是经过运算后的ebx加上第一个参数。其中根据传进参数的大小,可以大致算出如果第一个参数如果等于7,则结果明显小于37,所以选比7大的数。所以第一递归会走jge这条路,因此新的参数为输入的第一个数,8,14.然后重新调用函数。可以自己画出每次递归传进的参数图。稍微对比下可以发现传入的数为10即可满足题意.

 然后继续看phase_4函数,最后有这句话 cmpl   $0x25,-0x10(%ebp)可以看出只要第二个参数为37即可满足。第二个参数的要求就这么简单。是不是很无语?

因此这道题的答案为4 37.

第五道关卡:phase_5

  上代码:

08048d83 <phase_5>:
 8048d83:       55                      push   %ebp
 8048d84:       89 e5                   mov    %esp,%ebp
 8048d86:       83 ec 28                sub    $0x28,%esp
 8048d89:       8d 45 f0                lea    -0x10(%ebp),%eax
 8048d8c:       89 44 24 0c             mov    %eax,0xc(%esp)
 8048d90:       8d 45 f4                lea    -0xc(%ebp),%eax
 8048d93:       89 44 24 08             mov    %eax,0x8(%esp)
 8048d97:       c7 44 24 04 25 a6 04    movl   $0x804a625,0x4(%esp)
 8048d9e:       08
 8048d9f:       8b 45 08                mov    0x8(%ebp),%eax
 8048da2:       89 04 24                mov    %eax,(%esp)
 8048da5:       e8 36 fa ff ff          call   80487e0 <__isoc99_sscanf@plt>
 8048daa:       83 f8 01                cmp    $0x1,%eax
 8048dad:       7f 05                   jg     8048db4 <phase_5+0x31>
 8048daf:       e8 84 05 00 00          call   8049338 <explode_bomb>
 8048db4:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048db7:       83 e0 0f                and    $0xf,%eax
 8048dba:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048dbd:       83 f8 0f                cmp    $0xf,%eax
 8048dc0:       74 28                   je     8048dea <phase_5+0x67>
 8048dc2:       b9 00 00 00 00          mov    $0x0,%ecx
 8048dc7:       ba 00 00 00 00          mov    $0x0,%edx
 8048dcc:       83 c2 01                add    $0x1,%edx
 8048dcf:       8b 04 85 60 a3 04 08    mov    0x804a360(,%eax,4),%eax
 8048dd6:       01 c1                   add    %eax,%ecx
 8048dd8:       83 f8 0f                cmp    $0xf,%eax
 8048ddb:       75 ef                   jne    8048dcc <phase_5+0x49>
 8048ddd:       89 45 f4                mov    %eax,-0xc(%ebp)
 8048de0:       83 fa 0f                cmp    $0xf,%edx
 8048de3:       75 05                   jne    8048dea <phase_5+0x67>
 8048de5:       3b 4d f0                cmp    -0x10(%ebp),%ecx
 8048de8:       74 05                   je     8048def <phase_5+0x6c>
 8048dea:       e8 49 05 00 00          call   8049338 <explode_bomb>
 8048def:       c9                      leave
 8048df0:       c3                      ret

 首先,看到这题不是递归,代码又这么短,心理就有种蔑视这道题的感觉。首先可以看到需要输入两个数,否则bomb。然后就对第一个数进行操作了,首先取其后四位,如果其后四位全为1则爆炸。然后看到mov    $0x0,%ecx    mov    $0x0,%edx就可以知道下面是个循环,edx为循环变量。这个循环里会根据eax,以其为索引找以地址0x804a360开头的数组中的值。然后求和。最后和等于输入的第二个参数即可。可以通过p/x *(int *)(0x804a360)@16得到这个数组,然后拼凑即可。我选则的值为4 115.

第六道关卡:phase_6

  上代码:

08048df1 <phase_6>:
 8048df1:       55                      push   %ebp
 8048df2:       89 e5                   mov    %esp,%ebp
 8048df4:       56                      push   %esi
 8048df5:       53                      push   %ebx
 8048df6:       83 ec 40                sub    $0x40,%esp
 8048df9:       8d 45 e0                lea    -0x20(%ebp),%eax
 8048dfc:       89 44 24 04             mov    %eax,0x4(%esp)
 8048e00:       8b 45 08                mov    0x8(%ebp),%eax
 8048e03:       89 04 24                mov    %eax,(%esp)
 8048e06:       e8 95 06 00 00          call   80494a0 <read_six_numbers>
 8048e0b:       be 00 00 00 00          mov    $0x0,%esi
 8048e10:       8b 44 b5 e0             mov    -0x20(%ebp,%esi,4),%eax
 8048e14:       83 e8 01                sub    $0x1,%eax
 8048e17:       83 f8 05                cmp    $0x5,%eax
 8048e1a:       76 05                   jbe    8048e21 <phase_6+0x30>
 8048e1c:       e8 17 05 00 00          call   8049338 <explode_bomb>
 8048e21:       83 c6 01                add    $0x1,%esi
 8048e24:       83 fe 06                cmp    $0x6,%esi
 8048e27:       74 1b                   je     8048e44 <phase_6+0x53>
 8048e29:       89 f3                   mov    %esi,%ebx
 8048e2b:       8b 44 9d e0             mov    -0x20(%ebp,%ebx,4),%eax
 8048e2f:       39 44 b5 dc             cmp    %eax,-0x24(%ebp,%esi,4)
 8048e33:       75 05                   jne    8048e3a <phase_6+0x49>
 8048e35:       e8 fe 04 00 00          call   8049338 <explode_bomb>
 8048e3a:       83 c3 01                add    $0x1,%ebx
 8048e3d:       83 fb 05                cmp    $0x5,%ebx
 8048e40:       7e e9                   jle    8048e2b <phase_6+0x3a>
 8048e42:       eb cc                   jmp    8048e10 <phase_6+0x1f>
 8048e44:       8d 55 e0                lea    -0x20(%ebp),%edx
 8048e47:       8d 45 f8                lea    -0x8(%ebp),%eax
 8048e4a:       bb 07 00 00 00          mov    $0x7,%ebx
 8048e4f:       89 d9                   mov    %ebx,%ecx
 8048e51:       2b 0a                   sub    (%edx),%ecx
 8048e53:       89 0a                   mov    %ecx,(%edx)
 8048e55:       83 c2 04                add    $0x4,%edx
 8048e58:       39 c2                   cmp    %eax,%edx
 8048e5a:       75 f3                   jne    8048e4f <phase_6+0x5e>
 8048e5c:       bb 00 00 00 00          mov    $0x0,%ebx
 8048e61:       eb 16                   jmp    8048e79 <phase_6+0x88>
 8048e63:       8b 52 08                mov    0x8(%edx),%edx
 8048e66:       83 c0 01                add    $0x1,%eax
 8048e69:       39 c8                   cmp    %ecx,%eax
 8048e6b:       75 f6                   jne    8048e63 <phase_6+0x72>
 8048e6d:       89 54 b5 c8             mov    %edx,-0x38(%ebp,%esi,4)
 8048e71:       83 c3 01                add    $0x1,%ebx
 8048e74:       83 fb 06                cmp    $0x6,%ebx
 8048e77:       74 17                   je     8048e90 <phase_6+0x9f>
 8048e79:       89 de                   mov    %ebx,%esi
 8048e7b:       8b 4c 9d e0             mov    -0x20(%ebp,%ebx,4),%ecx
 8048e7f:       b8 01 00 00 00          mov    $0x1,%eax
 8048e84:       ba fc c4 04 08          mov    $0x804c4fc,%edx
 8048e89:       83 f9 01                cmp    $0x1,%ecx
 8048e8c:       7f d5                   jg     8048e63 <phase_6+0x72>
 8048e8e:       eb dd                   jmp    8048e6d <phase_6+0x7c>
 8048e90:       8b 5d c8                mov    -0x38(%ebp),%ebx
 8048e93:       8b 45 cc                mov    -0x34(%ebp),%eax
 8048e96:       89 43 08                mov    %eax,0x8(%ebx)
 8048e99:       8b 55 d0                mov    -0x30(%ebp),%edx
 8048e9c:       89 50 08                mov    %edx,0x8(%eax)
 8048e9f:       8b 45 d4                mov    -0x2c(%ebp),%eax
 8048ea2:       89 42 08                mov    %eax,0x8(%edx)
 8048ea5:       8b 55 d8                mov    -0x28(%ebp),%edx
 8048ea8:       89 50 08                mov    %edx,0x8(%eax)
 8048eab:       8b 45 dc                mov    -0x24(%ebp),%eax
 8048eae:       89 42 08                mov    %eax,0x8(%edx)
 8048eb1:       c7 40 08 00 00 00 00    movl   $0x0,0x8(%eax)
 8048eb8:       be 00 00 00 00          mov    $0x0,%esi
 8048ebd:       8b 43 08                mov    0x8(%ebx),%eax
 8048ec0:       8b 10                   mov    (%eax),%edx
 8048ec2:       39 13                   cmp    %edx,(%ebx)
 8048ec4:       7d 05                   jge    8048ecb <phase_6+0xda>
 8048ec6:       e8 6d 04 00 00          call   8049338 <explode_bomb>
 8048ecb:       8b 5b 08                mov    0x8(%ebx),%ebx
 8048ece:       83 c6 01                add    $0x1,%esi
 8048ed1:       83 fe 05                cmp    $0x5,%esi
 8048ed4:       75 e7                   jne    8048ebd <phase_6+0xcc>
 8048ed6:       83 c4 40                add    $0x40,%esp
 8048ed9:       5b                      pop    %ebx
 8048eda:       5e                      pop    %esi
 8048edb:       5d                      pop    %ebp
 8048edc:       c3                      ret

 这道题,很长,很烦,很无聊,会有大段的代码在那把数据映射来映射去,很多人在这上面有些晕。首先分析一下,怎么映射的,大家画出图,一看便知。首先对六个数进行判断,每个数都不能大于六。无语了,总过个整数,还都不大于六,就是个随机排列呗。而且代码下面的逻辑是首先分别用7减这6个数,将这个6个数“调转个头”。然后对这后来的六个数就开始大量的映射了。映射来映射去最后根据后来的六个数找内存某块地址的6个值,这6个值必须是递增的。所以根据这可以确定后来的6个值为2 6 3 4 5 1。反过来答案就为 5 1 4 3 2 6 。

第七道关卡:secret_phase

  首先在objdumb bomb>assemble.然后搜索secret_phase可以发现在phase_defused会调用这个函数。而这个函数在正常情况下是不会调用到的,怎么办??怎么让代码运行到这一段??可以设置在phase_defused这函数的入口处设置断点,然后每解开一个炸弹都会在这个断点处停止。然后操作技巧如下:

  首先,上代码:这个是phase_defused的代码

 80494f1:       55                      push   %ebp
 80494f2:       89 e5                   mov    %esp,%ebp
 80494f4:       81 ec 88 00 00 00       sub    $0x88,%esp
 80494fa:       65 a1 14 00 00 00       mov    %gs:0x14,%eax
 8049500:       89 45 f4                mov    %eax,-0xc(%ebp)
 8049503:       31 c0                   xor    %eax,%eax
 8049505:       c7 04 24 01 00 00 00    movl   $0x1,(%esp)
 804950c:       e8 21 fd ff ff          call   8049232 <send_msg>
 8049511:       83 3d ec c7 04 08 06    cmpl   $0x6,0x804c7ec
 8049518:       75 7a                   jne    8049594 <phase_defused+0xa3>
 804951a:       8d 45 a4                lea    -0x5c(%ebp),%eax
 804951d:       89 44 24 10             mov    %eax,0x10(%esp)
 8049521:       8d 45 9c                lea    -0x64(%ebp),%eax
 8049524:       89 44 24 0c             mov    %eax,0xc(%esp)
 8049528:       8d 45 a0                lea    -0x60(%ebp),%eax
 804952b:       89 44 24 08             mov    %eax,0x8(%esp)
 804952f:       c7 44 24 04 2b a6 04    movl   $0x804a62b,0x4(%esp)
 8049536:       08
 8049537:       c7 04 24 f0 c8 04 08    movl   $0x804c8f0,(%esp)
 804953e:       e8 9d f2 ff ff          call   80487e0 <__isoc99_sscanf@plt>
 8049543:       83 f8 03                cmp    $0x3,%eax
 8049546:       75 34                   jne    804957c <phase_defused+0x8b>
 8049548:       c7 44 24 04 34 a6 04    movl   $0x804a634,0x4(%esp)
 804954f:       08
 8049550:       8d 45 a4                lea    -0x5c(%ebp),%eax
 8049553:       89 04 24                mov    %eax,(%esp)
 8049556:       e8 f0 fa ff ff          call   804904b <strings_not_equal>
 804955b:       85 c0                   test   %eax,%eax
 804955d:       75 1d                   jne    804957c <phase_defused+0x8b>
 804955f:       c7 04 24 90 a4 04 08    movl   $0x804a490,(%esp)
 8049566:       e8 b5 f3 ff ff          call   8048920 <puts@plt>
 804956b:       c7 04 24 b8 a4 04 08    movl   $0x804a4b8,(%esp)
 8049572:       e8 a9 f3 ff ff          call   8048920 <puts@plt>
 8049577:       e8 b2 f9 ff ff          call   8048f2e <secret_phase>
 804957c:       c7 04 24 f0 a4 04 08    movl   $0x804a4f0,(%esp)
 8049583:       e8 98 f3 ff ff          call   8048920 <puts@plt>
 8049588:       c7 04 24 1c a5 04 08    movl   $0x804a51c,(%esp)
 804958f:       e8 8c f3 ff ff          call   8048920 <puts@plt>
 8049594:       8b 45 f4                mov    -0xc(%ebp),%eax
 8049597:       65 33 05 14 00 00 00    xor    %gs:0x14,%eax
 804959e:       74 05                   je     80495a5 <phase_defused+0xb4>
 80495a0:       e8 4b f3 ff ff          call   80488f0 <__stack_chk_fail@plt>
 80495a5:       c9                      leave
 80495a6:       c3                      ret

 

 可以在80495a0:       e8 4b f3 ff ff          call   80488f0 __stack_chk_fail@plt设置断点,然后jump ×8049577,这样就会强行跳到隐藏关卡执行代码。下面上隐藏关的代码:

 

08048f2e <secret_phase>:
 8048f2e:       55                      push   %ebp
 8048f2f:       89 e5                   mov    %esp,%ebp
 8048f31:       53                      push   %ebx
 8048f32:       83 ec 14                sub    $0x14,%esp
 8048f35:       e8 40 04 00 00          call   804937a <read_line>
 8048f3a:       c7 44 24 08 0a 00 00    movl   $0xa,0x8(%esp)
 8048f41:       00
 8048f42:       c7 44 24 04 00 00 00    movl   $0x0,0x4(%esp)
 8048f49:       00
 8048f4a:       89 04 24                mov    %eax,(%esp)
 8048f4d:       e8 0e f9 ff ff          call   8048860 <strtol@plt>
 8048f52:       89 c3                   mov    %eax,%ebx
 8048f54:       8d 40 ff                lea    -0x1(%eax),%eax
 8048f57:       3d e8 03 00 00          cmp    $0x3e8,%eax
 8048f5c:       76 05                   jbe    8048f63 <secret_phase+0x35>
 8048f5e:       e8 d5 03 00 00          call   8049338 <explode_bomb>
 8048f63:       89 5c 24 04             mov    %ebx,0x4(%esp)
 8048f67:       c7 04 24 b0 c5 04 08    movl   $0x804c5b0,(%esp)
 8048f6e:       e8 6a ff ff ff          call   8048edd <fun7>
 8048f73:       83 f8 01                cmp    $0x1,%eax
 8048f76:       74 05                   je     8048f7d <secret_phase+0x4f>
 8048f78:       e8 bb 03 00 00          call   8049338 <explode_bomb>
 8048f7d:       c7 04 24 08 a3 04 08    movl   $0x804a308,(%esp)
 8048f84:       e8 97 f9 ff ff          call   8048920 <puts@plt>
 8048f89:       e8 63 05 00 00          call   80494f1 <phase_defused>
 8048f8e:       83 c4 14                add    $0x14,%esp
 8048f91:       5b                      pop    %ebx
 8048f92:       5d                      pop    %ebp
 8048f93:       c3                      ret

 这个函数首先将输入的字符串转换成一个长整形,然后得到的书不能大于0x3e9然后将得到的数和地址$0x804c5b0分别作为第二个和第一个参数传递个func7。然后func7返回的是1即可。下面上func7的代码。

08048edd <fun7>:
 8048edd:       55                      push   %ebp
 8048ede:       89 e5                   mov    %esp,%ebp
 8048ee0:       53                      push   %ebx
 8048ee1:       83 ec 14                sub    $0x14,%esp
 8048ee4:       8b 55 08                mov    0x8(%ebp),%edx
 8048ee7:       8b 4d 0c                mov    0xc(%ebp),%ecx
 8048eea:       b8 ff ff ff ff          mov    $0xffffffff,%eax
 8048eef:       85 d2                   test   %edx,%edx
 8048ef1:       74 35                   je     8048f28 <fun7+0x4b>
 8048ef3:       8b 1a                   mov    (%edx),%ebx
 8048ef5:       39 cb                   cmp    %ecx,%ebx
 8048ef7:       7e 13                   jle    8048f0c <fun7+0x2f>
 8048ef9:       89 4c 24 04             mov    %ecx,0x4(%esp)
 8048efd:       8b 42 04                mov    0x4(%edx),%eax
 8048f00:       89 04 24                mov    %eax,(%esp)
 8048f03:       e8 d5 ff ff ff          call   8048edd <fun7>
 8048f08:       01 c0                   add    %eax,%eax
 8048f0a:       eb 1c                   jmp    8048f28 <fun7+0x4b>
 8048f0c:       b8 00 00 00 00          mov    $0x0,%eax
 8048f11:       39 cb                   cmp    %ecx,%ebx
 8048f13:       74 13                   je     8048f28 <fun7+0x4b>
 8048f15:       89 4c 24 04             mov    %ecx,0x4(%esp)
 8048f19:       8b 42 08                mov    0x8(%edx),%eax
 8048f1c:       89 04 24                mov    %eax,(%esp)
 8048f1f:       e8 b9 ff ff ff          call   8048edd <fun7>
 8048f24:       8d 44 00 01             lea    0x1(%eax,%eax,1),%eax
 8048f28:       83 c4 14                add    $0x14,%esp
 8048f2b:       5b                      pop    %ebx
 8048f2c:       5d                      pop    %ebp
 8048f2d:       c3                      ret

 这个代码里有递归,首先会检查传入的第一个参数是不是0,如果不是0则取其对应的内容。然后将取的内容和第二个参数比较,从而如果第二个参数大,则重新取值,进行递归。递归的边界是相等,且返回0。如果小于则取地址依然重新递归。递归的参数不同之处在于如果是小于则取后的值越来越大,否者越来越小。最后选取50的原因是让递归首先执行地址8048f15对应的部分,然后递归后会返回0,然后接着执行给eax赋值为1返回。所以答案为50.可以自己用p/u *(int *)(地址)@3看内存中的数据。

以上是对隐藏关的分析,并得出了其需要的输入为50,然后接着上面的jump之后输入50,然后程序就继续运行到设置的下一个断点,然后此时仍然需要一次jump再跳回去(phase_defused入口),这样就跟什么都没发生一样。(当然事实上,这样对后续的题是有影响的,不过没有关系,这样做,没有什么大的地址错误,仍然可以解决掉隐藏关)。

注:

  1:由于call指令会push返回地址到栈中,且每个新的函数调用都会最开始push一个ebp,所以新的帧顶到上个帧的帧底有个8字节的差距,而非下一个帧的ebp即为上个帧的esp。

  2:可以用x/s 地址 来检查内存中的一段字符串。

  3:可以用p来看地址的内容,并且输出为制定格式(x/s也可)

  4:可以用info registers来看寄存器的值。

  5:隐藏关里,jump很好使。

 

 

 

 

 

 

 

 

posted on 2011-10-26 14:01  hydah  阅读(8314)  评论(2编辑  收藏  举报