给进程伪造一个父亲

传统的进程树模型不仅是系统管理的图谱,更是安全审计与调查的关键线索。然而,通过特定的技术手段,一个进程完全可以“认贼作父”——将其父进程信息伪装成另一个合法或高权限进程,从而隐匿自己的真实起源,逃逸监控,混淆侦查视线。这不仅是攻击者用于规避检测的方法,也为防御方深入理解系统底层机制打开了另一扇窗。本文将探索这项技术在 Windows 系统下的实现原理。

该技术实现起来并不难。首先需要选择一个有权限打开的进程作为伪父进程,比如 explorer.exe,然后使用 ProcThreadAttribute 等系列函数来创建一个属性列表,并更新列表中的 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS 信息。最后在创建进程时,还需要指定 EXTENDED_STARTUPINFO_PRESENT 标志。

详细代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <windows.h>

int main()
{
HANDLE hFakeParent = NULL;
LPPROC_THREAD_ATTRIBUTE_LIST pAttrList = NULL;

do
{
hFakeParent = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 13244);
if (!hFakeParent)
break;

SIZE_T attrBufferSize = 0;

// 将第一个参数指定为NULL来获取属性缓冲区的大小
// 第一次调用时,会始终返回失败,见MSDN
InitializeProcThreadAttributeList(NULL, 1, 0, &attrBufferSize);

pAttrList = (LPPROC_THREAD_ATTRIBUTE_LIST)malloc(attrBufferSize);
if (!pAttrList)
break;

if (!InitializeProcThreadAttributeList(pAttrList, 1, 0, &attrBufferSize))
break;

if (!UpdateProcThreadAttribute(pAttrList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hFakeParent, sizeof(HANDLE), NULL, NULL))
break;

STARTUPINFOEXW si = { sizeof(STARTUPINFOEXW) };
si.lpAttributeList = pAttrList;
PROCESS_INFORMATION pi = { 0 };
WCHAR szCMD[] = { L"mspaint.exe" };
BOOL ret = CreateProcessW(NULL, szCMD, NULL, NULL, FALSE,
EXTENDED_STARTUPINFO_PRESENT, // 需要指定该标志
NULL,
L"C:\\Windows\\System", // 需要指定一个工作目录,不能传NULL,否则会使用当前进程的工作目录
(LPSTARTUPINFOW)&si, &pi);
if (!ret) {
std::wcerr << L"CreateProcessW failed, error: " << GetLastError() << std::endl;
break;
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
} while (false);

if (hFakeParent) {
CloseHandle(hFakeParent);
hFakeParent = NULL;
}

if (pAttrList) {
DeleteProcThreadAttributeList(pAttrList);
free(pAttrList);
pAttrList = NULL;
}

return 0;
}

通过上述方式伪造的父进程 ID,无论是在用户模式下,通过 NtQueryInformationProcess 查询 pbi.InheritedFromUniqueProcessId,还是在内核模式下,通过_EPROCESS.InheritedFromUniqueProcessId 查询,都指向的是伪父进程 ID。