Young87

SmartCat's Blog

So happy to code my life!

游戏开发交流QQ群号60398951

当前位置:首页 >跨站数据测试

CSAPP 二进制炸弹 binary bomb lab 2 第二关 ——深入理解计算机系统

CSAPP bomb lab2

1.phase_2主函数:

//arg1=input (phase_2有一个参数input,是传入的字符串)
0000000000400efc <phase_2>:
  400efc:	55                   	push   %rbp		
  400efd:	53                   	push   %rbx		
  400efe:	48 83 ec 28          	sub    $0x28,%rsp
  400f02:	48 89 e6             	mov    %rsp,%rsi	
// 参数1=input,参数2=rsp地址,调用函数read_six_number。
  400f05:	e8 52 05 00 00       	callq  40145c <read_six_numbers>

将外部传入的input字符串作为第一参数,(input是什么先不用管,后面就知道了) phase_1中分配一段内存空间后,将该内存空间的首地址作为第二参数传给read_six_numbers函数中(猜测这段内存空间是一个数组)
接下来先进入read_six_numbers函数观察里面发生甚摸事了–>

2.read_six_numbers函数:

// arg1=input,arg2=a (a是已经分配好空间的数组)
000000000040145c <read_six_numbers>:
  40145c:	48 83 ec 18         sub    $0x18,%rsp	#24栈帧
  401460:	48 89 f2            mov    %rsi,%rdx	# rdx=rsi=y
  401463:	48 8d 4e 04         lea    0x4(%rsi),%rcx	# rcx=y+4
  401467:	48 8d 46 14         lea    0x14(%rsi),%rax	# rax=y+20
  40146b:	48 89 44 24 08      mov    %rax,0x8(%rsp)	# (rsp+8)=y+20
  401470:	48 8d 46 10         lea    0x10(%rsi),%rax	# rax=y+16
  401474:	48 89 04 24         mov    %rax,(%rsp)		# (rsp+0)=y+16
  401478:	4c 8d 4e 0c         lea    0xc(%rsi),%r9	# r9=y+12
  40147c:	4c 8d 46 08         lea    0x8(%rsi),%r8	# r8=y+8
  401480:	be c3 25 40 00      mov    $0x4025c3,%esi	# rsi=0x4025c3
  401485:	b8 00 00 00 00      mov    $0x0,%eax		# rax=0
  40148a:	e8 61 f7 ff ff      callq  400bf0 <__isoc99_sscanf@plt>	
  40148f:	83 f8 05            cmp    $0x5,%eax			
  401492:	7f 05               jg     401499 <read_six_numbers+0x3d>	 
// if (eax>5),退出
  401494:	e8 a1 ff ff ff      callq  40143a <explode_bomb>		
// 否則爆炸
  401499:	48 83 c4 18         add    $0x18,%rsp
  40149d:	c3                  retq 

read_six_numbers函数中调用了sscanf函数int sscanf(char *input,char *format,arg1,..),用于将input字符串按照format模式串的形式,将字符输出给指定的变量地址,返回成功输入的参数个数。第二个参数(模式串)rsi=0x4025c3,查找0x4025c3的值为"%d %d %d %d %d %d" .
在这里插入图片描述

所以共需要8个参数,其中两个char *类型,6个int类型的地址。
而寄存器传参最多只能传6个,分别存于rdi rsi rdx rcx r8 r9。
第七个参数需要置于栈顶,第八个参数置于第七个参数上方。
纵观整个流程,应该是在phase_2调用前,先要求我们在终端中输入字符串,
将该地址存在某个地址,假设为input,然后调用phase_2(input),其中会调用
sscanf(input,"%d %d %d %d %d %d",rsp+0,rsp+4,rsp+8,rsp+12,rsp+16,rsp+20)存入数据

将read_six_numbers函数简化为C代码:

int read_six_numbers(char *input,int *a)
// input是phase_2函数从其调用者传入的一个字符串,a是栈上分配的一个数组
{	
	return ssacnf(input,"%d %d %d %d %d %d",&a[0],&a[1],&a[2],&a[3],&a[4]);
// 注意:这里没有实际通过寄存器传8个参数,因为限制最多6个,最后两个通过栈传递
} 

3.回到phase_2主函数:

0000000000400efc <phase_2>:
  400efc:	55                  push   %rbp	# push rbp
  400efd:	53                  push   %rbx	# push rbx
  400efe:	48 83 ec 28         sub    $0x28,%rsp	# rsp-=0x28
  400f02:	48 89 e6            mov    %rsp,%rsi	# rsi=rsp
  400f05:	e8 52 05 00 00      callq  40145c <read_six_numbers>
  400f0a:	83 3c 24 01         cmpl   $0x1,(%rsp)	
  400f0e:	74 20               je     400f30 <phase_2+0x34> 
// if (rsp内存的值为1,转到400f30)
  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	
  400f1a:	01 c0               add    %eax,%eax	# eax=2*eax
  400f1c:	39 03               cmp    %eax,(%rbx)			
  400f1e:	74 05               je     400f25 <phase_2+0x29>
// if (rbx内存的值=eax,转到{400f25})
  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>		 
// if (rbx不等于rbp,转到{400f17})
  400f2e:	eb 0c               jmp    400f3c <phase_2+0x40>
// 否则,转到{400f3c}
  400f30:	48 8d 5c 24 04      lea    0x4(%rsp),%rbx
  400f35:	48 8d 6c 24 18      lea    0x18(%rsp),%rbp
  400f3a:	eb db               jmp    400f17 <phase_2+0x1b>
  400f3c:	48 83 c4 28         add    $0x28,%rsp
  400f40:	5b                  pop    %rbx
  400f41:	5d                  pop    %rbp
  400f42:	c3                  retq   ss

翻译为C代码,大致为:

void phase_2(char *input)
{
	int a[6];
	if (sscanf(input,"%d %d %d %d %d %d",&a[0],&a[1],&a[2],&a[3],&a[4],&a[5])!=6)
		bomb();
	if (a[0]!=1)
		bomb();
begin:
	int *p=a+1;
	int mid=(*(p-1))*2;
	if (mid!=*p) 
		bomb();
	else goto begin;
	// 展示代码大致逻辑<尽管这个代码不正确>
}
所以整个代码的逻辑是,先判断a[0]是否为1,不是1就bomb。之后需要保证a[n+1]=2*a[n],
才不会bomb所以显然写入  "1 2 4 8 16 32".

结果:"1 2 4 8 16 32".

除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog

上一篇: 运行monibuca脚本报错: Bad file descriptor

下一篇: CSAPP 二进制炸弹 binary bomb lab 1 第一关 ——深入理解计算机系统

精华推荐