1、缓冲区数据的组成:
- 填充物:一般用NOP指令对应的0x90来填充缓冲区,并把shellcode布置于其后。这样即使不能准确跳转到shellcode开始,只要跳进缓冲区,处理器最终也会顺序执行shellcode。
- 淹没返回地址的数据:可以是跳转指令的地址、shellcode的地址,甚至是近似的shellcode的地址。
- shellcode:可执行的机器代码。
2、缓冲区数据的布置对于exploit的成功很重要。
- 在代码植入实验中,shellcode直接放在缓冲区buffer[44]里,也就是shellcode位于返回地址之前;
- 在定位shellcode实验中,我们用jmp esp来定位shellcode,在溢出时,会比代码植入实验多覆盖一片内存空间,把shellcode恰好布置在函数返回地址之后。
两种数据布置方式各有各的特点:
(1)当缓冲区较大时,最好还是把shellcode布置在缓冲区内。
优点:合理利用缓存区,使攻击串的总长度减小,且对于远程攻击,有时所有数据必须包含在一个数据包中;对程序破坏性小,比较稳定,且溢出基本发生在当前栈帧中,不会大范围破坏前栈帧。
缺点:如果shellcode中存在push指令,push指令会向栈中暂存数据,压栈数据可能会破坏到shellcode本身。因为函数返回时,当前栈帧被弹出,这时缓冲区位于栈顶ESP之上的内存区域,也就是说shellcode存放在返回地址之前的内存空间中,但是在计算机看来,ESP以上的内存空间的数据已经作废,而shellcode使用push指令压数据入栈,也就会可能破坏到shellcode。
解决方法:写shellcode之前,抬高栈顶,把shellcode“藏在”栈内。
(2)当缓冲区较小时,使用跳转指令布置shellcode。
优点:可以存放更大的shellcode,不会破坏前栈帧的数据,可以达到执行完shellcode,再返回到原程序。
缺点:分几种情况:
- 一些情况下,返回地址距离缓冲区的偏移量往往不确定,可以这样做:将shellcode布置在一大片nop之后,扩大shellcode面积,提高命中概率;
- 如果函数返回地址的偏移按双字(DWORD)不定,可以用一片连续的跳转指令的地址来覆盖函数返回地址,这样只要其中一个能够成功覆盖,shellcode就能得到执行;
- strcat函数产生的漏洞:
......
strcat("程序安装目录",输入字符串);
......
而不同的主机可能会有不同的程序安装目录。例如:
c:\failwest\
c:\failwestq\
c:\failwestqq\
c:\failwestqqq\
这样,函数返回地址距离我们输入的字符串的偏移在不同的计算机上就有可能字节错位,如图1:
图1
图一中,本想把函数返回地址覆盖为0x7C81CDDA处的跳转地址,在本机调试通过后,有可能会由于其他计算机上作为字符串前半部分的程序安装目录不同,而使覆盖的地址错位失效。
这种情况的解决办法:使用按字节相同的双字跳转地址,甚至可以使用堆中的地址,然后想办法将shellcode用堆扩展的方法放置到相应区域。如图2。