LAB1实验报告实验目的:使用课程知识拆除一个“Binary Bombs”来增强对程序的机器级表示、汇编语言、调试器和逆向工程等理解。
实验简介:一个“Binary Bombs”(二进制炸弹,简称炸弹)是一个Linux可执行C程序,包含phase1~phase6共6个阶段。
炸弹运行各阶段要求输入一个字符串,若输入符合程序预期,该阶段炸弹被“拆除”,否则“爆炸”。
实验目标是你需要拆除尽可能多的炸弹。
运行结果:通关密码储存在0014301-151420131.txt文件中。
成功运行结果截图:实验中的六组密码:PHASE1:字符串比较本关比较简单,根据课件中的提示用GDB将最先压栈的那个字符串常量打印出来,然后将其作为密码输入,比较成功后即通关。
08048ab2 <phase_1>:8048ab2: 83 ec 14 sub $0x14,%esp8048ab5: 68 04 9f 04 08 push $0x8049f048048aba: ff 74 24 1c pushl 0x1c(%esp)8048abe: e8 4d 04 00 00 call 8048f10 <strings_not_equal> 将地址0x8049f04中的值打印出来:即“The future will be better tomorrow.”PHASE2:循环在查看汇编语言的时候,会看到有调用一个read_six_number函数,猜测此题是让输入六个数字。
08048ad3 <phase_2>:8048ad3: 56 push %esi8048ad4: 53 push %ebx8048ad5: 83 ec 2c sub $0x2c,%esp8048ad8: 8d 44 24 10 lea 0x10(%esp),%eax8048adc: 50 push %eax8048add: ff 74 24 3c pushl 0x3c(%esp)8048ae1: e8 46 05 00 00 call 804902c <read_six_numbers>8048ae6: 83 c4 10 add $0x10,%esp8048ae9: 83 7c 24 08 01 cmpl $0x1,0x8(%esp)------→判定是否为1 8048aee: 74 1e je 8048b0e <phase_2+0x3b>8048af0: e8 12 05 00 00 call 8049007 <explode_bomb>8048af5: eb 17 jmp 8048b0e <phase_2+0x3b>8048af7: 8b 03 mov (%ebx),%eax8048af9: 01 c0 add %eax,%eax----→进行自加,扩大两倍 8048afb: 39 43 04 cmp %eax,0x4(%ebx)8048afe: 74 05 je 8048b05 <phase_2+0x32>8048b00: e8 02 05 00 00 call 8049007 <explode_bomb>8048b05: 83 c3 04 add $0x4,%ebx8048b08: 39 f3 cmp %esi,%ebx8048b0a: 75 eb jne 8048af7 <phase_2+0x24>8048b0c: eb 0a jmp 8048b18 <phase_2+0x45>8048b0e: 8d 5c 24 08 lea 0x8(%esp),%ebx8048b12: 8d 74 24 1c lea 0x1c(%esp),%esi8048b16: eb df jmp 8048af7 <phase_2+0x24>→循环8048b18: 83 c4 24 add $0x24,%esp8048b1b: 5b pop %ebx8048b1c: 5e pop %esi8048b1d: c3 ret有汇编语言进行分析,不难看出,这道题目要求输入六个数字,并且要求第一个数字为1,之后跳入一个循环,将第一个数字加倍和已有的数字进行比较,所以不难看出所需要的密码是1,2,4,8,16,32这六个数字。
PHASE3:条件分支语句这道题的汇编语句明显变长了,但是由于PPT中已经提示这是条件分支语句,以此为切入点,此题也不难分析。
08048b1e <phase_3>:8048b1e: 83 ec 1c sub $0x1c,%esp8048b21: 8d 44 24 08 lea 0x8(%esp),%eax8048b25: 50 push %eax8048b26: 8d 44 24 10 lea 0x10(%esp),%eax8048b2a: 50 push %eax8048b2b: 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 <__isoc99_sscanf@plt> 上面这一段调用了一个函数sscanf(),查询可知这个函数的原型为:int sscanf(const char *buffer,const char *format,[argument ]...);即读取输入的字符串,并以指定的格式赋给参数。
其中一个参数在地址0x804a10f中。
可知需要输入两个整数。
8048b39: 83 c4 10 add $0x10,%esp8048b3c: 83 f8 01 cmp $0x1,%eax8048b3f: 7f 05 jg 8048b46 <phase_3+0x28>8048b41: e8 c1 04 00 00 call 8049007 <explode_bomb>8048b46: 83 7c 24 0c 07 cmpl $0x7,0xc(%esp)---------→不大于78048b4b: 77 66 ja 8048bb3<phase_3+0x95>-→否则引爆有这些可以得知第一个参数的信息,可以看出这是一个不大于7的数,因此缩小了选择,不难猜出可能是分支条件。
8048b4d: 8b 44 24 0c mov 0xc(%esp),%eax8048b51: ff 24 85 80 9f 04 08 jmp *0x8049f80(,%eax,4)8048b58: b8 0c 03 00 00 mov $0x30c,%eax8048b5d: eb 05 jmp 8048b64 <phase_3+0x46>8048b5f: b8 00 00 00 00 mov $0x0,%eax8048b64: 2d d5 03 00 00 sub $0x3d5,%eax8048b69: eb 05 jmp 8048b70 <phase_3+0x52>8048b6b: b8 00 00 00 00 mov $0x0,%eax8048b70: 05 35 01 00 00 add $0x135,%eax8048b75: eb 05 jmp 8048b7c <phase_3+0x5e>8048b77: b8 00 00 00 00 mov $0x0,%eax8048b7c: 2d e9 02 00 00 sub $0x2e9,%eax8048b81: eb 05 jmp 8048b88 <phase_3+0x6a>8048b83: b8 00 00 00 00 mov $0x0,%eax8048b88: 05 e9 02 00 00 add $0x2e9,%eax8048b8d: eb 05 jmp 8048b94 <phase_3+0x76>8048b8f: b8 00 00 00 00 mov $0x0,%eax8048b94: 2d e9 02 00 00 sub $0x2e9,%eax8048b99: eb 05 jmp 8048ba0 <phase_3+0x82>8048b9b: b8 00 00 00 00 mov $0x0,%eax8048ba0: 05 e9 02 00 00 add $0x2e9,%eax8048ba5: eb 05 jmp 8048bac <phase_3+0x8e>8048ba7: b8 00 00 00 00 mov $0x0,%eax8048bac: 2d e9 02 00 00 sub $0x2e9,%eax8048bb1: eb 0a jmp 8048bbd <phase_3+0x9f>8048bb3: e8 4f 04 00 00 call 8049007 <explode_bomb> 上面是各种分支情况,看起来比较复杂,先放一放8048bb8: b8 00 00 00 00 mov $0x0,%eax8048bbd: 83 7c 24 0c 05 cmpl $0x5,0xc(%esp)--- 参数不能大于58048bc2: 7f 06 jg 8048bca <phase_3+0xac>8048bc4: 3b 44 24 08 cmp 0x8(%esp),%eax8048bc8: 74 05 je 8048bcf <phase_3+0xb1>8048bca: e8 38 04 00 00 call 8049007 <explode_bomb>8048bcf: 83 c4 1c add $0x1c,%esp8048bd2: c3 ret可以看出参数不能大于五,因此这道题可能有多组解,不过结合分支语句,不难看出当第一个参数比较大的时候,计算量比较小,所以我选择了第一个参数为5,代入进行逐步计算,可以得到此时的值为-745。
PHASE4:递归调用栈这一步是递归调用栈,所以有两部分汇编代码,其中一个是被调用的函数,简单地看一下代码,应该是一个递归的函数。
先分析主程序部分的代码,其中也有sscanf函数:08048c2c <phase_4>:8048c2c: 83 ec 1c sub $0x1c,%esp8048c2f: 8d 44 24 08 lea 0x8(%esp),%eax8048c33: 50 push %eax8048c34: 8d 44 24 10 lea 0x10(%esp),%eax8048c38: 50 push %eax8048c39: 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 <__isoc99_sscanf@plt>8048c47: 83 c4 10 add $0x10,%esp8048c4a: 83 f8 02 cmp $0x2,%eax----→返回值为2 从上面这部分看出我们需要输入两个参数,且两个都是整数型的。