缓冲区溢出:
前提:
一般发生在C这种需手工管理内存的语言编写的程序中
原理:
进程分控制层面和数据层面两个部分,每个部分各占一部分内存。
当程序没有对数据层面内存大小做限制时,输入一个超过数据内存大小的数据就会发生数据层面的数据把控制层面内存覆盖的情况,此时如果在数据尾部加上一些操作系统指令就会把该指令加载到控制层面
内存(即寄存器)当中去,当CPU执行下一个控制层面内存里的内容时就会加载该恶意指令。 (注:寄存器中的EIP为CPU要执行的下一条指令的内存地址)
思路:
对存在缓冲区溢出程序输入1000个A,假如第900至904个A溢出到了寄存器中的EIP(CPU要执行的下一条指令的内存地址,注意EIP存储的是一个16进制的内存地址。它本属于控制层面的内存空间),那也就意味着只要将第900到904位置的数值替换为一个存放有shellcode的内存地址就可以拿下该主机。
然后测试发现从第905个位置往后的数据都放入寄存器ESP中,那么也就意味着可以将第905个位置往后的数据替换为shellcode,再将900到904位置的数据替换为ESP的内存地址。
注意:但是由于目标程序每次启动占用内存位置的不同,ESP的内存地址也就每次都不同,所以EIP想要直接指定ESP内存地址基本不可能。
解决方法:找一个每次占用内存地址都一样且拥有“JMP ESP”的系统进程,将EIP指向这个进程中“JMP ESP”的内存地址,然后再跳到ESP。通过这种间接跳转的方式最终跳到ESP。
思考:
1、为什么数据层面内存中的系统指令不会被执行
(猜:应该是软件对数据层面做了限制,规定数据层面的内容只能当数据使用。如果没有该规定则该程序此处就是命令注入或者SQL注入漏洞了。也就是说缓冲区溢出是在没有命令注入漏洞的基础上更深一步的漏洞)
2、为什么数据内存占满后剩下的数据会写入寄存器中的EIP和ESP中?
(猜:寄存器中的数据存放是有严格顺序的,每次都是EIP、ESP、数据内存这样循环执行。所以可以推测只要是缓冲区溢出问题就都会先溢出到EIP和ESP内)