我是靠谱客的博主 愤怒裙子,这篇文章主要介绍计算机系统基础(bomb实验报告),现在分享给大家,希望可以做个参考。

山东大学 计算机系统基础实验报告

bomblab

一、实验目的

1) 理解arm汇编语言,学会使用调试器。
2) 熟悉安卓开发板的使用和环境配置;
3)熟悉并掌握在linux系统下的shell命令使用。

二、实验环境

linux系统,终端,arm-gdb工具,安卓开发板

三、小组成员及任务分配

四、实验原理

二进制炸弹是作为一个目标代码文件提供给我们的程序,程序运行中有6个关卡(6个phase),运行时,它提示用户输入6个不同的字符串。如果其中任何一个不正确,炸弹就会“爆炸”:打印出一条错误信息。我们首先要在linux下配置好arm-gdb环境并且得到反汇编问卷,然后通过反汇编和逆向工程来确定是哪六个字符串,从而解除他们各自炸弹的雷管。

五、知识储备

在实验过程中我们运用了课上对于ARM部分指令的知识,例如读写指令ldr和str,跳转指令b和bl的区别,以及比较指令cmp等,还有条件域的实践应用。并且为了完成实验我们自学了关于在Linux环境下运用gdb设置断点进行调试,并且了解了更多的ARM指令和与之相关的寄存器和堆栈的使用。在拆炸弹似过程中我也运用到了相关的数学知识,主要是递归的算法和循环算法。

六、实验内容与步骤

复制代码
1
2
步骤一:环境配置

在进行环境配置时,我们按照指导书进行了Linux下的环境配置和gdb安装包的解压安装。在此阶段我们学习了在Linux终端用命令行进行新建,打开,检验文件夹,以及保存文档中的内容。主要运用了sudo来执行一些root命令,cd用来打开或退出文件夹,tar命令进行文件的备份。主要命令行如下:
tar -jxvf gdb-7.10.tar.bz2 解压gdb安装包
sudo gedit ~/.bashrc 修改环境变量
在进行PC与目标板的连接时,先分别获取IP地址,然后在目标板上运行PC中的bomb程序,在PC上运用arm-gdb进行程序的调试。主要运用了调试工具adb,ifconfig配置网络设备来设置IP,gdbserver来让PC可以对目标板进行远程调试。主要命令行如下:
adb push bomb /data/local 将bomb程序push到目标板上
ifconfig eth0 192.168.0.100 设置目标板IP
ifconfig eth1 192.168.0.101 设置PC的IP
gdbserver 192.168.0.101:2345 bombg (ip 为 pc 机机 ip)在目标板上可以运行bomb程序。
步骤二:六个phase的解决
首先是找到main函数,发现它调用了从phase1到phase6这六个函数。这应该就是每一关需要看懂的函数了。

实验三:

开头还是栈的开辟,往下看,首先特别明显注意到sscanf函数,推测应该是一个类似C中的一个函数,然后想要知道将要返回的参数,发现
“84ec: e59f1198 ldr r1, [pc, #408] ; 868c

复制代码
1
2
3
4
5
8890:e50b0048 str r0, [fp, #-72] ; 0x48 8894:e59f3260 ldr r3, [pc, #608] ; 8afc <phase_6+0x278> 8898:e50b3010 str r3, [fp, #-16] 889c:e24b3028 sub r3, fp, #40 ; 0x28 88a0:e51b0048 ldr r0, [fp, #-72] ; 0x48”

储存和取值的代码,推测应该是个链表结构,.word中存的应该是链表头。
仔细看了一遍代码后,大概找到了几个循环,推测应该是给链表从小到大的排序,用C语言表示大概是:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for(int i=0;i<=5;i++){ if(a[i]>6) explode_bomb(); for(int j=i+1;j<=5;j++){ if(a[i]=a[j]) explode_bomb(); }}//输入的小于66个整数两两不等 for(int i=0;i<=5;i++){ l=list; for(int j=1;j<a[i];j++) l=l->next; list_array[i]=l; }//把链表里面数存入数组 l=list_array; for(int i=0;i<=4;i++){ if(*l<*l->next) explode_bomb(); l=l->next; }//排序
复制代码
1
2
基本确定好是给链表从小到大排序后,只需找到链表中的数据就可以了。看到“88b8: e51b200c ldr r2, [fp, #-12]”里面把地址减去12经常出现,猜测应该是链表每隔12位存一个数据,所以用打印16进制地址的方式“(gdb)p/x *(0x00091104-12)”依次打印出地址,然后找到数据就可以了。最后打印出链表中数据是:“253,725,301,997,212,432”,然后给他们排序就是“5 1 3 6 2 4”即应该输入的6个整数。

隐藏关卡: —共同完成

隐藏关的开启方式在phase_defused中,由9158: e3530002 cmp r3, #2可以看出需要输入两个字符才能进入隐藏关卡。

复制代码
1
2
3
9168: e59f103c ldr r1, [pc, #60] ; 91ac <phase_defused+0x88> 916c: ebffff04 bl 8d84 <strings_not_equal>

通过gdb查看91ac中的文档,文档中存储的是一个字符串austinpower,通过查看另一文档可知输入的路径密码格式是(d%,s%),因此在前面的六个关卡中,只有实验四是输入一个数字9,因此密码为9 austinpower,从而进入了隐藏关卡。
隐藏关的关键代码如下:

复制代码
1
2
3
4
5
6
7
8
9
8bb0: eb0000f5 bl 8f8c <read_line> 读入一行 8bb4: e1a03000 mov r3, r0 8bb8: e50b300c str r3, [fp, #-12] 8bbc: e51b300c ldr r3, [fp, #-12] 8bc0: e1a00003 mov r0, r3 8bc4: e3a01000 mov r1, #0 8bc8: e3a0200a mov r2, #10 8bcc: eb000d0b bl c000 <strtol> 把数字转化为长整型 8bd0: e1a03000 mov r3, r0
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
在读入数字之后,接着调用了另一个文档中的数字: 8bec: e59f0028 ldr r0,[pc,#40];8c1c<secret_phase+0x78> 8bf0: e51b1008 ldr r1, [fp, #-8] 8bf4: ebffffc1 bl 8b00 <fun7> 可见从文档中读入的数字和输入的数字一起作为参数进入了函数fun7。接着向下看secret_phase中的代码。 8bfc: e3530007 cmp r3, #7 因此输出的值应为7,接着就进行fun函数,主要部分如下: 8b18: e3530000 cmp r3, #0 r3为0时,输出0 8b1c: 1a000001 bne 8b28 <fun7+0x28> 8b20: e3e03000 mvn r3, #0 8b24: ea00001b b 8b98 <fun7+0x98> 跳出函数 对于一些寄存器的变换不再赘述。 8b34: e1520003 cmp r2, r3 8b38: da000007 ble 8b5c <fun7+0x5c> 8b3c: e51b3008 ldr r3, [fp, #-8] 此时r2>r3 8b40: e5933004 ldr r3, [r3, #4] r3取其地址加4的地址所存数字 8b44: e1a00003 mov r0, r3 8b48: e51b100c ldr r1, [fp, #-12] 8b4c: ebffffeb bl 8b00 <fun7> fun7函数是一个循环嵌套 8b50: e1a03000 mov r3, r0 8b54: e1a03083 lsl r3, r3, #1 r3=r3*2 8b58: ea00000e b 8b98 <fun7+0x98> 8b68: e1520003 cmp r2, r3 8b6c: aa000008 bge 8b94 <fun7+0x94> 8b70: e51b3008 ldr r3, [fp, #-8] 此时r2<r3 8b74: e5933008 ldr r3, [r3, #8] r3为其地址加8所得地址中存的数字 8b78: e1a00003 mov r0, r3 8b7c: e51b100c ldr r1, [fp, #-12] 8b80: ebffffde bl 8b00 <fun7> 8b84: e1a03000 mov r3, r0 8b88: e1a03083 lsl r3, r3, #1 8b8c: e2833001 add r3, r3, #1 r3=r3*2+1 8b90: ea000000 b 8b98 <fun7+0x98> 8b94: e3a03000 mov r3, #0 8b98: e1a00003 mov r0, 此时可以看出这是一个if-else的递归循环。C语言代码如下: fun7(const int *a, int b) { if (a == NULL) return -1; int ret = 0; if (*a - b > 0) { ret = fun7(*(a + 4), b); ret *= 2 } else if (*a - b == 0) return 0; else { ret = fun7(*(a + 8), b); ret = ret * 2 + 1; } return ret; }

由于最终返回值为7,我们进行逆向递归,7=2*3+1,3=1*2+1,1=0*2+1。所以前三次比较中都是a

七、实验中遇到的问题及解决

1.环境配置过程中我们遇到的主要问题比如安装包与PC的位数不符,无法正确读出bomb的.s文件,在设置IP时因连接其他网络而无法获取地址,运行gdb进行调试时找不到目标文件等,但在我们仔细阅读指导书并且询问助教老师后,都得到了及时的解决。
2.实验三耗费了比较长的时间,关键就是一直在读反汇编的代码,没有去用gdb直接调试,所以总是在猜测哪里会存储什么数据,陷入了瓶颈。后来去机房调试,发现只要找到各个word里面存的数据就很容易知道这个题目答案,问题解决。
3.实验六遇到的问题主要是循环体没搞清楚,r3和r2的重复出现,弄得很混乱。但是在发现是链表结构后,基本上就豁然开朗了,gdb打印出链表内容,估计也就是个排序,按照自己的猜测再来用C语言把汇编翻译出来,整个题目就解决了。
4.隐藏关主要问题有两个,一个是寻找隐藏关打开方式,另一个是弄清楚函数。因为发现每一次成功过一关都会调用defuse函数,所以研究那个函数就搞明白进去的方法了;函数后来是突然想到了第四关的递归,再加上第六关中地址中存放地址的特点,找到了最终需要输入的数据。

最后

以上就是愤怒裙子最近收集整理的关于计算机系统基础(bomb实验报告)的全部内容,更多相关计算机系统基础(bomb实验报告)内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(71)

评论列表共有 0 条评论

立即
投稿
返回
顶部