一、SSP (Stack Smashing Protection)
owl@owl-VirtualBox:~$ cat ./smallbuffer.c
//smallbuffer.c
#include <string.h>
int main (int argc[],char * argv[]){
char buffer[10];
strcpy(buffer,argv[1]);
}
owl@owl-VirtualBox:~$ gcc -fno-stack-protector -mpreferred-stack-boundary=2 -o smallbuffer smallbuffer.c //关闭SSP
owl@owl-VirtualBox:~$ gdb -q smallbuffer
Reading symbols from /home/owl/smallbuffer...(no debugging symbols found)...done.
(gdb) disassemble main
Dump of assembler code for function main:
0x080483e4 <+0>: push ebp
0x080483e5 <+1>: mov ebp,esp
0x080483e7 <+3>: sub esp,0x14
0x080483ea <+6>: mov eax,DWORD PTR [ebp+0xc] //将参数地址,放至esp+0x4
0x080483ed <+9>: add eax,0x4
0x080483f0 <+12>: mov eax,DWORD PTR [eax]
0x080483f2 <+14>: mov DWORD PTR [esp+0x4],eax
0x080483f6 <+18>: lea eax,[ebp-0xa] //将buffer的地址,放至esp
0x080483f9 <+21>: mov DWORD PTR [esp],eax
0x080483fc <+24>: call 0x8048300 <strcpy@plt>
0x08048401 <+29>: leave //pop ebp
0x08048402 <+30>: ret
End of assembler dump.
owl@owl-VirtualBox:~$ gcc -mpreferred-stack-boundary=2 -o smallbuffer smallbuffer.c //默认开启SSP
owl@owl-VirtualBox:~$ gdb -q smallbuffer
Reading symbols from /home/owl/smallbuffer...(no debugging symbols found)...done.
(gdb) disassemble main
Dump of assembler code for function main:
0x08048434 <+0>: push ebp
0x08048435 <+1>: mov ebp,esp
0x08048437 <+3>: sub esp,0x20
0x0804843a <+6>: mov eax,DWORD PTR [ebp+0x8] //get argc
0x0804843d <+9>: mov DWORD PTR [ebp-0x14],eax
0x08048440 <+12>: mov eax,DWORD PTR [ebp+0xc] //get argv pointer
0x08048443 <+15>: mov DWORD PTR [ebp-0x18],eax
0x08048446 <+18>: mov eax,gs:0x14 //set the canary
0x0804844c <+24>: mov DWORD PTR [ebp-0x4],eax
0x0804844f <+27>: xor eax,eax //eax=0
0x08048451 <+29>: mov eax,DWORD PTR [ebp-0x18] //strcpy()
0x08048454 <+32>: add eax,0x4
0x08048457 <+35>: mov eax,DWORD PTR [eax]
0x08048459 <+37>: mov DWORD PTR [esp+0x4],eax
0x0804845d <+41>: lea eax,[ebp-0xe]
0x08048460 <+44>: mov DWORD PTR [esp],eax
0x08048463 <+47>: call 0x8048350 <strcpy@plt>
0x08048468 <+52>: mov edx,DWORD PTR [ebp-0x4] //stack_overflow_check
0x0804846b <+55>: xor edx,DWORD PTR gs:0x14
0x08048472 <+62>: je 0x8048479 <main+69>
0x08048474 <+64>: call 0x8048340 <__stack_chk_fail@plt>
0x08048479 <+69>: leave
0x0804847a <+70>: ret
End of assembler dump.
存在的问题:1,未保护栈中的其他变量;
2,在特定情况,可以利用数组,绕过canary;
3,栈溢出检查是在程序最后,程序中调用函数造成溢出,仍可控制eip;
二、不可执行栈
不可执行栈属于编译器层面防护,为编译的程序段提供读R,写W,可X执行标志(栈为RW),意味着之前存储的shellcode 将不能够执行。
gcc 默认开启不可执行栈功能;
关闭不可执行栈功能:gcc -z execstack
存在的问题:1,可以将shellcode写入环境变量,exploit !;
2,Return To Libc攻击(把返回地址直接指向系统某个已存在的函数,如system);
三、不可执行内存页
不可执行内存页属于系统内核层面的防护,可结合cpu的NX位,将内存分为可读写的页和可执行的页(程序的代码等部分所在的页不可修改)。
存在的问题:1,Borrowed Code Chunks攻击(限于涉及的链接库);
2,ROP(Retrun Oriented Programming)攻击(所有的恶意攻击都通过现存函数的指令片断串连而成);
四、ALSR(Address Space Layout Randomization)
ALSR属于系统内核层面的防护,是目前对ROP最有效的办法。
现在的Linux默认开启ASLR功能
关闭ASLR(Ubuntu)以root用户执行:echo "0" > /proc/sys/kernel/randomize_va_space
(gdb时为了方便调试,默认关闭ASLR,调试时启用ASLR,(gdb) i proc map)
本文介绍了四种防止栈溢出和代码注入攻击的保护机制:SSP(Stack Smashing Protection)、不可执行栈、不可执行内存页和ALSR(Address Space Layout Randomization)。SSP在程序最后检查栈溢出,但存在绕过可能;不可执行栈阻止shellcode执行,但Return To Libc攻击仍可行;不可执行内存页结合CPU的NX位增强防护,但面临ROP攻击挑战;ALSR通过随机化内存布局有效抵御ROP攻击,是当前最有效的防御手段之一。

9209

被折叠的 条评论
为什么被折叠?



