【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 软件环境Windows1064位。1.2.3 开发工具VM Virtua
第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
更多推荐
所有评论(0)