Which process loads ntdll.dll?

I'm trying to learn how ntdll.dll gets mapped in Windows, specifically looking for address space that ntdll.dll can execute from across processes. Since ntdll is mapped to every user-space process address range, I’m curious about which component is responsible for loading it first and then mapping it, and whether there’s a shared memory region I can leverage.

WinDbg lm shows that ntkrnlmp.exe appears to be involved (theoritically), but I can't find any actual file for it on disk. I’ve dumped ntkrnlmp.exe using .writemem, and did a few quick searches on IDA. But I still couldn't find anything valuable about ntdll loading.

If you are wondering about the bigger picture, I am able to write to globally mapped ntdll and have verified it works and affects every process. The problem is that I am not sure where my trampoline function should be at.

I looked for ZwExtendSection, but from research it seems like it cannot be used for image-mapped sections.

I tried to specify an address in kernel space. As expected, every process crashed with an access violation.

A few things I want to point out before you do:
Yes, I am trying to do a some kind of global user-land hook.
Yes, I am aware what I am trying to do is dangerous and can cause system instability.
No, I don't think it's bad enough for you to advice everyone to avoid my product.
No, I am not trying to develop malware.

Ntkrnlmp.exe is just the object name. The file is ntoskrnl.exe, which is located in System32. There used to be separate executables for uniprocessor and multiprocessor machines, and the "mp" version was the multiprocessor version. There's only one now, but the old name persists.

Ntkrnlmp.exe needs imports from Ntdll.dll (plus others). It obviously can't load ntdll; ntdll has to be present and linked in before it can begin execution.

The creation of a process has to be done in kernel mode. It sets up the process structures, the memory space, and the primary thread. The kernel has to map in the DLLs that are required to initiate the process.

Ntdll.dll only gets loaded once, and thereafter is mapped into every new process.

Thanks for the information about ntkrnlmp.exe.

I know its only loaded once, but I am asking where. Is there a way for me to know where it can execute from? I need to jmp to an address it can reach to.

I don't know the exact answer. It's somewhere very early in the boot process.

Ntdll contains the "native API" that sits underneath the subsystems (like Win32) and acts as a layer between Win32 and the NT kernel. It is an integral part of the boot process and gets loaded as the first or second DLL at boot time when user mode is initialized.

there is a way to globally hook user land APIs look at this maybe it helps

- The AppInit_DLLs mechanism is not a recommended approach for legitimate applications because it can lead to system deadlocks and performance problems.
- The AppInit_DLLs mechanism is disabled by default when secure boot is enabled.
- Using AppInit_DLLs in a Windows 8 desktop app is a Windows desktop app certification failure.

This won't work.

@Peter_Viscarola_OSR Sorry for mention but, could this be related to PspMapSystemDll perhaps?

The particular address is randomized. When NT is initializing, it creates a section object to use when mapping NTDLL.

During Phase 1 of the NT initialization process, the IO manager maps all the supported system DLLs in the System process address space and stores their base addresses.

PsMapSystemDlls()/PspMapSystemDll() maps the system DLL into the specified process. It's called during the process initialization by the memory manager when setting up the address space.

Would a modification on this section trigger PG?

EDIT: Seems like I cannot modify size of this section without hooking PsLocateSystemDll() (and directly MmCheckSystemImage), which would definitely trigger PG.

Thanks for helps.

You already found out that you can't modify the section. Right? That was in your very first message.

I can modify contents the section. I can read and write to it.
I cannot modify the size of the section, since its an image-mapped section.
My goal is to modify size of the section (which can't be done), or make a new section that ntdll can jmp to.

I have to ask the question: What are you really attempting to do here? The only person I know of who tried to play games with ntdll, was trying to break security of the whole system.

1 Like

Since PatchGuard guards the SSDT, my only hope for doing a global hook (at least, in user-mode. But that's enough for now.) is modifying exported functions in ntdll. Which is loaded once and mapped everywhere(tm).

@Don_Burn for old time's sake, perhaps your usual admonition about crap ware would be in order?

1 Like

Mark,

I'm retired and mellowed. I will say to RsQUE that 25 years ago it was determined that hooking was the problem not a solution. You will never get a reliable solution from hooking, but most of the problem people are trying to solve with hooking can be solved with other approaches.

1 Like

have you considered why SSDT patching is forbidden? And why no suitable substitute exists?

no legitimate product could rely on this approach, and although members of this forum have inadvertently helped malware authors in the past, we try not to

If you think you are keeping some kind of trade secret by not sharing your ultimate aim, I suggest that it is probably naïve of you. If you want real help, you are going to have to

I agree. After some more "tinkering", which would be the wrong word, it's obvious that this won't get to anything useful. Trying to hook ntdll "with help of kernel" is the ridiculous.