Linux保护机制
Canary
Canary的中文名字叫做金丝雀保护,它的目的是防止栈的进行溢出攻击,首先glibc可以分为两种形式:第一种是用\x00进行截断字符,这个主要用来才处理意外的memcpy等函数的覆盖溢出;另一种是初始化时根据计算机周围环境产生熵值,存放在如.bss的地方。不同的OS的型号(x86||x64)会有不同的canary初始化方式,如不同的寄存器。
攻击Canary有两种方式:第一种是泄露canary的值,然后原封不动的覆盖上去,常见的实在子线程中,如socket通信中,canary的值是一样的可以暴力破解出来;另一种是修改canary的值同时在.bss中也修改xor的值,使它们保持一致。
No-execute
no-execute表示的是当前页(栈||堆)的可执行权限,如果第63位是1,则不可执行;如果是0,则可执行。在init()的时候会对其进行检查,然后进行权限赋值。我们通常根据页的权限来判断攻击方式。如下的程序,如果开启了保护,那么我们就要利用system或者系统调用来进行攻击;否则可以选择栈上注入shellcode来攻击。
#include<unistd.h>
void vuln_func(){
char buf[128];
read(STDIN_FILENO,buf,256);
}
int main(int argc,char *argv[]) {
vuln_func();
write(STDOUT_FILENO,"Hello world!\n",13);
}
ASLR
全称为Address Space Layout Randomization,在Linux中它的值在/proc/sys/kernel/randomize_va_space中,可以进行更改:0时无开启,1时随机化mmap,stack,vdso,2时在1的基础上随机化heap。可以用下面的代码做个实验。
#include<stdio.h> 2 #include<stdlib.h>
#include<dlfcn.h>
int main() {
int stack;
int *heap=malloc(sizeof(int));
void *handle=dlopen("libc.so.6",RTLD_NOW | RTLD_GLOBAL);
printf("executable:%p\n",&main);
printf("system@plt:%p\n",&system);
printf("heap:%p\n",heap);
printf("stack:%p\n",&stack);
printf("libc:%p\n",handle);
free(heap);
return 0;
}
PIE
PIE会随机化内存中的代码位置,但是只是随机化base,其中的offset还是没有变化。
gcc -pie -fpie test.c -ldl
FORTIFY_SOURCE
FORTIFY_SOURCE是一种用来检测字符串操作的机制,现在这种机制不仅仅在glibc中,在string.h和stdio.h也有相应的保护。
-D_FORTIFY_SOURCE=0:无保护机制
-D_FORTIFY_SOURCE=1:开启缓冲区溢出攻击检查
-D_FORTIFY_SOURCE=2:开启缓冲区溢出以及格式化字符串攻击检查
RELRO
Partial RELRO开启时标记为可读,在Ubuntu16.04上,默认开启。
Full RELRO开启时,mprotect会默认标记它为只读,同时在初始化时就避免了延长绑定。