内存结构
缓冲区溢出漏洞
缓冲区溢出漏洞就是在向缓冲区写入数据时,由于没有做边界检查,导致写入缓冲区的数据超过预先分配的边界,从而使溢出数据覆盖在合法数据上而引起系统异常的一种现象。
ESP、EPB
ESP:扩展栈指针(Extended Stack Pointer)寄存器,其存放的指针指向当前栈帧的栈顶。
EBP:扩展基址指针(Extended Base Pointer)寄存器,其存放的指针指向当前栈帧的栈底。
EIP:控制了进程的执行流程,EIP指向哪里,CPU就会执行哪里的指令!
一个函数栈帧中主要包含如下信息:
1)前一个栈帧的栈底位置,即前栈帧EBP,用于在函数调用结束后恢复主调函数的栈帧(前栈帧的栈顶可计算得到)。
2)该函数的局部变量。
3)函数调用的参数。
4)函数的返回地址RET,用于保存函数调用前指令的位置,以便函数返回时能恢复到调用前的代码区中继续执行指令。
栈溢出攻击
栈溢出攻击是一种利用栈溢出漏洞所进行的攻击行动,目的在于扰乱具有某些特权运行的程序的功能,使得攻击者取得程序的控制权。
JMP ESP覆盖方法
在实际的漏洞利用中,由于动态链接库的装入和卸载等原因,Windows进程的函数栈帧可能发生移位,即Shellcode在内存中的地址是动态变化的,所以上述采用直接赋地址值的简单方式在以后的运行过程中会出现跳转异常。
JMP ESP覆盖方法是覆盖函数返回地址的一种攻击方式。考虑到函数返回时ESP总是指向函数返回后的下一条指令,根据这一特点,如果用指令JMP ESP的地址覆盖返回地址,则函数也可以跳转到函数返回后的下一条指令,而从函数返回后的下一条指令开始都已经被Shellcode所覆盖,那么程序就可以跳转到该Shellcode上并执行,从而实现了程序流程的控制。
SEH覆盖方法
SEH覆盖方法就是覆盖异常处理程序地址的一种攻击方式。由于SHE结构存放在栈中,因此攻击者可以利用栈溢出漏洞,设计特定的溢出数据,将SEH中异常函数的入口地址覆盖为Shellcode的起始地址或可以跳转到Shellcode的跳转指令地址,从而导致程序发生异常时,Windows异常处理机制执行的不是预设的异常处理函数,而是Shellcode。
堆溢出漏洞及利用
如果能够修改链表节点的指针,在“卸下”和“链入”的过程中就有可能获得一次读写内存的机会。
DWORD Shoot
堆溢出利用的精髓就是用精心构造的数据去溢出覆盖下一个堆块的块首,使其改写块首中的前向指针(flink)和后向指针(blink),然后在分配、释放、合并等操作发生时伺机获得一次向内存任意地址写入任意数据的机会。 攻击者可以进而劫持进程,运行shellcode。
Heap Spray
首先将shellcode放置到堆中,然后在栈溢出时,控制函数执行流程,跳转到堆中执行shellcode。
格式化串漏洞
格式化串漏洞的产生源于数据输出函数中对输出格式解析的缺陷,其根源也是C语言中不对数组边界进行检查的缓冲区错误。
printf函数进行格式化输出时,会根据格式化串中的格式化控制符在栈上取相应的参数,然后按照所需格式输出。 如果函数调用给出的输出数据列表少于格式控制符个数,甚至于没有给出输出数据列表,系统仍然会按照格式化串中格式化控制符的个数输出栈中的数据。
格式化串漏洞利用
格式化串漏洞的利用可以通过如下方法实现:
通过改变格式化串中输出参数的个数实现修改指定地址的值:可以修改填充字符串长度实现;也可以通过改变输出的宽度实现,如%8d。
通过改变格式化串中格式符的个数,调整格式符对应参数在栈中位置,从而实现对栈中特定位置数据的修改。
Windows平台溢出漏洞保护机制
栈溢出检测选项/GS
调用函数时将一个随机生成的秘密值存放在栈上,当函数返回时,检查这个堆栈检测仪的值是否被修改,以此判断是否发生了栈溢出。
对抗/GS保护
- 猜测Cookie值
- 通过同时替换栈中的Cookie和Cookie副本
- 覆盖SEH绕过Cookie检查
- 覆盖父函数的栈数据绕过Cookie检查
数据执行保护DEP
通过使可写内存不可执行或使可执行内存不可写来消除类似的威胁。
执行已经加载的模块中的指令或调用系统函数则不受DEP影响,而栈上的数据只需作为这些函数/指令的参数即可。
对抗数据执行保护DEP
- 利用ret-to-libc执行命令或进行API调用,如调用WinExec实现执行程序。
- 将包含Shellcode的内存页面标记为可执行,然后再跳过去执行。
- 通过分配可执行内存,再将Shellcode复制到内存区域,然后跳过去执行。
- 先尝试关闭当前进程的DEP保护,然后再运行Shellcode。
地址空间布局随机化ASLR
通过对堆、栈、共享库映射等线性区域布局的随机化,增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止漏洞利用的目的。
ASLR机制的缺陷和绕过方法
- 对本地攻击者无能为力
- 造成内存碎片的增多
- 利用没有采用/DYNAMICBASE选项保护的模块做跳板
安全结构化异常处理SafeSEH
SafeSEH保护机制的作用是防止覆盖和使用存储栈上的SEH结构。
其实现原理是,编译器在链接生成二进制IMAGE时,把所有合法的异常处理函数的地址解析出来制成一张安全的SEH表,保存在程序的IMAGE数据块里面,当程序调用异常处理函数时会将函数地址与安全SEH表中的地址进行匹配,检查调用的异常处理函数是否位于该表中。
微软在.Net编译器中加入了/safeSEH连接选项。
对抗SafeSEH机制的方法
- 利用未启用SafeSEH的模块作为跳板进行绕过
- 利用加载模块之外的地址进行绕过
增强缓解体验工具包EMET
- 增强型DEP
- SafeSEH的升级版——SEHOP
- 强制性ASLR
- HeapSpray防护