Windows安全攻防-进程创建的几种方式

admin 2026-01-12 01:21:54 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档详解Windows创建进程的三种API:ShellExecuteA、ShellExecuteEx及CreateProcess。涵盖各函数参数、关键结构体与标志位,并附带C语言示例。理解这些底层机制对分析恶意软件行为、实施红队操作及进行安全开发至关重要。 综合评分: 78 文章分类: 二进制安全,红队,安全开发


cover_image

Windows安全攻防-进程创建的几种方式

原创

R0x7e

剑外思归客

2026年1月11日 00:00 江苏

相关windows API

ShellExecuteA

位于 Shellapi.h 中对指定文件执行操作 返回值是一个大于 32 的值表示成功;小于 32 的值表示错误,并且每个值代表特定的错误类型。例如,值为 2 表示“文件未找到”,值为 11 表示“无效的可执行文件”等。

HINSTANCE ShellExecuteA(
  [in, optional] HWND   hwnd,   //父窗口的句柄。 如果操作未与窗口关联,则可以NULL。
  [in, optional] LPCSTR lpOperation,
  [in]           LPCSTR lpFile,
  [in, optional] LPCSTR lpParameters,
  [in, optional] LPCSTR lpDirectory,
  [in]           INT    nShowCmd
);
  • hwnd  父窗口的句柄。 如果操作未与窗口关联,则可以NULL。
  • lpOperation 指向一个以 null 结尾的字符串,指定要进行的操作,例如 "open""edit" 或 "print"。如果此参数为 NULL,则默认执行 "open" 操作。
  • lpFile   指向要执行或打开的文件名或程序名的字符串。该文件可以是可执行文件或其他类型的文件(如文档、URL等)。
  • lpParameters: 如果 lpFile 指定了一个可执行文件,此参数指向命令行参数的字符串。如果 lpFile 不是可执行文件,则此参数应为 NULL
  • lpDirectory: 指向一个以 null 结尾的字符串,指定默认目录。
  • nShowCmd: 指定应用程序窗口如何显示。常见的值包括 SW_HIDESW_MAXIMIZESW_MINIMIZESW_SHOW 等。

ShellExecuteEx

位于 Shellapi.h中,对指定文件执行操作 如果成功,则返回 TRUE;否则,FALSE。 调用 GetLastError 以获取扩展的错误信息。

BOOL ShellExecuteExW(
  [in, out] SHELLEXECUTEINFOW *pExecInfo
);

函数都需要传入一个 SHELLEXECUTEINFO 结构体指针,这个结构体包含执行操作所需的所有信息

typedef struct _SHELLEXECUTEINFOW {
    DWORD     cbSize;         // 结构体大小
    ULONG     fMask;          // 操作标志位
    HWND      hwnd;           // 父窗口句柄
    LPCWSTR   lpVerb;         // 动作:open, print, runas 等
    LPCWSTR   lpFile;         // 文件或程序路径
    LPCWSTR   lpParameters;   // 命令行参数(仅用于可执行文件)
    LPCWSTR   lpDirectory;    // 工作目录
    INT       nShow;          // 窗口显示方式(如 SW_SHOW, SW_HIDE)
    HINSTANCE hInstApp;       // 返回值(不使用)
    void      *lpIDList;      // 保留,通常为 NULL
    LPCWSTR   lpClass;        // 文件类型(可选)
    HKEY      hkeyClass;      // 注册表项(可选)
    DWORD     dwHotKey;       // 热键(可选)
    HANDLE    hIcon;          // 图标句柄(可选)
    HANDLE    hProcess;       // 输出:被启动进程的句柄(如果指定了 SEE_MASK_NOCLOSEPROCESS)
} SHELLEXECUTEINFOW, *LPSHELLEXECUTEINFOW;

fMask 常用值

| 标志 | 说明 | | — | — | | SEE_MASK_NOCLOSEPROCESS | 获取被启动进程的句柄(可通过 hProcess 成员访问) | | SEE_MASK_NOASYNC | 强制同步执行(等待操作完成) | | SEE_MASK_FLAG_DDEWAIT | 等待 DDE 操作完成 | | SEE_MASK_INVOKEIDLIST | 使用 IDList 而不是 lpFile | | SEE_MASK_UNICODE | 表示传入的字符串是 Unicode 格式(用于 ShellExecuteExA 时) | | | |

示例

#include&nbsp;<windows.h>
#include&nbsp;<shellapi.h>
#include&nbsp;<stdio.h>
int&nbsp;main()&nbsp;{
&nbsp; &nbsp; SHELLEXECUTEINFOW sei = {&nbsp;0&nbsp;};
&nbsp; &nbsp; sei.cbSize =&nbsp;sizeof(SHELLEXECUTEINFOW);
&nbsp; &nbsp; sei.fMask = SEE_MASK_NOCLOSEPROCESS;
&nbsp; &nbsp; sei.hwnd =&nbsp;NULL;
&nbsp; &nbsp; sei.lpVerb =&nbsp;L"open";
&nbsp; &nbsp; sei.lpFile =&nbsp;L"notepad.exe";
&nbsp; &nbsp; sei.lpParameters =&nbsp;NULL;
&nbsp; &nbsp; sei.lpDirectory =&nbsp;NULL;
&nbsp; &nbsp; sei.nShow = SW_SHOW;
&nbsp; &nbsp;&nbsp;if&nbsp;(ShellExecuteExW(&sei)) {
&nbsp; &nbsp; &nbsp; &nbsp; WaitForSingleObject(sei.hProcess, INFINITE);
&nbsp; &nbsp; &nbsp; &nbsp; CloseHandle(sei.hProcess);
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("记事本已打开。\n");
&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;else&nbsp;{
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("执行失败,错误代码:%d\n", GetLastError());
&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;return0;
}

CreateProcess

位于kernel32.dll中,用于创建一个新的进程(process)及其主线程。它允许你启动一个可执行文件(EXE),并控制其运行方式,包括指定命令行参数、环境变量、安全属性、工作目录等

BOOL&nbsp;CreateProcess(
&nbsp; LPCWSTR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lpApplicationName, &nbsp; &nbsp;// 可执行文件路径
&nbsp; LPWSTR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lpCommandLine, &nbsp; &nbsp; &nbsp; &nbsp;// 命令行参数(可包含程序名)
&nbsp; LPSECURITY_ATTRIBUTES lpProcessAttributes, &nbsp;// 进程安全属性
&nbsp; LPSECURITY_ATTRIBUTES lpThreadAttributes, &nbsp;&nbsp;// 线程安全属性
&nbsp; BOOL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bInheritHandles, &nbsp; &nbsp; &nbsp;// 是否继承句柄
&nbsp; DWORD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dwCreationFlags, &nbsp; &nbsp; &nbsp;// 创建标志
&nbsp; LPVOID &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lpEnvironment, &nbsp; &nbsp; &nbsp; &nbsp;// 环境变量
&nbsp; LPCWSTR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lpCurrentDirectory, &nbsp;&nbsp;// 当前工作目录
&nbsp; LPSTARTUPINFOW &nbsp; &nbsp; &nbsp; &nbsp;lpStartupInfo, &nbsp; &nbsp; &nbsp; &nbsp;// 启动信息
&nbsp; LPPROCESS_INFORMATION lpProcessInformation &nbsp;// 输出:进程和线程信息
);

1. lpApplicationName 要执行的模块(EXE 文件)的完整路径, 如果为 NULL,则从 lpCommandLine 中提取可执行文件名。 2. lpCommandLine 命令行字符串,通常包括可执行文件名和参数。 如果 lpApplicationName 为 NULL,则第一个空格前的部分会被当作程序名。示例:L"notepad.exe C:\\test.txt"3. lpProcessAttributes 指向一个结构体,决定进程句柄是否可被继承。通常设为 NULL 表示使用默认安全属性。 4. lpThreadAttributes  决定主线程句柄是否可被继承。通常设为 NULL。 5. bInheritHandles 是否允许子进程继承句柄。如果为 TRUE,子进程可以继承父进程中具有可继承属性的句柄。 6. dwCreationFlags  控制进程创建行为的标志位。 常用标志:

| 标志 | 说明 | | — | — | | CREATE_NEW_CONSOLE | 为新进程创建新的控制台 | | CREATE_SUSPENDED | 创建后挂起主线程,直到调用 ResumeThread | | DETACHED_PROCESS | 不关联控制台 | | CREATE_NO_WINDOW | 不创建窗口(适用于 GUI 程序) | | HIGH_PRIORITY_CLASS | 高优先级 | | IDLE_PRIORITY_CLASS | 低优先级 | | CREATE_UNICODE_ENVIRONMENT | 指定环境变量为 Unicode 格式 | | | |

7. lpEnvironment 指向新进程使用的环境块。通常为 NULL,表示使用当前进程的环境变量。 8. lpCurrentDirectory  新进程的工作目录。 为 NULL 表示使用调用进程的当前目录。 9. lpStartupInfo   类型:LPSTARTUPINFOW,指定新进程的主窗口特性,如控制台、标准输入输出等。 结构体定义

typedef&nbsp;struct&nbsp;_STARTUPINFOW&nbsp;{
&nbsp; &nbsp; DWORD &nbsp;cb; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 结构体大小
&nbsp; &nbsp; LPWSTR lpReserved; &nbsp; &nbsp; &nbsp;// 保留
&nbsp; &nbsp; LPWSTR lpDesktop; &nbsp; &nbsp; &nbsp;&nbsp;// 桌面名称
&nbsp; &nbsp; LPWSTR lpTitle; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 窗口标题(用于控制台)
&nbsp; &nbsp; DWORD &nbsp;dwX; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 窗口位置
&nbsp; &nbsp; DWORD &nbsp;dwY;
&nbsp; &nbsp; DWORD &nbsp;dwXSize; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 窗口大小
&nbsp; &nbsp; DWORD &nbsp;dwYSize;
&nbsp; &nbsp; DWORD &nbsp;dwXCountChars;
&nbsp; &nbsp; DWORD &nbsp;dwYCountChars;
&nbsp; &nbsp; DWORD &nbsp;dwFillAttribute;
&nbsp; &nbsp; DWORD &nbsp;dwFlags; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 标志(如 STARTF_USESTDHANDLES)
&nbsp; &nbsp; WORD &nbsp; wShowWindow; &nbsp; &nbsp;&nbsp;// 窗口显示方式
&nbsp; &nbsp; WORD &nbsp; cbReserved2; &nbsp; &nbsp;&nbsp;// 保留
&nbsp; &nbsp; BYTE &nbsp; *lpReserved2; &nbsp; &nbsp;// 保留
&nbsp; &nbsp; HANDLE hStdInput; &nbsp; &nbsp; &nbsp;&nbsp;// 标准输入句柄
&nbsp; &nbsp; HANDLE hStdOutput; &nbsp; &nbsp; &nbsp;// 标准输出句柄
&nbsp; &nbsp; HANDLE hStdError; &nbsp; &nbsp; &nbsp;&nbsp;// 标准错误句柄
} STARTUPINFOW, *LPSTARTUPINFOW;

10. lpProcessInformation  类型:LPPROCESS_INFORMATION,输出参数,返回新进程和主线程的句柄与 ID。 结构体定义

typedef&nbsp;struct&nbsp;_PROCESS_INFORMATION&nbsp;{
&nbsp; &nbsp; HANDLE hProcess; &nbsp; &nbsp;// 进程句柄
&nbsp; &nbsp; HANDLE hThread; &nbsp; &nbsp;&nbsp;// 主线程句柄
&nbsp; &nbsp; DWORD &nbsp;dwProcessId;&nbsp;// 进程 ID
&nbsp; &nbsp; DWORD &nbsp;dwThreadId; &nbsp;// 线程 ID
} PROCESS_INFORMATION, *PPROCESS_INFORMATION;

示例

#include&nbsp;"TestCreateProcessAPI.h"
#include&nbsp;<windows.h>
#include&nbsp;<stdio.h>
int&nbsp;TestCreateProcess()&nbsp;{
&nbsp; &nbsp; STARTUPINFOW si = {&nbsp;0&nbsp;};
&nbsp; &nbsp; PROCESS_INFORMATION pi = {&nbsp;0&nbsp;};
&nbsp; &nbsp; si.cb =&nbsp;sizeof(STARTUPINFO);

&nbsp; &nbsp; WCHAR cmdLine[] =&nbsp;L"notepad.exe";
&nbsp; &nbsp;&nbsp;// 创建进程
&nbsp; &nbsp;&nbsp;if&nbsp;(CreateProcessW(
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;NULL, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 应用程序名(从命令行中提取)
&nbsp; &nbsp; &nbsp; &nbsp; cmdLine,&nbsp;// 命令行
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;NULL, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 进程安全属性
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;NULL, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 线程安全属性
&nbsp; &nbsp; &nbsp; &nbsp; FALSE, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 不继承句柄
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;0, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 默认标志
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;NULL, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 使用当前环境
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;NULL, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 使用当前目录
&nbsp; &nbsp; &nbsp; &nbsp; &si, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 启动信息
&nbsp; &nbsp; &nbsp; &nbsp; &pi &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 进程信息
&nbsp; &nbsp; )) {
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("记事本已启动,等待关闭...\n");

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 等待进程结束
&nbsp; &nbsp; &nbsp; &nbsp; WaitForSingleObject(pi.hProcess, INFINITE);

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// 关闭句柄
&nbsp; &nbsp; &nbsp; &nbsp; CloseHandle(pi.hProcess);
&nbsp; &nbsp; &nbsp; &nbsp; CloseHandle(pi.hThread);

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("记事本已关闭。\n");
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return1;
&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;else&nbsp;{
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("创建进程失败,错误代码:%d\n", GetLastError());
&nbsp; &nbsp; }
&nbsp; &nbsp;&nbsp;return0;

}

相关参考

https://learn.microsoft.com/zh-cn/windows/win32/api/shellapi/nf-shellapi-shellexecutea

By:《剑外思归客》公众号,R0x7e

免责声明 / Ethical & Legal Disclaimer

  • 本文内容仅面向网络安全教育、网络安全研究与防御加固目的,所有演示均应在明确书面授权自有资产范围内进行。
  • 任何将本文内容用于未授权测试、攻击、渗透、持久化、权限提升、数据访问或破坏行为的,均与作者无关,后果由行为人自行承担。
  • 本文不构成针对任何系统/组织的攻击指引或操作保证;读者应评估适用性与风险,确保测试过程不影响生产环境与第三方权益。
  • 如本文引用或展示的工具、样本、截图或配置涉及第三方内容,其版权与责任归原权利人所有。
  • 继续阅读/使用本文内容,视为你已理解并同意上述条款。

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:剑外思归客 R0x7e《Windows安全攻防-进程创建的几种方式》

评论:0   参与:  0