CSAPP LAB————二进制炸弹(bomblab)

LAB3
预先准备
首先查看整个bomb.c的代码,发现整个炸弹组是由6个小炸弹(函数)组成的。整个main函数比较简单,函数间变量几乎没有影响。因此,只需要依次解除6个小炸弹即可。
所以,接下来便开始依次调试各函数。
调试函数1:
汇编源码与说明:
Dump of assembler code for functionphase_1:
0x08048f61 <+0>: push %ebp ///压栈 ebp为栈指针 esp为栈指针
0x08048f62<+1>: mov %esp,%ebp //把esp赋值给ebp
0x08048f64 <+3>: sub $0x18,%esp //0x18赋值给esp 
0x08048f67 <+6>: movl $0x804a15c,0x4(%esp) 
//把内存中地址为$0x804a15c的内容赋值给*(esp+4)
0x08048f6f <+14>: mov 0x8(%ebp),%eax //*(esp+8)=》eax 就是输入的字符串 (字符串的理由:在后面的代码里,它至于一个对于内存中的内容相等。如果是一个数字或者char的话,也太简单了。我就先猜了是字符串。后来用gdb读一下 果然是字符串。当然这里如果不是字符串也没问题的,只是这样就相对简单。)
0x08048f72 <+17>: mov %eax,(%esp) //eax的值赋值给*esp
0x08048f75 <+20>: call 0x8048fab <strings_not_equal> //比较两字符串是否相等,如果相等令eax为0 否则为1(这里我是根据前后逻辑关系推测的!严谨的讲可以反汇编这个函数 具体看其中值的具体变化)
0x08048f7a <+25>: test %eax,%eax 
0x08048f7c <+27>: je 0x8048f83 <phase_1+34> //如果eax=0 则进入phase2 否则爆炸
0x08048f7e <+29>: call 0x80490d1 <explode_bomb>
0x08048f83 <+34>: leave //为结束函数做准备
0x08048f84 <+35>: ret //返回
End of assembler dump.


画图分析与解答:
(上图的内存地址与后来在linux中汇编出来的地址有出入= =,不过具体就是这个意思)
从上述的汇编代码可以推出,%eax用来保存输入的字符串。如果输入的字符串与内存$0x804a15c处的字符串相同,炸弹就不会爆炸,可以进入到第二个函数,完成第一个函数的破解!
所以,只需要查看$0x804a15c处的字符串。
首先,我使用(gdb) x/s 0x804a15c 进行调试(s代表用字符串的形式读取数据)
读出数据{ We have to stand with ourNorth Korean allies.}
(竟然结果是这玩意!!!中朝真是世代友好啊= =)
然后使用run命令,测试是否成功?
测试成功
 
调试函数2:
汇编源码与说明:
0x08048d6a <+0>: push %ebp
0x08048d6b <+1>: mov %esp,%ebp
0x08048d6d <+3>: push %esi
0x08048d6e <+4>: push %ebx
0x08048d6f <+5>: sub $0x30,%esp
0x08048d72 <+8>: lea -0x20(%ebp),%eax
0x08048d75 <+11>: mov %eax,0x4(%esp)
0x08048d79 <+15>: mov 0x8(%ebp),%eax %eax为中间变量 用于储存输入的数据
0x08048d7c <+18>: mov %eax,(%esp) 前面几行就是初始化与说明这几个数字在栈中的具体地址分布情况 参照图 这里再说明
0x08048d7f <+21>: call 0x804910b <read_six_numbers> 这里是关键!!读取6个数据,说明这个函数的密码很有可能就是6个数字
0x08048d84 <+26>: cmpl $0x0,-0x20(%ebp)
0x08048d88 <+30>: jne 0x8048d90 <phase_2+38> 这里说明-0x20(%ebp)的值等于0
(+38为炸弹)
0x08048d8a <+32>: cmpl $0x1,-0x1c(%ebp)
0x08048d8e <+36>: je 0x8048d95 <phase_2+43> 说明-0x1c(%ebp)等于1
0x08048d90 <+38>: call 0x80490d1 <explode_bomb>
0x08048d95 <+43>: lea -0x18(%ebp),%ebx 将-0x18(%ebp)加载到%ebx
0x08048d98 <+46>: lea -0x8(%ebp),%esi 将-0x8(%ebp)加载到%esi
0x08048d9b <+49>: mov -0x4(%ebx),%eax 将-0x4(%ebx)(也就是-1c(%ebp),所以为1)赋给%eax
0x08048d9e <+52>: add -0x8(%ebx),%eax 0+1(-0x8(%ebx)就是-0x20(%ebp) 
0x08048da1 <+55>: cmp %eax,(%ebx) 0+1 => 即-0x20(%ebp)
0x08048da3 <+57>: je 0x8048daa <phase_2+64> 
0x08048da5 <+59>: call 0x80490d1 <explode_bomb>
---Type <return> to continue, or q<return> to quit---
0x08048daa <+64>: add $0x4,%ebx ebx 上移一位(存的是一个int类型的数组 4个字节 32位)
0x08048dad <+67>: cmp %esi,%ebx 如果ebx与esi指向同一地址退出循环
0x08048daf <+69>: jne 0x8048d9b <phase_2+49> // 这几行形成一个循环
0x08048db1 <+71>: add $0x30,%esp 下面就是退出函数的处理
0x08048db4 <+74>: pop %ebx
0x08048db5 <+75>: pop %esi
0x08048db6 <+76>: pop %ebp
0x08048db7 <+77>: ret 
End of assembler dump.


画图分析与解答:
这题最关键的就是注意<read_six_numbers>这个函数,依据函数名字可以猜测这函数的密码应该是6个数字。 紧接着通过分析
 
0x08048d88 <+30>: jne 0x8048d90 <phase_2+38> 这里说明-0x20(%ebp)的值等于0
(+38为炸弹) 
0x08048d8a <+32>: cmpl $0x1,-0x1c(%ebp)
0x08048d8e <+36>: je 0x8048d95 <phase_2+43> 说明-0x1c(%ebp)等于1
0x08048d90 <+38>: call 0x80490d1 <explode_bomb>
 
可以得到第一个数是0 第二个数是1  (为什么数值的前后顺序参照栈结构FILO)
6个数分别分配在 -20 -1c -18 -14 -10 -1c 位置上  当ebx与esi指向同一位置时,循环结束
  然后就是在上图画具体循环,找到逻辑关系
a[0]=0 a[1]=1 a[2]=a[0]+a[1]=1a[3]=a[2]+a[1]=2 a[4]=3 a[5]=5
即答案为  0 1 1 2 3 5
测试:
调试函数3:
发现直接GDBdisassemble 出来的汇编代码太长,看起来不方便 所以用objdump命令 汇编导出到一个文件下
 
汇编源码与说明:
 
<strong> 
</strong>0x08048ea2 <+1>: mov %esp,%ebp
0x08048ea4 <+3>: sub $0x28,%esp
0x08048ea7 <+6>: lea -0x10(%ebp),%eax 第二个数
0x08048eaa <+9>: mov %eax,0xc(%esp)
0x08048eae <+13>: lea -0xc(%ebp),%eax 第一个数
0x08048eb1 <+16>: mov %eax,0x8(%esp)
0x08048eb5 <+20>: movl $0x804a23e,0x4(%esp) x/s 读出%d %d
0x08048ebd <+28>: mov 0x8(%ebp),%eax
0x08048ec0 <+31>: mov %eax,(%esp)//前面的句子用来构造栈
0x08048ec3 <+34>: call 0x8048840 <__isoc99_sscanf@plt> 调用函数sscanf
0x08048ec8 <+39>: cmp $0x1,%eax eax-1
0x08048ecb <+42>: jg 0x8048ed2 <phase_3+49> 说明%eax>1 即输入参数个数必须大于1 (sscanf)
0x08048ecd <+44>: call 0x80490d1 <explode_bomb>
0x08048ed2 <+49>: cmpl $0x7,-0xc(%ebp)
0x08048ed6 <+53>: ja 0x8048f43 <phase_3+162> 说明储存在-0xc(%ebp)的数不超过7
0x08048ed8 <+55>: mov -0xc(%ebp),%eax
0x08048edb <+58>: jmp *0x804a1a0(,%eax,4)//看到这句,那么这里肯定有switch语句
(这是典型的switch跳转语句,即跳转到以地址*0x804a1a0为基址的跳转表中)读出基值为+113 这里假设-0xc(%ebp)为0 不唯一
0x08048ee2 <+65>: mov $0x0,%eax %eax=0
0x08048ee7 <+70>: jmp 0x8048f3c <phase_3+155>
0x08048ee9 <+72>: mov $0x0,%eax
0x08048eee <+77>: xchg %ax,%ax
0x08048ef0 <+79>: jmp 0x8048f37 <phase_3+150>
0x08048ef2<+81>: mov $0x0,%eax
0x08048ef7 <+86>: jmp 0x8048f32 <phase_3+145>
0x08048ef9 <+88>: mov $0x0,%eax
0x08048efe <+93>: xchg %ax,%ax
0x08048f00 <+95>: jmp 0x8048f2d <phase_3+140>
0x08048f02 <+97>: mov $0x0,%eax
0x08048f07 <+102>: jmp 0x8048f28 <phase_3+135>
0x08048f09 <+104>: mov $0x0,%eax
0x08048f0e <+109>: xchg %ax,%ax
0x08048f10 <+111>: jmp 0x8048f23 <phase_3+130>
0x08048f12 <+113>: mov $0x314,%eax eax=314
0x08048f17 <+118>: jmp 0x8048f1e <phase_3+125>
0x08048f19 <+120>: mov $0x0,%eax
0x08048f1e <+125>: sub $0x35a,%eax eax=314-35a=-46
0x08048f23 <+130>: add $0x2ef,%eax
0x08048f28 <+135>: sub $0x216,%eax
0x08048f2d <+140>: add $0x216,%eax
0x08048f32 <+145>: sub $0x216,%eax
0x08048f37 <+150>: add $0x216,%eax -46+2ef-216+216-216+216=2A9
0x08048f3c <+155>: sub $0x216,%eax 2a9-216=93
0x08048f41 <+160>: jmp 0x8048f4d <phase_3+172>
0x08048f43 <+162>: call 0x80490d1 <explode_bomb>
0x08048f48 <+167>: mov $0x0,%eax
0x08048f4d <+172>: cmpl $0x5,-0xc(%ebp) 
0x08048f51 <+176>: jg 0x8048f58 <phase_3+183> -0xc(%ebp)<=5
0x08048f53 <+178>: cmp -0x10(%ebp),%eax -0x10(%ebp)==93转为10进制 147 
0x08048f56 <+181>: je 0x8048f5d <phase_3+188>
0x08048f58 <+183>: call 0x80490d1 <explode_bomb>
0x08048f5d <+188>: leave 
0x08048f5e <+189>: xchg %ax,%ax//不明白这句啥意思
0x08048f60 <+191>: ret 
 

分析与解答:
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值