学生实验报告
实验课程名称:计算机系统基础
实验项目名称:BinaryBomb实验
实验类型: 验证性
指导教师:
实验日期: 2020 年 11 月 29 日
学生姓名 |
|
学号 |
07 |
班级 |
|
专业名称 |
软件工程 |
实验组 其他成员 |
无 |
||
实验地点 |
|
||
实验成绩 (教师签名) |
|
实验目的与要求 1.加深对IA-32函数调用规则和栈结构的具体理解。 2. 了解汇编语言的特点和实际执行过程。特别是,针对高级语言中的分支、循环、嵌套等、结构体、指针、链表等在汇编语言级别如何实现加深理解。 3. 通过逆向工程进行程序执行过程的分析并抽取和破译通过密码。 |
实验原理与内容 n 作为实验目标的二进制炸弹“binary bombs” Linux可执行程序包含了多个阶段(或关卡),在每个阶段程序要求你输入一个特定字符串,如果输入满足程序代码所定义的要求,该阶段的炸弹就被拆除了,否则程序输出“炸弹爆炸BOOM!!! ”的提示并转到下一阶段再次等待对应的输入 ——实验的目标是设法得出解除尽可能多阶段的字符串。 n 为完成二进制炸弹拆除任务,需要通过反汇编和理解可执行炸弹文件程序或使用gdb调试器跟踪每一阶段的机器代码,从中理解关键机器指令的行为和作用,进而设法推断拆除炸弹所需的目标字符串。
通过逆向工程分析,拆解二进制炸弹程序 包含了7个阶段以及1个隐藏阶段,分别集中考察对以下二进制程序表示各方面的理解和掌握: n 阶段0:字符串比较 n 阶段1:浮点表示 n 阶段2:循环 n 阶段3:条件/分支 n 阶段4:递归调用和栈 n 阶段5:指针 n 阶段6:链表/指针/结构 n 隐藏阶段:只有在阶段4的拆解字符串后再附加一特定字符串后才会出现(作为最后一个阶段)
|
实验设备与软件环境 1.硬件环境:笔记本电脑 2.软件环境:Debian10 32位 3.虚拟机 |
实验过程与结果 我只做了前四道,结果:
Phase_0: 08049455 <phase_0>: 8049455: 55 push %ebp 8049456: 89 e5 mov %esp,%ebp 8049458: 83 ec 08 sub $0x8,%esp 804945b:83 ec 08 sub $0x8,%esp 804945e: 68 ec a1 04 08 push $0x804a1ec #存放预定字符串的地址 8049463: ff 75 08 pushl 0x8(%ebp) 8049466: e8 44 07 00 00 call 8049baf <strings_not_equal> 804946b:83 c4 10 add $0x10,%esp 804946e: 85 c0 test %eax,%eax 8049470: 74 0c je 804947e <phase_0+0x29> 8049472: e8 a0 09 00 00 call 8049e17 <explode_bomb> 8049477: b8 00 00 00 00 mov $0x0,%eax 804947c: eb 05 jmp 8049483 <phase_0+0x2e> 804947e: b8 01 00 00 00 mov $0x1,%eax 8049483: c9 leave 8049484: c3 ret
Phase_0的答案就是Disks are constructed from platters. Phase_1: 08049485 <phase_1>: 8049485: 55 push %ebp 8049486: 89 e5 mov %esp,%ebp 8049488: 83 ec 18 sub $0x18,%esp 804948b:c7 45 f4 50 cd 4f 35 movl $0x354fcd50,-0xc(%ebp) 8049492: db 45 f4 fildl -0xc(%ebp) 8049495: d9 5d f0 fstps -0x10(%ebp) 8049498: 8d 45 e8 lea -0x18(%ebp),%eax 804949b:50 push %eax 804949c: 8d 45 ec lea -0x14(%ebp),%eax 804949f: 50 push %eax 80494a0: 68 11 a2 04 08 push $0x804a211 #明码地址,由此行得知需要输入两个“%d %d”数 80494a5: ff 75 08 pushl 0x8(%ebp) 80494a8: e8 23 fc ff ff call 80490d0 <__isoc99_sscanf@plt> 80494ad: 83 c4 10 add $0x10,%esp 80494b0:83 f8 02 cmp $0x2,%eax #判断输入的是不是两个数,是的话跳到8049e17,不是的话bomb 80494b3:74 0c je 80494c1 <phase_1+0x3c> 80494b5:e8 5d 09 00 00 call 8049e17 <explode_bomb> 80494ba: b8 00 00 00 00 mov $0x0,%eax 80494bf: eb 34 jmp 80494f5 <phase_1+0x70> 80494c1: 8d 45 f0 lea -0x10(%ebp),%eax 80494c4: 83 c0 02 add $0x2,%eax #%eax+2 80494c7: 0f b7 00 movzwl (%eax),%eax 80494ca: 0f bf d0 movswl %ax,%edx 80494cd: 8b 45 ec mov -0x14(%ebp),%eax 80494d0:39 c2 cmp %eax,%edx #输入的第一个数和%edx的值是否相等,不相等的话,跳到80494e4->bomb 80494d2:75 10 jne 80494e4 <phase_1+0x5f> 80494d4:8d 45 f0 lea -0x10(%ebp),%eax 80494d7:0f b7 00 movzwl (%eax),%eax 80494da: 0f bf d0 movswl %ax,%edx 80494dd:8b 45 e8 mov -0x18(%ebp),%eax 80494e0: 39 c2 cmp %eax,%edx #输入的第二个与%edx的值是否相等,相等的话,跳到80494f0,正常结束,不相等bomb 80494e2: 74 0c je 80494f0 <phase_1+0x6b> 80494e4: e8 2e 09 00 00 call 8049e17 <explode_bomb> 80494e9: b8 00 00 00 00 mov $0x0,%eax 80494ee: eb 05 jmp 80494f5 <phase_1+0x70> 80494f0: b8 01 00 00 00 mov $0x1,%eax 80494f5: c9 leave 80494f6: c3 ret
Phase_1的答案,第一个数是20053 第二个数是16181 Phase_2 080494f7 <phase_2>: 80494f7: 55 push %ebp 80494f8: 89 e5 mov %esp,%ebp 80494fa: 83 ec 28 sub $0x28,%esp 80494fd: 83 ec 04 sub $0x4,%esp 8049500: 6a 07 push $0x7 #输入7个数字 8049502: 8d 45 d8 lea -0x28(%ebp),%eax 8049505: 50 push %eax 8049506: ff 75 08 pushl 0x8(%ebp) 8049509: e8 e7 05 00 00 call 8049af5 <read_n_numbers> #读取7个数字 804950e: 83 c4 10 add $0x10,%esp 8049511: 85 c0 test %eax,%eax 8049513: 75 07 jne 804951c <phase_2+0x25> 8049515: b8 00 00 00 00 mov $0x0,%eax 804951a: eb 65 jmp 8049581 <phase_2+0x8a> 804951c: 8b 45 d8 mov -0x28(%ebp),%eax 804951f: 83 f8 1c cmp $0x1c,%eax #第一个数必须为28,如果不是28bomb 8049522: 75 08 jne 804952c <phase_2+0x35> 8049524: 8b 45 dc mov -0x24(%ebp),%eax 8049527: 83 f8 39 cmp $0x39,%eax #第二个数必须为57,不等就bomb,相等跳到8049538执行 804952a: 74 0c je 8049538 <phase_2+0x41> 804952c: e8 e6 08 00 00 call 8049e17 <explode_bomb> 8049531: b8 00 00 00 00 mov $0x0,%eax 8049536: eb 49 jmp 8049581 <phase_2+0x8a> 8049538: c7 45 f4 02 00 00 00 movl $0x2,-0xc(%ebp) #初始i=2,跳到判断条件 804953f: eb 35 jmp 8049576 <phase_2+0x7f> //循环体 8049541: 8b 45 f4 mov -0xc(%ebp),%eax 8049544: 8b 44 85 d8 mov -0x28(%ebp,%eax,4),%eax 8049548: 8b 55 f4 mov -0xc(%ebp),%edx 804954b:83 ea 02 sub $0x2,%edx #第i-2个数,num[i-2] 804954e: 8b 54 95 d8 mov -0x28(%ebp,%edx,4),%edx 8049552: 89 d1 mov %edx,%ecx 8049554: d1 f9 sar %ecx #第i-2个数除以2 8049556: 8b 55 f4 mov -0xc(%ebp),%edx 8049559: 83 ea 01 sub $0x1,%edx #第i-1个数减1 804955c: 8b 54 95 d8 mov -0x28(%ebp,%edx,4),%edx 8049560: 01 ca add %ecx,%edx #num[i]=(num[i-2]-1)+num[i-1] 8049562: 39 d0 cmp %edx,%eax 8049564: 74 0c je 8049572 <phase_2+0x7b> //跳出循环 8049566: e8 ac 08 00 00 call 8049e17 <explode_bomb> 804956b: b8 00 00 00 00 mov $0x0,%eax 8049570: eb 0f jmp 8049581 <phase_2+0x8a> //循环判断条件 8049572: 83 45 f4 01 addl $0x1,-0xc(%ebp) #i++ 8049576: 83 7d f4 06 cmpl $0x6,-0xc(%ebp) #i<=6 804957a: 7e c5 jle 8049541 <phase_2+0x4a> 804957c: b8 01 00 00 00 mov $0x1,%eax 8049581: c9 leave 8049582: c3 ret
Phase_2的答案前两个规定为28 57后面的可以调试出来,或者有规律的,规律就是第三个数等于第一个数除以2加上第二个数,第四个数就等于第二个数减1除以2加第三个数,以此类推,得到的答案就是 28 57 71 99 134 183 250 Phase3 08049583 <phase_3>: 8049583: 55 push %ebp 8049584: 89 e5 mov %esp,%ebp 8049586: 83 ec 18 sub $0x18,%esp 8049589: 8d 45 e8 lea -0x18(%ebp),%eax 804958c: 50 push %eax 804958d:8d 45 ec lea -0x14(%ebp),%eax 8049590: 50 push %eax 8049591: 68 11 a2 04 08 push $0x804a211 #此行说明输入两个 %d % d的数 8049596: ff 75 08 pushl 0x8(%ebp) 8049599: e8 32 fb ff ff call 80490d0 <__isoc99_sscanf@plt> 804959e: 83 c4 10 add $0x10,%esp 80495a1: 89 45 f0 mov %eax,-0x10(%ebp) 80495a4: 83 7d f0 01 cmpl $0x1,-0x10(%ebp) #输入的数要大于1就跳转,否则bomb 80495a8: 7f 0f jg 80495b9 <phase_3+0x36> 80495aa: e8 68 08 00 00 call 8049e17 <explode_bomb> 80495af: b8 00 00 00 00 mov $0x0,%eax 80495b4:e9 8a 00 00 00 jmp 8049643 <phase_3+0xc0> 80495b9:c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp) 80495c0: 8b 45 ec mov -0x14(%ebp),%eax 80495c3: 83 e8 1d sub $0x1d,%eax #%eax-29 80495c6: 83 f8 08 cmp $0x8,%eax #%eax-29<8,无符号比较减去29要小于8,即要小于37 80495c9: 77 53 ja 804961e <phase_3+0x9b> 80495cb: 8b 04 85 18 a2 04 08 mov 0x804a218(,%eax,4),%eax #0x804a218,此地址查看第一个数输入跳到哪里,决定第二个数是多少 80495d2:ff e0 jmp *%eax 80495d4:81 45 f4 14 02 00 00 addl $0x214,-0xc(%ebp) #第一个数为29时,第二个数为532 80495db:81 45 f4 d5 02 00 00 addl $0x2d5,-0xc(%ebp) #第一个数为30时,第二个数为725 80495e2: 81 6d f4 14 02 00 00 subl $0x214,-0xc(%ebp) #第一个数为31时,第二个数为532 80495e9: 81 45 f4 14 02 00 00 addl $0x214,-0xc(%ebp) #第一个数为32时,第二个数为532 80495f0: 81 45 f4 d5 02 00 00 addl $0x2d5,-0xc(%ebp) #第一个数为33时,第二个数为725 80495f7: 81 6d f4 14 02 00 00 subl $0x214,-0xc(%ebp) #第一个数为34时,第二个数为532 80495fe: 81 45 f4 d5 02 00 00 addl $0x2d5,-0xc(%ebp) #第一个数为35时,第二个数为725 8049605: 81 6d f4 d5 02 00 00 subl $0x2d5,-0xc(%ebp) #第一个数为36时,第二个数为725 804960c: 81 45 f4 14 02 00 00 addl $0x214,-0xc(%ebp) #第一个数为37时,第二个数为532 8049613: 90 nop 8049614: 8b 45 ec mov -0x14(%ebp),%eax 8049617: 83 f8 23 cmp $0x23,%eax #第一个数要小于35,大于就bomb 804961a: 7f 16 jg 8049632 <phase_3+0xaf> 804961c: eb 0c jmp 804962a <phase_3+0xa7> 804961e: e8 f4 07 00 00 call 8049e17 <explode_bomb> 8049623: b8 00 00 00 00 mov $0x0,%eax 8049628: eb 19 jmp 8049643 <phase_3+0xc0> 804962a: 8b 45 e8 mov -0x18(%ebp),%eax 804962d:39 45 f4 cmp %eax,-0xc(%ebp) #比较输入的第二个数是否与-0xc(%ebp)里的值相等,相等结束,不等bomb 8049630: 74 0c je 804963e <phase_3+0xbb> 8049632: e8 e0 07 00 00 call 8049e17 <explode_bomb> 8049637: b8 00 00 00 00 mov $0x0,%eax 804963c: eb 05 jmp 8049643 <phase_3+0xc0> 804963e: b8 01 00 00 00 mov $0x1,%eax 8049643: c9 l eave 8049644: c3 ret
我输入的第一个数是33,由图知道下一个就转到0x080495d4,得出第二个数是725,这题的答案不唯一 |
操作异常问题与解决方案 对于linux操作命令的不熟悉,不懂得如何调试,对于反汇编代码的指令不熟悉,经过百度和csdn已经可以解决 |
实验总结 经过本次实验,我对汇编代码有了进一步的了解,加深了我对计算机系统基础的认识,让我受益良多 |