0

I am using Windows 7 Professional x64.

I need to hook DefWindowProcW procedure. But when I try to get it's address via GetProcAddress(), it returns address of NtdllDefWindowProcW(), which is located in ntdll.dll. There is a jump to real user32 function DefWindowProcW() at the beginning of NtdllDefWindowProcW().

Is there a way to get real procedure address instead of ntdll procedure?

cls
  • 501
  • 1
  • 5
  • 18

1 Answers1

3

This is what is known as a forwarded export. The function was implemented in user32 in earlier versions of Windows. But at some point, Microsoft decided to move it into ntdll. In order to avoid breaking application the user32 export forwards to the function named "NtdllDefWindowProc_W" in ntdll.

The forwarded address in ntdll is where the function is actually implemented. That it might subsequently call into user32 is an implementation detail. So, if you want to hook DefWindowProcW, you can perfectly well hook the address returned by your call to

GetProcAddress(GetModuleHandle("user32.dll"), "DefWindowProcW")
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I only care about Windows 7 x64 because I did not see forwarded export of DefWindowProcW on earlier versions of Windows. So, I need more general solution. Where can I find real address? In export directory? – cls Jun 16 '15 at 15:24
  • Which one jumps to which? From the question, it sounds like the version in `ntdll.dll` is not the desired address. – Ben Voigt Jun 16 '15 at 15:24
  • @BenVoigt DefWindowProc was originally implemented in user32. When MS decided to move it to ntdll they use the mechanism of forwarding to make that transparent to consumers. A consumer asks for the function from user32, but the loader knows that it is actually in ntdll. – David Heffernan Jun 16 '15 at 15:25
  • @deselect The function is implemented in ntdll. It is not implemented in user32. The fact that the function in ntdll might call into user32 is an implementation detail. – David Heffernan Jun 16 '15 at 15:27
  • So the question's claim "There is a jump to real ... DefWindowProcW() at the beginning of NtdllDefWindowProcW()." is incorrect? – Ben Voigt Jun 16 '15 at 15:28
  • @BenVoigt There might well be a jump there. But that's just an implementation detail. – David Heffernan Jun 16 '15 at 15:29
  • But [MSDN](https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms633572(v=vs.85).aspx) says that it is in `user32`. – cls Jun 16 '15 at 15:37
  • It was once upon a time. But then it moved. And in order not to break old programs a forwarded export was used. And all MSDN says is that to import it you look in user32. It doesn't guarantee that the value returned is in that module. – David Heffernan Jun 16 '15 at 15:43
  • So I can not rely on disassembler? – cls Jun 16 '15 at 16:05
  • The address in ntdll is the one you want – David Heffernan Jun 16 '15 at 16:14
  • 1
    The function is implemented in user32, but linking to it is set up dynamically via ntdll -- I guess to add flexibility. In Windows 7, before user32 has been initialized the jump instead goes to `ntdll!UninitUser32Proc`, which calls `DbgPrintEx(0, 0, "User32 init not called")` and then `ZwTerminateProcess(0xC000000D)`. After user32 has been initialized it jumps to `user32!DefWindowProcW`. – Eryk Sun Jun 16 '15 at 17:54
  • @eryksun I'd say it was implemented in ntdll by calling into user32. But for purposes of hooking, the address in ntdll is the one that is needed. – David Heffernan Jun 16 '15 at 22:42
  • I think the bottom line here is that, regardless of the details, the code making the calls that need to be intercepted will be doing the same thing the OP is. So hooking that address should be fine. – Harry Johnston Jun 16 '15 at 23:49
  • @HarryJohnston and David, I wasn't trying to contradict the answer. I was just providing some extra information. That said, the OP should note that not all code necessarily calls this address. Internal code is likely to directly call `user32!DefWindowProcWorker` or maybe `user32!RealDefWindowProcWorker`. Also, the jump target is a procedure set up in the table `ntdll!NtUserPfn`, which I believe win32k captures at startup for callbacks into user mode. I don't see why the kernel side would call the user-mode `DefWindowProc`, but it's something to consider in general. – Eryk Sun Jun 17 '15 at 05:56