【发布时间】: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, &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