Why are DLLs uninitialized in the "wrong" order?


This is really just a corollary to Why are DLLs unloaded in the "wrong" order. Exactly the same logic that explains why DLLs are unloaded in the "wrong" order also explains why they are uninitialized in the "wrong" order. Once you understand the first issue, the second comes for free; just change DLL_PROCESS_DETACH to DLL_THREAD_DETACH in your analysis.

Apply the logic to the scenario posed in this comment and you'll see why it too is flawed.

Comments (4)
  1. Miral says:

    I’m still not quite sure why the dependency tracking you dismissed in your earlier post wouldn’t actually work.

    Surely if A.DLL loads MIDDLE.DLL (implicitly or explicitly) and MIDDLE.DLL loads B.DLL (implicitly or explicitly) then the dependency chain can be set such that MIDDLE.DLL won’t unload until after A.DLL does, and B.DLL won’t unload until after MIDDLE.DLL does, which preserves the expected behaviour that B.DLL will still be loaded when A.DLL unloads.

    There are still cases where you can trip it up, of course (such as setting up a circular or reverse dependency, as you mentioned), but doing this seems safer than not doing it.

    And yes, you can’t trust the return address, but I doubt modifying DLL dependency relationships is much of an attack vector.  So I don’t see any harm in trusting it in this case.

    Maybe I’m missing some vital point…?

  2. Dean Harding says:

    "And yes, you can’t trust the return address, but I doubt modifying DLL dependency relationships is much of an attack vector."

    I don’t think it’s a matter of security as such. There are plenty of non-security related cases where you can’t trust the return address (for example, what about on-the-fly generated code?)

    Besides, all of this is moot if developers just stick to the "don’t call methods in other DLLs (except kernel32.dll, maybe) from your DllMain" rule.

  3. Triangle says:

    Besides, all of this is moot if developers just stick to the "don’t call methods in other DLLs (except kernel32.dll, maybe) from your DllMain" rule.

    I agree with you completely, however those who aren’t ignorant to its existance in the first place seem to find that abiding to this particular rule to be unbearably difficult. So any discussion about it surely can’t be a bad thing.

  4. Tepsifüles says:

    Miral said:

    Surely if A.DLL loads MIDDLE.DLL (implicitly or explicitly) and MIDDLE.DLL loads B.DLL (implicitly or explicitly) then the dependency chain can be set such that MIDDLE.DLL won’t unload until after A.DLL does, and B.DLL won’t unload until after MIDDLE.DLL does, which preserves the expected behaviour that B.DLL will still be loaded when A.DLL unloads.

    The indicated context was that MIDDLE is a common wrapper, likely to be unloaded only when the lights go out. So adding a dependency on B would just stick B in the memory forever, which is not the desired outcome.

Comments are closed.