Parent Process ID (PPID) Spoofing
字数 1196 2025-08-07 08:22:05
Parent Process ID (PPID) Spoofing 技术详解
0x00 前言
PPID Spoofing(父进程ID欺骗)是一种允许攻击者选择任意进程作为其恶意程序父进程的技术。本文将从原理、实现、检测和工具等方面全面解析这项技术。
0x01 目的和原理
技术目的
- 逃避基于父/子进程关系的安全检测
- 使恶意程序看起来由可信进程生成
- 隐藏恶意活动的真实来源
基本原理
Windows系统中,进程默认继承创建它的父进程ID。通过修改CreateProcess函数的lpStartupInfo参数,可以指定任意进程作为新进程的父进程。
关键数据结构链:
CreateProcessA -> lpStartupInfo -> STARTUPINFOEX -> lpAttributeList -> InitializeProcThreadAttributeList -> UpdateProcThreadAttribute -> PROC_THREAD_ATTRIBUTE_PARENT_PROCESS
0x02 基础实现
核心代码实现
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <TlHelp32.h>
#include <iostream>
int main()
{
STARTUPINFOEXA si;
PROCESS_INFORMATION pi;
SIZE_T attributeSize;
ZeroMemory(&si, sizeof(STARTUPINFOEXA));
// 指定父进程PID
HANDLE parentProcessHandle = OpenProcess(MAXIMUM_ALLOWED, false, 12896);
InitializeProcThreadAttributeList(NULL, 1, 0, &attributeSize);
si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attributeSize);
InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &attributeSize);
UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
&parentProcessHandle, sizeof(HANDLE), NULL, NULL);
si.StartupInfo.cb = sizeof(STARTUPINFOEXA);
CreateProcessA(NULL, (LPSTR)"notepad", NULL, NULL, FALSE,
EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &si.StartupInfo, &pi);
return 0;
}
关键API解析
- CreateProcessA: 创建新进程
- 使用
EXTENDED_STARTUPINFO_PRESENT标志启用扩展启动信息
- 使用
- InitializeProcThreadAttributeList: 初始化线程属性列表
- UpdateProcThreadAttribute: 设置父进程属性
PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: 指定父进程的关键属性
0x03 代码优化与完善
自动获取父进程PID
DWORD getPPID(LPCWSTR processName) {
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process = { 0 };
process.dwSize = sizeof(process);
if (Process32First(snapshot, &process)) {
do {
if (!wcscmp(process.szExeFile, processName))
break;
} while (Process32Next(snapshot, &process));
}
CloseHandle(snapshot);
return process.th32ProcessID;
}
处理权限问题
系统进程通常以SYSTEM完整性级别运行,普通程序无法访问。解决方案是只选择MEDIUM完整性级别的进程。
获取进程完整性级别
LPCWSTR getProcessIntegrityLevel(HANDLE hProcess, PDWORD pdwIntegrityLevel) {
// ... [完整实现见原文]
if (*pdwIntegrityLevel == SECURITY_MANDATORY_LOW_RID) {
return L"LOW";
}
else if (*pdwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID &&
*pdwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID) {
return L"MEDIUM";
}
// ... [其他级别判断]
}
改进的getPPID函数
DWORD getPPID(LPCWSTR processName) {
// ... [初始化部分]
if (Process32First(snapshot, &process)) {
do {
if (!wcscmp(process.szExeFile, processName)) {
HANDLE hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, process.th32ProcessID);
if (hProcess) {
LPCWSTR integrityLevel = NULL;
DWORD dwIntegrityLevel;
integrityLevel = getProcessIntegrityLevel(hProcess, &dwIntegrityLevel);
if (!wcscmp(integrityLevel, L"MEDIUM")) {
flag = true;
break;
}
}
}
} while (Process32Next(snapshot, &process));
}
// ... [清理和返回]
}
0x04 检测方法
使用ETW(Event Tracing for Windows)
检测步骤
-
查询Providers
logman query providers Microsoft-Windows-Kernel-Process -
创建跟踪会话
logman create trace ppid-spoofing -p Microsoft-Windows-Kernel-Process 0x10 -ets -
分析日志
- 在事件查看器中打开生成的.etl文件
- 检查
Execution下的ProcessID和Data下的ParentProcessID是否一致 - 不一致则可能为PPID欺骗
-
终止会话
logman stop ppid-spoofing -ets
检测原理
- 真实父进程ID记录在
Execution.ProcessID中 - 欺骗的父进程ID显示在
Data.ParentProcessID中 - 排除UAC等合法情况(检查是否有
appinfo服务)
Python检测脚本
# 检测逻辑核心
if event_data['ParentProcessID'] != event_header['ProcessID']:
if not is_uac_event(event_data):
print(f"Possible PPID Spoofing detected: {process_name}")
0x05 相关工具
利用工具
- Metasploit:
set PPID <pid> - Cobalt Strike:
ppid <pid> - 各种开源实现(见参考链接)
检测工具
0x06 防御建议
- 监控进程创建事件,特别是异常父子关系
- 使用ETW持续收集进程创建日志
- 检查进程完整性级别异常变化
- 关注常见被利用的父进程(如svchost.exe, explorer.exe)
0x07 总结
PPID Spoofing是一种有效的防御规避技术,通过理解其原理和检测方法,安全团队可以更好地防御此类攻击。同时,这项技术常与其他技术如APC注入结合使用,需要综合防御。