Loading msvcr90.dll with loadlibrary

Started by
8 comments, last by Salvinger 14 years, 11 months ago
I'm attempting to manually map a dll into a target process, and so far everything is going well but with one hitch. The dll I am mapping is being linked dynamically with the c++ runtime, but the target process does not have that dependency, so I am having to load msvcr90.dll before I can call the entrypoint. When I try to load msvcr90.dll with loadlibrary, I always get the error that the dll is not found. If I specify the full path, the dll says that it has been loaded incorrectly. Does anyone have experience in doing this? When I just flat out call loadlibrary on my own dll in the target process, msvcr90.dll somehow then gets successfully loaded so it's not a problem with the actual target program. I also know that I could statically link to the runtime, but I would prefer not to do that. Any help would be appreciated.
Advertisement
Can you post the exact text of the error you get when you pass LoadLibrary the full DLL path?

Also, what version of Windows are you on?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Does your application have a manifest file?
It occurs both on windows XP and 7, it's actually windows error code 126 which is where I got the dll not found from.

About the manifiest file, I think I might have that, it's the file with the .manifest extension right? Do I need to place that in the same folder as my dll?
If you're injecting a DLL into another process, you should be minimizing it's external dependencies as much as possible (kernel32.dll and that's about it, in my opinion). So with that in mind, I would suggest if you really need the C++ runtime in your injected DLL (and maybe you don't), you should statically link to it.
Since MSVC 2005, the runtime DLLs have been shared side-by-side assemblies, so you need the manifest attached to your application. You would do that using mt.exe.
Quote:Original post by SiCrane
Since MSVC 2005, the runtime DLLs have been shared side-by-side assemblies, so you need the manifest attached to your application. You would do that using mt.exe.
The problem is that he's injecting a DLL into another process, so he can't modify the manifest of the other process.
Codeka: Statically linking would be a good option, but it adds a lot of bloat to the exe (like an extra 50kb), and when I have more than one I want injected I would end up with two copies of that. But if I end up not being able to solve this then I will just have to deal with that.

SiCrane: I tried using mt.exe, and looked on msdn on how to use it. When I ran it from the command line with what I thought was the right input, the output from the console seemed to suggest that it worked fine, but my actual file was unchanged and loadlibrary still did not work. Here is what I used if it helps:

mt.exe -manifest "Self extracting injector.exe.intermediate.manifest" -outputresource:"Self extracting injector.exe";1


And the output:

Microsoft (R) Manifest Tool version 5.2.3790.2075Copyright (c) Microsoft Corporation 2005.All rights reserved.


The output from the console looks fine to me but may be it is supposed to say more than that.

Edit: Yea I just read what Codeka posted, I was thinking about that problem too but was thinking I might be able to solve that with this manifest thing.

I'm still confused on how the windows loader loads the msvcr90.dll in the target process too since I didn't embed the manifest in the dlls I made.
To use LoadLibrary on SxS versioned dll, you've first got to create and activate an activation context. That requires a manifest to achieve, but you don't need mt.exe to create one as they're simple XML files.

<?xml version='1.0' encoding='UTF-8' standalone='yes'?><assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>  <dependency>    <dependentAssembly>      <assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.30729.1' processorArchitecture='*' publicKeyToken='1fc8b3b9a1e18e3b' />    </dependentAssembly>  </dependency></assembly>


Save that as example.manifest (change the version number to match the file version of msvcr90 on your machine), or change the path in the code below to point to the one in <VS Install Path>\VC\redist\<arch>\Microsoft.VC90.CRT\. Then in code, you use the ActCtx family of functions to load and activate it before LoadLibrary-ing:

ACTCTX ctx = {sizeof(ACTCTX), 0};ctx.lpSource = TEXT("D:\\Path\\To\\Saved\\example.manifest");HANDLE hCtx = CreateActCtx(&ctx);if(hCtx != INVALID_HANDLE_VALUE){    ULONG_PTR actToken;    BOOL activated = ActivateActCtx(hCtx, &actToken);    if(activated)    {        HMODULE hCRT = LoadLibrary(TEXT("D:\\WINDOWS\\WinSxS\\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e\\msvcr90.dll"));        if(hCRT)        {            // use the dynamic CRT            typedef int (__cdecl*PrintF)(const char*, ...);            PrintF print = reinterpret_cast<PrintF>(GetProcAddress(hCRT, "printf"));            if(print)            {                print("The dynamic CRT is loaded at 0x%p\n", hCRT);            }            FreeLibrary(hCRT);        }        DeactivateActCtx(0, actToken);    }    ReleaseActCtx(hCtx);}
Dang that's way complicated just to achieve loading the runtime, I think it was just something simple I had to do. Not sure how that would work out on a machine without the same version that I am running too. I appreciate the help though, but unfortunately I'm just going to have to do it the other way and just statically link to the runtime.

This topic is closed to new replies.

Advertisement