如何将程序的句柄赋予它创建的进程?

问题描述 投票:0回答:3

我有两个程序,ParentKid

在父母使用CreateProcess创建Kid之后,我希望Kid获得Parent的Handle。传递这个句柄的最简单方法似乎是将Handle放在CreateProcess的命令行参数中,但是我无法看到在Parent中获取Parent的句柄。 GetCurrentProcess返回一个奇怪的非价值,DuplicateHandle没有孩子的手柄不能工作(不可能,因为我需要创建孩子来得到它的句柄,但CreateProcess也是唯一的机会将父母的句柄发送到儿童)。

有什么方法我可以给Kid它的Parent's容易处理?

c++ windows winapi
3个回答
2
投票

传递此句柄的最简单方法似乎是将Handle放在CreateProcess的命令行参数中

这是一种方法,但它不是唯一的方法。

另一个简单的方法是让Parent将其进程ID从GetCurrentProcessId()发送到Kid,然后Kid可以使用OpenProcess()来获取Parent的句柄。

我无法看到在父母内部获得父母的句柄。

GetCurrentProcess(),返回表示调用进程的伪句柄。当在调用进程的上下文中使用时,所有接受进程句柄的API都将接受此伪句柄。

但是,为了将调用进程的句柄传递给另一个进程,Parent必须使用DuplicateHandle()将伪句柄转换为真正的句柄(将Parent设置为源和目标进程)。这是记录在案的行为。

GetCurrentProcess返回一个奇怪的非值,并且DuplicateHandle在没有Kid's Handle的情况下不起作用

Parent将伪句柄从GetProcessHandle()复制到真实句柄之后,它可以在命令行上将该副本传递给Kid。只要确保副本是可继承的,然后在bInheritHandles=TRUE调用中使用CreateProcess(),或者将STARTUPINFOEX传递给包含CreateProcess()PROC_THREAD_ATTRIBUTE_HANDLE_LIST(请参阅Programmatically controlling which handles are inherited by new processes in Win32)。

不可能,因为我需要创建Kid来获得它的句柄

如果你不想使用可继承的句柄,那么Parent也可以创建Kid而不在命令行上传递任何句柄,然后用GetCurrentProcess()作为目标进程复制Kid伪句柄,然后使用你选择的IPC机制发送Kid已经运行后的副本。

CreateProcess也是将父母的手柄送给孩子的唯一机会

不,这不是唯一的方法。 IPC是另一种方式。


1
投票

尝试从自己的进程句柄获取父PID:

DWORD pid = GetProcessId(Parent);

然后在孩子中,给予pid,拿回手柄:

OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);

PID可以很容易地传递,因为它的数字。

有关详细信息,请参阅以下内容


0
投票

首先,我们需要在Kid中获取父进程的进程ID。这可以通过与NtQueryInformationProcess调用ProcessBasicInformation来完成。在PROCESS_BASIC_INFORMATION内部(这个结构在ntddk.h中声明)存在InheritedFromUniqueProcessId成员。严格说这可能不是父进程id,以防你在创建Kid时使用PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,但如果你在调用CreateProcess时没有使用这个属性 - InheritedFromUniqueProcessId - 这将是你的父进程id。

比我们需要了解的那样,父母可以终止并且在这个新进程之后以相同的id开始。所以在我们使用InheritedFromUniqueProcessId打开进程之后,我们需要检查这是否真的是父进程,而不是新进程,在父进程后创建并重用此id。这可以通过查询进程开始时间来完成 - 显然如果这不是父进程,它在父进程之后已经启动(在此id之前无法重用),并且在他启动之后父进程退出。所以InheritedFromUniqueProcessId只有在创造时间> =孩子创造时间时才能成为父母。我们可以用ProcessTimes查询NtQueryInformationProcess的创建时间。所以最终的代码可以是:

NTSTATUS OpenParent(PHANDLE phProcess, ULONG DesiredAccess)
{
    HANDLE hProcess;
    KERNEL_USER_TIMES kut, _kut;
    PROCESS_BASIC_INFORMATION pbi;

    NTSTATUS status;

    if (0 <= (status = NtQueryInformationProcess(
        NtCurrentProcess(), ProcessBasicInformation, 
        &pbi, sizeof(pbi), 0)) && 
        0 <= (status = NtQueryInformationProcess(
        NtCurrentProcess(), ProcessTimes, 
        &kut, sizeof(kut), 0)))
    {

        static OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
        CLIENT_ID cid = { (HANDLE)pbi.InheritedFromUniqueProcessId };
        if (0 <= (status = NtOpenProcess(&hProcess, DesiredAccess|
            PROCESS_QUERY_LIMITED_INFORMATION, &zoa, &cid)))
        {

            if (0 > (status = NtQueryInformationProcess(
                hProcess, ProcessTimes, &_kut, sizeof(_kut), 0)) || 
                kut.CreateTime.QuadPart <= _kut.CreateTime.QuadPart)
            {
                NtClose(hProcess);
                return STATUS_PROCESS_IS_TERMINATING;
            }

            *phProcess = hProcess;
        }
    }

    return status;
}
© www.soinside.com 2019 - 2024. All rights reserved.