I've just found out by accident that doing this GetModuleHandle("ntdll.dll") works without a previous call to LoadLibrary("ntdll.dll").
This means ntdll.dll is already loaded in my process.
Is it safe to assume that ntdll.dll will always be loaded on Win32 applications, so that a call to LoadLibrary is not necessary?
From MSDN on LoadLibrary() (emphasis mine):
The system maintains a per-process reference count on all loaded
modules. Calling LoadLibrary increments the reference count. Calling
the FreeLibrary or FreeLibraryAndExitThread function decrements the
reference count. The system unloads a module when its reference count
reaches zero or when the process terminates (regardless of the
reference count).
In other words, continue to call LoadLibrary() and ensure you get your handle to ntdll.dll to be safe -- but the system will almost certainly be bumping a reference count as it should already be loaded.
As for "is it really always loaded?", see Windows Internals on the Image Loader (the short answer is yes, ntdll.dll is part of the loader itself and is always present).
The relevant paragraph is:
The image loader lives in the user-mode system DLL Ntdll.dll and not in the kernel library. Therefore, it behaves just like standard code that is part of a DLL, and it is subject to the same restrictions in terms of memory access and security rights. What makes this code special is the guaranty that it will always be present in the running process (Ntdll.dll is always loaded) and that it is the first piece of code to run in user mode as part of a new application. (When the system builds the initial context, the program counter, or instruction pointer is set to an initialization function inside Ntdll.dll.)
Related
I'm trying to write an APC dll injection driver, I've found this example and thought to modify it to my needs.
After I understood the code, this is how I thought to modify it (and my question come from there).
In the code, the writer used PsLookupThreadByThreadId to receive a referenced pointer to the ETHREAD structure of the targeted process.
PsLookupThreadByThreadId(pSpi->Threads[0].ClientId.UniqueThread,&Thread)
but to get the SYSTEM_THREAD_INFORMATION for the UniqueThread handle, he used ZwQuerySystemInformation
I want to load my dll right after ntdll is loaded, so I want to use PsSetCreateProcessNotifyRoutineEx and save the UniqueThread from the PS_CREATE_NOTIFY_INFO I got when the callback is called for the process I'm targeting.
And after ntdll is loaded, which I'll know thanks to PsSetLoadImageNotifyRoutineEx I could inject my dll using his APC injection logic.
my goal is to inject my dll in the PloadImageNotifyRoutine callback, but don't use ZwQuerySystemInformation as he does to get the UniqueThread, but save it in the PcreateProcessNotifyRoutineEx callback.
So, my question is: Can I trust the UniqueThread I get from PS_CREATE_NOTIFY_INFO is the same during all the process loading time?
I want to use PsSetCreateProcessNotifyRoutineEx and save the
UniqueThread from the PS_CREATE_NOTIFY_INFO I got when the
callback is called for the process I'm targeting.
about CreatingThreadId from PS_CREATE_NOTIFY_INFO
The process ID and thread ID of the process and thread that
created the new process
this id not for new created process/thread, but for creator. if you want inject self dll in the PloadImageNotifyRoutine callback - the PcreateProcessNotifyRoutineEx is useless for you.
the PloadImageNotifyRoutine called when image is mapped to target process - inside ZwMapViewOfSection . you need check that ProcessId (second parameter of PcreateProcessNotifyRoutineEx - The process ID of the process where image is loaded) is equal to PsGetCurrentProcessId(). this mean that image loaded to the current process and you can use KeGetCurrentThread() - you not need PsLookupThreadByThreadId at all
I want to load my dll right after ntdll is loaded
at this moment any user mode structures in process yet not initialized. because it initialized by ntdll. as result - if you inject your apc and force execute it at this moment - you got crash of process. nothing more
i can advice you inject your dll when kernel32.dll is loaded. and here you need check that this is load as dll, not simply image mapping - check ArbitraryUserPointer in thread teb - are it point to L"*\\kernel32.dll": smss.exe map kernel32.dll during create \\KnownDlls (ArbitraryUserPointer == 0 in this case), wow64 process several time map kernel32.dll (32 and 64 bit) with L"WOW64_IMAGE_SECTION" or L"NOT_AN_IMAGE" names in ArbitraryUserPointer
What would happen if I load same .dll twice or more times using:
handle = ::LoadLibraryExW(dllpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)
Does it return same address when ASLR(DYNAMICBASE) is on?
Nothing different than without ASLR. The second LoadLibraryEx call will return the same handle as the first call and the usage count of the DLL is incremented.
So the DLL isn't loaded "twice". Is is loaded on the first call.
Except the different use of the search path the behavior is identical to LoadLibrary.
From MSDN,
Section: Remarks [3rd Para]
If the specified module is a DLL that is not already loaded for
the calling process, the system calls the DLL's DllMain function with
the DLL_PROCESS_ATTACH value.
[11th Para]
The system maintains a per-process reference count on all loaded
modules. Calling LoadLibrary increments the reference count. Calling
the FreeLibrary or FreeLibraryAndExitThread function decrements the
reference count. The system unloads a module when its reference count
reaches zero or when the process terminates (regardless of the
reference count).
If the module is already loaded in the process memory, it will just return you back the same HMODULE handle with incremented reference count. Also, it will not call the DLL_PROCESS_ATTACH in subsequent calls.
What is the purpose of this flag (from the OS side)?
Which functions use this flag except isDebuggerPresent?
thanks a lot
It's effectively the same, but reading the PEB doesn't require a trip through kernel mode.
More explicitly, the IsDebuggerPresent API is documented and stable; the PEB structure is not, and could, conceivably, change across versions.
Also, the IsDebuggerPresent API (or flag) only checks for user-mode debuggers; kernel debuggers aren't detected via this function.
Why put it in the PEB? It saves some time, which was more important in early versions of NT. (There are a bunch of user-mode functions that check this flag before doing some runtime validation, and will break to the debugger if set.)
If you change the PEB field to 0, then IsDebuggerPresent will also return 0, although I believe that CheckRemoteDebuggerPresent will not.
As you have found the IsDebuggerPresent flag reads this from the PEB. As far as I know the PEB structure is not an official API but IsDebuggerPresent is so you should stick to that layer.
The uses of this method are quite limited if you are after a copy protection to prevent debugging your app. As you have found it is only a flag in your process space. If somebody debugs your application all he needs to do is to zero out the flag in the PEB table and let your app run.
You can raise the level by using the method CheckRemoteDebuggerPresent where you pass in your own process handle to get an answer. This method goes into the kernel and checks for the existence of a special debug structure which is associated with your process if it is beeing debugged. A user mode process cannot fake this one but you know there are always ways around by simply removing your check ....
One should not use functions other than those in kernel32.dll from DllMain:
From MS documentation:
Because Kernel32.dll is guaranteed to be loaded in the process address space when the entry-point function is called, calling functions in Kernel32.dll does not result in the DLL being used before its initialization code has been executed. Therefore, the entry-point function can call functions in Kernel32.dll that do not load other DLLs. For example, DllMain can create synchronization objects such as critical sections and mutexes, and use TLS. Unfortunately, there is not a comprehensive list of safe functions in Kernel32.dll.
...
Calling functions that require DLLs other than Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions load other system components. Conversely, calling functions such as these during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized.
My question:
But the documentation does not mention ntdll.dll. - Can I call LoadLibrary for "ntdll" and use functions in ntdll from DllMain:
1) during DLL_PROCESS_ATTACH (load and use functions of ntdll)?
2) during DLL_PROCESS_DETACH (use functions of previously loaded ntdll)?
Also, please, would somebody with 1500+ reputation like to create a new tag titled "dllmain" ?
The answer to the question "is it safe in DllMain" always defaults to "no". In this case, calling LoadLibrary is never okay.
Generally speaking, calling anything in ntdll.dll is not recommended even places where it is safe to do so.
Take a standard Windows application. It loads a DLL using LoadLibrary to call a function in it (we'll call this DLL_A). That function loads another DLL (we'll call it DLL_B). The application now unloads the DLL_A DLL using FreeLibrary as it no longer requires it.
The question is:
Is DLL_B still in memory and loaded?
Is this something I can depend upon, or is it undocumented?
No. DLL_B will not be unloaded. The LoadLibrary() call made by DLL_A will increment the load count for DLL_B. Since there is no corresponding FreeLibrary() call for DLL_B, the refcount will not go to zero.
From the LoadLibrary() docs:
The system maintains a per-process
reference count on all loaded modules.
Calling LoadLibrary increments the
reference count. Calling the
FreeLibrary or
FreeLibraryAndExitThread function
decrements the reference count. The
system unloads a module when its
reference count reaches zero or when
the process terminates (regardless of
the reference count).
You will have a handle leak in the case:
Program -Load> Dll A
-Load> Dll B
-Unload> Dll A
No code is implicitly executed by a module being unloaded to unload the modules that it loaded.
Since no code is executed to decrease the reference count, the module B will never be unloaded.
Here are the rules for loading / unloading dlls:
Each call to LoadLibrary and LoadLibraryEx will increment the reference count for that module. This is in the context of the calling process only, not across process boundaries.
Each call to FreeLibrary or FreeLibraryAndExitThread will decrement the reference count.
When the reference count reaches 0, it will be unloaded.
When Windows sees that your program is closed, any leaked unloaded modules will then be unloaded.
Depending on what you are doing, DllCanUnloadNow might be useful to you.
Still in memory vs still loaded:
There is no guarantee that your module will be released from memory at a certain time when the reference reaches 0. But you should consider the module as if it is unloaded when the reference count reaches 0.
Stopping the DLL from being unloaded:
To force the DLL from being unloaded you could try
The system calls DllMain with the DLL_PROCESS_DETACH flag. You could try to not return from this via some kind of blocking operation.
You could try to call LoadLibrary from within the DLL that you want to not be able to unload. (Self load)
Edit:
You mentioned your goal is to injet code into the running program and that you wanted to leak the handle on purpose.
That is fine, but if you run this operation a lot it can lead to a crash in your source Program because too many handles will be used, or eventually too much memory will be used.
You can return FALSE from your DllMain to stop it from being loaded so that you don't waste memory. You do this when fdwReason is DLL_PROCESS_ATTACH. You can read more about it here.
If you are trying to emulate a DLL and add in your own extra functionality, you will need to implement all of the functions that the source DLL implements and delegate each call back to the source DLL.
Read the Remarks section for a detailed explanation.
The key thing to note is:
The system maintains a per-process reference count for each loaded module
and further down
When a module's reference count reaches zero or the process terminates, the system unloads the module from the address space of the process
From MSDN:
Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. When the reference count reaches zero, the module is unloaded from the address space of the calling process and the handle is no longer valid.
DLLs in windows are reference counted. When A is unloaded you are decrementing the reference count on A, if it hits zero it will unload, and (assuming no bugs in the code) decrement the reference count on B. If the refcount on B goes to zero it will then be unloaded. It is possible DLL C has a refcount on B, and unloading A will not unload B.