none
r6030 - CRT not initialized error when loading imported dll

    Question

  • I have some dll loaded via AppInit_DLLs key (HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows).
    It is compiled with Multi-threaded DLL (/MD) switch with VS 2008 express, output dll imports MSVCR90.DLL.
    When some application also linked with MSVCR90.DLL starts, i get r6030 error.

    Windbg reports following stack:

    0012ed00 7858d748 USER32!MessageBoxA+0x45
    0012ed38 78542675 MSVCR90!__crtMessageBoxA+0x160
    0012ed60 78583a0e MSVCR90!_NMSG_WRITE+0x16f
    0012ed78 785833fe MSVCR90!malloc+0x2f
    0012ed8c 1000101d MSVCR90!_malloc_crt+0x11
    0012ed98 7854222a minedll!pre_c_init+0xe [f:\dd\vctools\crt_bld\self_x86\crt\src\crtdll.c @ 167]
    0012eda4 10001107 MSVCR90!_initterm_e+0x19
    0012edc8 100012eb minedll!_CRT_INIT+0xa9 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtdll.c @ 307]
    0012ee0c 100013b8 minedll!__DllMainCRTStartup+0x67 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtdll.c @ 537]
    0012ee18 7c81a352 minedll!_DllMainCRTStartup+0x1e [f:\dd\vctools\crt_bld\self_x86\crt\src\crtdll.c @ 507]
    0012ee38 7c833465 ntdll!LdrpCallInitRoutine+0x14
    0012ef40 7c834311 ntd
    ll!LdrpRunInitializeRoutines+0x367

    lm at this point gives:

    start    end        module name
    00400000 00407000   minexe   (deferred)            
    10000000 10006000   minedll   (private pdb symbols)  C:\WINDOWS\system32\minedll.pdb
    76f50000 76f63000   Secur32    (deferred)            
    770e0000 771e8000   SETUPAPI   (deferred)            
    77380000 77411000   USER32     (pdb symbols)          c:\symbols\user32.pdb\B29B53A483EA4F5DAF2BF0FB1A4E7DB92\user32.pdb
    77670000 777a9000   ole32      (deferred)            
    77ba0000 77bfa000   msvcrt     (deferred)            
    77c00000 77c48000   GDI32      (deferred)            
    77c50000 77cef000   RPCRT4     (deferred)            
    77e40000 77f42000   kernel32   (deferred)            
    77f50000 77feb000   ADVAPI32   (deferred)            
    78520000 785c3000   MSVCR90    (pdb symbols)          c:\symbols\msvcr90.i386.pdb\2AA5F2EF13C54F26987FB6B738E846331\msvcr90.i386.pdb
    7c800000 7c8c0000   ntdll      (pdb symbols)          c:\symbols\ntdll.pdb\93E72E109DC84F16AA54797E4DA8C1682\ntdll.pdb


    Currently I workaround it by linking static CRT to the dll, but this seems to be a CRT bug.

    Monday, December 17, 2007 2:26 PM

Answers

  • That's the kind of fun you should expect from AppInit. I think some system DLL (user32.dll?) just does a LoadLibrary from its DllMain which screws up initialization order. I suppose the OS builds the dependency graph for static imports and then initalizes things in order seen in the graph. Since initialization is already in progress the OS won't call the msvcr90.dll initializers. Things are different for a completely static dependency graph (i.e. msvcr90.dll is referenced directly or indirectly from the .EXE via import tables) because the OS can see when it builds the init list during process initialization.

     

    You can enable NT loader diagnostics (e.g. with gflags.exe) to see what's going on.

     

    Short story, that's a design limitation of AppInit.

     

    -hg

    Monday, December 17, 2007 4:54 PM
  • Hi Bolkin,

     

    Do you mean that the application you wanted to inject is not developed by you?

     

    Your requirement looks like a hack task and I do not think Windows do not have much build-in support for it yet. Could you please explain the background information about why you need such requirement? Maybe we have some other solution for your scenario.

     

    Would it be possible for you to use Win32 debugging API to monitor various loader events and inject the dll after certain module CREATE_THREAD_DEBUG_EVENT event? However, this approach may have performance hint to the application.

     

    Another possible approach may be modifying the IAT of the Exe of that application; you may add an extra entry to your inject dll. This will make your dll module static linked with the Exe. However, this needs an accurate modification to the Exe PE structure and will change the digital signature of the Exe.

    "An In-Depth Look into the Win32 Portable Executable File Format"

    http://msdn.microsoft.com/msdnmag/issues/02/02/PE/ 

     

    Hope this helps.

     

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

     

    Thursday, December 20, 2007 6:11 AM

All replies

  • That's the kind of fun you should expect from AppInit. I think some system DLL (user32.dll?) just does a LoadLibrary from its DllMain which screws up initialization order. I suppose the OS builds the dependency graph for static imports and then initalizes things in order seen in the graph. Since initialization is already in progress the OS won't call the msvcr90.dll initializers. Things are different for a completely static dependency graph (i.e. msvcr90.dll is referenced directly or indirectly from the .EXE via import tables) because the OS can see when it builds the init list during process initialization.

     

    You can enable NT loader diagnostics (e.g. with gflags.exe) to see what's going on.

     

    Short story, that's a design limitation of AppInit.

     

    -hg

    Monday, December 17, 2007 4:54 PM

  • Loader joy, that's what i suspected, thanks for reply.
    I've found warning about Dllmain and LoadLibrary (http://msdn2.microsoft.com/en-us/library/ms682583.aspx).
    Another question then. I'd still need to load additional libraries.
    Safest place to do this would be just before the call to the application entry point.
    I know the dirty method of doing it, but maybe there exists some official interface for this purpose?

    Monday, December 17, 2007 5:16 PM
  • Hi Bolkin,

     

    I do not think I understand your question completely. If you wanted to load some DLL, why not staticly link with them?

     

    If you wanted to inject a library into remote process dynamically, the classic method is using CreateRemoteThread with LoadLibrary:

    http://www.codeproject.com/KB/threads/winspy.aspx

     

    If I have misunderstood you, please feel free to clarify for us. Thanks.

     

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, December 19, 2007 3:10 AM
  • Thank you Jeffrey.
    I cannot link these dlls, because the product I develop deals with already compiled modules.

    I'm aware of the CreateRemoteThread method, it doesn't suit my needs for two reasons:
    1. My code might be executed later than i'd need.
    2. And/Or potentially can cause havoc:
    http://www.defendion.com/EliCZ/bugs/WinBugs.htm (Remote thread into not-yet-initialized process ...)


    So ideally i need a method of executing my code after loader finished resolving imports, but before actual process entry point.
    I know that i can replace initial entry point with my code, but this method is dirty/undocumented and potentially buggy.
    Wednesday, December 19, 2007 8:39 AM
  • Hi Bolkin,

     

    Do you mean that the application you wanted to inject is not developed by you?

     

    Your requirement looks like a hack task and I do not think Windows do not have much build-in support for it yet. Could you please explain the background information about why you need such requirement? Maybe we have some other solution for your scenario.

     

    Would it be possible for you to use Win32 debugging API to monitor various loader events and inject the dll after certain module CREATE_THREAD_DEBUG_EVENT event? However, this approach may have performance hint to the application.

     

    Another possible approach may be modifying the IAT of the Exe of that application; you may add an extra entry to your inject dll. This will make your dll module static linked with the Exe. However, this needs an accurate modification to the Exe PE structure and will change the digital signature of the Exe.

    "An In-Depth Look into the Win32 Portable Executable File Format"

    http://msdn.microsoft.com/msdnmag/issues/02/02/PE/ 

     

    Hope this helps.

     

    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

     

    Thursday, December 20, 2007 6:11 AM