【HIT-计算机系统】ICS-Lab3 BinaryBomb

第1章 实验基本信息

1.1 实验目的

熟练掌握计算机系统的ISA指令系统与寻址方式;

熟练掌握Linux下调试器的反汇编调试跟踪分析机器语言的方法;

增强对程序机器级表示、汇编语言、调试器和逆向工程等的理解 。

1.2 实验环境与工具

1.2.1 硬件环境

x64 CPU;1.60GHz;8G RAM;256GHD Disk。

1.2.2 软件环境

Windows10 64位。

1.2.3 开发工具

VM VirtualBox 6.1;Ubuntu 20.04 LTS 64位;

Visual Studio 2019 64位;CodeBlocks 17.12 64位;vi/vim/gedit+gcc。

1.3 实验预习

上实验课前,必须认真预习实验指导书(PPT或PDF)

了解实验的目的、实验环境与软硬件工具、实验操作步骤,复习与实验有关的理论知识。

请写出C语言下包含字符串比较、循环、分支(含switch)、函数调用、递归、指针、结构、链表等的例子程序sample.c。

生成执行程序sample.out。

用gcc –S或CodeBlocks或GDB或OBJDUMP等,反汇编,比较。

列出每一部分的C语言对应的汇编语言。

修改编译选项-O (缺省2)、O0、O1、O3、Og、-m32/m64。再次查看生成的汇编语言与原来的区别。

注意O1之后缺省无栈帧,RBP为普通寄存器。用 -fno-omit-frame-pointer加上栈指针。

GDB命令详解 –tui模式 ^XA切换  layout改变等等

有目的地学习: 看VS的功能,GDB命令用什么?

第2章 实验环境建立

2.1 Ubuntu下CodeBlocks反汇编(10分)

CodeBlocks运行hellolinux.c。反汇编查看printf函数的实现。

要求:C、ASM、内存(显示hello等内容)、堆栈(call printf前)、寄存器同时在一个窗口。

2.2 Ubuntu下EDB运行环境建立(10分)

用EDB调试hellolinux.c的执行文件,截图,要求同2.1

第3章 各阶段炸弹破解与分析

每阶段40分,密码20分,分析20分,总分不超过80分

3.1 阶段1的破解与分析

密码如下:He is evil and fits easily into most overhead storage bins.

破解过程:

在phase_1处设置断点。反汇编查看到调用了string_not_equal函数,可以猜测是判断字符串是否相等的函数,+16处通过判断eax跳转炸弹爆炸的函数,查看rax得知rax储存输入的字符串,则rsi储存判断的字符串。

经过验证第一阶段密码正确。

3.2 阶段2的破解与分析

密码如下:0 1 1 2 3 5

破解过程:

查看phase_2的反汇编代码,调用了read_six_number函数,猜测程序读取了输入的六个数字。函数调用完毕后,分别与0x0和0x1进行了两次比较,通过查看栈信息查到对比的两个数是输入的前两个数字11和22(输入11 22 33 44 55 66),并且栈中连续存放输入的六个数字,则可以先得到前两个数字应该输入0和1。

接下来查看对比后的反汇编代码,发现是一个循环,每次循环中edx的值从2变化到5,每次加1。且每次循环中以[rbp-30+4rax]+[rbp-30+4rcx]与[rbp-30+4rdx]进行比较,化简后即[rbp-30+4(rbx-1)]+[rbp-30+4(rbx-2)]与[rbp-30+4rbx]比较,即栈中的数字与前两个数字比较。则可以得知这是一个斐波那契数列,则剩下的数字为1 2 3 5 。

3.3 阶段3的破解与分析

密码如下:2 106或3 266或4 56或5 979或6 379或7 366

破解过程:

查看phase_3反汇编代码,发现调用sscanf函数前esi为“%d %d”,猜测函数输入两个整形数。

输入后eax和7比较,查看eax发现eax储存第一个输入数字0xe9(十进制233)。判断小于等于1大于7则爆炸,则可以得出第一个数只能在2到7之间。

下面的语句利用rax相对寻址跳转,跳转后对rax赋值一个数字,然后用栈中的一个数字与其进行比较,若不相等则爆炸。经过查询rbp-0x08得知储存第二个数字,则可以得知这里进行switch条件判断,针对第一个数字2~7之间每个数字在跳转表中都对应着第二个数字。

观察得知0x4031c0储存跳转基地址,查看其内存得到地址为0x004014ac,rax=2时地址加8*2个字节后到达0x004014b8即第一个跳转表位置,eax被赋值为0x6a即第二个数为0x6a;rax=3时地址加8*3个字节到达0x004014bf即第二个跳转表位置,对应第一个数为3时的第二个数;以此类推。

通过进制转换计算得知2对应0x6a即106,3对应0x10a即266,4对应0x38即56,5对应0x3d3即979,6对应0x17b即379,7对应0x16e即366。

3.4 阶段4的破解与分析

密码如下:8 35

破解过程:

在调用sscanf函数前查看esi内容得知输入为两个整型数。

调用完毕后,函数查看eax的正负,若为负则爆炸,判断eax与14的大小,若大于14则爆炸。通过查看eax内存得知eax为输入的第一个数字。则得知eax在[0,14]内。然后看到函数即将调用func4,对传递参数进行准备。函数参数为edx=14,esi=0,edi为第一个输入的数字。

进入函数func4内看到函数反复调用func4,猜测这是一个递归函数。对调用fun4前进行分析,进行计算ebx=((edx-esi)>>31(算术右移)+(edx-esi))>>1(逻辑右移)+esi,然后与第一个输入的数字进行比较,若相等停止递归,返回计算出来的数;若大于第一个数则edx=ebx-1,继续调用fun4并将新调用的返回值加上旧计算的值并返回;若小于第一个数则esi=ebx+1,同样继续调用fun4并将新调用的返回值加上旧计算的值并返回。

func4递归返回后,返回的数不等于35爆炸,第二个数不等于35爆炸。由于第一个数在0到14之间,则要求第二个数为35且第一个数能递归出第二个数。

编写C语言计算得出只有8 35满足条件。则密码为8 35。

3.5 阶段5的破解与分析

密码如下:第四位为0101的整型数(如5) 115

破解过程:

调用sscanf前查看esi得知输入两个整型数字。分析下面的指令,将第一个输入数字更新为其低4位数字。将ecx和edx赋初值位0,从+55开始循环,每次取出第一个数字与15比较,若不相等edx+1,eax更新并将ecx加上eax,重新开始循环;若相等则又将edx与15比较,若相等将第二个输入数字与ecx比较,相等则返回,否则这两步比较任一步不相等则爆炸。

分析eax更新方式发现其根据一数组赋值,由于eax低8位只能从0到14则查看数组的15个元素,发现的确与eax的更新一致。则程序即为第一个数低八位更新到0x1111,edx从0每次加一到15时,ecx得到的数需与输入的第二个数相等,否则爆炸。

用C语言模拟过程,得到低4为5即(0x0101)的数作为第一个数,115作为第二个数为密码。

3.6 阶段6的破解与分析

密码如下:1 3 4 2 5 6

破解过程:

阶段7反汇编代码较长,程序调用<read_six_number>输入六个数字,存储在栈中。可以看出指令中有多次跳转,分析出程序中有很多循环,如可分析出上图从+22到+100即为一个循环,循环终止条件为+75处跳转+102的指令。分析循环可知以r12d为循环计数变量,从0变化到5,将栈中偏移从0到5的输入取出减一与5无符号比较,大于5则爆炸,由于有符号的负数首位为1必大于0x5,则即输入的六个必须都小于等于6且大于等于0。并且每次与5比较后,利用edx将栈中r12d对应偏移的数之后的每个数与r12d对应的偏移的数比较,若相等则爆炸,则六个数中的任何两个数字不能相等。即输入的六个数小于等于6且各不相等。

接下来从+102到+131又是一个循环,初始化eax=0,eax从0到5将栈底偏移从0到5的六个输入的数分别用7减去其本身再保存回原来的栈帧。

接下来又是一个循环,循环中esi被赋初值1,每次循环加一,rbx被赋地址0x4016d3,经过地址查看发现这是一个链表,每个链表节点地址相差16,结构体内成员为一个数字和一个标号,标号从1到6。继续分析循环可以发现,循环是在以我们输入数字(被7减去后)的顺序将对应的结构体地址压入栈中,其中esi从0到5循环遍历我们输入的数字,eax从0加到1寻找标号对应输入数字的结构体,找到后利用-0x70(%rbp,%rcx,8)压入栈中。

继续看下面的代码,发现这又是一个循环,其中eax为循环变量,赋初值为1,每次循环加一,将rcx赋值为刚压入栈的结构体地址,即结构体按照栈中顺序重新排列并在最后一位空出一个第七位置。

接下来从+218开始以r12d从0到4循环五次,每次比较结构体与其后一个结构体,若前一个结构体内成员的数字比后一个小,则爆炸,则结构体应按第一个成员数字大小按以大到小排列。

6个结构体数字排列好分别为 682 644 532 443 425 266

对应数字为6 4 3 5 2 1,被7减去前排列为 1 3 4 2 5 6 即为密码

3.7 阶段7的破解与分析(隐藏阶段)

密码如下:107

破解过程:

查看bomb反汇编代码中main中语句发现在各个阶段后都有调用read_line和phase_defused,因为read_line在每个阶段前面。

进入gdb设置断点进入phase_defused查看string_not_equal前esi内容为“DrEvil”,推测为进入隐藏阶段密码;查看sscanf前edi内容为“%d %d %s”,推测为输入形式:两个整型数一个字符串。

查看phase_defused函数,发现当0x3cae(%rip)为6时会进入隐藏阶段secret_phase,猜测第六阶段之后才可进入隐藏阶段。进入隐藏阶段前,phase_defused调用了strings_not_equal,猜测需要输入特定字符串“DrEvil”才能进入secret_phase。

由上面几个阶段的密码形式破解,推测阶段3、4、5有可能进入特殊阶段。

secret_phase调用了atoi将read-line输入字符串的转换为整形数字,分析下面的代码eax-1需要小于等于1000,然后调用fun4:

查看内容得知eax被赋初值rdi=36,eax与esi比较大小,esi储存着输入的数字。

可以分析出来,函数为递归函数,eax>esi时rdi+8,调用fun7,eax=2eax,函数返回;eax<esi时rdi+16,调用fun7,eax=2eax+1,函数返回;eax=esi,函数停止递归。

fun7完毕后,eax不等于3爆炸。则从eax=3回推,3=(0*2+1)*2+1,即递归结束的一次调用返回值为0,此时esi=eax,rdi+16+16,查看其地址内容得到值为107,即密码为107。

整体拆弹过程(以阶段三2 106、阶段五5 115为例):

代码、附件github地址

https://github.com/ChenDolph7in/HITICS-LABS-in-21-Spring/tree/master/Lab3

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值