buflab

目录

 

1.Get ready(getbuf&&test)

2.LEVEL0 Candle

3.LEVEL1 Sparkler

4.LEVAL2 Firecracker

5.LEVEL3 Dynamite

6.LEVEL4 Nitroglycerin


1.Get ready(getbuf&&test)

将bufbomb的汇编代码输出到文件:

getbuf函数:

test函数:


2.LEVEL0 Candle

Your task is to get BUFBOMB to execute the code for smoke when getbuf executes its return statement, rather than returning to test. Note that your exploit string may also corrupt parts of the stack not directly related to this stage, but this will not cause a problem, since smoke causes the program to exit directly.

smoke函数的首地址:0x08048e0a

题目要求在test函数中调用getbuf后不返回test而跳到smoke的函数入口处。

看到getbuf函数汇编代码中,第4、5、6行,正是为调用Gets函数做准备,传入的参数是栈内的一个地址,容易知道是用来存储输入字符串的数组的首地址(%ebp-0x28),getbuf函数的栈帧大致如下:

 

 

ebp+0x4

返回地址

ebp

旧ebp

ebp-0x4

Buf[35]~buf[39]

ebp-0x8

Buf[30]~buf[34]

……

 

ebp-0x28

Buf[0]~buf[3]

 

Call Gets

  • 如果要使得getbuf调用结束后转移到smoke函数的入口地址,只需要将函数的返回地址进行修改,可以通过数组的溢出,用字符串覆盖原来的返回地址处。
  • 从图中可以看到,buf数组溢出到buf[44]~buf[47]的部分将覆盖返回地址。
  • 那么我们输入的字符串应该含有至少48个字符,根据小端法,最后四个字符应的ascii码应该为:0a 8e 04 08

但是发现结果不对:段错误

注意到输入的字符串序列中含有0x0a是换行符,getbuf调用Gets函数用力啊输入数据,遇到0x0a会停止输入。

 

解决办法:

想想可不可以在原来的返回地址的基础上稍微增减,因为我们的getbuf函数最终是回不到test函数的,因此push ebp指令没有实际意义,因此把返回地址改为下一句mov esp,ebp即0x8048e0b

结果:


 

3.LEVEL1 Sparkler

Similar to Level 0, your task is to get BUFBOMB to execute the code for fizz rather than returning totest. In this case, however, you must make it appear to fizz as if you have passed your cookie as its argument. How can you do this?

FIZZ:

  • fizz函数有一个参数 val,题目要求我们进入fizz函数的时候,需要构造函数的参数(为cookie),进入fizz函数可以有如下的入口地址:0x8048daf、0x8048db0
  • 还是分析getbuf函数栈帧的结构:当我们要从getbuf函数退出,转移到返回地址处的时候,栈帧的esp指向返回地址,将返回地址弹出以后,esp继续上移4个字节
  • 进入fizz后,如果从0x8048db0进入,首先执行mov esp,ebp,那么根据函数栈帧结构,此时的ebp或esp所指处,往上8个字节才是fizz函数的参数,因此我们传递给fizz的参数在返回地址上方12个字节处。
  • 看到fizz的5、6行,知道cookie应该存在地址0x804d104内,gdb调试查看cookie的值为0x1005b2b7:

 getbuf函数退出,转移到返回地址处的时候,getbuf函数栈帧:

 

 

 

 

esp

 

 

返回地址

 

旧ebp

 

Buf[35]~buf[39]

 

…………

 

Buf[0]~buf[3]

 

Call Gets

结果:


 


4.LEVAL2 Firecracker

Similar to Levels 0 and 1, your task is to get BUFBOMB to execute the code for bang rather than returning to test. Before this, however, you must set global variable global_value to your userid's cookie. Your exploit code should set global_ value, push the address of bang on the stack, and then execute a ret instruction to cause a jump to the code for bang.
bang:

题目要求进入getbuf函数后不返回test,而是①修改全局变量global_value的值为我的cookie②进入bang函数

  • 因为global_value是全局变量,首先我们gdb调试来查看它的地址:0x804d10c

  •  要修改全局变量的值,需要相应的赋值代码,我们只能利用的是字符数组缓冲区溢出,那么我们想到先获取执行代码的权力,函数getbuf在return 返回地址前都拥有代码的执行权,那么我们可以将返回地址修改为我们已经设置好的代码的首地址,所以我们要得到buf的运行时地址:0x55683588

  • 在getbuf中调用ret指令之前执行了leave指令:

    Leave等价于:

    movl %ebp %esp

    popl %ebp

    那么此时的getbuf函数栈帧中, ebp已经改变为相应保存的旧ebp处,esp转移到保存返回地址的位置。因此如果我们把返回地址更改为buf的起始位置,执行ret指令eip指向我们设置的代码处。执行完代码后想转移到bang函数入口,如果我们的代码不会改变esp指针的值,那么可以先更改esp指向的地址内容为bang函数的入口地址,然后再ret。
mov  $0x1005b2b7,%eax /*将cookie保存到eax内*/
movl %eax,0x804d10c   /*将eax值保存到global_value内*/
pushl $0x8048d52      /*将bang函数地址存到栈顶*/
ret                   /*eip转移到返回地址*/

因为我们输入文本的是二进制的数据,因此可以将以上的代码先汇编为.o文件:

 

 

 

 

 

 

 

 

ebp+0x4

返回地址

ebp

旧ebp

ebp-0x4

Buf[35]~buf[39]

ebp-0x8

Buf[30]~buf[34]

……

 

ebp-0x28

Buf[0]~buf[3]

 

Call Gets

结果:


 5.LEVEL3 Dynamite

Your job for this level is to supply an exploit string that will cause getbuf to return your cookie back to test, rather than the value1. You can see in the code for test that this will cause the program to go “Boom! .” Your exploit code should set your cookie as the return value, restore any corrupted state, push the correct return location on the stack, and execute a ret instruction to really return to test .

①首先我们要获得代码的执行权,在buf中存储我们的代码数据,所以在getbuf执行ret的时候返回地址应该是buf的首地址。
②其次执行完我们的代码后要返回test函数,堆栈的状态都要恢复,因此ebp,esp的值都不能错。
因为要覆盖返回地址,那么必然覆盖原来的旧ebp的值,因此我们获得运行时的test的ebp的值:0x556835e0
test函数中调用getbuf原本的返回地址第8行:0x848e50
代码:
mov  $0x1005b2b7,%eax /*将cookie保存到eax内*/
pushl $0x8048e50    /*将test函数调用getbuf原本返回地址地址存到栈顶*/
ret                   /*eip转移到返回地址*/

 

 

 

 

 

 

 

执行buf中代码时,esp指向此处

ebp+0x4

返回地址 

ebp

旧ebp

ebp-0x4

Buf[35]~buf[39]

ebp-0x8

Buf[30]~buf[34]

……

 

ebp-0x28

Buf[0]~buf[3]

 

Call Gets

结果:

6.LEVEL4 Nitroglycerin

Your task is identical to the task for the Dynamite level. Once again, your job for this level is to supply an exploit string that will cause getbufn to return your cookie back to test, rather than the value 1. You can see in the code for test that this will cause the program to go “KABOOM! .” Your exploit code should set your cookie as the return value, restore any corrupted state, push the correct return location on the stack, and execute a ret instruction to really return to testn.
testn:
getbufn:

这个函数与getbuf所不同的是,分配了512字节的字符数组,而调用getbufn的函数会在栈中随机分配一段存储区,这导致getbufn使用的栈基址ebp随机变化。此外,在Nitro模式运行时,bufbomb会要求提供5次输入字符串,每一次都要求getbufn的返回值为实验者的cookie。

  • 因为调用完getbufn后转移到我们的恶意代码,执行完毕后再回到testn,那么要保证我们回到testn时寄存器状态不变,即ebp和esp不能改变
  • 因为我们要覆盖返回地址,那么必然会覆盖旧ebp的值,在覆盖的时候我们无法确定一个固定的testn的ebp的值,所以我们在代码中恢复ebp的正确值。
  • 看testn中调用getbufn时esp指针距离ebp指针0x28个字节(在esp-0x24之前还有push ebx),getbufn函数没有参数,因此在getbufn中调用ret指令后指向getbufn函数栈帧ebp再往上8个字节,即恢复到了testn函数调用getbufn时的esp位置,因此旧ebp的恢复可以通过指令:leal 0x28(%esp),%ebp
  • 所以我们的恶意代码的任务:①将寄存器eax的内容改为cookie②恢复testn的ebp③执行完跳转到testn中调用getbufn的下一条指令地址(指令的地址是不变的,至少运行时栈的地址变化:call的下一条指令地址是0x8048ce2。
  • 代码:
leal  -0x28(esp),ebp    /*恢复testn的ebp*/
mov   $0x1005b2b7,%eax  /*将cookie保存到eax内*/
pushl $0x8048ce2        /*将返回地址压栈*/
ret

要一开始修改返回地址到我们的恶意代码的起始位置,我们无法确定一个固定的地址,因此在代码前加入很长的一段nop序列,成为空操作雪橇,如果我们的返回地址是这段序列中的一个,那么就可以顺着nop序列到达我们的恶意代码的入口:

知道我们的代码恶意代码序列长度为15字节,结束位置在ebp+0x3,因此入口在ebp-0xb,buf数组起始地址是ebp-0x208,因此nop序列长度为0x208-0xb=509

 

 

 

 

 

 

 

执行buf中代码时,esp指向此处

ebp+0x4

返回地址 

ebp

旧ebp

ebp-0x4

 

……

……

ebp-0xc

nop 恶意代码入口

 

nop nop nop nop

 

nop nop nop nop

 

……

ebp-0x208

Buf[0]~buf[3]:nop nop nop nop

 

 

 

gdb调试查看运行时调用四次getbufn时,其ebp的值各为多少:发现最大为0x556835e0最小为0x55683560,那么恶意代码的首地址最小为ebp-0xb=0x55683560-0xb=0x55683555

 

 结果:


 7.Summarize

  • 这个实验利用缓冲区的溢出来进行攻击,要求我们十分熟悉函数栈以及函数调用时栈帧的变化情况
  • 综合利用反汇编后端代码和gdb调试来查看程序运行时的寄存器状态和内存里的数据,来必须能够熟练地预判栈指针的变化情况
  • 在最后的几个LEVEL更是要求我们掌握编写汇编代码
  • 要利用函数调用结束后的ret指令使得eip的值修改为函数的返回地址,以此让恶意代码获得执行权
  • 要注意当我们在执行完恶意代码以后如果要把执行权力还给原本要返回的函数,要恢复寄存器的状态
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hnu哈哈

请接受直女的么么哒????

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值