The question below is for educational purposes only and the discussed featured are not meant to alter registered DLLs or develop a malware but for learning and experiencing.
Recently I've been exploring few methods to load my own custom DLLs instead of an application's original DLLs.
One of the methods that came up was the <exe>.local method.
After experiencing with this method a little bit and after I removed the KnownDlls entry from the registry I managed to replace some system DLLs with my patched DLLs successfully.
These are the DLLs:
However, the DLLs are IN the local folder:
However, there are still some DLLs that insist loading from the system32 directory, although they are present in the local folder.
Is there any way I can force the DLL's to load from the local folder instead of the system32 folder?
This is not an answer so much as a rambling, unsourced, brain dump.
It does serve to explain why I am not surprised at your result. This boils down, for me, to the crucial difference between CreateProcess and LoadLibrary, and how Win32 processes work.
Normally, when using LoadLibrary, you are using it from within the process you want the dll to be loaded into. As such, it can take advantage of a whole bunch of in-process context information about activation contexts, dll search paths etc. including knowledge of things like the app.local flag.
All these values are specific to the current process and it is not the job of any other process (or even the Kernel) to track stuff like this.
But, if we look at CreateProcess we can see some problems. When it is initially called, it is called in the context of the launching, not destination, process, so it knows nothing of the destination processes activation context. In fact, the destination process does not exist yet.
The CreateProcess implementation needs to create a NT process, and execute some code in it asap to perform the process load as it doesn't make any sense to instantiate all that per process context stuff in the current process.
But, to do that, there needs to be at least some code in the destination process: The kernel code responsible for parsing the EXE files header, extracting the headers and building the activation contexts that will be used to load the remaining dlls.
This means that, unfortunately for you, kernel32.dll and some dependencies need to be mapped into a process long before that process is capable of building a dll search context, noticing the app.local flag etc.
You should look at how the Windows loader works. This is OS version dependent, but some of those DLLs load before your program and the loader always looks for them on a path provided by the system. Look at the sequence by starting your program with WinDbg.
Related
Question concerns only Windows for now - other OS's are not so relevant right now.
Just by quick googling - it's possible to load native .dll from RAM, there are for example following libraries:
https://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/
=>
https://github.com/fancycode/MemoryModule
https://forum.nim-lang.org/t/7943
But all of them requires:
in-depth knowledge of PE file format
mostly those approaches are not debugger friendly.
What I have checked - windows's LoadLibraryA / LoadLibraryW are directed to ntdll.dll / LdrLoadDll - and best picture of how things works can be found from here: https://github.com/hlldz/RefleXXion
And even thus I don't have windows source code - I've checked same functionality from Wine:
LdrLoadDll: https://source.winehq.org/source/dlls/ntdll/loader.c#3169
load_dll: https://source.winehq.org/source/dlls/ntdll/loader.c#3083
load_native_dll:
https://source.winehq.org/source/dlls/ntdll/loader.c#2564
NtMapViewOfSection: https://source.winehq.org/source/dlls/ntdll/unix/virtual.c#4469
find_dll_file: https://source.winehq.org/source/dlls/ntdll/loader.c#3021
open_dll_file: https://source.winehq.org/source/dlls/ntdll/loader.c#2467
Suspect loading dll happens via following function calls:
NtOpenFile, NtQueryAttributesFile, NtCreateSection/NtOpenSection, NtMapViewOfSection (*)
(More information could be found in
https://github.com/Hagrid29/PELoader
https://gist.github.com/bats3c/59932dfa1f5bb23dd36071119b91af0f
https://www.octawian.ro/fisiere/situri/asor/build/html/_downloads/122f95f9a032396603a837c53b125bb8/Russinovich_M_WinInternals_part1_7th_ed.pdf
)
I was also thinking if I could just override NtOpenFile and just redirect file open (in
https://github.com/SegaraRai/PathRedirector manner)
to different path - but main question what is the alternative location where to store file?
I was thinking if NtOpenFile can open even device, then maybe just replace file
with some sort of named pipe (https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipe-client) - but then in maps on how well this will work with NtMapViewOfSection.
Since I was not able to find any working example of such hook or operation (E.g. LoadLibary("\\.\pipe\mynamedpipe_as_dll")) - there is always a risk that such combination is not simply supported.
Is it possible to load native .dll purely from RAM:
Without using file system (not to store .dll e.g. in temporary folder)
Without involving custom drivers (like Dokan) ?
So loaded .dll would be still debugger friendly ?
Not tightly bound to PE file format structures (or use PE structures as less as possible)
If you miss bit more information, check also my own experiments with native dll loading (maybe can give some hints on solving the issue):
https://github.com/tapika/test_native_dll_loading
https://github.com/tapika/test_native_dll_loading/discussions/2
Distinguish between debug and release use cases. In debug, save the DLL in a temp file and load with LoadLibrary, which will enable debugging. In release, run from memory with no capability for debugging.
Here's another idea, from considering the linked Guthub issue. If the purpose is to let the users provide their own compression/decompression logic while building a ReadyToRun executable, let them provide that as a static library (object) as opposed to a DLL. The larger project is already about packaging stuff into a single executable, might do some linking while at it.
Yet another idea would be to let the users provide the codec in some kind of interpreted language and optionally plug in the interpreter that supports debugging. Windows comes with a built-in JavaScript interpreter, look up Active Scripting, and debugging those is a free bonus. The performance probably won't be on par with a native code implementation, though.
I think you could probably do something similar with Frida. Hook the functions LoadLibraryA / LoadLibraryW and reimplement them in Frida. but I don't believe this is something that would be stable for production.
For some reference
By analyzing existing approaches (like PE Loader https://github.com/Hagrid29/PELoader) and using minhook library - I've managed to load .dll from RAM.
I've created git repository with example code on github:
https://github.com/tapika/dllloader
Could you create a ramdisk to put your DLL there? What exactly is the use-case for this? There are a couple ways to spin up a file in RAM, C#'s MemoryMappedFile for example. I'm not sure if this would be debugger friendly.
This question is a bit similar to this one, except for a little twist :
Can I modify the side-by-side assembly search sequence?
We have a couple different softwares, made with different languages, that talk to each other when they run. To achieve this we made .NET COM objects that we load using Registration-Free COM Activation. This works well. Some of the languages we use can't load COMs, so we made a C++ Wrapper DLL that uses ACTCTX to activate the COMs from their embeded manifests. Also working well.
But now, we have a case where our C++ Wrapper is loaded by code that is ran by an application that isn't ours (let's call it the runtime) that is located somewhere and our application is located somewhere else. We'd rather deploy our COM objects at the same place as application is deployed rather than next to the runtime application.
Not that it is important as the concept remains the same, but the runner is FourJ's Genero (fgl.exe) and the code that calls our C++ wrapper are in .42m files. The runner (fgl.exe) is installed with Genero, by default in Program Files\FourJs and our applications are in another directory with our company's name ie : Program Files\MyCompany
This is similar to what you'd get with Java. Runtime at one place, applcation somewhere else.
So in our case, our .42m loads the C++ Wrapper properly, the wrappers activates the COM (located in the same directory as our .42m and the wrapper) properly but once we try to instanciate an object, we get a "80070002" file not found error.
I've read
Assembly Searching Sequence and noticed the described behavior using Process Monitor.
So what happens is, since ultimately it's fgl.exe that is running, the Windows Side-By-Side loader looks into :
C:\Program Files(x86)\FourJs\fgl\gen2.50\bin\MyCom.dll
C:\Program Files(x86)\FourJs\fgl\gen2.50\bin\MyCom.dll\MyCom.dll
While my COM is really inside of C:\Program Files(x86)\MyCompany\MyApplication\MyCom.dll
To confirm the behavior, we copied the COM in the same directory as fgl.exe and as expected, it works.
So i would like to be able to add a Search Directory to my Activation Context so that it looks for this DLL in my deployment directory.
Is this possible ?
If i can't find another solution, we'll end up deploying our COMs inside of that directory, but that's just not the right.
Thanks
I am trying to use dll injection to intercept a call to Direct3DCreate8 from my application to acquire a handle to the Direct3d device and draw an overlay on the screen that it projects. The call to this API happens right after the application's execution which, if I understand correctly, renders useless the dll injection into running process technique as the API call I was after has already happened when I inject the dll.
Is this assumption correct? If yes, how can one inject the dll during process execution to catch a desired API call?
EDIT: I am aware of system-wide api hooks but would be nice to hear a 'local' solution to this problem.
EDIT 2: Forgot to mention, replacing the .dll in the application's folder is of no use, as the application looks for the .dll (d3d8.dll in my case) in System32/SysWOW64 directories.
Being a bit late for the party I wanted to offer you a solution of using Microsoft Detours (which is free for non-commercial use on x86 platforms and costs tremendous money otherwise). They have a DetourCreateProcessWithDllEx function that might suit your needs.
Quoting Detours documentation:
The process is created in a suspended state with the CREATE_SUSPENDED flag to CreateProcess. Detours then modifies the image of the application binary in the new process to include the specified DLL as its first import. Execution in the process is then resumed. When execution resumes, the Windows process loader will first load the target DLL and then any other DLLs in the application's import table, before calling the application entry point.
What I've seen so far, there can only be one plugin per .dll file, is that correct? The Browser calls NP_GetEntryPoints, NP_Initialize and NP_Shutdown only "once" per dll, right?
What I'm aiming for is to create multiple plugins in one dynamic library. Is that possible, and if, how?
What I've seen so far, there can only be one plugin per .dll file, is that correct?
No, you can have multiple plugins implemented in one DLL.
The Browser calls NP_GetEntryPoints, NP_Initialize and NP_Shutdown only "once" per dll, right?
Only once per process and loading (keep in mind that it will be unloaded while when no instance is alive anymore).
What I'm aiming for is to create multiple plugins in one dynamic library. Is that possible, and if, how?
It's possible. You just register the different mimetypes for the same dynamic library (e.g. on Windows several mimetype entries in the registry pointing to the same DLL).
NPP_New() gets a NPMIMEType as it's first parameter, which let's you identify which "plugin" was requested.
Also, NP_GetMIMEDescription() needs to be adjusted (used on Linux and Mac OS).
On Windows you should have the list of mimetypes, seperated by |, in the version info (entry MIMEType).
One part of some software I have written is a COM dll.
Other software uses this COM dll.
My software has an update function where it will download a newer version of the dll, but the update will fail if the dll is in use because the file cannot be deleted or written to.
The question is, how can I update a COM dll that is in use?
I have considered popping up a message asking the user to close any applications that are using the DLL if it is in use, if this is the best solution how would I go about detecting if the COM dll was in use before popping up the message?
Thanks in advance.
You cannot update it in place for existing applications, but one way to do this would be to save it with a different file name or different folder and call DllRegisterServer on the DLL to register it under the new name. New applications which begin using your object should now use the new version.
If this is just a matter of detecting whether you can replace the file then it is easy. Just try to open it with a share flag that denies reading. That's going to fail if the DLL is loaded in another process. Use _fsopen() or CreateFile(). Beware of the race condition.
Detecting which processes have the file loaded is a harder problem, CreateToolhelp32Snapshot() and Process32First/Next plus Module32First/Next to enumerate processes and the DLLs they have loaded. Still tough to generate a good diagnostic for the user, the process name isn't that helpful.
When you have downloaded the update, you must launch a third program (which you write) that does not have any dependancies on your COM component, or any other piece that is to be updated. This launcher, or bootstrapper, must shut down all your pieces, uninstall them, and install the update. When the update is installed you may then re-launch your application.
If you need also to download updates to the updater itself, your main program can do that.
Here is a simple solution for you. Create a wrapper DLL, which will be used by the other processes. Inside that DLL you explicitly load/unload your DLL, which is subject to updates. Of course you will have to suspend all callers when an update process kicks in.