-
Notifications
You must be signed in to change notification settings - Fork 750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crash in MemoryLoadLibraryEx(): 0xC0000005: Access violation reading location 0x00000000. #31
Comments
The VS2015 generates a TLS (thread local storage) section for the SampleDLL, so this But this does not explain why it works when the DLL is loaded from a file with LoadLibrary(). The behaviour should be identical, but isn't. From what I can see there are no TLS callbacks in the DLL, so #25 does not fit. In http://www.nynaeve.net/?p=186 there is the section
I don't see where MemoryModule is doing this. |
Great. How easy would be to protect code from MemoryModule. |
Upon further reading the wonderful article series by Ken Johnson, I think that MemoryModule currently behaves just like pre-Vista Windows did with regards to implicit TLS in DLLs. MemoryLoadLibraryEx() does not allocate the necessary structures, but compiler and linker generated a DLL that expect these to be in place. Mayhem ensues. http://www.nynaeve.net/?p=187 describes the situation in a slightly discouraging fashion:
Emphasis mine. I guess this initial access happens in GetCallable() when the control flow reaches the static variable for the first time. And because Windows after Vista gained support for implicit TLS in DLLs (http://www.nynaeve.net/?p=189), the regular LoadLibrary() works fine. And if it happens to be called before MemoryLoadLibraryEx() it will (IMHO) allocate everything for the process to access the TLS variables without a glitch. |
Not really MemoryModule related, but one question is why the compiler generates TLS accesses without any occurrence of "declspec(thread)" in the source. This is because of magic statics which are a new feature in VS2015 (https://www.visualstudio.com/en-us/news/vs2015-vs.aspx):
And if this bites MemoryModule, it also affects VS2015 code running on pre-Vista Windows: |
Does the DLL work in MemoryModule if compiled with the switch |
Yes. In my case that's good enough. In other cases where you want to embed some existing dll that's not really helpful though since you can't control how it was compiled. |
A recent article in the D language blog reminded me of this issue (https://dlang.org/blog/2016/08/12/project-highlight-visual-d/):
When those D DLLs are loaded/attached they set up the implicit TLS for their global variables themselves. So even under XP where the Windows loader did not handle implicit TLS they magically work. And the code for this is in dll.d [1] -- thus it might be a guide on how to do this in MemoryModule. [1] which even quotes the page from http://www.nynaeve.net mentioned above, I should have googled for that back last year, it would have been the second entry. |
currently running into a problem with this, as I can not use a mingw compiled binary to "load" (with memorymodule) a mingw compiled binary (the TLSCallback points to a giant (wrong) address upon the first iteration of the while loop inside "executeTLS()". Has there been any progress on fixing the implementation here (to work on modern systems) or should I simply look into trying to figure how to disable TLS support in mingw? |
I'm not aware of any progress on this issue. If you do not rely on thread safe initialization of local statics (e.g. you do not use threads at all) you could experiment with -fno-threadsafe-statics in gcc/mingw, this is what solved our problem with VS2015. |
sadly, my targets are complicated (a mixture of multiple languages and a convoluted build system), and while this might work for some of them, the best solution for me would be to actually "fix" memory module to allocate things correctly (sadly this is a bit beyond me at the moment). |
Would it be possible that some experts here could implement the required change described by http://www.nynaeve.net/?p=189? The blogger has posted the reference implementation along with the blog, although it is somewhat beyond my ability to follow that... |
Hmmm. This interesting virus implementation seems to be able to solve the issue here: https://github.com/devilogic/xvirus/blob/master/EvilKernel/RefixTlsPrivate.c Update: did more investigation. The code is not thread-safe and does not consider special cases where acceleration is applicable. Nevertheless, I will try to use it as a starting point and see how far I can go. Update 2: suddenly found that WINE should have the best open-source PE loader implementation. I guess I would implement my loader directly by migrating their code. Update 3: the WINE implementation is based on POSIX API, might need a huge refractor to make it collaborate with Windows native process management and file management. Working on it. P.S. the virus code is poorly designed and it could have many problems related with TLS handling, e.g. only currently thread has TLS storage allocated... |
Why can't we just parse the whole binary, replace references to In x86, TLS block array is accessed by something like:
Why can't we just replace that with a function call Most workarounds for Windows seem to "reserve" a specific range of module IDs instead of legitimately acquire a real ID, allowing chaos to happen when enough modules are loaded the right way. |
I believe https://github.com/bb107/MemoryModulePP implements this |
I'm using the latest version of MemoryModule (f02a8e6).
To reproduce, replace
SampleDLL.cpp
with:(this should be valid C++ code as far as I'm aware)
and
DllLoader.cpp
with:If
LoadFromFile()
is run, the program exits with 0.However, if
LoadFromMemory()
is run, it crashes with:Stacktrace:
Line 560 in
MemoryModule.c
:Strangely enough, if both
LoadFromLibrary()
andLoadFromMemory()
are run (and in that order!), there is no crash.The text was updated successfully, but these errors were encountered: