2019-06-17 YTF

炸弹一:

在phase_1函数中,调用了string_not_equal函数,根据函数的返回值EAX判断是否执行explode_bomb函数
两种情况:
(1)如果EAX是0,那么调用explode_bomb函数
(2)如果EAX不是0,那么退出phase_1函数,炸弹成功的拆除.

因此,我们自然而然的想到:我们要让string_not_equal这个函数的返回值为0.下面我们就分析一下这个函数的功能:
1.首先我们根据函数名称,大致的知道函数的功能是判断字符串是否相等的问题
2.然后两次调用了string_length函数计算字符串的长度,这里的计算字符串的长度使用的参数是RDI和RSI这两个寄存器中保存的内容。于是,思考RDI和RSI中保存的内容是什么?我们返回调用string_not_equal的函数phase_1,发现RSI保存的是一个立即数0x402400,但是RDI的内容是什么还是不是很清楚,因此,继续查看调用phase_1的函数main,我们发现RDI保存的是readline函数的返回值,也就是我们输入的字符串的地址。分析到了这里,线索已经比较清晰了,这个函数处理的两个字符串分别为:
(1)我输入的字符串(字符串结尾是‘\0’,ASCII为0)
(2)内存中从0x402400这个地址开始的字符串(字符串结尾是‘\0’,ASCII为0)
3.知道了处理的内容是什么(即对什么进行了处理),那么我接下来要知道进行了什么处理?进行了如下几个操作:

(1)判断两个字符串的长度是否相等,即比较R12D和RAX的内容,两个寄存器分别保存两个字符串的长度。如果不相等,执行跳转指令之后返回EDX保存的值(EDX此时为1).在前面的分析中,我已经知道:string_not_equal需要返回0。因此这里得到一个结果:我们输入的字符串要和程序给出的字符串长度相同。



(2)依次比较两个字符串中的字符内容是否相同,如果字符相同,那么继续循环判断,知道遇到空字符为止,此时返回0.如果出现字符不相同,那么返回1.
汇编中:使用RBX,RBP不断增加一的操作实现对每一个字符的访问。


4.分析到了这里我知道,我输入的字符串需要和内存中字符串内容一致才可以,因此使用gdb调试查看一下内存中这个地址保存的内容到底是什么.



这个字符串就是:

Border relations with Canada have never been better.

5.输入并运行一下:

运行截图

炸弹二:

在phase_2函数中,首先是调用了read_six_number函数,根据函数名称,我们可以知道这个函数的作用大致是读入6个数.然后我主要分析一下这个phase_2函数的执行流程:
(1)读入6个数,这六个数存放到RSP,RSP+4,RSP+8,RSP+12,RSP+16,RSP+20这6个地址
(2)判断M[R[rsp]]中的内容是否为1?如果是1,那么执行跳转指令继续执行,否则调用explode_bomb.
(3)如果M[R[rsp]]内容为1,那么通过不断的移动RBX进行相邻值之间的比较,当RBP的值=RBX的值时候停止比较,RBP值为RBX+24.每次比较都是判断M[R[rbx]]==2*M[R[rbx]-4],如果不满足这个条件,那么调用explode_bomb函数。

由以上的分析可以知道,第一个数为1,其次的每一个数都是前面的一个数的二倍。一共有6个数,那么输入的内容是:

1 2 4 8 16 32
运行截图

炸弹三:

在phase_3中,分析一下做了什么事情:
(1)首先是调用了一个函数__iosc99_sscanf@plt,然后函数的返回值EAX和1做比较,如果EAX>1,那么执行跳转指令,否则爆炸,调用explode_bomb函数.

这里的EAX作为返回值,表示输入的参数的个数,说明至少有两个输入的数.且输入的数据保存在RSP+8,RSP+12这两个位置.

(2)然后判断第一个参数的范围是否满足要求,如果大于7,那么爆炸,因此第一个输入的参数需要小于等于7

(3)再接下来遇到一个跳转指令,跳转的地址是(0x402470+RAX8),这里的RAX保存第一个参数的值.为了知道执行完了这条指令之后跳转到那里,需要查看一下,这个内存单元保存的内容


如果输入了0,那么跳转到0x400f7c,那么把0xcf和第二个数比较,相同则成功拆除.

执行截图:


执行成功截图

你可能感兴趣的:(2019-06-17 YTF)