热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

计算机系统基础实验——拆除二进制炸弹

实验简要介绍:该实验是书籍深入理解计算机操作系统中最有趣的实验之一,主要使用gdb来拆解二进制(或者说程序)的一个文件,了解其运行逻辑。我

实验简要介绍:
     该实验是书籍深入理解计算机操作系统中最有趣的实验之一,主要使用 gdb来拆解二进制(或者说程序)的一个文件,了解其运行逻辑。我们对这个程序的了解有:


  1. 有六个关卡,分别是 phase_1 - phase_6
  2. 每一步都会要求你输入一个内容,就好像是密码,但是密码需要自己通过技术手段获取。
  3. 程序是 C 写的。
  4. bomb.c 是程序的总逻辑,可以看到每一个关卡都是调用一个 phase 开头的函数。

     首先使用命令objdump -d bomb > disassemble.txt反汇编bomb文件,将生成的汇编文件重定向到disassemble.txt文件中,然后结合gdb设置断点调试进行每一关炸弹的拆除。
phase_1
图1.1
                                   图1.1
在这里插入图片描述
                                   图1.2
     首先阅读汇编代码,发现图1.1中1处进行了有效地址传送,使用命令x/2s查看一下内容,发现是“I am just a renegade hockey mom.” 于是猜测这个字符串应该和答案有关,接下来看到2处调用了strings_not_equal函数,应该是用来比较两个字符串是否相等,于是查看该函数的汇编代码,图1.3所示的两行可知是入口参数,执行完这两句汇编语句之后可以看到图1.4所示EBX储存的是我输入的字符串“My name is Kerin.”,ESI存储的是“I am just a renegade hockey mom.”,通过分析后面的代码可知该函数的作用即为比较用户输入字符串和程序中这个固定的字符串是否相等,相等则strings_not_equal函数返回值为0,回到phase_1函数经过图1.1中14bf处的跳转语句不会跳转到14c6引爆炸弹,而是顺序执行离开函数phase_1,因此可知答案即为“I am just a renegade hockey mom.”。
图1.3
                                   图1.3
在这里插入图片描述
                                   图1.4
在这里插入图片描述
phase_2

     从汇编代码图2.1中可知调用函数read_six_numbers,进入到该函数里面通过命令p (char*)($ebx-0x1c5f)可以查看到要求输入数据的格式(图2.2),通过sscanf函数也可以看到格式(图2.3),其中“0 1 2 3 4 5”是我输入的6个数字。

在这里插入图片描述
     读入6个数字后再看phase_2的汇编代码(图2.4),首先拿M[R[ebp]-0x30]的数据和0比较,于是先查看这个位置的数据,如图2.5所示,发现这一块连续的存储单元存储了我刚才输入的“0 1 2 3 4 5”(下面均以这个输入为例解释),那么很显然M[R[ebp]-0x30]处存储的是我输入第一个数字0,如果两者不相等就会跳转到14fc引爆炸弹,因此输入的第一个数字必为0,接下来比较M[R[ebp]-0x2c]和数字1,即比较我输入的第二个数字和数字1的大小,如果不相等则引爆炸弹,相等则跳转到1501处执行,因此这一部分代码的作用就是检查输入的前两个数字是否为“0 1”。
在这里插入图片描述
     图2.6所示,接下来进行有效地址传送,将R[ebp]-0x30放入到esi中,将R[ebp]-0x20放入到edi中,可知esi即指向“0 1 2 3 4 5”中的0的地址,edi指向“4 5”中的4的地址,接下来看1515-151a部分,首先将M[R[esi]+0x4]放入eax,即eax等于1,又进行M [R[esi]]+R[eax]给R[eax],即进行0+1给eax,比较eax中的值和M[R[esi]+0x8]的值,M[R[esi]+0x8]值为2,相等则跳转到150e,不等则引爆炸弹,若跳转到150e,进行R[esi]+0x4放到R[esi],实现esi指向的存储单元向后移动了四个字节,接下来比较R[edi]和R[esi]是否相等,相等则终止循环,可以知道刚才让edi指向“4 5”中的4的地址,实际上就是终止条件,若不等则继续刚才的操作进行比较(将前两个数相加和后一个数进行比较),很容易看出这实际就在验证输入的6个数字是否是斐波那契数列,因此答案是“0 1 1 2 3 5”。
在这里插入图片描述
phase_3
在这里插入图片描述
在这里插入图片描述
     在这个分支下,解释如图3.4所示,可知要求输入的第二个参数应该为686,相等的话继续跳转到166c处进行比较,解释如图3.5所示。al中存进去了字母‘e’,后面要将M[R[ebp]-0x11]的低8位与‘e’,进行比较,因此知道第二个参数应该为‘e’才能通关。综上,其中一个答案是“1 e 686”,同理可得其他答案,比如“2 c 559”也可以通关。故本关答案不唯一。
在这里插入图片描述
在这里插入图片描述
phase_4
     惯例,先查看要求的输入格式,即“%d %d”, 汇编代码部分如图4.2所示,可知要求输入的第一个参数小于等于0xe,要求输入的第二个参数必须为6,(可用x/x命令查看-0x10(%ebp)储存的值),要求调用func4函数的返回值应该为6,传递给fun4函数的参数是0xe,0,以及输入的第一个参数,接下来看fun4函数。
在这里插入图片描述
在这里插入图片描述
                    图4.3 fun4函数的汇编代码解释
     如图4.3所示为fun4函数的详细解释,代码可分为3块来解读,圈出来的是递归调用自己之后两种情况对应的返回值,根据此汇编代码的逻辑可以得到对应的C代码为图4.4中fun4所示:
在这里插入图片描述
在这里插入图片描述
phase_5
     首先由图5.1所示汇编代码可知要求输入一个长度为6的字符串,否则将引爆炸弹。
在这里插入图片描述
     再看图5.2所示汇编代码,首先将累加器ecx清零,然后进行了有效地址传送,将R[ebx]-0x1e40给了R[edi],在这里用命令x/70cb查看该地址,如图5.3所示,可以看到这应该是一个数组,相当于把数组的首地址给了R[edi],接下来汇编语句的解释详见图5.2,可知这一部分的作用就是用输入的字符串的每个字符的末四位作为变址去获取内存中固有数组对应的元素进行累加,要求累加6次并且累加结果等于0x24,该数组如表5.4所示,
在这里插入图片描述
手推可知0x24=0x10+0x10+0x1+0x1+0x1+0x1=a[5]+a[5]+a[3]+a[3]+a[3]+a[3],所以只需要6个字符的末四位分别是553333即可,最简单的当然就是字符串“553333”,当然对此重新排列成“333355”等也会是答案,故本题答案也不唯一。
在这里插入图片描述
phase_6
     本部分代码很长,分部分来看。首先需要读入6个数字,先查看格式如图6.1所示,即“%d %d %d %d %d %d”。
在这里插入图片描述
     进入下一块,保证输入的6个数字互不相同且都在1-6之内,汇编代码及解释如图6.2所示,图6.3为相应的c语言的逻辑,这里用数组来简化,真正的汇编代码使用的是指针。
在这里插入图片描述
                                                  图6.2
在这里插入图片描述
     如果输入的数据符合规范,执行180多步就能跳转到1818处执行,可用命令n 180,节省时间。
     最开始R[ebp]-0x30存的是我输入的数字的首地址,图6.4展示了查看到这几个数字。接下来进行了有效地址传送,将R[ebx]+0x578给edx,使用命令x/32wx查看一下,发现这些数字存储的很有规律,可认为3个一组,第一个数字是二进制数,第二个数字是序号,第三个数字是地址,如0x00405584指向的就是0x18e,加上开头由node单词,于是可以判断出这是一个链表,其结构如表6.6所示。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
     见图6.7汇编代码解释,接下来是按照我输入数字的顺序,将链表每个节点的地址存到一个新数组中,这里也是用一个大循环套一层小循环,大循环负责选定我某一个输入的数字n,小循环根据这个数字n将第n个节点地址存储到一个新数组中,以“6 5 4 3 2 1”为例,执行完这个大循环后用命令x/32wx $ebp-0x48查看这个新数组存的数据,如图6.8所示,可以看到新数组中依次存放的是0x00405100、0x004055a8、0x0040559c、0x00405590、0x00405584、0x00405578,是一开始链表地址的逆序(因为我输入的是“6 5 4 3 2 1”)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
     如图6.9所示,接下来就是按照新的顺序将这节点衔接起来,组成一个新的链表,最后又是一个循环来检查这个链表的数据域是否按照从大到小的顺序排列,如图6.10所示,edi用来计数,循环中依次比较当前节点的数据域是否大于等于后一个节点的数据域,若大于等于继续循环,否则将爆炸,因此可以知道要输入的6个数字应该使链表重排后数据域从大到小排列,因为0x28b>0x18e>0x17b>0x172>0x14c>0xb2, 对应顺序为“3 2 6 5 4 1”,此即为答案。
在这里插入图片描述
secret_phase
1.隐藏关的进入
     首先在phase_defused的反汇编代码中找到调用secret_phase函数(图7.1),所以应该是拆除完每个炸弹的时候才有机会进入隐藏关卡,当拆完6个炸弹之后,使用s命令进入phase_defused函数中逐步调试,在sccanf的时候(图7.2)查看一下输入的格式(图7.3),发现要求属入“%d %d %s”,而我输入的是“6 6”,为第四关的答案,可知要求在第四关的答案后面再附加一个字符串才能进入隐藏关。为了弄清这个字符串是什么,先输入“6 6 mds”进行实验,在phase_defused函数中进入strings_not_equal函数调试,在比较字符串长度之前将我输入的“mds”放入到了ebx,把“DrEvil”放入到esi中(图7.4所示),由第一关的经验可知想进入隐藏关卡的字符串即为“DrEvil”。

在这里插入图片描述
在这里插入图片描述
2.隐藏关炸弹的拆除
     由汇编代码知,调用完fun7函数之后,test了返回值eax,如果不为0将引爆炸弹(图7.5),如果为0则通关,于是进入fun7函数(图7.6),发现很有意思的是18ab处比较了R[ecx]和R[ebx],若不满足大于,则不进行跳转而是执行18af处,eax清零,紧着判断两者是否相等,相等的话也不进行跳转,直接返回到secret_phase函数了,因此可以知道只需保证R[ecx]和R[ebx]相等即可通关。
在这里插入图片描述
     图7.8所示,单步运行到比较R[ecx]和R[ebx]时,发现ebx存储的是0x24(十进制36),ecx存储的是0x23(十进制35,我实验中输入的),因此可以正确答案是36。
在这里插入图片描述
在这里插入图片描述


推荐阅读
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • C语言自带的快排和二分查找
    Author🚹:CofCaiEmail✉️:cai.dongjunnexuslink.cnQQ😙:1664866311personalPage&#x ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
  • 利用空间换时间减少时间复杂度以及以C语言字符串处理为例减少空间复杂度
    在处理字符串的过程当中,通常情况下都会逐个遍历整个字符串数组,在多个字符串的处理中,处理不同,时间复杂度不同,这里通过利用空间换时间等不同方法,以字符串处理为例来讨论几种情况:1: ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 电话号码的字母组合解题思路和代码示例
    本文介绍了力扣题目《电话号码的字母组合》的解题思路和代码示例。通过使用哈希表和递归求解的方法,可以将给定的电话号码转换为对应的字母组合。详细的解题思路和代码示例可以帮助读者更好地理解和实现该题目。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
author-avatar
liuleyi
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有