先来看看基于 Red Hat 与 Fedora 衍生版(例如 CentOS)系统用于阻止栈溢出攻击的内核参数,主要包含两项:

kernel.exec-shield

可执行栈保护,字面含义比较“绕”,

实际上就是用来控制能否执行存储在栈

中的代码,其值为1时表示禁止;为0时表示允许;默认为1,表示禁止执行栈

中的代码,如此一来,即便覆盖了函数的返回地址导致栈溢出,也无法执行

shellcode

查看与修改系统当前的可执行栈保护参数:

[root@localhost 桌面]# sysctl -a | grep -e exec

ernel.exec-shield = 1

[root@localhost 桌面]# cat /proc/sys/kernel/exec-shield

1

[root@localhost 桌面]# sysctl -w kernel.exec-shield=0

kernel.exec-shield = 0

[root@localhost 桌面]# cat /proc/sys/kernel/exec-shield

0

注意:

一,只有在学习和测试栈溢出攻击的原理时,才建议关闭可执行栈保护机制

二,在基于 Debian 与 Ubuntu 衍生版

(例如 BackTrack 5 Release 3)的系统上,不支持可执行栈保护机制:

root@bt:~# uname -a

Linux bt 3.2.6 #1 SMP Fri Feb 17 10:40:05 EST 2012 i686 GNU/Linux

root@bt:~# sysctl -a | grep -e kernel.exec

error: permission denied on key 'vm.compact_memory'

error: permission denied on key 'dev.parport.parport0.autoprobe'

error: permission denied on key 'dev.parport.parport0.autoprobe0'

error: permission denied on key 'dev.parport.parport0.autoprobe1'

error: permission denied on key 'dev.parport.parport0.autoprobe2'

error: permission denied on key 'dev.parport.parport0.autoprobe3'

error: permission denied on key 'net.ipv4.route.flush'

error: permission denied on key 'net.ipv6.route.flush'

root@bt:~#

或许是社区的开发人员认为,有下面另一种叫做堆栈地址随机化的机制,就足够应对缓冲区溢出攻击了,也可能是由于 Debian / Ubuntu 面向运行桌面应用居多的用户群体,它并不像销售给企业公司用户的 Red Hat 类发行版那样,对安全性的要求更为严格,才能保护用户的服务器,资产安全

kernel.randomize_va_space

堆栈地址随机初始化,很好理解,就是在每次将程序加载到内存时,进程地

址空间的堆栈起始地址都不一样,动态变化,导致猜测或找出地址来执行

shellcode 变得非常困难,它和可执行栈保护的区别在于,后者即便是找到了

地址也是无法执行的;所有的 2.6 以上版本的  Linux 内核都支持并启用了

这一项特性;

查看与修改系统当前的堆栈地址随机初始化参数:

[root@localhost 桌面]# sysctl -a | grep randomize

kernel.randomize_va_space = 2

[root@localhost 桌面]# cat /proc/sys/kernel/randomize_va_space

2

[root@localhost 桌面]# sysctl -w kernel.randomize_va_space=0

kernel.randomize_va_space = 0

[root@localhost 桌面]# cat /proc/sys/kernel/randomize_va_space

0

参数值为2时,表示启用随机地址功能;0表示关闭;

基于 Debian 与 Ubuntu 衍生版默认支持并且启用了随机地址功能:

1

2

root@bt:~# sysctl -a | grep -e kernel.randomize

kernel.randomize_va_space = 2

下面,我们在一个启用了随机地址功能的机器上,查看执行同一个程序4次加载的动态链接共享库的入口地址(linux-gate.so.1),发现每次的入口地址都不同,验证了随机地址的效果:

[root@centos6-5 桌面]# cat /proc/sys/kernel/randomize_va_space

2

[root@centos6-5 桌面]# ldd /bin/ls | grep linux-gate.so.1

linux-gate.so.1 =>  (0x00dff000)

[root@centos6-5 桌面]# ldd /bin/ls | grep linux-gate.so.1

linux-gate.so.1 =>  (0x00503000)

[root@centos6-5 桌面]# ldd /bin/ls | grep linux-gate.so.1

linux-gate.so.1 =>  (0x00213000)

[root@centos6-5 桌面]# ldd /bin/ls | grep linux-gate.so.1

linux-gate.so.1 =>  (0x004b5000)

[root@centos6-5 桌面]#

同理,关闭随机地址功能,连续5次查看执行程序时加载的 linux-gate.so.1 入口地址:

[root@centos6-5 桌面]# sysctl -w kernel.randomize_va_space=0

kernel.randomize_va_space = 0

[root@centos6-5 桌面]# ldd /bin/ls | grep linux-gate.so.1

linux-gate.so.1 =>  (0x00110000)

[root@centos6-5 桌面]# ldd /bin/ls | grep linux-gate.so.1

linux-gate.so.1 =>  (0x00110000)

[root@centos6-5 桌面]# ldd /bin/ls | grep linux-gate.so.1

linux-gate.so.1 =>  (0x00110000)

[root@centos6-5 桌面]# ldd /bin/ls | grep linux-gate.so.1

linux-gate.so.1 =>  (0x00110000)

[root@centos6-5 桌面]# ldd /bin/ls | grep linux-gate.so.1

linux-gate.so.1 =>  (0x00110000)

再来看看 GCC 4.1 版本以后引入的两个编译参数:

(默认情况下,编译时不会指定这两个参数,用于阻止缺乏安全编码意识的程序员写出存在缓冲区溢出漏洞的程序,

但是站在逆向工程的角度来看,指定这两个参数,特意构造有漏洞的程序,对于学习和理解栈溢出的原理还是有帮助的;

再次提醒,这里介绍的两个编译参数必须同时打开,而且还要同时禁用前面讲的可执行栈保护与栈地址随机初始化,满足这4个条件后,一般而言,就可以测试 shellcode 的效果了

GCC 编译选项  -fno-stack-protector

禁用栈保护功能,默认是启用的;

gcc 的栈保护机制是指,在栈的缓冲区(大小通常由程序员给定)写入内容前

,在结束地址之后与返回地址之前,放入随机的验证码,由于栈帧是从内存高

址段向内存低址段增长的(回顾第一张图),结束地址在高址段;返回地

址在低址段,栈溢出时,会从高址段向低址段覆盖数据,因此如果想要覆盖返

回地址的内容,必定先覆盖结束地址,验证码,才能覆盖返回地址,

因此可以通过比较写入缓冲区前后的验证码是否发生改变,来检测并阻止溢出

攻击

GCC 编译选项  -z execstack

启用可执行栈,默认是禁用的;

该选项与 ld 链接器有关:ld 链接器在链接程序的时候,如果所有的 .o 文

件的堆栈段都标记为不可执行,那么整个库的堆栈段才会被标记为不可执行;

相反,即使只有一个 .o 文件的堆栈段被标记为可执行,那么整个库的堆栈段

将被标记为可执行,

换言之,默认是所有的 .o 文件的堆栈段都标记为不可执行

检查堆栈段可执行性的方法是:

1

[root@centos6-5vm /]# readelf -lW stack-overflow1-test | grep GNU_STACK

找出在输出中有无 E 标记;有 E 标记就说明堆栈段是可执行的,其中,

stack-overflow1-test  为我们编写的简单栈溢出测试程序,源码如下:

#include <stdio.h>

greeting(char *temp1, char *temp2){

char name[20];

strcpy(name, temp2);

printf("hello  %s  %s\n", temp1, name);

}

main(int argc, char *argv[]){

greeting(argv[1], argv[2]);

printf("bye  %s  %s\n", argv[1], argv[2]);

}

这是一个典型的存在缓冲区溢出漏洞的程序,greeting 函数定义了一个只有20字节大小的字符数组(缓冲区),strcpy 函数不检查用户输入的第二个参数(由 main 函数的第二个参数传递)是否超过20字节,就写入这个缓冲区中

我们用 gcc 默认参数配置来编译这个源文件,然后检查堆栈段的可执行性:

[root@centos6-5vm /]# gcc -v -Wall  -o stack-overflow1-test stack-overflow1-test.c

(***************省略部分输出*************

GNU C (GCC) 版本 4.4.7 20120313 (Red Hat 4.4.7-4) (i686-redhat-linux)

由 GNU C 版本 4.4.7 20120313 (Red Hat 4.4.7-4) 编译,GMP 版本 4.3.1,MPFR 版本 2.4.1。

GGC 准则:--param ggc-min-expand=100 --param ggc-min-heapsize=131072

Compiler executable checksum: 5f02f32570d532de29ae0b402446343a

stack-overflow1-test.c:2: 警告:返回类型默认为‘int’

stack-overflow1-test.c: 在函数‘greeting’中:

stack-overflow1-test.c:4: 警告:隐式声明函数‘strcpy’

stack-overflow1-test.c:4: 警告:隐式声明与内建函数‘strcpy’不兼容

stack-overflow1-test.c: 在文件层:

stack-overflow1-test.c:8: 警告:返回类型默认为‘int’

stack-overflow1-test.c: 在函数‘main’中:

stack-overflow1-test.c:11: 警告:在有返回值的函数中,控制流程到达函数尾

stack-overflow1-test.c: 在函数‘greeting’中:

stack-overflow1-test.c:6: 警告:在有返回值的函数中,控制流程到达函数尾

COLLECT_GCC_OPTIONS='-v' '-Wall' '-o' 'stack-overflow1-test' '-mtune=generic' '-march=i686'

as -V -Qy -o /tmp/ccv9qpvk.o /tmp/ccT7rHyO.s

GNU assembler version 2.20.51.0.2 (i686-redhat-linux) using BFD version version 2.20.51.0.2-5.36.el6 20100205

***************省略部分输出*************

可以看到, -Wall  选项(参考前文解释)显示所有的警告和错误信息,对于增加程序的可移植性非常有帮助,例如它指出在源码的二行,greeting 自定义函数没有定义返回类型,将采用默认返回类型:int

另外,在 greeting 函数中,调用 strcpy 函数前未声明和定义(在程序中调用 strcpy 函数需要包含系统头文件 string.h)

同样,我们没有为 main 函数指定返回类型

在上面的例子中,虽然每个警告都非致命的语法或词法错误,但是 -Wall 选项确实可以“强制”培养程序员的良好编程习惯

言归正传,检查生成的二进制可执行文件:

[root@centos6-5vm /]# readelf -lW stack-overflow1-test | grep GNU_STACK

GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

其中没有 E 标记,这说明该程序即便存在溢出漏洞,但是由于 GCC 的堆栈段不可执行保护机制,该漏洞也没有太大被利用的可能性

我们“故意”关掉 GCC 的堆栈段不可执行保护机制:指定 -z execstack  选项,再次编译源文件:

[root@centos6-5vm /]# gcc -v -Wall -z execstack -o stack-overflow1-test stack-overflow1-test.c

[root@centos6-5vm /]# readelf -lW stack-overflow1-test | grep GNU_STACK

GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4

这次的输出中,带有 E 标记,说明堆栈段是可执行的,

再次强调,在 CentOS6.5 中,要真正能利用这个程序测试你编写的 shellcode ,需要执行下面操作:

[root@localhost 桌面]# sysctl -w kernel.randomize_va_space=0

kernel.randomize_va_space = 0

[root@localhost 桌面]# sysctl -w kernel.exec-shield=0

kernel.exec-shield = 0

[root@localhost 桌面]# gcc -v -fno-stack-protector -z execstack -g -o stack-overflow1-test stack-overflow1-test.c

ubuntu –buffer-overflow

Ubuntu下面的GCC默认开启了Stack Smashing Protector,如果想在这个系统中学习缓冲区溢出的原理,在编译时要加上fno-stack-protector选项,否则运行时会出现*** stack smashing detected ***: xxx terminated,而不是期望的Segmentation fault。同时还需要加上允许栈执行的选项。

gcc -fno-stack-protector -z execstack -mpreferred-stack-boundary=2 -ggdb -o xxx xxx.c

execstack

用于阻止缓冲区溢出攻击的 Linux 内核参数与 gcc 编译选项的更多相关文章

  1. CSAPP:逆向工程【缓冲区溢出攻击】

    逆向工程[缓冲区溢出攻击] 任务描述 掌握函数调用时的栈帧结构,利用输入缓冲区的溢出漏洞,将攻击代码嵌入当前程序的栈帧中,使程序执行我们所期望的过程. 主要方法 溢出的字符将覆盖栈帧上的数据,会覆盖程 ...

  2. Linux下缓冲区溢出攻击的原理及对策(转载)

    前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...

  3. Linux下缓冲区溢出攻击的原理及对策

    前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈 帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实 ...

  4. linux内核参数sysctl.conf,TCP握手ack,洪水攻击syn,超时关闭wait

    题记:优化Linux内核sysctl.conf参数来提高服务器并发处理能力 PS:在服务器硬件资源额定有限的情况下,最大的压榨服务器的性能,提高服务器的并发处理能力,是很多运维技术人员思考的问题.要提 ...

  5. linux内核参数sysctl.conf,TCP握手ack,洪水攻击syn,超时关闭wait(转)

    http://www.xshell.net/linux/Linux_sysctl_conf.html 优化Linux内核sysctl.conf参数来提高服务器并发处理能力 Posted by 破冰 o ...

  6. CSAPP缓冲区溢出攻击实验(上)

    CSAPP缓冲区溢出攻击实验(上) 下载实验工具.最新的讲义在这. 网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.只是没有关系,大体上仅仅是程序名(sendstring)或者參数 ...

  7. CSAPP缓冲区溢出攻击实验(下)

    CSAPP缓冲区溢出攻击实验(下) 3.3 Level 2: 爆竹 实验要求 这一个Level的难度陡然提升,我们要让getbuf()返回到bang()而非test(),并且在执行bang()之前将g ...

  8. CSAPP阅读笔记-变长栈帧,缓冲区溢出攻击-来自第三章3.10的笔记-P192-P204

    一.几个关于指针的小知识点: 1.  malloc是在堆上动态分配内存,返回的是void *,使用时会配合显式/隐式类型转换,用完后需要用free手动释放. alloca是标准库函数,可以在栈上分配任 ...

  9. Linux内核参数配置

    Linux在系统运行时修改内核参数(/proc/sys与/etc/sysctl.conf),而不需要重新引导系统,这个功能是通过/proc虚拟文件系统实现的. 在/proc/sys目录下存放着大多数的 ...

随机推荐

  1. 【Alpha】第七次Scrum meeting

    今日任务一览: 姓名 今日完成任务 所耗时间 刘乾 今日没有做很多事...一天都在沟通细化需求与画电路图 2 鲁聃 生成物理报告实验页面的生成 Issue链接:https://github.com/b ...

  2. Linux内核分析——第六周学习笔记20135308

    第六周 进程的描述和进程的创建 一.进程描述符task_struct数据结构 1.操作系统三大功能 进程管理 内存管理 文件系统 2.进程控制块PCB——task_struct 也叫进程描述符,为了管 ...

  3. KNY三人组对YiSmile小程序的项目总结

    设想和目标 1.我们的小程序要解决什么问题? 针对于本校学生,服务于本校学生.由于丢东西,找东西的事情每天都在上演,空间说说,朋友圈,官方QQ,信息比较冗杂,没有一个固定的平台来专门提供学生.此外,教 ...

  4. c语言四则运算

    #include<stdio.h>#define W 5main(){ int a,b,i=0,c,d,r=0; while(i<W) { i++; srand(time()); a ...

  5. Sprint report

    Sprint report 一.需求分析:随着在校大学生人数的不断增加,许多高校出现了许多个校区并存的局面,并且校区之间的地理位置跨度非常大,给高校选课带来了很大的不方便,数据处理手工操作,工作量大, ...

  6. Mysql设置允许外网访问(图文)

    1.打开mysql.exe(MySQL Command Line Client),输入密码 2.输入:use mysql; 3.查询host输入: select user,host from user ...

  7. Mac安装Appium的Android环境

    1.下载android sdk http://down.tech.sina.com.cn/page/45703.html   2.解压,配置环境变量   ANDROID_HOME=/Users/wp/ ...

  8. offices 激活

    http://www.xitongcheng.com/jiaocheng/dnrj_article_44577.html  破解工具见cnblos文件中 : https://blog.csdn.net ...

  9. 关于vue-eslint自动补全代码,以及自动生成雪碧图

    一.配置eslint module.exports={ "printWidth": 240, //一行的字符数,如果超过会进行换行,默认为80 "tabWidth&quo ...

  10. OneZero第二次站立会议(2016.3.22)

    会议时间:2016年3月22日 9:33~9:57 会议成员:冉华,张敏,王巍,夏一鸣. 会议目的:汇报前一天工作,全体成员评论并修改. 会议内容:以下为会议插图 1.界面原型方面,小组成员对夏所画的 ...