题目是求以下数列:1/2+3/4+5/6+…的前n项和,为什么不管输入的n为多少,s输出的都是1?

这个实验是通过反汇编一个可执行文件,分析汇编代码来找到六个炸弹的密码。完成实验需要熟悉一些比较基础的汇编知识,掌握GDB的使用。然后就只需要耐心读汇编,通过GDB查看有用信息,就可以完成这个lab了。

bomb.s反汇编工具来得到汇编代码。

首先定位到main函数对应的机器代码。分析这段代码,可以看到前面都是和bomb.cmain()函数对应的。

main开头是一个if分支语句,机器代码对应的就是cmpjmp。继续分析:

我们会发现对应于这个else部分的机器代码是这样的:

字符串常量会存放在代码的静态内存区,所以我们一般都会用一个指针来引用这个字符串常量。所以,只要我们知道了这个地址,就能够用gdb来print得到这个字符串常量。我们可以在这里验证一下,观察这段机器代码,可以确定mov $0x4022d3,%esi是在调用printf("Usage: %s [<input_file>]\n",

结果验证了这个想法是正确的,所以我们可以利用这个思路来进行接下来的lab。

通过阅读代码,找到bomb1对应的函数:

根据我们上面的思路,很容易发现这里把0x402400加载进了%esi作为函数参数,然后调用了string_not_equal函数。所以,那个地址想必就是bomb1的key了。

轻易找到答案,热身完毕。

找到phase_2,看到开始是用sub $0x28, %rsp分配了一个40bytes的栈空间,然后调用了函数read_six_numbers,根据这个函数的名字,猜想应该是从输入读取六个数字。

可以确定,phase_2是调用了read_six_numbers来读取六个数字。因此,我们只需要找出这六个数,就可以拆除炸弹了。

这里比较了处于栈顶的数和$0x1,如果不相等就会explode,所以确定第一个数就是1。再根据je跳转,发现这里将%rsp+0x4%rsp+0x18对应的值存入了寄存器,然后跳转到400f17,而这里将%rbx-4指向的数放入%eax后,对其乘以2再和%rbx对应的数进行比较,如果不相等就会引爆炸弹,否则就是一个循环。

至此,我们可以确定这里是一个循环,并且每次都是将%rbx-4对应的值乘以2和%rbx对应的值进行比较,也就是说,每次都是将栈中前一个数的两倍和后一个数比较。因此,可以确定这六个数是一个等比数列,并且第一个数是1。

开始调用了sscanf,按照我们之前的经验,可以用GDB调试器查看调用的参数,也就是数据输入的格式,根据mov $0x4025cf,%esi:

可以得知我们输入的应该是两个整数,然后再继续下面的分析。先是%rax只有大于1,才不会爆炸。然后比较(%rsp+8)对应的值和0x7的大小关系,如果大于7就会爆炸,然后jmpq *0x402470(,%rax,8)进行跳转。这样的结构就是switch的特征!然后再结合后面的若干mov和jmp,可以断定这是一个switch结构,并且每次跳转后,都会比较一个常数和%eax中的值,如果相等就会结束,否则会爆炸。

所以,我们推断,输入的两个数中的第一个数应该是索引,然后第二个数就是索引对应的case中的数。

如我们所料,会得到一个地址,然后转换成十六进制就是400fb9,而这个对应的就是:

于是,我们得到了其中的一个答案就是: 1 311。

当然,还有其他的case都能够正确地通,如2 707等。

还是之前的套路,分析输入的应该是两个整数。然后,phase_4部分其实很简单,就是读取输入的两个数。然后第一个数作为参数(存入%edi,并且第一个参数小于等于14),另外0xe和0x0作为第二个和第三个参数来调用函数func4。调用结束后,返回值(%eax)应该是0。根据cmpl $0x0,0xc(%rsp)可知,第二个输入的数字也应该为0。

接下来,分析函数func4。由前面的分析,这个函数应该有三个参数,接下来只需要给每个寄存器一个名字,然后将汇编代码转换成逻辑图就行了:

根据这个逻辑,如果函数返回值为0,则是b == a的情况,而上面分析到了另外两个参数c = 0, d = 14,所以此时a = b = (d+c)/2 = 7。

所以,输入的第一个数应该是7!输入的第二个数应该是0!

分析这部分,调用了string_length函数,并且要求返回值为6,所以输入的应该是一个字符串,而且长度为6。

这里分别以(%rsp+0x10到%rsp+0x16)的字符串和地址0x40245e的字符串作为参数,调用了函数string_not_equal。根据这段可以肯定,我们需要输入长度为6的字符串来和存放在地址0x40245e的字符串来进行比较,如果不同,就会Bomb。用GDB可以得到这个字符串是"flyers":

所以,现在我们的目的就很明确了,如果得到"flyers"。再分析这段:

在跳转到这段之前,%eax已经被设置为0。显而易见,这里是一个循环,循环条件为%rax != 0x6。所以,这里就是循环六次,每次都向栈中写入了一个字符,最后得到的就是"flyers"。但是,这些字符都是怎样产生的呢?

这是一条更长的字符串,并且包括了"flyers"的所有字符,所以推测是从这个长字符串取出的字符。而这验证了我们的猜想:

%rbx存放的是我们输入的字符串的地址,然后%rax是索引,每次从我们输入的字符串取出一个字符后,都会对其进行截断,只取最低4位存放在%edx中,然后这个%edx被用做了从长字符串取字符的索引。

这里又是用到了前面的read_six_number,所以我们的任务就是寻找6个数。开头这一部分代码的意思就是,必须每个数都要小于等于6。

首先,第一个元素被放在0x(%rbp)中,然后通过增加%ebx的值,循环了五次,也就是把数组后面的五个元素都和第一个元素进行比较,如果相同,就会触发炸弹。然后,同样有是一个循环,用来判断后面的元素依次不同。所以,这个部分就是用来判定每个数都是不同的。另外,对于栈中那六个数,每个数x,都被改成了7-x。

后面这部分就很复杂,刚开始一直没有看懂。然后发现有一个地址0x6032d0有被用到,所以用GDB打印它的内容可以发现:

再结合mov 0x8(%rdx),%rdx可以想到,这个应该是一个链表的结构,所以我们再打印出这个地址附近的信息:

然后再分析代码,会发现把我们输入的数处理后,将其作为链表的索引,读取数据存放在栈中,然后又串连成了链表。

这里遍历链表,要求链表的顺序是升序。所以,我们可以根据GDB打印出来的每一个结点的值,来找到数据的排列顺序为:3 4 5 6 1 2。然后,7-x后: 4 3 2 1 6 5。

最后,还有隐藏关卡,但是天已经亮了,无力再战。。

数列11/21/31/41/5……此数列的前n项和怎么表示、过程、... 数列1 1/2 1/3 1/4 1/5…… 此数列的前n项和怎么表示、过程、

你对这个回答的评价是?

下载百度知道APP,抢鲜体验

使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。

从偶数哥德巴赫猜想的容斥公式到哈代-李特伍德猜想(A)从偶数哥德巴赫猜想的容斥公式到哈代,李特伍德猜想(A)童信平关键词偶数哥德巴赫猜想表法个数容斥公式哈代,李特伍德猜想(A)摘要参照素数个数的容斥公式,可以得到偶数哥德巴赫猜想的表法个数(解数)的容斥公式,再通过一些数学变换得到哈代,李特伍德猜想(A)。1名词、术语、符号、引理。N——偶数。N,4。p、p、p、P——素数,p,(p+1),p,(N-p-1),P,N。i=1,2,…,r。r=π()。Nirirr偶数哥德巴赫猜想:每一个大于4的偶数都可以写成二个奇素数相加。又称哥德巴赫猜想(A)。简称“1+1”、{1,1}、(1+1)、1+1等等。存在N=p+(N-p)=p+(N-p)=P+(N-P)。p是参变量。实验证明,存在许多N,使得(N-p)、(N-P)都是合数,iiii不能用p、P来证明大于4的每一个偶数都存在“1+1”。只能用p来证明“1+1”的存在。i[A]——数值A的整数部分。例如,[转载请标明出处.

我要回帖

更多关于 等差数列题目 的文章

 

随机推荐