如何将应用程序作为新创建的资源管理器进程的子进程启动?
How to start an application as a child of a newly created explorer process?
我正在开发一个类似于信息亭的应用程序。应用程序启动后,它会创建一个功能有限的新桌面。使用组合键,我可以在桌面之间来回移动。为了通知用户它当前正在使用的桌面或任何其他信息,我创建了一个应用程序,它在系统托盘区域显示气球消息。
在新创建的桌面中,我使用 CreateProcess
函数启动 explorer.exe,并通过 STARTUPINFO
结构提供新桌面,我将在 PROCESS_INFORMATION
结构中返回进程的句柄。
使用相同的技术,我尝试在新桌面中启动图标托盘应用程序,在 STARTUPINFO
结构中提供新桌面。麻烦的是,根据任务管理器,应用程序是运行,但是托盘图标不显示
我的直觉告诉我,在新桌面中,图标没有显示,因为它不是新 explorer.exe 进程的子进程,来自 live.systernals 的 procexp 应用程序显示了这两个进程,在树形表示的同一级别上。
有没有办法向 CreateProcess
提供参数,也许是 explorer 进程句柄,以便图标托盘应用程序作为该进程的子进程启动?
L.E.: 这是我用来创建启动 explorer.exe 和 图标托盘[=40 的代码=] 进程:
STARTUPINFO sInfoNT; /// startupinfo for the explorer.exe
PROCESS_INFORMATION pInfoNT; /// process infromation for the explorer.exe
ZeroMemory(&sInfoNT, sizeof(sInfoNT));
sInfoNT.lpDesktop = L"threadDesktop"; /// setting the desktop for the process
pInfoNT = startProcess(sInfoNT, L"C:\Windows\explorer.exe"); /// starting the process
if (!pInfoNT.hProcess)
LOG(ERROR) << "Unable to start the new explorer process";
else
LOG(INFO) << "Started the new explorer process";
STARTUPINFO sInfoTITD; /// doing the same thing for the tray icon application
PROCESS_INFORMATION pInfoTITD;
ZeroMemory(&sInfoTITD, sizeof(sInfoTITD));
sInfoTITD.lpDesktop = L"threadDesktop";
pInfoTITD = startProcess(sInfoTITD, L"DesktopTrayIcon.exe");
if (!pInfoTITD.hProcess)
LOG(ERROR) << "Unable to start the tray icon for the new desktop";
else
LOG(INFO) << "Started the tray icon for the new desktop";
这是 startProcess
函数:
PROCESS_INFORMATION KioskLauncher::startProcess(STARTUPINFO startUpInfo, LPCTSTR lpApplicationName)
{
PROCESS_INFORMATION processInformation;
ZeroMemory(&processInformation, sizeof(processInformation));
if (!CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startUpInfo, &processInformation))
MessageBox(0, L"Unable to start the process!\nThe path is broken!", L"Path Error!", MB_ICONERROR);
return processInformation;
}
如果您真的想让新进程成为其他进程的子进程,则必须使用代码注入。搜索 CreateRemoteThread
将为您提供大量阅读 material。最大的问题是,您的过程必须与目标具有相同的位数。有 3 种使用方法:
- Dll 注入(标准)
- 注入实际的 shellcode:将自行解析所有依赖项的汇编程序代码。 (不适用于启用 EMET)
- 从您的应用程序复制一段代码并修复导入(棘手)
我正在开发一个类似于信息亭的应用程序。应用程序启动后,它会创建一个功能有限的新桌面。使用组合键,我可以在桌面之间来回移动。为了通知用户它当前正在使用的桌面或任何其他信息,我创建了一个应用程序,它在系统托盘区域显示气球消息。
在新创建的桌面中,我使用 CreateProcess
函数启动 explorer.exe,并通过 STARTUPINFO
结构提供新桌面,我将在 PROCESS_INFORMATION
结构中返回进程的句柄。
使用相同的技术,我尝试在新桌面中启动图标托盘应用程序,在 STARTUPINFO
结构中提供新桌面。麻烦的是,根据任务管理器,应用程序是运行,但是托盘图标不显示
我的直觉告诉我,在新桌面中,图标没有显示,因为它不是新 explorer.exe 进程的子进程,来自 live.systernals 的 procexp 应用程序显示了这两个进程,在树形表示的同一级别上。
有没有办法向 CreateProcess
提供参数,也许是 explorer 进程句柄,以便图标托盘应用程序作为该进程的子进程启动?
L.E.: 这是我用来创建启动 explorer.exe 和 图标托盘[=40 的代码=] 进程:
STARTUPINFO sInfoNT; /// startupinfo for the explorer.exe
PROCESS_INFORMATION pInfoNT; /// process infromation for the explorer.exe
ZeroMemory(&sInfoNT, sizeof(sInfoNT));
sInfoNT.lpDesktop = L"threadDesktop"; /// setting the desktop for the process
pInfoNT = startProcess(sInfoNT, L"C:\Windows\explorer.exe"); /// starting the process
if (!pInfoNT.hProcess)
LOG(ERROR) << "Unable to start the new explorer process";
else
LOG(INFO) << "Started the new explorer process";
STARTUPINFO sInfoTITD; /// doing the same thing for the tray icon application
PROCESS_INFORMATION pInfoTITD;
ZeroMemory(&sInfoTITD, sizeof(sInfoTITD));
sInfoTITD.lpDesktop = L"threadDesktop";
pInfoTITD = startProcess(sInfoTITD, L"DesktopTrayIcon.exe");
if (!pInfoTITD.hProcess)
LOG(ERROR) << "Unable to start the tray icon for the new desktop";
else
LOG(INFO) << "Started the tray icon for the new desktop";
这是 startProcess
函数:
PROCESS_INFORMATION KioskLauncher::startProcess(STARTUPINFO startUpInfo, LPCTSTR lpApplicationName)
{
PROCESS_INFORMATION processInformation;
ZeroMemory(&processInformation, sizeof(processInformation));
if (!CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startUpInfo, &processInformation))
MessageBox(0, L"Unable to start the process!\nThe path is broken!", L"Path Error!", MB_ICONERROR);
return processInformation;
}
如果您真的想让新进程成为其他进程的子进程,则必须使用代码注入。搜索 CreateRemoteThread
将为您提供大量阅读 material。最大的问题是,您的过程必须与目标具有相同的位数。有 3 种使用方法:
- Dll 注入(标准)
- 注入实际的 shellcode:将自行解析所有依赖项的汇编程序代码。 (不适用于启用 EMET)
- 从您的应用程序复制一段代码并修复导入(棘手)