【问题标题】:Routing stdout of process with PPID Spoofing使用 PPID 欺骗路由进程的标准输出
【发布时间】:2021-02-16 22:20:07
【问题描述】:

我尝试编写使用CreateProcess() 执行CMD 命令并将stdout 重定向到命名管道的代码。我想添加一个功能来欺骗父 PID,以便 cmd 将在 explorer.exe 下生成。每个功能都可以独立工作,但是当我尝试合并它们时,它就不起作用了。

标准输出路由:

int main()
{
    HANDLE hStdout_Rd = NULL;
    HANDLE hStdout_Wr = NULL;
    SECURITY_ATTRIBUTES saAttr;
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;

    CreatePipe(&hStdout_Rd, &hStdout_Wr, &saAttr, NULL);
    SetHandleInformation(hStdout_Rd, HANDLE_FLAG_INHERIT, 0);

    //Set startup info
    STARTUPINFO si;
    ZeroMemory(&si, (sizeof(STARTUPINFO)));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.hStdError = hStdout_Wr;
    si.hStdOutput = hStdout_Wr;
    si.wShowWindow = SW_HIDE;

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    CString cmd;
    if (CreateProcess(NULL, cmd.GetBuffer(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
    {
        //Great success read pipe contents
    }
    CloseHandle(hStdout_Rd);
    CloseHandle(hStdout_Wr);
}

PPID 欺骗:

int main() {

    CString cmd;
    STARTUPINFOEXA sInfoEX;
    PROCESS_INFORMATION pInfo;
    SIZE_T sizeT;

    HANDLE expHandle = OpenProcess(PROCESS_ALL_ACCESS, false, getParentProcessID());

    ZeroMemory(&sInfoEX, sizeof(STARTUPINFOEXA));
    InitializeProcThreadAttributeList(NULL, 1, 0, &sizeT);
    sInfoEX.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, sizeT);
    InitializeProcThreadAttributeList(sInfoEX.lpAttributeList, 1, 0, &sizeT);
    UpdateProcThreadAttribute(sInfoEX.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &expHandle, sizeof(HANDLE), NULL, NULL);
    sInfoEX.StartupInfo.cb = sizeof(STARTUPINFOEXA);

    CreateProcessA(NULL, cmd.GetBuffer(), NULL, NULL, TRUE, CREATE_SUSPENDED | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, reinterpret_cast<LPSTARTUPINFOA>(&sInfoEX), &pInfo);


    return 0;
}

齐心协力:

int main() {

    HANDLE hStdout_Rd = NULL;
    HANDLE hStdout_Wr = NULL;
    SECURITY_ATTRIBUTES saAttr;
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;
    CString cmd;
    STARTUPINFOEXA sInfoEX;
    PROCESS_INFORMATION pInfo;
    ZeroMemory(&pInfo, sizeof(PROCESS_INFORMATION));
    SIZE_T sizeT;

    HANDLE expHandle = OpenProcess(PROCESS_ALL_ACCESS, false, getParentProcessID());

    ZeroMemory(&sInfoEX, sizeof(STARTUPINFOEXA));
    sInfoEX.StartupInfo = sizeof(STARTUPINFO);
    sInfoEX.StartupInfo = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    sInfoEX.StartupInfo = hStdout_Wr;
    sInfoEX.StartupInfo = hStdout_Wr;
    sInfoEX.StartupInfo = SW_HIDE;
    InitializeProcThreadAttributeList(NULL, 1, 0, &sizeT);
    sInfoEX.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, sizeT);
    InitializeProcThreadAttributeList(sInfoEX.lpAttributeList, 1, 0, &sizeT);
    UpdateProcThreadAttribute(sInfoEX.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &expHandle, sizeof(HANDLE), NULL, NULL);
    sInfoEX.StartupInfo.cb = sizeof(STARTUPINFOEXA);

    if (CreateProcessA(NULL, cmd.GetBuffer(), NULL, NULL, TRUE, CREATE_SUSPENDED | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, reinterpret_cast<LPSTARTUPINFOA>(&sInfoEX), &pInfo))
    {
        //Read pipe contents
    }
    return 0;
}

我有什么遗漏的吗?

【问题讨论】:

  • 当您使用PROC_THREAD_ATTRIBUTE_PARENT_PROCESS - 从指定进程继承的属性包括句柄... - 因此进程中的管道句柄将不会被继承。您需要将此句柄复制到父级(资源管理器)并在 si.hStdOutput,si.hStdInput,si.hStdError 中使用重复值,也使用PROC_THREAD_ATTRIBUTE_HANDLE_LIST 仅继承此句柄
  • 我无法理解我应该在哪里复制句柄。我是否应该更改 explorer.exe 的 PROCESS_INFORMATION 并将其标准输出句柄设置为我创建的句柄?如果是这样,我不知道该怎么做。如果您能指出我将非常感激的代码示例。非常感谢
  • si.hStdOutput - 必须在资源管理器中处理管道值,但不能在您的进程中处理
  • 打开资源管理器的句柄后,我按以下方式复制 strout_Rd 句柄:DuplicateHandle(GetCurrentProcess(), hStdOut_Rd, hExplorer, &amp;dupHandle,0,FALSE,DUPLICATE_SAME_CLASS_); 并将 StartupInfo.hStdoOutput 设置为 dupHandle。我还将 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS 更改为 PROC_THREAD_ATTRIBUTE_HANDLE_LIST 但现在 CreateProcess 失败。
  • 示例代码足够大。当然不是硬写,但是从另一个进程中需要什么 exec cmd ?

标签: c++ c windows winapi stdout


【解决方案1】:

每个功能都可以独立运行,但是当我尝试 合并它们是行不通的。

匿名管道是一种未命名的单向管道,通常在父进程和子进程之间传输数据。要使用管道进行通信,管道服务器必须将管道句柄传递给另一个进程。通常,这是通过继承来完成的;即进程允许子进程继承句柄。

由于您将子进程的父进程更改为 explorer.exe。最初的父子关系不再存在。所以新进程无法访问旧父进程中创建的handlehStdout_Wr)。这就是它停止工作的原因。

为了达到你的目的:

【讨论】:

  • 所有这一切都不是解决方案 - 复制句柄给孩子,我们只能在 创建孩子之后。但我们需要在STARTUPINFOEX 子创建之前设置值。此时我们还不知道哪些值将具有重复句柄。并且使用管道名称不是解决方案,因为必须将子进程设计为使用此名称打开管道。我只是在 cmets 中给出的真正解决方案 - 只需在创建进程之前将管道句柄复制到父级(explorer),并且不要忘记在进程创建后关闭重复句柄
  • @RbMm 你的意思是父进程(不需要创建管道)和子进程都使用explorer.exe的重复std句柄吗?
  • 不,当然只有子进程从PROC_THREAD_ATTRIBUTE_PARENT_PROCESS (explorer.exe) 中传递的进程继承句柄。
  • @RbMm 如果父进程不使用explorer.exe的句柄,如何读取子进程的输出?
  • 我不懂你。父进程是我们的吗?我们需要使用资源管理器的句柄吗?!我们有自管手柄。 child 从 explorer 继承句柄,之后我们可以关闭句柄。都非常简单。
猜你喜欢
  • 1970-01-01
  • 2014-05-11
  • 2018-02-09
  • 2010-11-26
  • 2013-05-03
  • 2012-07-10
相关资源
最近更新 更多