CS:APP二进制炸弹phase4
来源:互联网 发布:海湾crt软件操作说明 编辑:程序博客网 时间:2024/05/16 08:34
写在前面
OK,已经完成一半任务了,继续吧。let's go!!!
分析
首先找到调用函数phase_4的代码:
反汇编函数phase_4如下:
跟phase_3同样的套路,先从我们的输入中获取两个int型整数。我们命令为num1和num2。
接着判断sscanf函数的返回值,如果不等于2则触发炸弹,否则继续。
接下来的几条指令看出,num1必须小于等于14,否则触发炸弹,难道本阶段又跟phase_3一样,存在多组答案? 不得而知,继续。
接下来调用函数func4,参数分别通过寄存器%edi,%esi和%edx传递,值分别为num1,0和14。
test %eax,%eax用于检测函数func4的返回值是否为0,如果不为0,跳转到0x0000000000401058处,触发炸弹,否则继续。
cmpl $0x0,0xc(%rsp)用于检测num2是否为0,为0的话,跳转到0x000000000040105d处,函数结束,一切OK,否则触发炸弹。所以可以断定输入的num2必须为0。
现在来看函数func4反汇编如下:
第一眼瞅过去,函数内部尽然有调用自己,原来这是个递归函数。通过刚才的分析,func4接受3个参数,并且都是int型的,所以func4的原型应该是int func4(int a, int b, int c);
mov %edx,%eax,将参数c存储在寄存器%eax中。
sub %esi,%eax,用%eax中的值减去%esi,结果存在寄存器%eaxz中,即c - b的值存储在寄存器%eax中。
为了直观,我们将%eax定义为一个局部变量int x,即int x = c - b;
mov %eax,%ecx,shr $0x1f,%ecx,add %ecx,%eax,sar %eax 这几句整合起来就是x = (x>>31 + x) >> 1。
lea (%rax,%rsi,1),%ecx,这句%rsi,意思是%ecx = %rax + %rsi * 1,其中%rax就是我们刚刚求得的x,%rsi是参数b。因此%ecx = (x>>31 + x) >> 1 + b; 我们将寄存器%ecx定义一个局部变量,名为tmp,即int tmp = (x>>31 + x) >> 1 + b;将x带进去就是int tmp = ((c - b) >> 31 + (c -b)) >> 1 + b;
好,得到了tmp的值,就好办了,因为我们发现后面的汇编一直在使用tmp的值与参数a在比较。继续分析。
cmp %edi,%ecx,就是用参数a和tmp值比较,即tmp - a,如果tmp小于等于a,则跳转到0x0000000000400ff2处执行。我根据接下来的汇编,将func4用C实现,大概如下:
// %edi %esi %edxstatic int func4(int a, int b, int c){ int tmp = (((c - b) + ((c - b) >> 31)) >> 1) + b; if (tmp <= a) { if (tmp <= a) { return (0); } else { return func4(a, tmp + 1, c) * 2 + 1; } } else { return func4(a, b, tmp - 1) * 2; }}发现没有,这里的逻辑很奇怪! 在tmp小于等于a后,紧接着判断tmp是否大于等a,很显然这里应该是判断tmp是否等于a的情况,所以代码修改如下:
// %edi %esi %edxstatic int func4(int a, int b, int c){ int tmp = (((c - b) + ((c - b) >> 31)) >> 1) + b; if (tmp <= a) { if (tmp == a) { return (0); } else { return func4(a, tmp + 1, c) * 2 + 1; } } else { return func4(a, b, tmp - 1) * 2; }}从前面的分析得到,只要func4最终的返回值是0就成功了。那我们先着眼于代码中的return 0语句吧。假设第一次调用func4,参数分别为num1,0和14,计算tmp得到7,那么如果num1等于7,就会走到return 0那里,函数返回0,bingo!因此num1是7,num2是0时就能过这一个phase。试试,果然可以。
但是本phase应该还有其他答案,不然不会大费周折的搞什么递归了。我们可以写个测试程序,输出最后的所有答案,程序如下:
#include <stdio.h>#include <stdlib.h>// %edi %esi %edxstatic int func4(int a, int b, int c){ int tmp = (((c - b) + ((c - b) >> 31)) >> 1) + b; if (tmp <= a) { if (tmp == a) { return (0); } else { return func4(a, tmp + 1, c) * 2 + 1; } } else { return func4(a, b, tmp - 1) * 2; }}int main(int argc, const char *argv[]){ int i, result; for (i = 0; i < 14; ++i) { result = func4(i, 0, 14); if (result == 0) { printf("%d\n", i); } } return 0;}程序输出0 1 3 7,因此本阶段的答案有4组,分别为(0,0)、(1,0)、(3,0)、(7,0)。
本阶段的C程序源码完整如下:
// %edi %esi %edxstatic int func4(int a, int b, int c){int tmp = (((c - b) + ((c - b) >> 31)) >> 1) + b;if (tmp <= a) {if (tmp == a) {return (0);} else {return func4(a, tmp + 1, c) * 2 + 1;}} else {return func4(a, b, tmp - 1) * 2;}}void phase_4(const char *input){// 0x8(%rsp) 0xc(%rsp)int num1, num2;// %rdi %rsi %rdx %rcx int result = sscanf(input, "%d %d", &num1, &num2);if (result != 2) {explode_bomb();}if (num1 > 0xe) {explode_bomb();}// %edi %esi %edxresult = func4(num1, 0, 0xe);if (result != 0) {explode_bomb();}if (num2 != 0) {explode_bomb();}}
总结:
本阶段的func4汇编代码有点晦涩难懂,其中shr和sar分别为逻辑右移和算术右移,并且sar %eax的意思是%eax中的值右移一位,即除以2。
知道了这几个生疏的汇编指令,应该没什么问题的。好,继续下一个阶段吧。
- CS:APP二进制炸弹phase4
- CS:APP二进制炸弹开篇
- CS:APP二进制炸弹phase1
- CS:APP二进制炸弹phase2
- CS:APP二进制炸弹phase3
- CS:APP二进制炸弹phase5
- CS:APP二进制炸弹phase6
- CS:APP二进制炸弹附加篇
- 《CS-APP》二进制炸弹实验(phase_1-3)
- 二进制炸弹实验报告
- 二进制炸弹BOMB报告
- 二进制炸弹(arm)
- 二进制炸弹(第二次实验)
- cmu二进制炸弹
- 二进制炸弹实验
- CS中如何拆除炸弹
- 【CSAPP】二进制炸弹 实验分析
- CSAPP的二进制炸弹实验
- Android中的抖动解码(inDither)
- 使用Nexus搭建Maven私服
- 深度学习资料整理
- php 生辟字数组处理
- 数据库系统概念(机械工业出版社,第六版)复习——第三章:SQL
- CS:APP二进制炸弹phase4
- 单例模式的七种写法
- I/O多路复用之epoll
- Python获取Mysql数据并Mail(多个附件的添加)
- CRC_16 校验code
- URL步骤
- 关于EditText自动获取焦点的处理
- 一切,从现在开始
- 爬虫 xpath 的使用与范例