Level 0
任务描述:Bufbomb中,运行了一个test()函数,在test()中又调用了一个getbuf(),我们的目标是,在执行getbuf()后,不再返回test(),而是返回到执行smoke()。
首先看test()函数,函数调用了一个getbuf()函数。
那么,getbuf()是个什么函数?通过对bufbomb进行反汇编处理,可以查看到getbuf()的汇编代码:
由此可以得知,getbuf()调用了Gets()函数,并以-0x28(%ebp)作为读入数据的缓冲区。由于Gets()函数并没有检查输入的字符长度的机制,所以,我们可以通过输入一定长度的字符串来将栈中的返回地址覆盖来达成我们的目的。
我们知道,返回地址保存的位置在0x4(%ebp),而0x4 - (-0x28) = 0x2c = 44,也就意味着,返回地址的首地址到缓冲区的首地址之间相差44个字节。这44个字节我们是可以随意填充的,重点在于,我们要在这44个字节后接上我们需要跳转到的地址。通过查看反汇编代码,发现smoke()函数的地址为0x08048e0a。由于hex2raw的限制,我们输入的序列不应该出现0x0A,所以,我们可以将地址设置为0x8048e0b以达到同样的效果。
在level0.txt中,我们要输入44个字节(这里统一用00)以及代表smoke()地址的4个字节。由于采用的是小端法,所以地址字节的顺序为 0b 8e 04 08。
通过终端执行bufbomb,可以看到,输出了Smoke!: You called smoke() 的字符串,说明成功跳转到了smoke()函数中。
Level 1
任务描述:执行getbuf()后,转向执行fizz()而不是回到test(),并输出自己的cookie
跟level0一样,先得到fizz函数的地址0x08048daf。然后我们观察fizz()的代码,可以发现函数中将0x804d104中的值与0x8(%ebp)进行比较,通过gdb查看内存可知,0x804d104中存储的是我们的COOKIE的值,所以说,0x8(%ebp)中存储的应该是传入的参数的值。
那该怎么修改这个值呢?由于fizz函数是通过返回地址跳转进而执行的,而不是采用call的方式,所以并不会放置原执行函数的返回地址。(这里将执行fizz()时的%esp、%ebp小写,而还在调用getbuf()时的%EBP、%ESP大写,以区分,我们要输入的字符串是相对于%EBP、%ESP而言的)由此可知,执行fizz()时的esp变回调用getbuf()前的位置,即调用getbuf()时的8(%EBP)。而执行fizz()时,前两行将执行fizz()时的%eb