再接再厉
来到第四关
gdb bomb
disas phase_4
看一看到什么东西送到esi并且做为sscanf的第二个输入
先看下是什么
(gdb) x/s 0x4025cf
0x4025cf: "%d %d"
那么这题就是输入两个数
接下来判断第一个数小于等于14我们才能接着游戏
调用func4 入口参数 第一个参数 第一个数 第二个参数 0 第三个参数0xe(14)
然后
disas func4
0x0000000000400fce <+0>: sub $0x8,%rsp
0x0000000000400fd2 <+4>: mov %edx,%eax
0x0000000000400fd4 <+6>: sub %esi,%eax
0x0000000000400fd6 <+8>: mov %eax,%ecx
0x0000000000400fd8 <+10>: shr $0x1f,%ecx
0x0000000000400fdb <+13>: add %ecx,%eax
0x0000000000400fdd <+15>: sar %eax
0x0000000000400fdf <+17>: lea (%rax,%rsi,1),%ecx
0x0000000000400fe2 <+20>: cmp %edi,%ecx
0x0000000000400fe4 <+22>: jle 0x400ff2 <func4+36>
0x0000000000400fe6 <+24>: lea -0x1(%rcx),%edx
0x0000000000400fe9 <+27>: callq 0x400fce <func4>
0x0000000000400fee <+32>: add %eax,%eax
0x0000000000400ff0 <+34>: jmp 0x401007 <func4+57>
0x0000000000400ff2 <+36>: mov $0x0,%eax
0x0000000000400ff7 <+41>: cmp %edi,%ecx
0x0000000000400ff9 <+43>: jge 0x401007 <func4+57>
0x0000000000400ffb <+45>: lea 0x1(%rcx),%esi
0x0000000000400ffe <+48>: callq 0x400fce <func4>
0x0000000000401003 <+53>: lea 0x1(%rax,%rax,1),%eax
0x0000000000401007 <+57>: add $0x8,%rsp
0x000000000040100b <+61>: retq
我们需要简单翻译下
入口参数 a,b,c rdi , rsi , rdx
int ans = c ; mov %edx,%eax
ans = ans - b ; sub %esi,%eax
int t = ans ; mov %eax,%ecx
t>>=31; shr $0x1f,%ecx
ans+=t; add %ecx,%eax
ans>>=1; sar %eax
t = ans+b; lea (%rax,%rsi,1),%ecx
if( t<=a){ cmp %edi,%ecx
jle 0x400ff2 <func4+36>
ans = 0 ;
if( t >= a ){
return ans ;
}
else{
b = t +1 ;
return func4(a,b,c);
}
}
else{
c=t-1;
return func4(a,b,c);
}
再简化一下
int ans = c-b;
int t = (c-b)>>31;
ans>>=1;
t = ans + b ;
14 0 14
ans = 14
t = 0
ans = 7
t = 7
这里可以看到func4在递归但是我们发现当第一个数也就是a=7的时候我们就可以不用递归返回0
接着回到phase_4看到只有第二个数等于0并且func4返回值等于0 我们才能过关
也就是答案是7 , 0 (应该还有别的只要第一个数进入func4返回0)