CS:APP二进制炸弹phase2
来源:互联网 发布:linux 定时重启tomcat 编辑:程序博客网 时间:2024/05/17 07:07
写在前面
在前文《CS:APP二进制炸弹phase1》中成功“破解”了phase_1,毕竟是第一个阶段,非常简单。本篇来破解第二阶段。let's go!!!
分析
反汇编调用phase_2处的代码如下:
同样的,跟phase_1一样,我们输入的字符串首地址存储在寄存器%rdi中。
反汇编phase_2:
一眼望去,phase_2明显要比phase_1要复杂一些。不过没关系,应该只是复杂一点。
先看前五行代码。先分别将寄存去%rbp和%rbx压栈,之所以将这两个寄存器压栈,可以通过后面的汇编语句得知在函数phase_2中用到了它们。
sub $0x28,%rsp 这条汇编语句是在开辟栈空间。
mov %rsp,%rsi 将栈首地址传送到寄存器%rsi中。根据x64 ABI文档,%rsi通常用来传递函数的第二个参数。
接下来通过callq调用函数read_six_numbers,从函数名就可以知道是从我们的输入中获取6个数字。那么就可以大胆的猜测,刚才开辟栈空间的操作是在栈上分配了一个具有6个元素的数组,至于数组元素是什么类型,目前不得而知。并且可以判断函数read_six_numbers具有两个参数,第一个参数使我们的输入input,第二个参数就是数组第一个元素的首地址,即函数read_six_numbers的原型为void read_six_numbers(const char *input, TYPE *p)。我们不妨将这个数组取名为a,TYPE a[6],即在函数phase_2有个局部数组a,数组元素总共6个,类型待定。
进入函数read_six_numbers,该函数反汇编如下:
原来函数read_six_numbers是通过函数sscanf从我们的输入中获得6个数字的。这就好办了,根据函数sscanf的原型,我们来仔细看看调用函数sscanf之前,它需要的参数是如何传递进去的。
为了方便,还是从X64 ABI文档中截个图吧,描述函数参数传递时的约定,即calling convention!
第一个参数肯定是我们的输入input的首地址,它目前储存在寄存器%rdi中,那么第二个参数应该是sscanf需要的格式化字符串,从mov $0x4025c3,%esi中知道这个格式化字符串存储在地址0x4025c3处,用x/s命令查看,原来是"%d %d %d %d %d %d",这下我们可以断定,在函数phase_2中的数组元素类型是int型,即int a[6]。
既然格式化字符串中有个6个%d,自然的sscanf函数还需要6个参数,应该分别是数组a每个元素的地址,即分别是&a[0],&a[1],&a[2],&a[3],&a[4],&a[5]。根据调用约定,前4个元素的地址应该用寄存器传递,分别是%rdx、%rcx、%r8、%r9,最后两个通过栈来传递,通过lea 0x10(%rsi),%rax,mov %rax,(%rsp)和lea 0x14(%rsi),%rax,mov %rax,0x8(%rsp)分别将&a[4]和&a[5]压栈,这就完成了sscanf所有参数的传递任务。
接下来判断sscanf函数的返回值,如果返回值大于5则OK,如果小于等于5则触发炸弹。也就是说我们需要输入大于等6个的数字,只要前6个数字正确即可。
OK,read_six_numbers函数分析完毕,返回函数phase_2继续分析。
现在我们可以确定数组a在栈空间中的布局了,如下:
static void read_six_numbers(const char *input, int *a){ // %rdi %rsi %rdx %rcx %r8 %r9 (%rsp) *(%rsp) int result = sscanf(input, "%d %d %d %d %d %d", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]); if (result <= 5) { explode_bomb(); }}void phase_2(const char *input){ int a[6]; read_six_numbers(input, a); int *begin = &a[1]; int *end = &a[6]; for ( ; begin < end; ++begin) { int prev_value = begin[-1] * 2; if (prev_value != begin[0]) { explode_bomb(); } }}
- CS:APP二进制炸弹phase2
- CS:APP二进制炸弹开篇
- CS:APP二进制炸弹phase1
- CS:APP二进制炸弹phase3
- CS:APP二进制炸弹phase4
- CS:APP二进制炸弹phase5
- CS:APP二进制炸弹phase6
- CS:APP二进制炸弹附加篇
- 《CS-APP》二进制炸弹实验(phase_1-3)
- 二进制炸弹实验报告
- 二进制炸弹BOMB报告
- 二进制炸弹(arm)
- 二进制炸弹(第二次实验)
- cmu二进制炸弹
- 二进制炸弹实验
- CS中如何拆除炸弹
- 【CSAPP】二进制炸弹 实验分析
- CSAPP的二进制炸弹实验
- Linux Kernel Interrupt 分析
- 24点游戏算法
- OPC--open packaging convention学习
- jQuery常用选择器和方法
- pushKit使用总结
- CS:APP二进制炸弹phase2
- Java集合类的总结
- iOS非常全的第三方库
- 用户Session 会话机制
- 04_程序员必须掌握的8大排序算法_堆排序
- hbase-scala-获取连接
- 开发环境搭建
- Java多线程并发基础面试题回答
- substr截取字符串 不用循环?