创建新的进程完成父进程欺骗
OpenProcess 函数 (processthreadsapi.h)
官方文档:https://learn.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
打开现有的本地进程对象。若要打开另一个本地进程的句柄并获取完全访问权限,必须启用 SeDebugPrivilege 特权。
HANDLE OpenProcess(
[in] DWORD dwDesiredAccess,
[in] BOOL bInheritHandle,
[in] DWORD dwProcessId
);
参数 | 作用 |
---|---|
[in] dwDesiredAccess | 对进程对象的访问。针对进程的安全描述符检查此访问权限。此参数可以是一个或多个 进程访问权限。如果调用方已启用 SeDebugPrivilege 特权,则会授予请求的访问权限,而不考虑安全描述符的内容。 |
[in] bInheritHandle | 如果此值为 TRUE,则此进程创建的进程将继承句柄。否则,进程不会继承此句柄。 |
[in] dwProcessId | 要打开的本地进程的标识符。 |
UpdateProcThreadAttribute 函数 (processthreadsapi.h)
官方文档:https://learn.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute
更新用于创建进程和线程的属性列表中的指定属性。属性列表是一个不透明的结构,它由一系列键/值对组成,每个属性对应一个键/值对。进程只能更新本主题中所述的属性键。
BOOL UpdateProcThreadAttribute(
[in, out] LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
[in] DWORD dwFlags,
[in] DWORD_PTR Attribute,
[in] PVOID lpValue,
[in] SIZE_T cbSize,
[out, optional] PVOID lpPreviousValue,
[in, optional] PSIZE_T lpReturnSize
);
参数 | 作用 |
---|---|
[in, out] lpAttributeList | 指向 由 InitializeProcThreadAttributeList 函数创建的属性列表的指针。 |
[in] dwFlags | 此参数是保留的,必须为零。 |
[in] Attribute | 属性列表中要更新的属性键。 |
[in] lpValue | 指向属性值的指针。此值必须保留,直到使用 DeleteProcThreadAttributeList 函数销毁属性列表。 |
[in] cbSize | lpValue 参数指定的属性值的大小。 |
[out, optional] lpPreviousValue | 此参数是保留的,必须为 NULL。 |
[in, optional] lpReturnSize | 此参数是保留的,必须为 NULL。 |
pAttributeList是要添加键/值对的属性列表,Attribute可取 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS或PROC_THREAD_ATTRIBUTE_HANDLE_LIST,取前者时,lpValue 参数应指向另外一个进程的句柄,cbSize取值应为sizeof(HANDLE),否则,lpValue 指向子进程要继承的所有内核对象的句柄数组,cbSize取值应是sizeof(HANDLE)乘以该数组的大小。
lpValue 参数是指向要使用 (的进程句柄的指针,而不是调用进程) 作为所创建进程的父进程的句柄。所用进程的句柄必须具有 PROCESS_CREATE_PROCESS 访问权限。
CreateProcessW 函数 (processthreadsapi.h)
官方文档:https://learn.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw
创建新进程及其主线程。新进程在调用进程的安全上下文中运行。如果调用进程正在模拟其他用户,则新进程将令牌用于调用进程,而不是模拟令牌。若要在模拟令牌表示的用户的安全上下文中运行新进程,请使用 CreateProcessAsUser 或 CreateProcessWithLogonW 函数。
BOOL CreateProcessW(
[in, optional] LPCWSTR lpApplicationName,
[in, out, optional] LPWSTR lpCommandLine,
[in, optional] LPSECURITY_ATTRIBUTES lpProcessAttributes,
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] BOOL bInheritHandles,
[in] DWORD dwCreationFlags,
[in, optional] LPVOID lpEnvironment,
[in, optional] LPCWSTR lpCurrentDirectory,
[in] LPSTARTUPINFOW lpStartupInfo,
[out] LPPROCESS_INFORMATION lpProcessInformation
);
参数 | 作用 |
---|---|
[in, optional] lpApplicationName | 要执行的模块的名称。此模块可以是基于 Windows 的应用程序。lpApplicationName 参数可以为 NULL。 |
[in, out, optional] lpCommandLine | 要执行的命令行。如果 lpApplicationName 为 NULL,则命令行的第一个空格分隔标记将指定模块名称。 |
[in, optional] lpProcessAttributes | 指向 SECURITY_ATTRIBUTES 结构的指针,该结构确定子进程是否可以继承新进程对象的返回句柄。如果 lpProcessAttributes 为 NULL,则无法继承句柄。 |
[in, optional] lpThreadAttributes | 指向 SECURITY_ATTRIBUTES 结构的指针,该结构确定子进程是否可以继承新线程对象的返回句柄。如果 lpThreadAttributes 为 NULL,则无法继承句柄。 |
[in] bInheritHandles | 如果此参数为 TRUE,则调用进程中的每个可继承句柄都由新进程继承。如果 参数为 FALSE,则不继承句柄。 |
[in] dwCreationFlags | 控制优先级类和进程的创建的标志。 |
[in, optional] lpEnvironment | 指向新进程的环境块的指针。如果此参数为 NULL,则新进程将使用调用进程的环境。 |
[in, optional] lpCurrentDirectory | 进程当前目录的完整路径。字符串还可以指定 UNC 路径。 |
[in] lpStartupInfo | 指向 STARTUPINFO 或 STARTUPINFOEX 结构的指针。若要设置扩展属性,请使用 STARTUPINFOEX 结构,并在 dwCreationFlags 参数中指定EXTENDED_STARTUPINFO_PRESENT。 |
[out] lpProcessInformation | 指向接收有关新进程的标识信息的 PROCESS_INFORMATION 结构的指针。 |
CreateProcess会按下面的顺序查找该文件:
-
包含当前进程可执行文件的目录
-
当前进程的当前目录
-
Windows系统目录,既GetSystemDirectory返回的目录
-
Windows目录
-
PATH环境变量列出的目录
源码分析
-
获取进程id为dwPid(父进程pid)的句柄;
-
调用UpdateProcThreadAttribute向属性链表添加键/值;
-
创建新的进程。
// 1. 获取进程id为dwPid(父进程pid)的句柄
hParentProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (NULL == hParentProcess)
{
DisplayErrorMessage((LPTSTR)"OpenProcess error", GetLastError());
return 0;
}
// 2. 调用UpdateProcThreadAttribute向属性链表添加键/值
if (!UpdateProcThreadAttribute(pAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParentProcess, sizeof(HANDLE), NULL, NULL))
{
DisplayErrorMessage((LPTSTR)"UpdateProcThreadAttribute error", GetLastError());
return 0;
}
// 3. 创建新的进程
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
sie.lpAttributeList = pAttributeList;
if (!CreateProcess(NULL,
argv[1],
NULL, NULL, FALSE, EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE, NULL, NULL, &sie.StartupInfo, &pi))
{
DisplayErrorMessage((LPTSTR)"CreateProcess error", GetLastError());
return 0;
}
参考
[1]https://blog.didierstevens.com/2009/11/22/quickpost-selectmyparent-or-playing-with-the-windows-process-tree/
原文始发于微信公众号(蟹堡安全团队):父进程欺骗--DidierStevens(三)
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论