计算机系统lab3_bomblab

lab3 bomb lab

个人博客地址

1. phase_1

  • 汇编代码:

image-20210316165036780

  • 指令思路:

    将地址$0x402400存到%esi中

    调用函数<strings_not_equal>将用户输入的内容与寄存器%esi中的值比较,结果返回至%eax,若相同,则返回0,反之返回1;

    test 将两个数相与,若为0,则ZF标志位变为1,反之ZF为0;

    若ZF为1,则je指令跳转,跳过 了explode_bomb函数,破解成功,反之不跳转,爆炸。

  • 解决方法:

    因此地址$0x402400中存储的值即为我们需要知道的密码

    运用GDB调试工具输入指令 :

    x/s 0x402400
    

可得密码为:Border relations with Canada have never been better.

image-20210315211917616

image-20210316171734306

2. phase_2

  • 汇编代码与指令思路

    0000000000400efc <phase_2>:
      400efc:	55                   	push   %rbp							*备份
      400efd:	53                   	push   %rbx
      400efe:	48 83 ec 28          	sub    $0x28,%rsp  					*开辟40字节空间		
      400f02:	48 89 e6             	mov    %rsp,%rsi					*
      400f05:	e8 52 05 00 00       	callq  40145c <read_six_numbers>	*读入六个数字,首个数字存放在栈顶%rsp
      400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp)					*判断a[0]是否和1相等,不相等直接爆炸
      400f0e:	74 20                	je     400f30 <phase_2+0x34>		*相等则跳到$0x400f30
      400f10:	e8 25 05 00 00       	callq  40143a <explode_bomb>
      400f15:	eb 19                	jmp    400f30 <phase_2+0x34>
      400f17:	8b 43 fc             	mov    -0x4(%rbx),%eax				*将当前数字的上一个数字存入%eax中
      400f1a:	01 c0                	add    %eax,%eax					*将%eax存放的元素乘二
      400f1c:	39 03                	cmp    %eax,(%rbx)					*与当前数字判断
      400f1e:	74 05                	je     400f25 <phase_2+0x29>		*相等则跳到$0x400f25,否则爆炸
      400f20:	e8 15 05 00 00       	callq  40143a <explode_bomb>		
      400f25:	48 83 c3 04          	add    $0x4,%rbx					*取下一数字
      400f29:	48 39 eb             	cmp    %rbp,%rbx					*与最后一个元素比较
      400f2c:	75 e9                	jne    400f17 <phase_2+0x1b>		*不相等则回到$400f17,继续乘二判断操作
      400f2e:	eb 0c                	jmp    400f3c <phase_2+0x40>		*相等则结束,跳转进行清理栈区操作
      400f30:	48 8d 5c 24 04       	lea    0x4(%rsp),%rbx				*将a[1]地址赋给%rba
      400f35:	48 8d 6c 24 18       	lea    0x18(%rsp),%rbp				*将a[5]地址赋给%rbp,用作终止条件
      400f3a:	eb db                	jmp    400f17 <phase_2+0x1b>		*直接跳转到$400f17
      400f3c:	48 83 c4 28          	add    $0x28,%rsp
      400f40:	5b                   	pop    %rbx
      400f41:	5d                   	pop    %rbp
      400f42:	c3                   	retq    
    
  • 解决方法

    由上述指令思路可知,第一个数为1,且之后每个数都会是前一个的两倍,否则就会爆炸。

    所以密码为:1 2 4 8 16 32

    image-20210316171653420

3. phase_3

  • 汇编代码

    0000000000400f43 <phase_3>:
      400f43:	48 83 ec 18          	sub    $0x18,%rsp
      400f47:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx				*sscanf第四个参数,即输入的第二个数
      400f4c:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx				*sscanf第三个参数,即输入的第一个数
      400f51:	be cf 25 40 00       	mov    $0x4025cf,%esi				*第二个参数
      400f56:	b8 00 00 00 00       	mov    $0x0,%eax					*第一个参数
      400f5b:	e8 90 fc ff ff       	callq  400bf0 <__isoc99_sscanf@plt>
      400f60:	83 f8 01             	cmp    $0x1,%eax					*%eax会返回参数个数
      400f63:	7f 05                	jg     400f6a <phase_3+0x27>		*大于1才继续,否则爆炸
      400f65:	e8 d0 04 00 00       	callq  40143a <explode_bomb>
      400f6a:	83 7c 24 08 07       	cmpl   $0x7,0x8(%rsp)				
      400f6f:	77 3c                	ja     400fad <phase_3+0x6a>
      400f71:	8b 44 24 08          	mov    0x8(%rsp),%eax
      400f75:	ff 24 c5 70 24 40 00 	jmpq   *0x402470(,%rax,8)
      400f7c:	b8 cf 00 00 00       	mov    $0xcf,%eax
      400f81:	eb 3b                	jmp    400fbe <phase_3+0x7b>
      400f83:	b8 c3 02 00 00       	mov    $0x2c3,%eax
      400f88:	eb 34                	jmp    400fbe <phase_3+0x7b>
      400f8a:	b8 00 01 00 00       	mov    $0x100,%eax
      400f8f:	eb 2d                	jmp    400fbe <phase_3+0x7b>
      400f91:	b8 85 01 00 00       	mov    $0x185,%eax
      400f96:	eb 26                	jmp    400fbe <phase_3+0x7b>
      400f98:	b8 ce 00 00 00       	mov    $0xce,%eax
      400f9d:	eb 1f                	jmp    400fbe <phase_3+0x7b>
      400f9f:	b8 aa 02 00 00       	mov    $0x2aa,%eax
      400fa4:	eb 18                	jmp    400fbe <phase_3+0x7b>
      400fa6:	b8 47 01 00 00       	mov    $0x147,%eax
      400fab:	eb 11                	jmp    400fbe <phase_3+0x7b>
      400fad:	e8 88 04 00 00       	callq  40143a <explode_bomb>
      400fb2:	b8 00 00 00 00       	mov    $0x0,%eax
      400fb7:	eb 05                	jmp    400fbe <phase_3+0x7b>
      400fb9:	b8 37 01 00 00       	mov    $0x137,%eax
      400fbe:	3b 44 24 0c          	cmp    0xc(%rsp),%eax
      400fc2:	74 05                	je     400fc9 <phase_3+0x86>
      400fc4:	e8 71 04 00 00       	callq  40143a <explode_bomb>
      400fc9:	48 83 c4 18          	add    $0x18,%rsp
      400fcd:	c3                   	retq    
    
    
  • 指令思路与解决方法

    这部分代码读入参数

    image-20210316174708562

    这部分代码先判断sscanf的参数个数返回值%eax是否大于1,大于继续,否则爆炸

    在判断输入的第一个数字是否小于7,小于继续,否则爆炸。

    image-20210316175205802

    这部分代码会跳转至M[0x402470+%rax*8]所在地址,

    用gdb指令查看0x402470 处的值image-20210316175832024

    通过观察可以发现,jump之后的指令都是功能类似的重复指令,因此我们只需选择一组跳转即可

    因为0x402470 处的值即为jmpq后第一个mov指令所在地址,该操作会将0xcf(207)赋值给%eax。因此我们可以取第一个数为0,第二个数为207。因为之后的cmp会比较%eax的值和我们输入的第二个数,不相同会爆炸

    image-20210316180239126

    故密码可为:0 207或2 707等等,答案不唯一

    image-20210316181230534

    image-20210316181134846

4. phase_4

  • 汇编代码:

    image-20210316204437370

    image-20210316204525714

  • 指令思路和解决方法:

    首先我们发现这还是和phase_3一样传入2参数,可以通过查看0x4025cf得知;

    之后将第一个数字和0xe比较,如果小于等于就跳转,否则爆炸;

    跳转后来到mov指令,赋值后:%edx=0xe,%esi=0x0,%edi=参数x1;之后调用函数func4(),可知前面三个寄存器存放函数func4的三个参数;

    来到func4里,%eax经过mov指令后变成0xe,sub后保持不变,之后将%eax的值赋给%ecx, shr为将%ecx逻辑右移31位,%ecx=0;

    sar无移位参数,默认右移一位,%eax=0x7;

    lea:%ecx=%rax+%rsi*1=0x7+0*1=0x7;

    之后将参数x1与%ecx比较,即0x7比较,若小于等于且大于等于则结束,且返回值%eax=0;否则将参数x1-1后继续调用func4。

    回到phase_4,可知要使func4返回值为0,否则就会爆炸,所以当x1为7时恰好可以使返回值为0,符合;

    之后很容易得到必须要使得第二个数为0,否则就会爆炸;

    故密码为:7 0

    image-20210316212318867

5. phase_5

  • 汇编代码与指令思路

    0000000000401062 <phase_5>:
      401062:	53                   	push   %rbx
      401063:	48 83 ec 20          	sub    $0x20,%rsp
      401067:	48 89 fb             	mov    %rdi,%rbx					*将我们输入的传给%rdx
      40106a:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
      401071:	00 00 
      401073:	48 89 44 24 18       	mov    %rax,0x18(%rsp)
      401078:	31 c0                	xor    %eax,%eax					*重置%rax为0
      40107a:	e8 9c 02 00 00       	callq  40131b <string_length>		*判断长度
      40107f:	83 f8 06             	cmp    $0x6,%eax					
      401082:	74 4e                	je     4010d2 <phase_5+0x70>		*不为6则爆炸
      401084:	e8 b1 03 00 00       	callq  40143a <explode_bomb>
      401089:	eb 47                	jmp    4010d2 <phase_5+0x70>
      40108b:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx
      40108f:	88 0c 24             	mov    %cl,(%rsp)
      401092:	48 8b 14 24          	mov    (%rsp),%rdx					*1.上述三个操作将我们输入的字符的低四位传给%rdx
      401096:	83 e2 0f             	and    $0xf,%edx
      401099:	0f b6 92 b0 24 40 00 	movzbl 0x4024b0(%rdx),%edx			*2.将%rdx的值作为偏移量,取内存中的M[0x4024b0+%rdx]的值
      4010a0:	88 54 04 10          	mov    %dl,0x10(%rsp,%rax,1)		*取出来的字符存到后面的地址中
      4010a4:	48 83 c0 01          	add    $0x1,%rax					*将上述操作重复6次
      4010a8:	48 83 f8 06          	cmp    $0x6,%rax
      4010ac:	75 dd                	jne    40108b <phase_5+0x29>
      4010ae:	c6 44 24 16 00       	movb   $0x0,0x16(%rsp)
      4010b3:	be 5e 24 40 00       	mov    $0x40245e,%esi
      4010b8:	48 8d 7c 24 10       	lea    0x10(%rsp),%rdi				*将取出来的6个字符存到%rdi中
      4010bd:	e8 76 02 00 00       	callq  401338 <strings_not_equal>	*与0x40245e地址中值比较,不相等就会爆炸
      4010c2:	85 c0                	test   %eax,%eax
      4010c4:	74 13                	je     4010d9 <phase_5+0x77>		
      4010c6:	e8 6f 03 00 00       	callq  40143a <explode_bomb>
      4010cb:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)
      4010d0:	eb 07                	jmp    4010d9 <phase_5+0x77>
      4010d2:	b8 00 00 00 00       	mov    $0x0,%eax
      4010d7:	eb b2                	jmp    40108b <phase_5+0x29>
      4010d9:	48 8b 44 24 18       	mov    0x18(%rsp),%rax
      4010de:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax
      4010e5:	00 00 
      4010e7:	74 05                	je     4010ee <phase_5+0x8c>
      4010e9:	e8 42 fa ff ff       	callq  400b30 <__stack_chk_fail@plt>
      4010ee:	48 83 c4 20          	add    $0x20,%rsp
      4010f2:	5b                   	pop    %rbx
      4010f3:	c3                   	retq  
    
  • 解决方法:

    上述指令简而言之就是我们输入6个字符,然后取这6个字符的后4位作为地址索引,取内存中的M[0x4024b0+%rdx]的值,存到另一个寄存器中,然后将这个值与M[0x40245e]中的值比较,相等则结束,否则爆炸;

    所以我们先查看内存0x4024b0为起始的地址中存放的元素:

    image-20210317085034624

    然后查看0x40245e中的值:

    image-20210317085132914

    然后在上一个字符串中查看后一个字符串对应的下标,很容易得到下标分别为:9 15 14 5 6 7

    这六个数低四位的16进制为:0x9 0xf 0xe 0x5 0x6 0x7

    查看ASSCI表可知9?n567或 9?>567都可以。

    所以密码可以为9?n567或 9?>567等等,答案不唯一

    image-20210317090128611

6. phase_6

  • 汇编代码和指令思路

    00000000004010f4 <phase_6>:
      4010f4:	41 56                	push   %r14
      4010f6:	41 55                	push   %r13
      4010f8:	41 54                	push   %r12
      4010fa:	55                   	push   %rbp
      4010fb:	53                   	push   %rbx
      4010fc:	48 83 ec 50          	sub    $0x50,%rsp
      401100:	49 89 e5             	mov    %rsp,%r13
      401103:	48 89 e6             	mov    %rsp,%rsi
      401106:	e8 51 03 00 00       	callq  40145c <read_six_numbers>	*读取六个数字
      40110b:	49 89 e6             	mov    %rsp,%r14
      40110e:	41 bc 00 00 00 00    	mov    $0x0,%r12d
      401114:	4c 89 ed             	mov    %r13,%rbp
      401117:	41 8b 45 00          	mov    0x0(%r13),%eax
      40111b:	83 e8 01             	sub    $0x1,%eax
      40111e:	83 f8 05             	cmp    $0x5,%eax
      401121:	76 05                	jbe    401128 <phase_6+0x34>		*第一个循环,判断a[0]<=6,是继续,否则爆炸
      401123:	e8 12 03 00 00       	callq  40143a <explode_bomb>
      401128:	41 83 c4 01          	add    $0x1,%r12d					*%r12d为第一个循环计数器
      40112c:	41 83 fc 06          	cmp    $0x6,%r12d
      401130:	74 21                	je     401153 <phase_6+0x5f>		*终止条件,六次后结束
      401132:	44 89 e3             	mov    %r12d,%ebx
      401135:	48 63 c3             	movslq %ebx,%rax
      401138:	8b 04 84             	mov    (%rsp,%rax,4),%eax
      40113b:	39 45 00             	cmp    %eax,0x0(%rbp)
      40113e:	75 05                	jne    401145 <phase_6+0x51>		*第二个循环,a[i++],依次和a[0]比较,相同则爆炸
      401140:	e8 f5 02 00 00       	callq  40143a <explode_bomb>
      401145:	83 c3 01             	add    $0x1,%ebx					*%ebx为第二个循环计数器,计数5次
      401148:	83 fb 05             	cmp    $0x5,%ebx
      40114b:	7e e8                	jle    401135 <phase_6+0x41>
      40114d:	49 83 c5 04          	add    $0x4,%r13					*结合这行,第一个循环就是判断每个数都小于等于6
      401151:	eb c1                	jmp    401114 <phase_6+0x20>
      401153:	48 8d 74 24 18       	lea    0x18(%rsp),%rsi
      401158:	4c 89 f0             	mov    %r14,%rax
      40115b:	b9 07 00 00 00       	mov    $0x7,%ecx
      401160:	89 ca                	mov    %ecx,%edx
      401162:	2b 10                	sub    (%rax),%edx
      401164:	89 10                	mov    %edx,(%rax)
      401166:	48 83 c0 04          	add    $0x4,%rax
      40116a:	48 39 f0             	cmp    %rsi,%rax
      40116d:	75 f1                	jne    401160 <phase_6+0x6c>		*第三层循环之后,a[i]=7-a[i] 
      40116f:	be 00 00 00 00       	mov    $0x0,%esi
      401174:	eb 21                	jmp    401197 <phase_6+0xa3>
      401176:	48 8b 52 08          	mov    0x8(%rdx),%rdx
      40117a:	83 c0 01             	add    $0x1,%eax
      40117d:	39 c8                	cmp    %ecx,%eax
      40117f:	75 f5                	jne    401176 <phase_6+0x82>
      401181:	eb 05                	jmp    401188 <phase_6+0x94>
      401183:	ba d0 32 60 00       	mov    $0x6032d0,%edx
      401188:	48 89 54 74 20       	mov    %rdx,0x20(%rsp,%rsi,2)
      40118d:	48 83 c6 04          	add    $0x4,%rsi
      401191:	48 83 fe 18          	cmp    $0x18,%rsi
      401195:	74 14                	je     4011ab <phase_6+0xb7>
      401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx
      40119a:	83 f9 01             	cmp    $0x1,%ecx
      40119d:	7e e4                	jle    401183 <phase_6+0x8f>
      40119f:	b8 01 00 00 00       	mov    $0x1,%eax
      4011a4:	ba d0 32 60 00       	mov    $0x6032d0,%edx				*存放链表结点数值的起始地址
      4011a9:	eb cb                	jmp    401176 <phase_6+0x82>
      4011ab:	48 8b 5c 24 20       	mov    0x20(%rsp),%rbx
      4011b0:	48 8d 44 24 28       	lea    0x28(%rsp),%rax
      4011b5:	48 8d 74 24 50       	lea    0x50(%rsp),%rsi
      4011ba:	48 89 d9             	mov    %rbx,%rcx
      4011bd:	48 8b 10             	mov    (%rax),%rdx
      4011c0:	48 89 51 08          	mov    %rdx,0x8(%rcx)
      4011c4:	48 83 c0 08          	add    $0x8,%rax
      4011c8:	48 39 f0             	cmp    %rsi,%rax
      4011cb:	74 05                	je     4011d2 <phase_6+0xde>
      4011cd:	48 89 d1             	mov    %rdx,%rcx
      4011d0:	eb eb                	jmp    4011bd <phase_6+0xc9>		*确定链表数字为降序排序
      4011d2:	48 c7 42 08 00 00 00 	movq   $0x0,0x8(%rdx)
      4011d9:	00 
      4011da:	bd 05 00 00 00       	mov    $0x5,%ebp
      4011df:	48 8b 43 08          	mov    0x8(%rbx),%rax
      4011e3:	8b 00                	mov    (%rax),%eax
      4011e5:	39 03                	cmp    %eax,(%rbx)
      4011e7:	7d 05                	jge    4011ee <phase_6+0xfa>
      4011e9:	e8 4c 02 00 00       	callq  40143a <explode_bomb>
      4011ee:	48 8b 5b 08          	mov    0x8(%rbx),%rbx
      4011f2:	83 ed 01             	sub    $0x1,%ebp
      4011f5:	75 e8                	jne    4011df <phase_6+0xeb>
      4011f7:	48 83 c4 50          	add    $0x50,%rsp
      4011fb:	5b                   	pop    %rbx
      4011fc:	5d                   	pop    %rbp
      4011fd:	41 5c                	pop    %r12
      4011ff:	41 5d                	pop    %r13
      401201:	41 5e                	pop    %r14
      401203:	c3                   	retq  
    
  • 解决思路:

    上述代码思路概括就是将链表结点数值按照降序排序,其对应的数值即为顺序,最后a[i]=7-a[i],即为我们要输入的值。

    首先我们用gdb指令查看链表的数据:

    image-20210317104905959

    这六个数字按照降序排列对应的编码顺序为:3 4 5 6 1 2

    运算后即为:4 3 2 1 6 5

    故密码为:4 3 2 1 6 5

    image-20210317105113068

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值