SECURITY

    技术2022-07-11  96

    调用 CreateProcess 创建进程时,可以让子进程继承父进程句柄表中可以被继承的内核对象。 一个内核对象能够被继承,必须在创建时通过 SECURITY_ATTRIBUTES 结构指定可继承;另一个条件是 CreateProcess 第五个参数 bInheritHandles 必须设置为 TRUE. 下面通过一个例子演示句柄继承。

    创建两个控制台程序扮演父进程和子进程,其中,内核对象使用事件来举例,使用了命令行参数传递事件句柄。子进程启动后,获取命令行参数,得到事件句柄,这样就完成了内核对象的继承,本质上是把父进程句柄表中的事件复制到子进程的句柄表中。

    父进程中,在 SetEvent 调用处设置断点,以便观察。

    父进程

    // ParentProcess.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <WINDOWS.H> int main(int argc, char* argv[]) { char szBuffer[256] = {0}; // 创建可继承内核对象必须在 SECURITY_ATTRIBUTES 中指定可继承 SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; // 创建可继承的内核对象 HANDLE hEvent = CreateEvent(&sa, TRUE, FALSE, NULL); sprintf(szBuffer, "c:\\SubProcess.exe %x", hEvent); STARTUPINFO si = {0}; PROCESS_INFORMATION pi; si.cb = sizeof(si); CreateProcess(NULL, szBuffer, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); // 设置事件为已通知 SetEvent(hEvent); // 关闭句柄,内核对象不会销毁,因为子进程已经获取了该句柄 CloseHandle(hEvent); return 0; }

    子进程

    // SubProcess.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <WINDOWS.H> #include <TCHAR.H> int main(int argc, char* argv[]) { char szBuffer[256] = {0}; memcpy(szBuffer, argv[1], strlen(argv[1])); DWORD dwHandle = 0; sscanf(szBuffer, "%x", &dwHandle); printf("%s\n", argv[0]); printf("%x\n", dwHandle); HANDLE hEvent = (HANDLE)dwHandle; printf("开始等待事件通知...\n"); WaitForSingleObject(hEvent, INFINITE); DWORD dwCode = GetLastError(); printf("事件已通知.\n"); getchar(); return 0; }

    运行结果 子线程以创建,并在 WaitForSingleObject 处阻塞,当父进程继续执行 SetEvent ,则事件对象设置为已通知,子进程 WaitForSingleObject 执行完成。

    Processed: 0.023, SQL: 9