Handle copy dump
字数 1879 2025-08-06 18:08:11

Windows 进程句柄复制与转储技术详解

1. 技术概述

本文介绍了一种利用 Windows NT API 进行进程句柄复制和内存转储的技术方法。该方法最初由国外研究人员在2020年提出,核心思路是通过 NtDuplicateObject 函数间接获取目标进程句柄,再结合其他 NT API 实现进程内存转储。

2. 核心 API 解析

2.1 NtDuplicateObject 函数

NTSYSAPI NTSTATUS ZwDuplicateObject(
  [in] HANDLE SourceProcessHandle,
  [in] HANDLE SourceHandle,
  [in, optional] HANDLE TargetProcessHandle,
  [out, optional] PHANDLE TargetHandle,
  [in] ACCESS_MASK DesiredAccess,
  [in] ULONG HandleAttributes,
  [in] ULONG Options
);

关键参数说明:

  • SourceProcessHandle: 源进程句柄
  • SourceHandle: 要复制的句柄
  • TargetProcessHandle: 目标进程句柄
  • TargetHandle: 接收复制后的句柄指针
  • DesiredAccess: 请求的访问权限
  • Options: 复制选项,常用 DUPLICATE_SAME_ACCESS

2.2 NtQuerySystemInformation 函数

__kernel_entry NTSTATUS NtQuerySystemInformation(
  [in] SYSTEM_INFORMATION_CLASS SystemInformationClass,
  [in, out] PVOID SystemInformation,
  [in] ULONG SystemInformationLength,
  [out, optional] PULONG ReturnLength
);

关键参数说明:

  • SystemInformationClass: 信息类别,使用 SystemHandleInformation 枚举值
  • SystemInformation: 接收系统信息的缓冲区
  • SystemInformationLength: 缓冲区大小

2.3 SYSTEM_HANDLE_INFORMATION 结构

该结构包含系统中所有打开的句柄信息:

  • NumberOfHandles: 句柄总数
  • Handles[1]: 句柄数组,每个元素包含:
    • UniqueProcessId: 拥有句柄的进程ID
    • HandleValue: 句柄值
    • ObjectTypeIndex: 对象类型索引
    • GrantedAccess: 授予的访问权限
    • Flags: 标志位

3. 技术实现步骤

3.1 基础示例:跨进程复制线程句柄

m.exe (源进程)

#include <iostream>
#include <windows.h>
#include <process.h>
#include <TlHelp32.h>
#include "ntdll.h"
#pragma comment(lib, "ntdll.lib")

using namespace std;

unsigned __stdcall thread(void* lpPragma) {
    while(1) {
        Sleep(500);
        cout << "terminal me" << endl;
    }
    return 0;
}

HANDLE GetProcessHandle() {
    DWORD pid;
    PROCESSENTRY32 ed;
    ed.dwSize = sizeof(PROCESSENTRY32);
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if(Process32First(snapshot, &ed) == TRUE) {
        while(Process32Next(snapshot, &ed) == TRUE) {
            if(string(ed.szExeFile) == "t.exe") {
                pid = ed.th32ProcessID;
                return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
            }
        }
    }
    return NULL;
}

int main(void) {
    HANDLE hThread;
    hThread = (HANDLE)_beginthreadex(NULL, 0, thread, NULL, 0, NULL);
    cout << "Thread Handle: " << hThread << endl;
    
    HANDLE hTarget;
    if(NtDuplicateObject(GetCurrentProcess(), hThread, GetProcessHandle(), 
                        &hTarget, PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ACCESS) == STATUS_SUCCESS) {
        cout << "句柄复制成功, 其句柄值为:" << hTarget << endl;
    }
    
    cin.get();
    return 0;
}

t.exe (目标进程)

#include <iostream>
#include <windows.h>
#include <stdlib.h>
#include <process.h>

using namespace std;

int main(void) {
    HANDLE hRecv;
    cout << "请输入复制过来的句柄:" << endl;
    cin >> hRecv;
    TerminateThread(hRecv, 0);
    system("pause");
    return 0;
}

3.2 完整进程转储实现流程

  1. 获取 SeDebug 权限

    • 需要提升至 DEBUG 权限才能访问其他进程
  2. 枚举系统句柄

    • 使用 NtQuerySystemInformation(SystemHandleInformation) 获取所有句柄
    • 遍历 SYSTEM_HANDLE_INFORMATION 结构中的句柄数组
  3. 筛选目标进程句柄

    • 通过 UniqueProcessIdObjectTypeIndex 筛选进程句柄
    • 使用 OpenProcess 打开目标进程,最小权限为 PROCESS_DUP_HANDLE
  4. 复制句柄

    • 使用 NtDuplicateObject 复制目标句柄到当前进程
  5. 验证句柄类型

    • 使用 NtQueryObject 查询句柄信息,确认是否为进程句柄
  6. 获取进程路径

    • 使用 QueryFullProcessImageNameW 获取进程完整路径
    • 根据路径判断是否为需要转储的目标进程
  7. 执行内存转储

    • 使用 MiniDumpWriteDump 函数将进程内存转储到文件

4. 关键实现细节

4.1 句柄复制权限

复制句柄时不需要 PROCESS_ALL_ACCESS 权限,最小权限为:

  • PROCESS_DUP_HANDLE: 允许复制句柄
  • PROCESS_QUERY_INFORMATION: 允许查询进程信息

4.2 错误处理

  • 检查每个 API 调用的返回值
  • 处理 STATUS_INFO_LENGTH_MISMATCH 错误(缓冲区不足时)
  • 处理 STATUS_ACCESS_DENIED 错误(权限不足时)

4.3 性能优化

  • 合理设置缓冲区大小,避免多次调用 NtQuerySystemInformation
  • 使用进程快照减少枚举时间
  • 尽早过滤不需要的句柄类型

5. 防御措施

检测此类攻击的方法包括:

  • 监控 NtDuplicateObject 调用
  • 检查进程是否获取了 SeDebug 权限
  • 监控异常的句柄复制操作
  • 使用受保护的进程(Protected Process)

6. 应用场景

  • 取证分析
  • 进程内存检查
  • 安全研究
  • 恶意软件分析

7. 注意事项

  1. 此技术需要管理员权限
  2. 可能触发部分安全软件的检测
  3. 仅限合法研究和授权测试使用
  4. 转储敏感进程内存可能涉及法律问题

8. 参考资源

Windows 进程句柄复制与转储技术详解 1. 技术概述 本文介绍了一种利用 Windows NT API 进行进程句柄复制和内存转储的技术方法。该方法最初由国外研究人员在2020年提出,核心思路是通过 NtDuplicateObject 函数间接获取目标进程句柄,再结合其他 NT API 实现进程内存转储。 2. 核心 API 解析 2.1 NtDuplicateObject 函数 关键参数说明: SourceProcessHandle : 源进程句柄 SourceHandle : 要复制的句柄 TargetProcessHandle : 目标进程句柄 TargetHandle : 接收复制后的句柄指针 DesiredAccess : 请求的访问权限 Options : 复制选项,常用 DUPLICATE_SAME_ACCESS 2.2 NtQuerySystemInformation 函数 关键参数说明: SystemInformationClass : 信息类别,使用 SystemHandleInformation 枚举值 SystemInformation : 接收系统信息的缓冲区 SystemInformationLength : 缓冲区大小 2.3 SYSTEM_ HANDLE_ INFORMATION 结构 该结构包含系统中所有打开的句柄信息: NumberOfHandles : 句柄总数 Handles[1] : 句柄数组,每个元素包含: UniqueProcessId : 拥有句柄的进程ID HandleValue : 句柄值 ObjectTypeIndex : 对象类型索引 GrantedAccess : 授予的访问权限 Flags : 标志位 3. 技术实现步骤 3.1 基础示例:跨进程复制线程句柄 m.exe (源进程) t.exe (目标进程) 3.2 完整进程转储实现流程 获取 SeDebug 权限 需要提升至 DEBUG 权限才能访问其他进程 枚举系统句柄 使用 NtQuerySystemInformation(SystemHandleInformation) 获取所有句柄 遍历 SYSTEM_HANDLE_INFORMATION 结构中的句柄数组 筛选目标进程句柄 通过 UniqueProcessId 和 ObjectTypeIndex 筛选进程句柄 使用 OpenProcess 打开目标进程,最小权限为 PROCESS_DUP_HANDLE 复制句柄 使用 NtDuplicateObject 复制目标句柄到当前进程 验证句柄类型 使用 NtQueryObject 查询句柄信息,确认是否为进程句柄 获取进程路径 使用 QueryFullProcessImageNameW 获取进程完整路径 根据路径判断是否为需要转储的目标进程 执行内存转储 使用 MiniDumpWriteDump 函数将进程内存转储到文件 4. 关键实现细节 4.1 句柄复制权限 复制句柄时不需要 PROCESS_ALL_ACCESS 权限,最小权限为: PROCESS_DUP_HANDLE : 允许复制句柄 PROCESS_QUERY_INFORMATION : 允许查询进程信息 4.2 错误处理 检查每个 API 调用的返回值 处理 STATUS_INFO_LENGTH_MISMATCH 错误(缓冲区不足时) 处理 STATUS_ACCESS_DENIED 错误(权限不足时) 4.3 性能优化 合理设置缓冲区大小,避免多次调用 NtQuerySystemInformation 使用进程快照减少枚举时间 尽早过滤不需要的句柄类型 5. 防御措施 检测此类攻击的方法包括: 监控 NtDuplicateObject 调用 检查进程是否获取了 SeDebug 权限 监控异常的句柄复制操作 使用受保护的进程(Protected Process) 6. 应用场景 取证分析 进程内存检查 安全研究 恶意软件分析 7. 注意事项 此技术需要管理员权限 可能触发部分安全软件的检测 仅限合法研究和授权测试使用 转储敏感进程内存可能涉及法律问题 8. 参考资源 Microsoft 文档: NtDuplicateObject NtQuerySystemInformation Process Security and Access Rights