内存地址 | 内存地址中的数 | 注释 | 指向这块内存的寄存器 |
0xffffd0e8 | 函数phase_2的栈帧 | ||
0xffffd0e4 | 0xffffd0f4 | 函数phase_2的栈帧 | |
0xffffd0e0 | 0x5655b7b0 | 函数phase_2的栈帧 | |
0xffffd0dc | 0x565566ca | 函数read_six_numbers的返回地址,函数phase_2的栈帧 | |
0xffffd0d8 | 0x5655af64 | 旧%ebx的值 | |
0xffffd0d4 | |||
0xffffd0d0 | |||
0xffffd0cc | 0xffffd108 | 第<read_six_numbers+26>行 push %edx | |
0xffffd0c8 | 0xffffd104 | 第<read_six_numbers+30>行 push %edx | |
0xffffd0c4 | 0xffffd100 | 第<read_six_numbers+34>行 push %edx | |
0xffffd0c0 | 0xffffd0fc | 第<read_six_numbers+38>行 push %edx | |
0xffffd0bc | 0xffffd0f8 | 第<read_six_numbers+42>行 push %edx | |
0xffffd0b8 | 0xffffd0f4 | 第<read_six_numbers+43>行 push %eax | |
0xffffd0b4 | 0x565583c1 | 0x565583c1是字符串'%d %d %d %d %d %d'的地址 | %esp |
(图1:实际运行与纸上分析——使用"ni"命令执行第<read_six_numbers+50>行汇编代码之后各寄存器与栈帧的情况)
是不是有点小激动了呀哈哈哈,耐住性子千万不要着急,一步一步慢慢来哦!
内存地址 | 内存地址中的数 | 注释 | 指向这块内存的寄存器 |
0xffffd0e8 | 函数phase_2的栈帧 | ||
0xffffd0e4 | 0xffffd0f4 | 函数phase_2的栈帧 | |
0xffffd0e0 | 0x5655b7b0 | 函数read_six_numbers的第一个入口参数,函数phase_2的栈帧 | |
0xffffd0dc | 0x565566ca | 函数read_six_numbers的返回地址,函数phase_2的栈帧 | |
0xffffd0d8 | 0x5655af64 | 旧%ebx的值 | |
0xffffd0d4 | |||
0xffffd0d0 | |||
0xffffd0cc | 0xffffd108 | 第<read_six_numbers+26>行 push %edx | |
0xffffd0c8 | 0xffffd104 | 第<read_six_numbers+30>行 push %edx | |
0xffffd0c4 | 0xffffd100 | 第<read_six_numbers+34>行 push %edx | |
0xffffd0c0 | 0xffffd0fc | 第<read_six_numbers+38>行 push %edx | |
0xffffd0bc | 0xffffd0f8 | 第<read_six_numbers+42>行 push %edx | |
0xffffd0b8 | 0xffffd0f4 | 第<read_six_numbers+43>行 push %eax | |
0xffffd0b4 | 0x565583c1 | 0x565583c1是字符串'%d %d %d %d %d %d'的地址 | |
0xffffd0b0 | 0x5655b7b0 | 0x5655b7b0是你输入的针对'phase_2'的字符串的地址 | %esp |
(图2:实际运行与纸上分析——使用"ni"命令执行第<read_six_numbers+51>行汇编代码之后各寄存器与栈帧的情况)
内存地址 | 内存地址中的数 | 注释 | 指向这块内存的寄存器 |
0xffffd0e8 | 函数phase_2的栈帧 | ||
0xffffd0e4 | 0xffffd0f4 | 函数phase_2的栈帧 | |
0xffffd0e0 | 0x5655b7b0 | 函数read_six_numbers的第一个入口参数,函数phase_2的栈帧 | |
0xffffd0dc | 0x565566ca | 函数read_six_numbers的返回地址,函数phase_2的栈帧 | |
0xffffd0d8 | 0x5655af64 | 旧%ebx的值 | |
0xffffd0d4 | |||
0xffffd0d0 | |||
0xffffd0cc | 0xffffd108 | 0x6 | |
0xffffd0c8 | 0xffffd104 | 0x5 | |
0xffffd0c4 | 0xffffd100 | 0x4 | |
0xffffd0c0 | 0xffffd0fc | 0x3 | |
0xffffd0bc | 0xffffd0f8 | 0x2 | |
0xffffd0b8 | 0xffffd0f4 | 0x1 | |
0xffffd0b4 | 0x565583c1 | 0x565583c1是字符串'%d %d %d %d %d %d'的地址 | |
0xffffd0b0 | 0x5655b7b0 | 0x5655b7b0是你输入的针对'phase_2'的字符串的地址 | %esp |
(图3:实际运行与纸上分析——使用"ni"命令执行第<read_six_numbers+55>行汇编代码之后各寄存器与栈帧的情。这时是不是觉得<__isoc99_sscanf@plt>非常神奇!!!在这一步过后,我们的思路便豁然开朗了起来)
内存地址 | 内存地址中的数 | 注释 | 指向这块内存的寄存器 |
0xffffd0e8 | 函数phase_2的栈帧 | ||
0xffffd0e4 | 0xffffd0f4 | 函数phase_2的栈帧 | |
0xffffd0e0 | 0x5655b7b0 | 函数read_six_numbers的第一个入口参数,函数phase_2的栈帧 | |
0xffffd0dc | 0x565566ca | 函数read_six_numbers的返回地址,函数phase_2的栈帧 | |
0xffffd0d8 | 0x5655af64 | 旧%ebx的值 | |
0xffffd0d4 | |||
0xffffd0d0 | %esp | ||
0xffffd0cc | 0xffffd108 | 0x6 | |
0xffffd0c8 | 0xffffd104 | 0x5 | |
0xffffd0c4 | 0xffffd100 | 0x4 | |
0xffffd0c0 | 0xffffd0fc | 0x3 | |
0xffffd0bc | 0xffffd0f8 | 0x2 | |
0xffffd0b8 | 0xffffd0f4 | 0x1 | |
0xffffd0b4 | 0x565583c1 | 0x565583c1是字符串'%d %d %d %d %d %d'的地址 | |
0xffffd0b0 | 0x5655b7b0 | 0x5655b7b0是你输入的针对'phase_2'的字符串的地址 |
(图4:实际运行与纸上分析——使用"ni"命令执行第<read_six_numbers+60>行汇编代码之后各寄存器与栈帧的情。)
内存地址 | 内存地址中的数 | 注释 | 指向这块内存的寄存器 |
0xffffd0e8 | 函数phase_2的栈帧 | ||
0xffffd0e4 | 0xffffd0f4 | 函数phase_2的栈帧 | |
0xffffd0e0 | 0x5655b7b0 | 函数read_six_numbers的第一个入口参数,函数phase_2的栈帧 | |
0xffffd0dc | 0x565566ca | 函数read_six_numbers的返回地址,函数phase_2的栈帧 | |
0xffffd0d8 | 0x5655af64 | 旧%ebx的值 | |
0xffffd0d4 | |||
0xffffd0d0 | %esp | ||
0xffffd0cc | 0xffffd108 | 0x6 | |
0xffffd0c8 | 0xffffd104 | 0x5 | |
0xffffd0c4 | 0xffffd100 | 0x4 | |
0xffffd0c0 | 0xffffd0fc | 0x3 | |
0xffffd0bc | 0xffffd0f8 | 0x2 | |
0xffffd0b8 | 0xffffd0f4 | 0x1 | |
0xffffd0b4 | 0x565583c1 | 0x565583c1是字符串'%d %d %d %d %d %d'的地址 | |
0xffffd0b0 | 0x5655b7b0 | 0x5655b7b0是你输入的针对'phase_2'的字符串的地址 |
寄存器名称 | 寄存器中的值 |
%eax | 0x6 |
(图5:实际运行与纸上分析——使用"ni"命令执行第<read_six_numbers+63>行汇编代码之后各寄存器与栈帧的情。因为此时我们的%eax寄存器中的值为0x6,大于0x5,所以不会跳转到<read_six_numbers+73>这个没有任何内容的空地址上,进而不会引爆炸弹。)
……………………
(图6:实际运行与纸上分析——使用"ni"命令执行第<phase_2+47>行汇编代码之后各寄存器与栈帧的情。接着,第<phase_2+50>行判断(%esp+4)和0的大小,如果不相等就会跳到第<phase_2+64>行,可是第<phase_2+64>行就是引爆炸弹,所以不能不相等,所以%esp+4应该是0,而我们输入的却是1,所以万万不能继续执行了)
按quit退出,接着再重复一遍,先输入phase_1的正确字符串,接着输入"0 1 2 3 4 5"作为我们假设的phase_2的答案,然后一路按"ni",一直到我们刚刚的那个地方,如 图7:又来到了同样的<phase_2+50>这个地方 所示。
(图7:又来到了同样的<phase_2+50>这个地方。接着,第<phase_2+50>行判断(%esp+4)和0的大小,如果不相等就会跳到第<phase_2+64>行。但是我们此时的函数栈帧中(%esp+4)的值就是0,相等,不会跳到<phase_2+64>,所以我们输入的6个数中对了第1个数,是"0"。)
(图8:实际运行与纸上分析——使用"ni"命令执行第<phase_2+55>行汇编代码之后各寄存器与栈帧的情况)
接着使用同样的方法,我们分别得到了剩下的几个数为:"1 1 2 3 5",也就是说,这其实是一个以0,1开头的斐波那契数列,所以我们针对phase_2的答案字符串即为"0 1 1 2 3 5"。
I turned the moon into something I call a Death Star.
0 1 1 2 3 5