-
Notifications
You must be signed in to change notification settings - Fork 770
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
Bug results in crash when loading some DLLs. (with code fix!) #101
Comments
We used "Load dll from memory" long before MemoryModule has come to scene. There always were loads of shitcode, and MemoryModule genetically consists of this legacy. It is not made by someone special, it is a compilation of knowledge that circulated long before - as code pastes, and many people used it does not really care how and why it works. Specifically, everything related to sections and relocation - topics which most people don't really understand. With all this I am just clarifying that it is not a bug but just common lack of knowledge. If what you say is right actually. The reason this comment is made is because someone around me has forked MemoryModule and as part of his modifications (under heavy usage in different cases), they actually fixed this issue, but never reported it - and this is what happened for years to code like memorymodule. Unfortunatelly I am not sure was the issue exactly FinalizeSections+VirtualProtect usage, but it was something you describe with self-patching code. |
It is definitely a bug. It results in a crash. DEP was introduced with Windows XP SP2 in 2004.
So it was wrong from the very beginning. I found several forks of fancycode here on Github. But they contain only minor changes. The only project which I found which does it correctly is not a fork of fancycode:
It is not difficult to understand how to load a DLL to memory. And the code would be far more easy to understand if there was a usefull TRACE implemented which shows what the code is doing. This is completely missing. For example showing the sections in the DLL.
I don't know why VisualStudio stores these rare values for the virtual size? This is a 32 bit DLL protected with WinLicense:
As you see Section 3 has a virtual size of 0x46B000 bytes but contains only 0x200 bytes of code which is copied from the file.
R = Read, W = Write, E = Execute |
Thanks for your patches and insights on this repo. I went with this repo to have a starting point myself because it was the most basic to start with (just one header and C files) and not someone's fanciful C++ machination (most so hard to read!). But making heavy modifications to fit my need (using a preallocated virtual memory section, and then plan on eventually adding support for sections it doesn't currently support (like SEH). Depends on what the developer wants. I wanted something that is more like shell code with my own minimal DLLs and don't expect it to support all possible DLL usages like the OS does. Hum.. I think one if they wanted to make the investment, they could go through leaked Windows sources like the WRK, Win2K3, etc., and use the ReactOS open-source too. Walk all the way from ntdll:LdrLoadDll() to kernel and back, filling in the blanks by reverse engineering ntdll.dll and ntoskrnl.exe as needed. One robust derivative solution that appears to be recent and maintained is this one. |
Hello BigJim I'am not working anymore on this. I got quite disappointed on the way because there are too many Microsoft secrets which would have to know to make a really good working own loader. On XP my modfied code works quite well, although not all is working neither. The problem is simple:
I studied ReactOS very thoroughly. The only way would be a complete reverse engineering of the Kernel. It is by purpose that we cannot load a DLL from memory easily. |
I tried to load a DLL which is protected with WinLicense into a process.
When calling the entry point I got a crash when Data Execution Prevention was enabled for the process.
I analyzed the problem and found that fancycode has a fat bug which has not yet been reported here.
These bugs are not relevant when you load a "normal" DLL.
But a DLL which is protected with WinLicense has strong anti-debugging techniques built in.
WinLicense modifies the executing code at runtime!
It permanently writes into the code section.
Apart from that I found fancycode (written by Joachim Bauch) is very clumsy and awkward.
There is lot of code which is superfluous and far more complicated than necessary.
For example in CopySections() he calls
memset(dest, 0, section_size);
This is nonsense because VirtualAlloc() already returns memory which is zeroed.
It is also nonsense that he calls VirtualAlloc() first for the entire image of the DLL (in MemoryLoadLibraryEx()) and then he calls VirtualAlloc() again for each section in CopySections() although the memory is already allocated.
It is also unnecessary to call VirtualFree() in FinalizeSection() in the case that a section has the flag IMAGE_SCN_MEM_DISCARDABLE.
I studied how the Microsoft's LoadLibrary() works and it does NOT free sections which are marked as discardable.
But the real fat bug is in FinalizeSections()
When he sets the protection flags in FinalizeSection() he passes the wrong size.
This results in the crash in my WinLicense protected DLL if DEP is enabled.
Correct would be:
VirtualProtect(..., Section->Misc.VirtualSize, ...)
But he uses instead
VirtualProtect(..., GetRealSectionSize(), ...)
This is wrong because the entire section must have the Execute flag, not only the first part where he has copied to with memcpy().
It is wrong because there are DLLs which unpack or modify code at runtime.
If the pages where the code is copied to do not have the Execute flag set, Data Execution Prevention triggers an Access Violation.
I don't post a pull request because nobody cares here since years.
This is a dead project. Joachim Bauch neither merges pull requests nor does he answer emails.
So if you are interested take my code and fix it on your own.
The following clumsy functions and structures are not needed anymore:
As you see my functions are far shorter than the original code.
And they work without crash!
Also have a look at my further postings here:
Create Activation Context Implementation (important)
#100
Remove unneccessay functions for searching resources:
#53 (comment)
and more...
By the way: The code from Joachim Bauch is not cleanly written.
You find a much cleaner code to load a DLL to memory on Codeproject:
https://www.codeproject.com/Tips/430684/Loading-Win-DLLs-manually-without-LoadLibrary
But it is lacking support for 64 bit Safe SEH and the Activation Context is not implemented in neither project.
The text was updated successfully, but these errors were encountered: