深入理解计算机系统LAB2

上传人:仙*** 文档编号:103413984 上传时间:2022-06-08 格式:DOC 页数:12 大小:157.50KB
返回 下载 相关 举报
深入理解计算机系统LAB2_第1页
第1页 / 共12页
深入理解计算机系统LAB2_第2页
第2页 / 共12页
深入理解计算机系统LAB2_第3页
第3页 / 共12页
点击查看更多>>
资源描述
. . LAB1实验报告实验目的:使用课程知识拆除一个“Binary Bombs”来增强对程序的机器级表示、汇编语言、调试器和逆向工程等理解。实验简介:一个“Binary Bombs”(二进制炸弹,简称炸弹)是一个Linux可执行C程序,包含phase1phase6共6个阶段。炸弹运行各阶段要求输入一个字符串,若输入符合程序预期,该阶段炸弹被“拆除”,否则“爆炸”。实验目标是你需要拆除尽可能多的炸弹。运行结果:通关密码储存在001431.txt文件中。成功运行结果截图:实验中的六组密码:PHASE1:字符串比较本关比较简单,根据课件中的提示用GDB将最先压栈的那个字符串常量打印出来,然后将其作为密码输入,比较成功后即通关。08048ab2 : 8048ab2:83 ec 14 sub $0x14,%esp 8048ab5:68 04 9f 04 08 push $0x8049f04 8048aba:ff 74 24 1c pushl 0x1c(%esp) 8048abe:e8 4d 04 00 00 call 8048f10 将地址0x8049f04中的值打印出来:即“The future will be better tomorrow.”PHASE2:循环在查看汇编语言的时候,会看到有调用一个read_six_number函数,猜测此题是让输入六个数字。08048ad3 : 8048ad3:56 push %esi 8048ad4:53 push %ebx 8048ad5:83 ec 2c sub $0x2c,%esp 8048ad8:8d 44 24 10 lea 0x10(%esp),%eax 8048adc:50 push %eax 8048add:ff 74 24 3c pushl 0x3c(%esp) 8048ae1:e8 46 05 00 00 call 804902c 8048ae6:83 c4 10 add $0x10,%esp 8048ae9:83 7c 24 08 01 cmpl $0x1,0x8(%esp)-判定是否为1 8048aee:74 1e je 8048b0e 8048af0:e8 12 05 00 00 call 8049007 8048af5:eb 17 jmp 8048b0e 8048af7:8b 03 mov (%ebx),%eax 8048af9:01 c0 add %eax,%eax-进行自加,扩大两倍 8048afb:39 43 04 cmp %eax,0x4(%ebx) 8048afe:74 05 je 8048b05 8048b00:e8 02 05 00 00 call 8049007 8048b05:83 c3 04 add $0x4,%ebx 8048b08:39 f3 cmp %esi,%ebx 8048b0a:75 eb jne 8048af7 8048b0c:eb 0a jmp 8048b18 8048b0e:8d 5c 24 08 lea 0x8(%esp),%ebx 8048b12:8d 74 24 1c lea 0x1c(%esp),%esi 8048b16:eb df jmp 8048af7 循环 8048b18:83 c4 24 add $0x24,%esp 8048b1b:5b pop %ebx 8048b1c:5e pop %esi 8048b1d:c3 ret 有汇编语言进行分析,不难看出,这道题目要求输入六个数字,并且要求第一个数字为1,之后跳入一个循环,将第一个数字加倍和已有的数字进行比较,所以不难看出所需要的密码是1,2,4,8,16,32这六个数字。PHASE3:条件分支语句这道题的汇编语句明显变长了,但是由于PPT中已经提示这是条件分支语句,以此为切入点,此题也不难分析。08048b1e : 8048b1e:83 ec 1c sub $0x1c,%esp 8048b21:8d 44 24 08 lea 0x8(%esp),%eax 8048b25:50 push %eax 8048b26:8d 44 24 10 lea 0x10(%esp),%eax 8048b2a:50 push %eax 8048b2b:68 0f a1 04 08 push $0x804a10f打印该值为”%d%d” 8048b30:ff 74 24 2c pushl 0x2c(%esp) 8048b34:e8 87 fc ff ff call 80487c0 上面这一段调用了一个函数sscanf(),查询可知这个函数的原型为:int sscanf(const char *buffer,const char *format,argument .);即读取输入的字符串,并以指定的格式赋给参数。其中一个参数在地址0x804a10f中。可知需要输入两个整数。 8048b39:83 c4 10 add $0x10,%esp 8048b3c:83 f8 01 cmp $0x1,%eax 8048b3f:7f 05 jg 8048b46 8048b41:e8 c1 04 00 00 call 8049007 8048b46:83 7c 24 0c 07 cmpl $0x7,0xc(%esp)-不大于7 8048b4b:77 66 ja 8048bb3 -否则引爆有这些可以得知第一个参数的信息,可以看出这是一个不大于7的数,因此缩小了选择,不难猜出可能是分支条件。 8048b4d:8b 44 24 0c mov 0xc(%esp),%eax 8048b51:ff 24 85 80 9f 04 08 jmp *0x8049f80(,%eax,4) 8048b58:b8 0c 03 00 00 mov $0x30c,%eax 8048b5d:eb 05 jmp 8048b64 8048b5f:b8 00 00 00 00 mov $0x0,%eax 8048b64:2d d5 03 00 00 sub $0x3d5,%eax 8048b69:eb 05 jmp 8048b70 8048b6b:b8 00 00 00 00 mov $0x0,%eax 8048b70:05 35 01 00 00 add $0x135,%eax 8048b75:eb 05 jmp 8048b7c 8048b77:b8 00 00 00 00 mov $0x0,%eax 8048b7c:2d e9 02 00 00 sub $0x2e9,%eax 8048b81:eb 05 jmp 8048b88 8048b83:b8 00 00 00 00 mov $0x0,%eax 8048b88:05 e9 02 00 00 add $0x2e9,%eax 8048b8d:eb 05 jmp 8048b94 8048b8f:b8 00 00 00 00 mov $0x0,%eax 8048b94:2d e9 02 00 00 sub $0x2e9,%eax 8048b99:eb 05 jmp 8048ba0 8048b9b:b8 00 00 00 00 mov $0x0,%eax 8048ba0:05 e9 02 00 00 add $0x2e9,%eax 8048ba5:eb 05 jmp 8048bac 8048ba7:b8 00 00 00 00 mov $0x0,%eax 8048bac:2d e9 02 00 00 sub $0x2e9,%eax 8048bb1:eb 0a jmp 8048bbd 8048bb3:e8 4f 04 00 00 call 8049007 上面是各种分支情况,看起来比较复杂,先放一放 8048bb8:b8 00 00 00 00 mov $0x0,%eax 8048bbd:83 7c 24 0c 05 cmpl $0x5,0xc(%esp)-参数不能大于5 8048bc2:7f 06 jg 8048bca 8048bc4:3b 44 24 08 cmp 0x8(%esp),%eax 8048bc8:74 05 je 8048bcf 8048bca:e8 38 04 00 00 call 8049007 8048bcf:83 c4 1c add $0x1c,%esp 8048bd2:c3 ret 可以看出参数不能大于五,因此这道题可能有多组解,不过结合分支语句,不难看出当第一个参数比较大的时候,计算量比较小,所以我选择了第一个参数为5,代入进行逐步计算,可以得到此时的值为-745。PHASE4:递归调用栈这一步是递归调用栈,所以有两部分汇编代码,其中一个是被调用的函数,简单地看一下代码,应该是一个递归的函数。先分析主程序部分的代码,其中也有sscanf函数:08048c2c : 8048c2c:83 ec 1c sub $0x1c,%esp 8048c2f:8d 44 24 08 lea 0x8(%esp),%eax 8048c33:50 push %eax 8048c34:8d 44 24 10 lea 0x10(%esp),%eax 8048c38:50 push %eax 8048c39:68 0f a1 04 08 push $0x804a10f-输出为”%d%d” 8048c3e:ff 74 24 2c pushl 0x2c(%esp) 8048c42:e8 79 fb ff ff call 80487c0 8048c47:83 c4 10 add $0x10,%esp 8048c4a:83 f8 02 cmp $0x2,%eax-返回值为2从上面这部分看出我们需要输入两个参数,且两个都是整数型的。 8048c4d:75 07 jne 8048c56 8048c4f:83 7c 24 0c 0e cmpl $0xe,0xc(%esp)第一个参数不大于14 8048c54:76 05 jbe 8048c5b 8048c56:e8 ac 03 00 00 call 8049007 8048c5b:83 ec 04 sub $0x4,%esp 8048c5e:6a 0e push $0xe 8048c60:6a 00 push $0x0 8048c62:ff 74 24 18 pushl 0x18(%esp) 8048c66:e8 68 ff ff ff call 8048bd3 8048c6b:83 c4 10 add $0x10,%esp 8048c6e:83 f8 25 cmp $0x25,%eax 8048c71:75 07 jne 8048c7a 8048c73:83 7c 24 08 25 cmpl $0x25,0x8(%esp)-第二个参数为37 8048c78:74 05 je 8048c7f 8048c7a:e8 88 03 00 00 call 8049007 8048c7f:83 c4 1c add $0x1c,%esp 8048c82:c3 ret 从上面这些可以看出,虽然输入了两个参数,但是只有第一个参数被传递给了func4另外一个没有变化,而且可以知道等于37。同时,第一个参数还不大于14。这样可能的情况就少了。考虑到func4本来就是一个递归函数,即使反汇编出来,也需要一步一步代入,不如直接进行尝试,枚举法得到第一个参数是10。PHASE5:指针这一道题的提示比较模糊,毕竟汇编程序里到处都有指针。08048c83 : 8048c83:83 ec 1c sub $0x1c,%esp 8048c86:8d 44 24 08 lea 0x8(%esp),%eax 8048c8a:50 push %eax 8048c8b:8d 44 24 10 lea 0x10(%esp),%eax 8048c8f:50 push %eax 8048c90:68 0f a1 04 08 push $0x804a10f-地址参数 8048c95:ff 74 24 2c pushl 0x2c(%esp) 8048c99:e8 22 fb ff ff call 80487c0 同样函数sscanf,其中有两个参数,有一个是地址0x804a10f,先记下等会可能会用到。 8048c9e:83 c4 10 add $0x10,%esp 8048ca1:83 f8 01 cmp $0x1,%eax 8048ca4:7f 05 jg 8048cab 8048ca6:e8 5c 03 00 00 call 8049007 8048cab:8b 44 24 0c mov 0xc(%esp),%eax 8048caf:83 e0 0f and $0xf,%eax-取低四位 8048cb2:89 44 24 0c mov %eax,0xc(%esp) 8048cb6:83 f8 0f cmp $0xf,%eax-不能等于15 8048cb9:74 2e je 8048ce9 8048cbb:b9 00 00 00 00 mov $0x0,%ecx 8048cc0:ba 00 00 00 00 mov $0x0,%edx 8048cc5:83 c2 01 add $0x1,%edx-计数用的 8048cc8:8b 04 85 c0 9f 04 08 mov 0x8049fc0(,%eax,4),%eax寻址 8048ccf:01 c1 add %eax,%ecx-求和用的 8048cd1:83 f8 0f cmp $0xf,%eax 8048cd4:75 ef jne 8048cc5 8048cd6:c7 44 24 0c 0f 00 00 movl $0xf,0xc(%esp) 8048cdd:00 8048cde:83 fa 0f cmp $0xf,%edx-到15跳出 8048ce1:75 06 jne 8048ce9 8048ce3:3b 4c 24 08 cmp 0x8(%esp),%ecx 8048ce7:74 05 je 8048cee 8048ce9:e8 19 03 00 00 call 8049007 8048cee:83 c4 1c add $0x1c,%esp 8048cf1:c3 ret 个别地方不是太清楚,不过已经基本可以猜出来程序的目的,设置一个计数器进行计数,每次按照变量的偏移寻址,找到之后变成新的变量,之后按照新的变量进行寻址,如此循环。没找到一个变量,求和。当变量刚好等于15的时候跳出,不过跳出的时候还需要看一下计数器有没有达到15,也就是说要循环15次才可以跳出,这为我们猜测其值提供了方便。所以我们需要做的是找到初始的变量和以这个变量开始循环所得到的总和。根据GDB输出的情况,我做了一个表格:01234567102147812151189101112131415041133965其中首行是相对于首地址便宜的字节,下面是其对应的常数。当变量为15的时候跳出,那么我们可以从15向后推:1561421100849131173125不难看出15个循环之后是5,因此第一个参数是5。之后把这十五个参数的值相加。最开始的时候,我犯了个错误就是直接把这十五个数相加,后来不通过,经过分析发现是15个偏移量对应的地址中的常数,所以为115。PHASE6:链表/指针/结构这一关看提示就觉得很难,首先对这三个词进行联想,“链表+结构”这个比较好联想,应该使用结构体定义了一个链表结构。至于“指针”,这个我猜测应该是和上一关所说的意思可能有相似之处,应给就是不停地变换地址比较之类的。这一关的汇编语言比较长,其中有一大部分都是对结构体的定义,所以这里只摘录要点进行解释说明。08048cf2 : 8048cf2:56 push %esi 8048cf3:53 push %ebx 8048cf4:83 ec 3c sub $0x3c,%esp 8048cf7:8d 44 24 20 lea 0x20(%esp),%eax 8048cfb:50 push %eax 8048cfc:ff 74 24 4c pushl 0x4c(%esp) 8048d00:e8 27 03 00 00 call 804902c 又是这个参数,这道题还是让你输入六个数 8048d05:83 c4 10 add $0x10,%esp 8048d08:be 00 00 00 00 mov $0x0,%esi 8048d0d:8b 44 b4 18 mov 0x18(%esp,%esi,4),%eax 8048d11:83 e8 01 sub $0x1,%eax 8048d14:83 f8 05 cmp $0x5,%eax 8048d17:76 05 jbe 8048d1e 8048d19:e8 e9 02 00 00 call 8049007 8048d1e:83 c6 01 add $0x1,%esi 8048d21:83 fe 06 cmp $0x6,%esi 8048d24:74 1b je 8048d41 8048d26:89 f3 mov %esi,%ebx 8048d28:8b 44 9c 18 mov 0x18(%esp,%ebx,4),%eax 8048d2c:39 44 b4 14 cmp %eax,0x14(%esp,%esi,4) 8048d30:75 05 jne 8048d37 8048d32:e8 d0 02 00 00 call 8049007 8048d37:83 c3 01 add $0x1,%ebx 8048d3a:83 fb 05 cmp $0x5,%ebx 8048d3d:7e e9 jle 8048d28 8048d3f:eb cc jmp 8048d0d 8048d41:8d 44 24 18 lea 0x18(%esp),%eax到这里为止,是一个循环,是对输入的六个数字进行判定,从这里可以看出,要0到6这几个数字符合要求,是这六个数字的一种组合。 8048d45:8d 5c 24 30 lea 0x30(%esp),%ebx 8048d49:b9 07 00 00 00 mov $0x7,%ecx 8048d4e:89 ca mov %ecx,%edx 8048d50:2b 10 sub (%eax),%edx 8048d52:89 10 mov %edx,(%eax) 8048d54:83 c0 04 add $0x4,%eax 8048d57:39 d8 cmp %ebx,%eax 8048d59:75 f3 jne 8048d4e 这一段很重要,第一次读的时候不明所以,不知道是在做什么,之后忽视去看后面的,发现结果怎么输入都不对。回过头来看,发现问题在这里,假如输入的是x,这里是将其变为7-x。即这个循环是做了一个置换,将我们所输入的数字置换了。 8048d75:74 17 je 8048d8e 8048d77:89 de mov %ebx,%esi 8048d79:8b 4c 9c 18 mov 0x18(%esp,%ebx,4),%ecx 8048d7d:b8 01 00 00 00 mov $0x1,%eax 8048d82:ba 3c b2 04 08 mov $0x804b23c,%edx 8048d87:83 f9 01 cmp $0x1,%ecx 8048d8a:7f d6 jg 8048d62 这是结构体中的一段,其中有地址常量,这个应该是结构体链表的首地址,不防输出进行查看:可以看出,这是由学号生成的一个有着六个元素的链表,元素分别是:12345670662491191554909 8048daf:be 05 00 00 00 mov $0x5,%esi 8048db4:8b 43 08 mov 0x8(%ebx),%eax 8048db7:8b 00 mov (%eax),%eax 8048db9:39 03 cmp %eax,(%ebx) 8048dbb:7d 05 jge 8048dc2 8048dbd:e8 45 02 00 00 call 8049007 8048dc2:8b 5b 08 mov 0x8(%ebx),%ebx 8048dc5:83 ee 01 sub $0x1,%esi 8048dc8:75 ea jne 8048db4 8048dca:83 c4 34 add $0x34,%esp 8048dcd:5b pop %ebx 8048dce:5e pop %esi 8048dcf:c3 ret 这一段又是一个循环,是对链表的一个排序,到这里就分析的差不多了,也就是说我们输入的是链表的次序,不过这个次序要被7减。比较大小,有:1 6 2 4 3 5隐藏关卡:这个如果没有提示应该是看不出来了。不过当时在分析PHASE6的时候看到下面有一个func7。但是PHASE6并没有用到,觉得很奇怪,看到提示后,又向后翻了翻,发现了func7是被secret_phase调用的。但是程序运行从开始到完毕都没有进入这里。我检索了一下secret_phase关键字,找到了调用它的函数。08049160 : 8049160:83 3d e8 b4 04 08 06 cmpl $0x6,0x804b4e8 8049167:75 73 jne 80491dc 8049169:83 ec 78 sub $0x78,%esp 804916c:8d 44 24 1c lea 0x1c(%esp),%eax 8049170:50 push %eax 8049171:8d 44 24 18 lea 0x18(%esp),%eax 8049175:50 push %eax 8049176:8d 44 24 20 lea 0x20(%esp),%eax 804917a:50 push %eax 804917b:68 69 a1 04 08 push $0x804a169-”%d %d %s” 8049180:68 f0 b5 04 08 push $0x804b5f0-”10 37” 8049185:e8 36 f6 ff ff call 80487c0 804918a:83 c4 20 add $0x20,%esp 804918d:83 f8 03 cmp $0x3,%eax-有三个参数 8049190:75 3a jne 80491cc 从这里可以看出只有通过了第六关才能到达隐藏关口,而且隐藏的关口需要收入三个参数,从提示中可以知道这三个参数是从第四行读取的,所以需要再在第四行添加一个字符串,至于这个字符串是什么,需要打印相应的地址查看。 8049192:83 ec 08 sub $0x8,%esp 8049195:68 72 a1 04 08 push $0x804a172 804919a:8d 44 24 1c lea 0x1c(%esp),%eax 804919e:50 push %eax 804919f:e8 6c fd ff ff call 8048f10 strings_not_equal 80491a4:83 c4 10 add $0x10,%esp 80491a7:85 c0 test %eax,%eax 80491a9:75 21 jne 80491cc 80491ab:83 ec 0c sub $0xc,%esp 80491ae:68 38 a0 04 08 push $0x804a038 80491b3:e8 a8 f5 ff ff call 8048760 80491b8:c7 04 24 60 a0 04 08 movl $0x804a060,(%esp) 80491bf:e8 9c f5 ff ff call 8048760 80491c4:e8 58 fc ff ff call 8048e21 80491c9:83 c4 10 add $0x10,%esp 80491cc:83 ec 0c sub $0xc,%esp 80491cf:68 98 a0 04 08 push $0x804a098 80491d4:e8 87 f5 ff ff call 8048760 80491d9:83 c4 7c add $0x7c,%esp 80491dc:f3 c3 repz ret 上面这些是判定字符是否相等,之后输入一些信息,并且进入函数func7。打印相关地址:可知,需要输入字符串是“DrEvil”。之后分析方程7:08048dd0 : 8048dd0:53 push %ebx 8048dd1:83 ec 08 sub $0x8,%esp 8048dd4:8b 54 24 10 mov 0x10(%esp),%edx 8048dd8:8b 4c 24 14 mov 0x14(%esp),%ecx 8048ddc:85 d2 test %edx,%edx 8048dde:74 37 je 8048e17 8048de0:8b 1a mov (%edx),%ebx 8048de2:39 cb cmp %ecx,%ebx 8048de4:7e 13 jle 8048df9 8048de6:83 ec 08 sub $0x8,%esp 8048de9:51 push %ecx 8048dea:ff 72 04 pushl 0x4(%edx) 8048ded:e8 de ff ff ff call 8048dd0 8048df2:83 c4 10 add $0x10,%esp 8048df5:01 c0 add %eax,%eax 8048df7:eb 23 jmp 8048e1c 8048df9:b8 00 00 00 00 mov $0x0,%eax 8048dfe:39 cb cmp %ecx,%ebx 8048e00:74 1a je 8048e1c 8048e02:83 ec 08 sub $0x8,%esp 8048e05:51 push %ecx 8048e06:ff 72 08 pushl 0x8(%edx) 8048e09:e8 c2 ff ff ff call 8048dd0 8048e0e:83 c4 10 add $0x10,%esp 8048e11:8d 44 00 01 lea 0x1(%eax,%eax,1),%eax 8048e15:eb 05 jmp 8048e1c 8048e17:b8 ff ff ff ff mov $0xffffffff,%eax 8048e1c:83 c4 08 add $0x8,%esp 8048e1f:5b pop %ebx 8048e20:c3 ret 由之前的参数可以看出来返回值是2。分析了一下,有参考了部分资料得到了函数:int fun7(constint*a,int b)if(a =NULL)return-1;int ret =0;if(*a - b 0) ret = fun7(*(a +4), b); ret *=2;elseif(*a - b =0)return0;else ret = fun7(*(a +8), b); ret = ret *2+1;return ret;之后进行分析,当返回值为2的时候,方程的输入值为20。12 / 12
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 管理文书 > 施工组织


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!