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: 拥有句柄的进程IDHandleValue: 句柄值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 完整进程转储实现流程
-
获取 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. 注意事项
- 此技术需要管理员权限
- 可能触发部分安全软件的检测
- 仅限合法研究和授权测试使用
- 转储敏感进程内存可能涉及法律问题