升入理解计算机系统BombLAB实验报告资料.docx
《升入理解计算机系统BombLAB实验报告资料.docx》由会员分享,可在线阅读,更多相关《升入理解计算机系统BombLAB实验报告资料.docx(15页珍藏版)》请在冰豆网上搜索。
![升入理解计算机系统BombLAB实验报告资料.docx](https://file1.bdocx.com/fileroot1/2023-1/6/d9cfca0e-7246-43cb-8c6e-021d02226f82/d9cfca0e-7246-43cb-8c6e-021d02226f821.gif)
升入理解计算机系统BombLAB实验报告资料
湖南大学课程实验报告
课程名称:
计算机组成与结构
实验项目名称:
二进制炸弹
专业班级:
姓名:
学号:
指导教师:
完成时间:
计算机科学与工程系
实验题目:
APPBombLab
实验目的:
实验环境:
linux,终端,gdb工具
实验内容及操作步骤:
查看给出的bomb.c中的代码,得知控制检测密码正误的6个函数分别为:
phase_1,phase_2,phase_3,phase_4,phase_5,phase_6。
使用gbd工具对可执行文件bomb进行反汇编:
得到六段汇编代码,将其复制成文本后,对其进行分析,
phase_1代码:
0x08048f61<+0>:
push%ebp
0x08048f62<+1>:
mov%esp,%ebp
0x08048f64<+3>:
sub$0x18,%esp
0x08048f67<+6>:
movl$0x804a15c,0x4(%esp)将esp寄存器地址指向$0x804a15c
0x08048f6f<+14>:
mov0x8(%ebp),%eax将$0x804a15c中的数据移给eax寄存器
0x08048f72<+17>:
mov%eax,(%esp)
0x08048f75<+20>:
call0x8048fab
0x08048f7a<+25>:
test%eax,%eax上一行与这一行比较用户输入和$0x804a15c中的值
0x08048f7c<+27>:
je0x8048f83
0x08048f7e<+29>:
call0x80490d1
0x08048f83<+34>:
leave
0x08048f84<+35>:
ret
可以看出,phase_1的密码是固定储存在$0x804a15c中的。
令$0x804a15c中的数据与用户输入的数据比较,若相同则跳过explode_bomb,避开炸弹。
用命令x/s0x804a15c查看其中的数据如下
因此知道第一个密码为:
WehavetostandwithourNorthKoreanallies.
phase_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>:
mov0x8(%ebp),%eax
0x08048d7c<+18>:
mov%eax,(%esp)
0x08048d7f<+21>:
call0x804910b读取六个数字
0x08048d84<+26>:
cmpl$0x0,-0x20(%ebp)0和第一个数字比较,不相等则爆炸。
0x08048d88<+30>:
jne0x8048d90
0x08048d8a<+32>:
cmpl$0x1,-0x1c(%ebp)1和第二个数字比较,相等则跳过爆炸。
0x08048d8e<+36>:
je0x8048d95
0x08048d90<+38>:
call0x80490d1
0x08048d95<+43>:
lea-0x18(%ebp),%ebxebx指向第三个数字。
0x08048d98<+46>:
lea-0x8(%ebp),%esiesi指向第六个数字再向后移一位的地址。
0x08048d9b<+49>:
mov-0x4(%ebx),%eaxebx向前第一位的数字赋给eax。
0x08048d9e<+52>:
add-0x8(%ebx),%eaxeax再加上ebx向前第二位的数字。
0x08048da1<+55>:
cmp%eax,(%ebx)比较ebx前两位的和与ebx指向的数字。
0x08048da3<+57>:
je0x8048daa相等则跳过爆炸(explode_bomb)
0x08048da5<+59>:
call0x80490d1
0x08048daa<+64>:
add$0x4,%ebxebx地址向后移动一位(四个字节)。
0x08048dad<+67>:
cmp%esi,%ebx如果还未超过第六位数字,则跳转到0x8048d9b行。
0x08048daf<+69>:
jne0x8048d9b
0x08048db1<+71>:
add$0x30,%esp
0x08048db4<+74>:
pop%ebx
0x08048db5<+75>:
pop%esi
0x08048db6<+76>:
pop%ebp
0x08048db7<+77>:
ret
从上面的代码分析中可以知道,phase_2的密码有六个数字,第一个是0,第二个是1,然后之后的每位都是前两位的和,即斐波拉契数列的前6位。
所以密码是:
011235。
phase_3代码:
0x08048ea1<+0>:
push%ebp
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/s0x804a23e命令查看$0x804a23e为
0x08048ebd<+28>:
mov0x8(%ebp),%eax%d%d,即要输入两个整数,上面已经指出。
0x08048ec0<+31>:
mov%eax,(%esp)
0x08048ec3<+34>:
call0x8048840<__isoc99_sscanf@plt>
0x08048ec8<+39>:
cmp$0x1,%eax以上两行即要求输入至少两组数据,否则引爆。
0x08048ecb<+42>:
jg0x8048ed2
0x08048ecd<+44>:
call0x80490d1
0x08048ed2<+49>:
cmpl$0x7,-0xc(%ebp)第一个数大于7引爆,即第一个数小于等于7。
0x08048ed6<+53>:
ja0x8048f43
0x08048ed8<+55>:
mov-0xc(%ebp),%eax
0x08048edb<+58>:
jmp*0x804a1a0(,%eax,4)跳转至0x804a1a0+eax*4(第一个数)内数据所
0x08048ee2<+65>:
mov$0x0,%eax指的行数。
0x08048ee7<+70>:
jmp0x8048f3c
0x08048ee9<+72>:
mov$0x0,%eax
0x08048eee<+77>:
xchg%ax,%ax
0x08048ef0<+79>:
jmp0x8048f37
0x08048ef2<+81>:
mov$0x0,%eax
0x08048ef7<+86>:
jmp0x8048f32
0x08048ef9<+88>:
mov$0x0,%eax
0x08048efe<+93>:
xchg%ax,%ax
0x08048f00<+95>:
jmp0x8048f2d
0x08048f02<+97>:
mov$0x0,%eax
0x08048f07<+102>:
jmp0x8048f28
0x08048f09<+104>:
mov$0x0,%eax
0x08048f0e<+109>:
xchg%ax,%ax
0x08048f10<+111>:
jmp0x8048f23
0x08048f12<+113>:
mov$0x314,%eax当第一个数为0时跳转到此处,第二个数x=788。
0x08048f17<+118>:
jmp0x8048f1e跳转到0x8048f1e。
0x08048f19<+120>:
mov$0x0,%eax
0x08048f1e<+125>:
sub$0x35a,%eaxx=x-858
0x08048f23<+130>:
add$0x2ef,%eaxx=x+751
0x08048f28<+135>:
sub$0x216,%eaxx=x-534
0x08048f2d<+140>:
add$0x216,%eaxx=x+534
0x08048f32<+145>:
sub$0x216,%eaxx=x-534
0x08048f37<+150>:
add$0x216,%eaxx=x+534
0x08048f3c<+155>:
sub$0x216,%eaxx=x-534
0x08048f41<+160>:
jmp0x8048f4d跳转到0x8048f4d行。
0x08048f43<+162>:
call0x80490d1
0x08048f48<+167>:
mov$0x0,%eax
0x08048f4d<+172>:
cmpl$0x5,-0xc(%ebp)第一个数大于5引爆,即第一个数小于等于5。
0x08048f51<+176>:
jg0x8048f58
0x08048f53<+178>:
cmp-0x10(%ebp),%eax第一个数是0时,算得x=147,即第二个数
0x08048f56<+181>:
je0x8048f5d为147。
0x08048f58<+183>:
call0x80490d1
0x08048f5d<+188>:
leave
0x08048f5e<+189>:
xchg%ax,%ax
0x08048f60<+191>:
ret
由以上分析可以得到,我们需要输入两个数,储存在%ebx-16和%edx-12中,%edx为输入的第一个数据,由0x08048f4d<+172>:
cmpl$0x5,-0xc(%ebp)可以判断第一个数输入不能大于5,即可以输入6组数据0,1,2,3,4,5,他们应该分别对应一个%edx-16的值!
假设第二个一个输入的数为x:
当输入第一个数为0时,x=788-858+751-534+534-534+534-534=147
当输入第一个数为1时,x=-858+751-534+534-534+534-534=-641
当输入第一个数为2时,x=751-534+534-534+534-534=217
当输入第一个数为3时,x=-534+534-534+534-534=-534
当输入第一个数为4时,x=534-534+534-534=0
当输入第一个数为5时,x=-534+534-534=-534
所以,可以输入的六组数据分别为:
0,1471,-6412,2173,-5344,05,-534
phase_4代码:
0x08048e2e<+0>:
push%ebp
0x08048e2f<+1>:
mov%esp,%ebp
0x08048e31<+3>:
sub$0x28,%esp
0x08048e34<+6>:
lea-0x10(%ebp),%eax
0x08048e37<+9>:
mov%eax,0xc(%esp)此处第二段数字。
0x08048e3b<+13>:
lea-0xc(%ebp),%eax
0x08048e3e<+16>:
mov%eax,0x8(%esp)此处第一段数字。
0x08048e42<+20>:
movl$0x804a23e,0x4(%esp)$0x804a23e内为%d%d,即输入两个整数。
0x08048e4a<+28>:
mov0x8(%ebp),%eax
0x08048e4d<+31>:
mov%eax,(%esp)
0x08048e50<+34>:
call0x8048840<__isoc99_sscanf@plt>
0x08048e55<+39>:
cmp$0x2,%eax以上两行要求之前输入的为两个数据,否则引爆。
0x08048e58<+42>:
jne0x8048e66
0x08048e5a<+44>:
mov-0xc(%ebp),%eax
0x08048e5d<+47>:
test%eax,%eax第一段数据大于等于0,否则引爆。
0x08048e5f<+49>:
js0x8048e66
0x08048e61<+51>:
cmp$0xe,%eax第一段数据小于等于14时跳过引爆。
0x08048e64<+54>:
jle0x8048e6b
0x08048e66<+56>:
call0x80490d1
0x08048e6b<+61>:
movl$0xe,0x8(%esp)
0x08048e73<+69>:
movl$0x0,0x4(%esp)
0x08048e7b<+77>:
mov-0xc(%ebp),%eax
0x08048e7e<+80>:
mov%eax,(%esp)
0x08048e81<+83>:
call0x8048b60这几行为运行一个递归函数func4来确定第一
0x08048e86<+88>:
cmp$0x1,%eax段数据的值。
0x08048e89<+91>:
jne0x8048e91
0x08048e8b<+93>:
cmpl$0x1,-0x10(%ebp)第二个数据等于1则跳过爆炸。
0x08048e8f<+97>:
je0x8048e9d
0x08048e91<+99>:
lea0x0(%esi,%eiz,1),%esi
0x08048e98<+106>:
call0x80490d1
0x08048e9d<+111>:
leave
0x08048e9e<+112>:
xchg%ax,%ax
0x08048ea0<+114>:
ret
由以上对代码的分析可以看出,第二个数据确定为1。
第一个数据范围为大于等于0,小于14,并且由一个递归函数func4又一次缩小了范围。
但因为这个递归函数太过繁杂,而第一个数据范围又不大,所以我没有细看,直接将第一个数据从0尝试到13,得到了三个数字8、9、11符合要求。
因此密码有三组:
81,91,111。
phase_5代码:
0x08048db8<+0>:
push%ebp
0x08048db9<+1>:
mov%esp,%ebp
0x08048dbb<+3>:
push%esi
0x08048dbc<+4>:
push%ebx
0x08048dbd<+5>:
sub$0x20,%esp
0x08048dc0<+8>:
lea-0x10(%ebp),%eax
0x08048dc3<+11>:
mov%eax,0xc(%esp)此处为第二个数。
0x08048dc7<+15>:
lea-0xc(%ebp),%eax
0x08048dca<+18>:
mov%eax,0x8(%esp)此处为第一个数。
0x08048dce<+22>:
movl$0x804a23e,0x4(%esp)$0x804a23e内为%d%d,即输入两个整数。
0x08048dd6<+30>:
mov0x8(%ebp),%eax
0x08048dd9<+33>:
mov%eax,(%esp)
0x08048ddc<+36>:
call0x8048840<__isoc99_sscanf@plt>
0x08048de1<+41>:
cmp$0x1,%eax以上两行保证输入数据多于1组,否则引爆。
0x08048de4<+44>:
jg0x8048deb
0x08048de6<+46>:
call0x80490d1
0x08048deb<+51>:
mov-0xc(%ebp),%eax
0x08048dee<+54>:
and$0xf,%eax按位与,即保留第一个数的后四位。
0x08048df1<+57>:
mov%eax,-0xc(%ebp)
0x08048df4<+60>:
cmp$0xf,%eax第一个数二进制后四位不能为(1111)2,否则引爆。
0x08048df7<+63>:
je0x8048e22
0x08048df9<+65>:
mov$0x0,%ecx
0x08048dfe<+70>:
mov$0x0,%edx
0x08048e03<+75>:
mov$0x804a1c0,%ebx$0x804a1c0指向的是一个数组,下面分析。
0x08048e08<+80>:
add$0x1,%edx
0x08048e0b<+83>:
mov(%ebx,%eax,4),%eax
0x08048e0e<+86>:
add%eax,%ecx
0x08048e10<+88>:
cmp$0xf,%eax
0x08048e13<+91>:
jne0x8048e08以上五行为一个for循环语句,下面分析。
0x08048e15<+93>:
mov%eax,-0xc(%ebp)
0x08048e18<+96>:
cmp$0xf,%edx上述的for循环要循环15次。
0x08048e1b<+99>:
jne0x8048e22
0x08048e1d<+101>:
cmp%ecx,-0x10(%ebp)确定第二个数的值,下面分析。
0x08048e20<+104>:
je0x8048e27
0x08048e22<+106>:
call0x80490d1
0x08048e27<+111>:
add$0x20,%esp
0x08048e2a<+114>:
pop%ebx
0x08048e2b<+115>:
pop%esi
0x08048e2c<+116>:
pop%ebp
0x08048e2d<+117>:
ret
根据上述的代码分析可以知道,第一个数二进制后四位不能为(1111)2。
密码主要由上述的一个for循环确定。
首先$0x804a1c0指向了一个数组,在for循环中每循环一次调用一次,因为必须循环15次,且最开始还要调用一次,因此需要16个元素,使用p*0x804a1c0@16命令来查看这个数组为:
将这个for循环写出:
设i在%edx中,数组a[16]在%ebx中,n在%eax中,sum在%ecx中。
sum=0;
for(i=1;n=15;i++)
{
n=a[n];
sum+=n;
}
n会取16次值,其中第一次n取的值应为用户输入的第一个数二进制下的后四位。
之后每次都等于a[n],sum为除去第一次之外所有n取值的和。
因此我采用逆推的方法来求出n第一次取的值。
序号
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
数组
10
2
14
7
8
12
15
11
0
4
1
13
3
9
6
5
for循环当n为15时终止,因此最后一个n为15,对应序号为上一个n,即6。
同理,可以得到,n从第一个到最后一个为:
5123711139480101214615。
sum=15*16/2-5=115。
即用户输入的第二个数为115。
用户输入第一个数二进制下的后四位为0101(即第一个n=5),而之前位可以随意取值。
因此有无数多的密码,如:
5115,21115。
phase_6代码:
0x08048c89<+0>:
push%ebp
0x08048c8a<+1>:
mov%esp,%ebp
0x08048c8c<+3>:
push%edi
0x08048c8d<+4>:
push%esi
0x08048c8e<+5>:
push%ebx
0x08048c8f<+6>:
sub$0x5c,%esp
0x08048c92<+9>:
lea-0x30(%ebp),%eax
0x08048c95<+12>:
mov%eax,0x4(%esp)
0x08048c99<+16>:
mov0x8(%ebp),%eax
0x08048c9c<+19>:
mov%eax,(%esp)
0x08048c9f<+22>:
call0x804910b
0x08048ca4<+27>:
mov$0x0,%esi
0x08048ca9<+32>:
lea-0x30(%ebp),%edi
0x08048cac<+3