CreatProcess创建可继承子进程

时间:2024-03-03 19:46:13

首先来看一下CreatProcess函数的原型:

BOOL CreateProcess(  LPCWSTR lpApplicationName, //指定可执行文件的文件名
      LPCWSTR lpCommandLine, //指定可执行文件的运行参数
      LPSECURITY_ATTRIBUTES lpProcessAttributes, //进程安全属性
      LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程安全属性
      BOOL bInheritHandles, //指定当前进程中的可继承句柄是否可以被新的进程继承
      DWORD dwCreationFlags,//指定新进程的优先级和其他创建标志
      LPVOID lpEnvironment, //指定新进程的环境变量
      LPWSTR lpCurrentDirectory, //指定新进程使用的当前目录
      LPSTARTUPINFO lpStartupInfo, //指定新进程使用的启动信息
      LPPROCESS_INFORMATION lpProcessInformation//返回新的进程和线程的相关信息
      );

其中在创建可继承的子进程这个过程中,第五个参数要设置为TURE,但是事实上还有一个信息容易被漏掉造成继承失败,

那就是第3个参数,关于线程安全的,先看一下SECURITY_ATTRIBUTES这个结构体的信息:

typedef struct _SECURITY_ATTRIBUTES { 
  DWORD  nLength; 
  LPVOID lpSecurityDescriptor; 
  BOOL   bInheritHandle; 
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES; 
该结构体的第三个参数指定了进程是否能被继承,所以我们要创建一个可继承的进程,除了设置CreatProcess第五个参数以外,还需要设置这个结构体。
下面这个例子是打开一个计算器,再打开一个程序,在程序中将前面打开的计算器关闭:
    //创建计算器进程
    SECURITY_ATTRIBUTES sa = {0};
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE; //此句柄可以继承

    STARTUPINFO si = {0};
    si.cb = sizeof(si);
    PROCESS_INFORMATION pi = {0};

    if (!CreateProcess("calc.exe", //
        NULL,
        &sa, //创建的计算器进程可以被继承
        NULL, 
        TRUE, 
        CREATE_FORCEDOS,
        NULL,
        NULL, 
        &si,
        &pi))
    {
        AfxMessageBox("创建进程失败");
    }
    //将计算机进程做参数传给子进程    
    CString str;
    str.Format("CloseCalc.exe %08x", pi.hProcess);
    
    //打开一个关闭计算器的程序
    STARTUPINFO si2 = {0};
    si2.cb = sizeof(si2);
    
    PROCESS_INFORMATION pi2 = {0};
    if (!CreateProcess(NULL,
        (LPSTR)(LPCSTR)str,
        NULL, 
        NULL, 
        TRUE, 
        CREATE_FORCEDOS,
        NULL,
        NULL, 
        &si2,
        &pi2))
    {
        AfxMessageBox("创建进程失败");
    }

关闭计算器的程序如下:
    

int main(int argc, char* argv[])
{
    HANDLE hProcess = (HANDLE)strtoul(argv[1], NULL, 16); 
    TerminateProcess(hProcess, 0);
    CloseHandle(hProcess);
    return 0;
}