CSAPP 二进制炸弹 binary bomb lab 2 第二关 ——深入理解计算机系统
日期: 2020-11-25 分类: 跨站数据测试 339次阅读
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
精华推荐