You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中读写其他进程标准句柄的问题及解决方法

问题原因

你代码里的win32api.GetStdHandle只能获取当前进程的标准输入/输出/错误句柄,和你通过OpenProcess打开的目标进程完全无关。如果当前进程没有关联控制台(比如用pythonw.exe运行),拿到的句柄本身就是无效的,自然会触发WriteFile的无效句柄错误。

解决方法

要操作其他进程的标准句柄,需要通过以下步骤实现:

  1. 调用原生Windows API NtQueryInformationProcess 获取目标进程的PEB(进程环境块)地址
  2. 读取目标进程内存中的PEB数据,从中提取标准句柄数组
  3. 使用DuplicateHandle将目标进程的句柄复制到当前进程的句柄表中(句柄是进程私有资源,不能直接跨进程使用)
  4. 用复制后的句柄进行读写操作

以下是修正后的代码示例:

import win32api
import win32con
import win32file
import ctypes
from ctypes import wintypes

# 定义所需的结构体和API
class PROCESS_BASIC_INFORMATION(ctypes.Structure):
    _fields_ = [
        ("Reserved1", wintypes.PVOID),
        ("PebBaseAddress", wintypes.PVOID),
        ("Reserved2", wintypes.PVOID * 2),
        ("UniqueProcessId", wintypes.ULONG),
        ("Reserved3", wintypes.PVOID)
    ]

class PEB(ctypes.Structure):
    _fields_ = [
        ("Reserved1", wintypes.BYTE * 2),
        ("BeingDebugged", wintypes.BYTE),
        ("Reserved2", wintypes.BYTE * 1),
        ("Reserved3", wintypes.PVOID * 2),
        ("Ldr", wintypes.PVOID),
        ("ProcessParameters", wintypes.PVOID),
    ]

class RTL_USER_PROCESS_PARAMETERS(ctypes.Structure):
    _fields_ = [
        ("Reserved1", wintypes.PVOID * 16),
        ("Reserved2", wintypes.PVOID * 10),
        ("StdHandle", wintypes.HANDLE * 3),  # 索引0:STD_INPUT, 1:STD_OUTPUT, 2:STD_ERROR
    ]

ntdll = ctypes.WinDLL("ntdll.dll")
ntdll.NtQueryInformationProcess.argtypes = [
    wintypes.HANDLE,
    wintypes.ULONG,
    wintypes.PVOID,
    wintypes.ULONG,
    wintypes.PULONG
]
ntdll.NtQueryInformationProcess.restype = wintypes.LONG

# 目标进程PID
pid = 4908

# 打开目标进程,需要足够权限
process_handle = win32api.OpenProcess(
    win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ | win32con.PROCESS_DUP_HANDLE,
    False,
    pid
)

# 获取PROCESS_BASIC_INFORMATION
pbi = PROCESS_BASIC_INFORMATION()
return_length = wintypes.ULONG()
ntdll.NtQueryInformationProcess(
    process_handle,
    0,  # ProcessBasicInformation
    ctypes.byref(pbi),
    ctypes.sizeof(pbi),
    ctypes.byref(return_length)
)

# 读取PEB数据
peb = PEB()
win32file.ReadProcessMemory(
    process_handle,
    pbi.PebBaseAddress,
    ctypes.byref(peb),
    ctypes.sizeof(peb),
    None
)

# 读取RTL_USER_PROCESS_PARAMETERS
params = RTL_USER_PROCESS_PARAMETERS()
win32file.ReadProcessMemory(
    process_handle,
    peb.ProcessParameters,
    ctypes.byref(params),
    ctypes.sizeof(params),
    None
)

# 复制目标进程的stdout句柄到当前进程
target_stdout = params.StdHandle[1]
current_process = win32api.GetCurrentProcess()
duplicated_handle = win32api.DuplicateHandle(
    process_handle,
    target_stdout,
    current_process,
    0,
    False,
    win32con.DUPLICATE_SAME_ACCESS
)

# 写入数据
win32file.WriteFile(duplicated_handle, b"Hello from Python!")

# 关闭句柄
win32api.CloseHandle(duplicated_handle)
win32api.CloseHandle(process_handle)
注意事项
  • 必须以管理员权限运行脚本,否则可能因权限不足无法读取目标进程内存或复制句柄
  • 目标进程必须是控制台进程,且其标准句柄已关联到控制台或其他可读写的对象(如果目标进程已重定向标准输出到文件,需确保有文件访问权限)
  • 不同Windows版本的PEB结构体可能存在差异,上述代码仅适用于常见的x86/x64系统

内容的提问来源于stack exchange,提问作者user0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 06:54:59