二进制实验报告
一.实验目的: 
    通过二进制实验,熟悉汇编语言及其机器码表示,熟悉GDB调试工具。 
二.实验简介: 
    这个实验是一个过关游戏,共有6关+一个隐藏关卡。在一台Linux服务器上有一个可执行的文件,运行它游戏就开始了。每一关都会要求你输入密码,只有密码正确才能通过,进入下一关,否则它会“爆炸”,每输入错误一次就会“爆炸”一次,服务器会记录你“爆炸”的次数,“爆炸”次数越多扣分越多。你所拥有的所有资源就是这个可执行的文件,你需要破译这个文件,从中出每一关的过关密码,如果破译错误,你需要付出相应的代价。需要先进行反汇编并利用winscp工具,将反汇编代码下载到你的电脑上便于阅读。 查看目标文件,并通过调试来得到每一关的密码。
三.具体过程:
第一关
    通读phase1的代码后发现这是一个简单的比较过程,将我输入的字符串与存储于某个指定位置处的字符串进行比较:
图1.1
    于是使用gdb工具读取指定地址处存储的内容:
图1.2
    便得到了第一关的密码为:I am not part of the problem. I am a Republican.
第二关
通读代码后发现,进行完push等准备工作后,程序调用了read_six_numbers函数来读入用户输入的六个十进制数并依次存放,两两之间的地址间隔为4。通读phase2的代码后发现这段代码进行的操作其实是比较输入数1与4是否相等,输入数2与5是否相等,输入数3与6是否相等,若有一对数不相等则引爆。
所以可以简单地输入A B C A B C类型的数字串来拆除这一关的。
这一关我选择的密码是1 2 3 1 2 3
第三关
第三关中用到了switch跳转语句。在这段代码中首先使用了scanf函数读入用户输入的数据,读取$0x8049e0a中的内容可以得到“%d %d”,这就表明了这一关我们要输入的密码是两个二进制数,若输入的参数个数少于两个则引爆。
图3.1
然后比较输入的第一个参数与7的大小关系,如果大于7则引爆:
图3.2
接下来要做的事情就是到switch的跳转表的起始位置,从代码中可以看到:
图3.3
所以调用gdb来查看这个位置中存储的内容,同时注意到循环变量%eax每次加一,所以寻的地址每次加4,总共存在8个case,而且一个case执行完之后并不会break而是按照顺序进入下一个case直到全部执行完:
图3.4
从后续的代码中可以得知每个case进行的都是简单的加或者减的操作。case表如下所示:
图3.5
我选择输入的第一个参数为0,要经历所有的case,也就是将所有的加减数操作都进行一遍,最后得出的结果为-420。
所以这一关我选择的密码是:0 -420
第四关
    程序流程: 
    1.读取参数,调用Sscanf函数传入参数
    2.比较输入参数与0的大小,小于等于则引爆
    3.把输入参数传入函数func4,并调用函数Func4
    4.若函数Func4返回值等于(0xa182584),则进入下一关,否则引爆
图4.2
    通过读取0x8049e0d中的内容可知输入scanf函数的是一个十进制数字:
图4.2
    尝试用C语言将Func4函数的功能表示出来:
int Func4(int a)
{
  if(a<=1)
      return 1;
  int b=0;
  for(int c=a; c>1; c-=2)
  {
      int d=c-1;
      b+=Func4(d);
  }
  return b+1;
}
    可以看出来这是一个递归函数。通过从零开始对上述迭代进行依次求值,可以确定下来Func(17)=0xa18(2584)。
    因此第四关的密码是:17
第五关
    程序流程: 
    1.调用string_length的字符串长度函数,测得的长度若不为6则引爆:
图5.1
    2.做一个6次的循环,每次取出对应位的字符,截取其低四位:
图5.2
    3.做一个6次的循环,每次取出对应位的字符,截取其低四位
    4.以输入的6个字符的ASCII码低四位为索引得到给出的字符串中的6个字符,存到一段连续的存储空间中
5.比较索引得到的字符串是否为“titans”,如果不等则引爆,相等则拆除
图5.3
我们得到的作为参考用——也就是索引表功能的字符串为isrveawhobpnutfg,而我们的目的字符串为titans,分别为13位,0位,13位,5位,11位和1位,所以只要我们输入的六个字符的相应的低四位的二进制表示为13,0,13,5,11,1即可。
所以这一关我选取的密码是:m0meka 其中第二位是数字0。
第六关
    程序流程:
    1.调用函数read_six_numbers,读入6个数字
    2.判断6个数字中是否存在大于6的数,如果存在则引爆
图6.1
3.判断6个数字两两之间是否有相等,如果存在相等则引爆
图6.2
    4.根据输入的参数到索引的节点
    5.给相应的节点赋地址、赋值,并把节点依次串联起来
    6.判断前一节点的值是否不小于下一节点,如果不满足则则引爆
    7.拆除
这其实是一个链表,每个节点中存储了两个信息,第一个是该节点的存储的数字的值;第二个是该节点存储的指向下一个节点的地址;采用这样的方式将各个节点串接起来形成链表。调用gdb工具后可得各节点的数据依次是0x1b6、0x1d1、0x158、0x13b、0x253、0x12f。
所以按照从大到小的顺序排列便可得到第六关的密码是:5 2 1 3 4 6
隐藏关卡
   
    在读反编译代码的时候,发现在phase6后面还有一个名为secret phase的隐藏关卡。
所以开始研究如何调出关卡。通篇代码读下来,发现只有在phase_defused函数的代码中调用了secret phase,而phase_defused是在每关成功拆除之后被调用的。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。