将C#窗体应用程序注入到另一个应用程序中

3

有很多答案可以介绍如何将一个DLL注入到另一个进程中。如果我想要做同样的事情,但是目标是C#窗体应用程序(exe)而不是DLL呢?

基本上,我想让它运行在另一个进程的虚拟地址空间中。首先,我分配内存,然后创建远程线程。现在我该如何让我的现有exe在其中运行?此外,是否存在任何限制(例如,我可以让它在explorer.exe中运行吗)?

1个回答

1

我之前为自己的非托管应用程序(没有任何注入 - 这并不重要)做过这件事。一旦将您的非托管DLL注入到所需应用程序的地址空间中,您应该创建一个专用线程,在其上初始化COM(使用CoInitializeExOleInitialize),然后执行以下操作(出于简洁起见跳过错误检查):

HMODULE hmodMscoree = LoadLibrary(_T("mscoree.dll"))

HRESULT (STDAPICALLTYPE *pCorBindToRuntimeEx)(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor, DWORD startupFlags, REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv);
GET_PROC_ADDRESS(hmodMscoree, CorBindToRuntimeEx);

CComQIPtr<ICorRuntimeHost> m_host;
pCorBindToRuntimeEx(NULL, NULL, 0, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, (void**)&m_host);
m_host->Start();

CComQIPtr<IUnknown> unk;
m_host->CreateDomainSetup(&unk);
CComQIPtr<mscorlib::IAppDomainSetup> domainSetup;
unk->QueryInterface(&domainSetup);
domainSetup->put_ApplicationBase(curDir);

CComBSTR appName;
ParseParam(m_commandLine, CMDLINEOPT_APPNAME, &appName);
domainSetup->put_ApplicationName(appName);

CComBSTR config;
ParseParam(m_commandLine, CMDLINEOPT_CONFIGFILE, &config);
domainSetup->put_ConfigurationFile(config);

unk.Release();
m_host->CreateDomainEx(m_managedApp, domainSetup, NULL, &unk);
CComQIPtr<mscorlib::_AppDomain> appDomain;
unk->QueryInterface(&appDomain);
appDomain->ExecuteAssembly_2(m_managedApp, &m_exitCode);

请确保所有依赖程序集(如果有)都在基础文件夹中可用(在我的代码中是curDir)。 编辑:这是针对.NET 2.0完成的。我不知道自那时以来是否有任何变化。您可以在此处找到更多关于CLR托管的信息。 编辑:GET_PROC_ADDRESS就是这样做的:
#ifdef _UNICODE
    #define FUNC_T(func) func##W
    #define GET_PROC_ADDRESS_T(mod, func) \
        ((FARPROC&)p##func = ::GetProcAddress(mod, #func "W"))
#else
    #define FUNC_T(func) func##A
    #define GET_PROC_ADDRESS_T(mod, func) \
        ((FARPROC&)p##func = ::GetProcAddress(mod, #func "A"))
#endif

您还需要包含 fusion.hmscoree.h(可在 Windows SDK 中找到),并导入 mscorlib.tlb(对于 .NET 2.0,它位于 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorlib.tlb)。

所以如果没有注入,它会做什么?正常启动一个exe吗? 抱歉,我只是想理解你的帖子。 - Peter
我刚刚在我的答案中添加了几行。只要你有自己的线程,并且主应用程序保持运行状态(即ExitProcess未被调用),它是否为注入代码都无关紧要。上述代码将在该线程上启动托管应用程序,应用程序将创建自己的消息循环。 - noseratio - open to work
我是C++的初学者。它告诉我“标识符‘GET_PROC_ADDRESS’未定义”。你的代码需要哪些依赖项? - Peter
谢谢,C++ 对我来说并不是很顺利,我仍然有许多未识别的依赖关系。虽然如此,我很感激你的努力,这可能会帮助其他人,所以我选择了你的答案作为解决方案。 - Peter
没问题。那段是一个大项目的一部分,我不能上传整个项目,但是这里有另一个示例,希望你能更好地使用它。 - noseratio - open to work
请记住,在该示例中,他们使用了默认域(GetDefaultDomain),如果您进行注入,我认为这是一个不好的选择。您需要创建一个新的域。 - noseratio - open to work

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接