Winapi C++/CLI:使用LoadLibrary+;带有exe的GetProcAddress

Winapi C++/CLI:使用LoadLibrary+;带有exe的GetProcAddress,winapi,c++-cli,exe,loadlibrary,Winapi,C++ Cli,Exe,Loadlibrary,到目前为止,我有一些插件机制,其中我使用LoadLibrary和GetProcAddress加载DLL,以创建一个具体对象并返回一个公共接口。在我决定其中一个DLL应该是exe之前,这一切都很顺利 说它也可以用于exe,所以我试了一下。exe以GetProcAddress的形式加载,没有错误。但是当我试图调用我的具体对象的构造函数时,我得到了一个访问冲突 我认为这会发生,因为加载exe并不会加载它使用的所有DLL。所以我试着用LoadLibrary加载它们,但是我得到了同样的错误。 有什么建议吗

到目前为止,我有一些插件机制,其中我使用LoadLibrary和GetProcAddress加载DLL,以创建一个具体对象并返回一个公共接口。在我决定其中一个DLL应该是exe之前,这一切都很顺利

说它也可以用于exe,所以我试了一下。exe以GetProcAddress的形式加载,没有错误。但是当我试图调用我的具体对象的构造函数时,我得到了一个访问冲突

我认为这会发生,因为加载exe并不会加载它使用的所有DLL。所以我试着用LoadLibrary加载它们,但是我得到了同样的错误。 有什么建议吗

下面是我的代码(混合C++/CLI):

Interface*MCFactory::LoadInstanceFromAssembly(字符串^concreteAssemblyName,字符串^param){
字符串fullPathToAssembly=“”;
fullPathToAssembly+=文件系统::GetPathToProgramDirectory();
fullPathToAssembly+=“\\\”+封送作为(concreteAssemblyName);
模块hDLL=AssemblyLoader::GetInstance().LoadAssembly(fullPathToAssembly);
接口*pObject=NULL;
如果(hDLL!=NULL){
t_pCreateInstanceFunction pCreateInstanceFunction=
(t_pCreateInstanceFunction)::GetProcAddress(hDLL,CREATE_INSTANCE_FUNCTION_NAME.c_str());
if(pCreateInstanceFunction!=NULL){
//是的,此程序集公开了我们需要的功能
//调用函数来创建对象
pObject=(*pCreateInstanceFunction)(封送作为(参数));
}
}           
返回对象;
}

(AssemblyLoader::GetInstance().LoadAssembly只是::LoadLibrary的包装)

您可以在进程的主可执行文件上使用
LoadLibrary
GetProcAddress
,这允许反向动态导出(.exe到.dll)

除了对资源/数据的访问外,无法将第二个.exe加载到进程内存空间,因为.exe代码不可重定位。(纯MSIL.exe文件是一个例外,因为文件中没有代码,全部由JIT生成。)

基本上,.exe上的
LoadLibrary
仅在以下情况下才有用

  • .exe是主进程exe,在这种情况下,您最好使用
    GetModuleHandle

  • 使用
    LOAD\u LIBRARY\u AS\u DATAFILE
    标志


虽然Ben的回答涵盖了大多数情况,但本文在某些情况下可能有用

这是可能的


想法是修补IAT,然后调用CRT。当然,EXE必须是可重定位的,默认情况下(ASLR)是可重定位的。

启用ASLR是否可以将多个.EXE加载到单个进程中?@ildjarn:你是说ASLR兼容编译器选项,而不是操作系统设置?我不这么认为。是的,我就是这个意思。只是好奇。@ildjarn:也许这些是相关的:@ildjarn:似乎表明一个可执行文件,即使是支持ASLR的,也不能作为代码加载。当然,这个方法需要对EXE进行一些非常有侵入性的更改。它可能在特定的场景下工作,但不适用于一般情况。因此,只要条件保持不变(即重新定位、称为CRT、IAT修补),它就会工作。嗯?你所使用的每一个技巧都是在做没有记录的假设。向我展示一份Microsoft官方文档,其中说明可以在第二个模块中调用
WinMainCRTStartup
(重要观察:每次
WinMainCRTStartup
调用
GetModuleHandle(0)
,它没有得到它正在初始化的模块的句柄,而是进程的主模块。无法正确找到所有类型的资源,包括清单。)这只是开始。你有道理,但调用CRT是没有必要的。它只用于初始化全局变量——如果需要的话。
Interface* MCFactory::LoadInstanceFromAssembly( String ^ concreteAssemblyName, String ^ param ){
    string fullPathToAssembly = "";
    fullPathToAssembly += FileSystem::GetPathToProgramDirectory();
    fullPathToAssembly += "\\" + marshal_as<string>(concreteAssemblyName);

    MODULE hDLL = AssemblyLoader::GetInstance().LoadAssembly( fullPathToAssembly ); 

    Interface* pObject = NULL;
    if (hDLL != NULL){
        t_pCreateInstanceFunction pCreateInstanceFunction =
            (t_pCreateInstanceFunction) ::GetProcAddress (hDLL, CREATE_INSTANCE_FUNCTION_NAME.c_str());

        if ( pCreateInstanceFunction != NULL ){
            //Yes, this assembly exposes the function we need
            //Invoke the function to create the object
            pObject = (*pCreateInstanceFunction)( marshal_as<string>(param) );              
        }
    }           
    return pObject;
}