欢迎光临
我们一直在努力

win32创建进程

CreateProcess 函数

  • 函数基础
    ● Win32 API,一共10 个参数,参数大量使用typedef重定义类型
    ● 命名前缀规则:
    ○ lp = long pointer 长指针
    ○ dw = double word 双字
    ● 查看原始定义:VS 选中标识符按 F12
    ● MSDN 查阅:选DLLs, Processes, and Threads,避开 Windows CE 文档
    功能:创建新进程 + 它的主线程;新进程运行在调用进程安全上下文
    若需要模拟令牌创建进程,使用:CreateProcessAsUser / CreateProcessWithLogonW
    核心参数:
  • BOOL CreateProcess(
    LPCTSTR lpApplicationName, // 可执行模块路径名,可以NULL
    LPTSTR lpCommandLine, // 命令行字符串,W版本不能传const字符串
    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    BOOL bInheritHandles,
    DWORD dwCreationFlags,
    LPVOID lpEnvironment,
    LPCTSTR lpCurrentDirectory,
    LPSTARTUPINFO lpStartupInfo, // 输入:启动信息
    LPPROCESS_INFORMATION lpProcessInformation // 输出:返回进程线程信息
    );

  • lpApplicationName
    ○ exe 完整路径;不给扩展名默认补.exe;不使用系统搜索路径
    ○ 传NULL时,从lpCommandLine第一个空格分割取程序名
    ○ 路径带空格,要用双引号包裹
  • lpCommandLine
    ○ 命令行参数;CreateProcessW不能传入 const 只读字符串,会崩溃
    ○ 可以传NULL,直接使用 lpApplicationName 作为命令行
    ○ 新进程内:argv[0]程序名,argv[1]…用户传入参数,空格分隔
    易错:lpApplicationName和lpCommandLine同时为 NULL → 0xC0000005 访问空指针崩溃
  • 两个重要结构体
    ① STARTUPINFO 【入参】
    设置新进程窗口、控制台属性
  • STARTUPINFO si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si); // ✅必须赋值结构体大小,用于版本兼容扩展

    成员:

    typedef struct _STARTUPINFO {
    DWORD cb; // ✅【必写】结构体字节大小
    LPTSTR lpReserved; // 保留,必须NULL
    LPTSTR lpDesktop; // 桌面名称,NULL使用当前桌面
    LPTSTR lpTitle; // 控制台窗口标题,仅控制台程序生效
    DWORD dwX; // 窗口X坐标
    DWORD dwY; // 窗口Y坐标
    DWORD dwXSize; // 窗口宽度
    DWORD dwYSize; // 窗口高度
    DWORD dwXCountChars; // 控制台:字符模式宽度
    DWORD dwYCountChars; // 控制台:字符模式高度
    DWORD dwFillAttribute; // 控制台文字背景前景颜色属性
    DWORD dwFlags; // 标志位,决定下面哪些成员生效
    WORD wShowWindow; // 窗口显示模式 SW_SHOW / SW_HIDE
    WORD cbReserved2; // 保留
    LPBYTE lpReserved2; // 保留,必须NULL
    HANDLE hStdInput; // 标准输入句柄
    HANDLE hStdOutput; // 标准输出句柄
    HANDLE hStdError; // 标准错误句柄
    } STARTUPINFO, *LPSTARTUPINFO;

    ● dwFlags标志位;很多 GUI 程序会覆盖窗口设置,这里设置不一定生效
    ● 调试场景:si 内容可以被反调试检测
    ② PROCESS_INFORMATION 【出参】

    CreateProcess 调用成功后,系统填充该结构体
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));

    成员:

    typedef struct _PROCESS_INFORMATION {
    HANDLE hProcess; // 新进程内核对象句柄
    HANDLE hThread; // 主线程内核对象句柄
    DWORD dwProcessId; // 全局进程ID PID
    DWORD dwThreadId; // 全局主线程ID TID
    } PROCESS_INFORMATION, *LPPROCESS_INFORMATION;

  • 完整示例框架代码
  • #include <windows.h>
    #include <stdio.h>
    int main()
    {
    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi = {0};
    si.cb = sizeof(si);

    TCHAR cmd[] = L"iexplore.exe http://www.ifeng.com/";

    BOOL bRet = CreateProcess(
    NULL,
    cmd,
    NULL,
    NULL,
    FALSE,
    0,
    NULL,
    NULL,
    &si,
    &pi
    );
    if (!bRet)
    {
    DWORD err = GetLastError();
    printf("CreateProcess failed, error:%d\\n", err);
    return 1;
    }
    printf("PID:%d, TID:%d\\n", pi.dwProcessId, pi.dwThreadId);
    // 必须关闭句柄
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 0;
    }

  • Win32 错误处理
  • API 失败不会靠返回值直接给出全部信息,调用失败立刻调用 GetLastError() 获取错误码
  • if(!CreateProcess(...)){
    DWORD code = GetLastError();
    }

  • VS 工具:Tools → Error Lookup,输入错误码查看文本描述
    ○ 错误码2:系统找不到指定的文件
    ○ 错误码1814:找不到指定资源类型
  • 关键易错点汇总

  • 子进程概念:A 调用 CreateProcess 生成 B,B 是 A 的子进程,Windows 所有用户进程都由别的进程创建
  • CreateProcessW中lpCommandLine不能传入只读 const 字符串,内部会修改该缓冲区
  • 两个参数同时 NULL → 访问违例0xC0000005
  • si.cb = sizeof(si)千万不能忘记,用于结构体版本兼容
  • PROCESS_INFORMATION返回的两个句柄,用完一定要 CloseHandle,否则内核对象泄漏
  • 路径带空格,命令行中程序路径要用双引号包裹
  • 补充拓展

    ● CreateProcess继承调用进程的令牌;想要模拟其他用户身份创建进程,不能直接用它,要用CreateProcessAsUser
    ● 进程创建 5 大内部步骤:映射 EXE → 创建 EPROCESS → 映射 DLL → 创建 ETHREAD 主线程 → LdrInitializeThunk 初始化加载全部 DLL

    赞(0)
    未经允许不得转载:171主机测评 » win32创建进程
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址