【计组】二进制炸弹bomblab Phase1-6

实验目的

  1. 通过二进制炸弹实验,熟悉汇编语言
  2. 熟悉GDB调试工具

算法思路

编译环境

gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) 
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1

GDB命令

1. gdb bomb 进入调试
2. b phase_1 在函数phase_1打断点
   b *0x1000 在具体地址打断点
3. c continue 继续调试,直到下一断点
4. si 单步调试
5. disas 反汇编

Phase_1

代码
00000000000015e7 <phase_1>:
    15e7:	f3 0f 1e fa          	endbr64 
    15eb:	48 83 ec 08          	sub    $0x8,%rsp
    15ef:	48 8d 35 5a 1b 00 00 	lea    0x1b5a(%rip),%rsi        # 3150 <_IO_stdin_used+0x150>
    15f6:	e8 56 05 00 00       	callq  1b51 <strings_not_equal>
    15fb:	85 c0                	test   %eax,%eax
    15fd:	75 05                	jne    1604 <phase_1+0x1d>
    15ff:	48 83 c4 08          	add    $0x8,%rsp
    1603:	c3                   	retq   
    1604:	e8 38 08 00 00       	callq  1e41 <explode_bomb>
    1609:	eb f4                	jmp    15ff <phase_1+0x18>

0000000000001b51 <strings_not_equal>:
    1b51:	f3 0f 1e fa          	endbr64 
    1b55:	41 54                	push   %r12
    1b57:	55                   	push   %rbp
    1b58:	53                   	push   %rbx
    1b59:	48 89 fb             	mov    %rdi,%rbx
    1b5c:	48 89 f5             	mov    %rsi,%rbp
    1b5f:	e8 cc ff ff ff       	callq  1b30 <string_length>
    1b64:	41 89 c4             	mov    %eax,%r12d
    1b67:	48 89 ef             	mov    %rbp,%rdi
    1b6a:	e8 c1 ff ff ff       	callq  1b30 <string_length>
    1b6f:	89 c2                	mov    %eax,%edx
    1b71:	b8 01 00 00 00       	mov    $0x1,%eax
    1b76:	41 39 d4             	cmp    %edx,%r12d
    1b79:	75 31                	jne    1bac <strings_not_equal+0x5b>
    1b7b:	0f b6 13             	movzbl (%rbx),%edx
    1b7e:	84 d2                	test   %dl,%dl
    1b80:	74 1e                	je     1ba0 <strings_not_equal+0x4f>
    1b82:	b8 00 00 00 00       	mov    $0x0,%eax
    1b87:	38 54 05 00          	cmp    %dl,0x0(%rbp,%rax,1)
    1b8b:	75 1a                	jne    1ba7 <strings_not_equal+0x56>
    1b8d:	48 83 c0 01          	add    $0x1,%rax
    1b91:	0f b6 14 03          	movzbl (%rbx,%rax,1),%edx
    1b95:	84 d2                	test   %dl,%dl
    1b97:	75 ee                	jne    1b87 <strings_not_equal+0x36>
    1b99:	b8 00 00 00 00       	mov    $0x0,%eax
    1b9e:	eb 0c                	jmp    1bac <strings_not_equal+0x5b>
    1ba0:	b8 00 00 00 00       	mov    $0x0,%eax
    1ba5:	eb 05                	jmp    1bac <strings_not_equal+0x5b>
    1ba7:	b8 01 00 00 00       	mov    $0x1,%eax
    1bac:	5b                   	pop    %rbx
    1bad:	5d                   	pop    %rbp
    1bae:	41 5c                	pop    %r12
    1bb0:	c3                   	retq   
答案
Border relations with Canada have never been better.
解答

由函数名“string_not_equal”可知,phase_1涉及字符串操作。

对phase_1反汇编,发现读入字符串地址为:

15ef:	48 8d 35 5a 1b 00 00 	lea    0x1b5a(%rip),%rsi        # 0x555555557150

使用GDB调试命令,得到字符串,留待观察。

x/s 0x555555557150
>>0x555555557150 :"Border relations with Canada have never been better."

在string_not_equal函数中,发现有以下程序段:

    1b59:	48 89 fb             	mov    %rdi,%rbx
    1b76:	41 39 d4             	cmp    %edx,%r12d
    1b79:	75 31                	jne    1bac <strings_not_equal+0x5b>

分析知,应该是将输入的字符串与既定的字符串进行比较,而既定的字符串存在%rdi中。那么可知,地址0x555555557150中存入的就是要输入的字符串。


Phase_2

代码
000000000000160b <phase_2>:
    160b:	f3 0f 1e fa          	endbr64 
    160f:	55                   	push   %rbp
    1610:	53                   	push   %rbx
    1611:	48 83 ec 28          	sub    $0x28,%rsp
    1615:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
    161c:	00 00 
    161e:	48 89 44 24 18       	mov    %rax,0x18(%rsp)
    1623:	31 c0                	xor    %eax,%eax
    1625:	48 89 e6             	mov    %rsp,%rsi
    1628:	e8 56 08 00 00       	callq  1e83 <read_six_numbers>
    162d:	83 3c 24 00          	cmpl   $0x0,(%rsp)
    1631:	75 07                	jne    163a <phase_2+0x2f>
    1633:	83 7c 24 04 01       	cmpl   $0x1,0x4(%rsp)
    1638:	74 05                	je     163f <phase_2+0x34>
    163a:	e8 02 08 00 00       	callq  1e41 <explode_bomb>
    163f:	48 89 e3             	mov    %rsp,%rbx
    1642:	48 8d 6c 24 10       	lea    0x10(%rsp),%rbp
    1647:	eb 0e                	jmp    1657 <phase_2+0x4c>
    1649:	e8 f3 07 00 00       	callq  1e41 <explode_bomb>
    164e:	48 83 c3 04          	add    $0x4,%rbx
    1652:	48 39 eb             	cmp    %rbp,%rbx
    1655:	74 0c                	je     1663 <phase_2+0x58>
    1657:	8b 43 04             	mov    0x4(%rbx),%eax
    165a:	03 03                	add    (%rbx),%eax
    165c:	39 43 08             	cmp    %eax,0x8(%rbx)
    165f:	74 ed                	je     164e <phase_2+0x43>
    1661:	eb e6                	jmp    1649 <phase_2+0x3e>
    1663:	48 8b 44 24 18       	mov    0x18(%rsp),%rax
    1668:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax
    166f:	00 00 
    1671:	75 07                	jne    167a <phase_2+0x6f>
    1673:	48 83 c4 28          	add    $0x28,%rsp
    1677:	5b                   	pop    %rbx
    1678:	5d                   	pop    %rbp
    1679:	c3                   	retq   
    167a:	e8 d1 fb ff ff       	callq  1250 <__stack_chk_fail@plt>
答案
0 1 1 2 3 5
解答

看到函数read_six_number,则试图进入函数。

    1628:	e8 56 08 00 00       	callq  1e83 <read_six_numbers>

disas反汇编phase_2,将断点打在0x1628处。si进入函数。

disas
b *0000555555555628
c
si

disas反汇编read_six_number,发现几行关键代码如下:

    1ea4:	48 8d 35 5e 15 00 00 	lea    0x155e(%rip),%rsi        # 3409 <array.3471+0x229>
    1eb0:	e8 3b f4 ff ff       	callq  12f0 <__isoc99_sscanf@plt>
    1eb9:	83 f8 05             	cmp    $0x5,%eax
    1ebc:	7e 05                	jle    1ec3 <read_six_numbers+0x40>

1ea4:读入格式字符串,对注释地址0x555555557490进行反汇编。说明需要输入6个整数。

x/s 0x555555557490
>>0x555555557490 :"%d %d %d %d %d %d"

1eb0:调用sscanf函数。C 库函数 int sscanf(const char *str, const char *format, …) 从字符串读取格式化输入。

1eb9:%eax中存入读取整数的数量,对此进行反汇编。

p $eax
>>$1 = 6

说明读入6个整数,不会爆炸。


之后进入对于数组的推断。由之后频繁的%rsp操作和其位移可知,输入数组结果存储在%rsp中。

    162d:	83 3c 24 00          	cmpl   $0x0,(%rsp)
    1631:	75 07                	jne    163a <phase_2+0x2f>

由以上汇编代码知,0x0(%rsp)中存值0。

    1633:	83 7c 24 04 01       	cmpl   $0x1,0x4(%rsp)
    1638:	74 05                	je     163f <phase_2+0x34>
    163a:	e8 02 08 00 00       	callq  1e41 <explode_bomb>

由以上汇编代码知,若0x4(%rsp)中存值1,则跳转,否则爆炸。

    163f:	48 89 e3             	mov    %rsp,%rbx
    1642:	48 8d 6c 24 10       	lea    0x10(%rsp),%rbp
    1647:	eb 0e                	jmp    1657 <phase_2+0x4c>
    
    164e:	48 83 c3 04          	add    $0x4,%rbx
    1652:	48 39 eb             	cmp    %rbp,%rbx
    1655:	74 0c                	je     1663 <phase_2+0x58>
    1657:	8b 43 04             	mov    0x4(%rbx),%eax
    165a:	03 03                	add    (%rbx),%eax
    165c:	39 43 08             	cmp    %eax,0x8(%rbx)
    165f:	74 ed                	je     164e <phase_2+0x43>
    1661:	eb e6                	jmp    1649 <phase_2+0x3e>

163f:将%rsp存入%rbx

1642:将%rsp+16存入%rbp

1657-165c:%eax=0x4(%rbx)+(%rbx),将结果与0x10(%rbx)(第三个值比较)。

​ 若相等则进行循环,%rbx向后位移0x4,直到%rbp==%rbx,即%rbx移动到倒数第二个。

​ 由此可知,设数组为a[6],则a[n+2]=a[n+1]+a[n]。根据前两个值,可以得出结论,数组为{0,1,1,2,3,5}。


Phase_3

代码
000000000000167f <phase_3>:
    167f:	f3 0f 1e fa          	endbr64 
    1683:	48 83 ec 18          	sub    $0x18,%rsp
    1687:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
    168e:	00 00 
    1690:	48 89 44 24 08       	mov    %rax,0x8(%rsp)
    1695:	31 c0                	xor    %eax,%eax
    1697:	48 8d 4c 24 04       	lea    0x4(%rsp),%rcx
    169c:	48 89 e2             	mov    %rsp,%rdx
    169f:	48 8d 35 6f 1d 00 00 	lea    0x1d6f(%rip),%rsi        # 3415 <array.3471+0x235>
    16a6:	e8 45 fc ff ff       	callq  12f0 <__isoc99_sscanf@plt>
    16ab:	83 f8 01             	cmp    $0x1,%eax
    16ae:	7e 1e                	jle    16ce <phase_3+0x4f>
    16b0:	83 3c 24 07          	cmpl   $0x7,(%rsp)
    16b4:	0f 87 9a 00 00 00    	ja     1754 <phase_3+0xd5>
    16ba:	8b 04 24             	mov    (%rsp),%eax
    16bd:	48 8d 15 fc 1a 00 00 	lea    0x1afc(%rip),%rdx        # 31c0 <_IO_stdin_used+0x1c0>
    16c4:	48 63 04 82          	movslq (%rdx,%rax,4),%rax
    16c8:	48 01 d0             	add    %rdx,%rax
    16cb:	3e ff e0             	notrack jmpq *%rax
    16ce:	e8 6e 07 00 00       	callq  1e41 <explode_bomb>
    16d3:	eb db                	jmp    16b0 <phase_3+0x31>
    16d5:	b8 8a 00 00 00       	mov    $0x8a,%eax
    16da:	2d a5 01 00 00       	sub    $0x1a5,%eax
    16df:	05 5c 01 00 00       	add    $0x15c,%eax
    16e4:	2d b8 03 00 00       	sub    $0x3b8,%eax
    16e9:	05 b8 03 00 00       	add    $0x3b8,%eax
    16ee:	2d b8 03 00 00       	sub    $0x3b8,%eax
    16f3:	05 b8 03 00 00       	add    $0x3b8,%eax
    16f8:	2d b8 0
  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值