所以我几天都在研究这种二元炸弹,我差不多完成了。还有两个阶段,明天晚上到期。我已经完成了下面发布的反汇编代码,但我似乎无法确切地知道发生了什么。
我所知道的是fscanf函数被调用并请求两个输入"%d%d"由字符串$ 0x8048baa给出。我们将按顺序调用这些输入y和x。在输入两个输入之后,程序将继续而不会爆炸并查看y是否小于4.接下来,进行比较以查看y是否为正,如果不是,则将其更改为正并恢复为%eax。
接下来,以y为参数调用函数f(下面的反汇编代码)。我在线< + 4>上有点困惑此函数的值为0x20(%esp)位于为此函数分配的空间之外,并且位于先前存储的项目中。 0x20(%esp)似乎是指向y之前推送到堆栈的指针。我不确定这是否正确,因为我不明白为什么当y已经作为一个存储在堆栈中时,程序会引用一个指向y的指针,该指针先前存储在该方法的调用之外。当前函数的参数。无论如何,我不知道这里还会发生什么,所以如果 正在发生什么,那么y存储在%ebx中,那么如果y小于1,程序会向前跳转,否则将新地址加载到eax中,然后递归调用该函数?我不完全理解这里发生了什么,所以我只是希望我可以通过将y设置为小于1的初始值而不必通过递归调用。如果y小于1,那么eax寄存器设置为1,y变为1,然后我们返回phase_4_of_5。
现在y被添加到自身。退出f函数后,y == 1所以y + y = 2.接下来进行比较以查看y和x是否相等,如果是,那么我们跳到第二次比较,确保x不等于值240.如果x!= 240,程序将重置堆栈指针并返回。
根据我的(显然有缺陷的)逻辑,如果y最初是-5而x最初是2,那么我应该在没有炸毁炸弹的情况下完成它。
也许有人可以指出我在这方面的正确方向?我不确定我哪里出错了,并且很难完全理解f函数。对我来说,实际上我理解我的作业非常重要,所以如果你想为我提供一个工作输入,这样我就可以一步一步地完成这个程序,知道我还在学习。
Dump of assembler code for function phase_4_of_5:
0x08048890 <+0>: sub $0x2c,%esp ;allocate 44 bytes for stack
0x08048893 <+3>: lea 0x1c(%esp),%eax ;load address of x into eax
0x08048897 <+7>: mov %eax,0xc(%esp) ;prepare &x for function call
0x0804889b <+11>: lea 0x18(%esp),%eax ;load address of y into eax
0x0804889f <+15>: mov %eax,0x8(%esp) ;prepare &y for function call
0x080488a3 <+19>: movl $0x8048baa,0x4(%esp) ;prepare "%d %d" for call
0x080488ab <+27>: mov 0x804b040,%eax ;load call to fscanf into eax
0x080488b0 <+32>: mov %eax,(%esp) ;push call to fscanf onto stack
0x080488b3 <+35>: call 0x8048480 <__isoc99_fscanf@plt> ;call fscanf("%d %d", &y, &x);
0x080488b8 <+40>: cmp $0x2,%eax ;if((# of numbers entered == 2))
0x080488bb <+43>: je 0x80488c9 <phase_4_of_5+57> ;jump to <+57>
0x080488bd <+45>: movl $0x4,(%esp)
0x080488c4 <+52>: call 0x80486ef <explode>
0x080488c9 <+57>: mov 0x18(%esp),%eax ;move y into eax
0x080488cd <+61>: cmp $0x4,%eax ;if(y <= 4)
0x080488d0 <+64>: jle 0x80488de <phase_4_of_5+78> ;jump to <+78>
0x080488d2 <+66>: movl $0x4,(%esp)
0x080488d9 <+73>: call 0x80486ef <explode>
0x080488de <+78>: test %eax,%eax ;if(y >= 0)
0x080488e0 <+80>: jns 0x80488e8 <phase_4_of_5+88> ;jump to <+88>
0x080488e2 <+82>: neg %eax ;else y = -y;
0x080488e4 <+84>: mov %eax,0x18(%esp) ;update y
0x080488e8 <+88>: mov 0x18(%esp),%eax ;update eax (unnecessary?)
0x080488ec <+92>: mov %eax,(%esp) ;load y as argument to f
0x080488ef <+95>: call 0x8048869 <f> ;call f
0x080488f4 <+100>: add %eax,%eax
0x080488f6 <+102>: mov 0x1c(%esp),%edx
0x080488fa <+106>: cmp %eax,%edx
0x080488fc <+108>: je 0x804890a <phase_4_of_5+122>
0x080488fe <+110>: movl $0x4,(%esp)
0x08048905 <+117>: call 0x80486ef <explode>
0x0804890a <+122>: cmp $0xf0,%edx
0x08048910 <+128>: jne 0x804891e <phase_4_of_5+142>
0x08048912 <+130>: movl $0x8048c98,(%esp)
0x08048919 <+137>: call 0x80484d0 <puts@plt>
0x0804891e <+142>: add $0x2c,%esp
0x08048921 <+145>: ret
End of assembler dump.
Dump of assembler code for function f:
0x08048869 <+0>: push %ebx ;load new base pointer
0x0804886a <+1>: sub $0x18,%esp ;make more room on the stack
0x0804886d <+4>: mov 0x20(%esp),%ebx ;move arg(y) into ebx
0x08048871 <+8>: cmp $0x1,%ebx ;if(y <= 1)
0x08048874 <+11>: jle 0x8048886 <f+29> ;jump to <+29>
0x08048876 <+13>: lea -0x1(%ebx),%eax ;else ??? what is happening here? 1 byte below ebx? does this mean I am dealing with low order and high order areas on the stack?
0x08048879 <+16>: mov %eax,(%esp)
0x0804887c <+19>: call 0x8048869 <f> ;recursively call f until ebx <= 1
0x08048881 <+24>: imul %ebx,%eax ;eax = eax*ebx
0x08048884 <+27>: jmp 0x804888b <f+34> ;jump to <+34>
0x08048886 <+29>: mov $0x1,%eax ;Does this literally mean to store the value '1' into eax? If so, what was the point of imul?
0x0804888b <+34>: add $0x18,%esp ;return esp to loc before call to f.
0x0804888e <+37>: pop %ebx
0x0804888f <+38>: ret
End of assembler dump.