target crash on RhInjectLibrary

May 11, 2009 at 12:38 AM


playing around with the unmanaged EsayHook API, i've noticed that some targets crash on RhInjectLibrary.

In other targets the same code (only different PID) works. I don't do anything in NativeInjectionEntryPoint, tried sleeping and a MessageBox, but no hooking or anything.

I my tests I had crashs attaching to Thunderbird.exe and Firefox, working injection with calc.exe, devenv.exe.

Any suggestions as to what the cause is and/or how I should go about debugging this further? I did my tests on vista x64, but had injecting code, injected library and target all 32bit processes. I'm not sure to what extend the warning about the native hooking API not being able to cross WOW64 boundaries applies here? The error code in thread.c only checks for x64 trying to inject x86 and vice versa, so I assume it should work?

The crash seems to happen after thread.c:933 calls NtCreateThreadEx.
NtCreateThreadEx itself returns without error.

In Line 948:
Code = WaitForMultipleObjects(2, Handles, FALSE, INFINITE);

Code is set to 0, the following error path ends up in
Line 986:
    case 0:
            THROW(STATUS_INTERNAL_ERROR, L"C++ completion routine has returned success but didn't raise the remote event.");

Attaching WinDbg to the target i can see an exception like:

ModLoad: 034d0000 0358c000   f:\dev\easyhook\unmanagedregtest\Injector\Debug\EasyHook32.dll
(13ac.3f4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=034d0000 ebx=032e0095 ecx=7684467f edx=005666d0 esi=032e0095 edi=00000000
eip=745c4618 esp=065efae4 ebp=034d0000 iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
745c4618 ??              ???
0:015> k
ChildEBP RetAddr  
WARNING: Frame IP not in any known module. Following frames may be wrong.
065efae0 032e0017 0x745c4618
065efaec 768be4a5 0x32e0017
065efaf8 7760cfed kernel32!BaseThreadInitThunk+0xe
065efb38 7760d1ff ntdll!RtlCreateUserProcess+0x8c
065efb50 00000000 ntdll!RtlCreateProcessParameters+0x4e



Benjamin Schwehn

May 11, 2009 at 1:34 PM

Turns out I just didn't run as Administrator. D'oh. Curious that it sometimes works, sometimes crashes, but as long as it works as admin, I'm happy.



Ben Schwehn

May 12, 2009 at 5:10 PM

>I'm not sure to what extend the warning about the native hooking API not being able to cross WOW64 boundaries applies here

The unmanaged API does not support this. Only the managed version of EasyHook will support hooking through WOW64 boundaries!


That it sometimes fails and sometimes succeed probably depends on the target, e.g. whether or not your process has access to the target. But the error you get is still strange. Normally the thing should fail earlier on, in case of access violation...

Jun 11, 2009 at 9:13 PM

Hi Christoph


Do you remember I have loaded an issue about EasyHook crashing targets when running from Explorer.exe as host? I have just read this and I notice I am getting the same error (access violation) when running that method in x86 machines with managed injection.

Maybe something in the asm code?



Jun 12, 2009 at 10:45 AM

Microsoft hooked explorer.exe process since Windows 2000 (may be after SP4) by its hooking engine shim.dll.  The hooking happen when the process loaded.  The LoadLibaray and GetProcAddress is detoured to return specific API to Microsoft's special hook handler (pointed to AcLayers.dll and other DLLs).  These API pointers is saved in the REMOTE_INFO structure (see RhInjectLibrary) and pass to the target process by calling CreateRemoteThread.  These API pointers are only valid in host process (with AcLayer.dll) but invalid in target process (without AcLayer.dll).  That's why the target crash.

One solution is to replace the LoadLibrary/GetProcAddress in the REMOTE_INFO by undocumented API LdrLoadDLL/LdrGetProcedureAddress as it seems that Microsoft doesn't hook these 2 API by the compatibility layer.  It incurs changes in the Injection_ASM.


Jun 12, 2009 at 1:23 PM


Thanks for your detailed information!, we spent a lot of time googling trying to find out why explorer.exe was not a good host for the injections.

There isn't a way to just remove the shim.dll from explorer? or to load it on the target processes to let the injection continue? We have passed the project deadline and I am not sure we can wait another EasyHook release :-\

Many Thanks foonson!

Jun 12, 2009 at 5:01 PM

I am not sure.  May be you can achieve it by modifying HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags.  Process loader read the registry and decide how to hook the application.

You can view the microsoft hooking database by Microsoft Application Compatibility Toolkit.  The list is long.  Hope you find the information about explorer.exe.

Jun 12, 2009 at 9:25 PM

Great information foonson!!!!!

I have managed to get this working by adding this to the registry:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags]

This disables all the compat options for Explorer.exe. So EasyHook can do the hooks.


Sep 10, 2009 at 10:59 AM


I have the same problem as original poster on Vista x64 running a x86 process, using x86-only easyhook library.

About half of the tested (2 of 4) applications crash upon call to vista-specific NtCreateThreadEx. Tracing the code before, only other error is that GCHandle hPassThru fails native check IsValidPointer. But the code seem to recover and continue flawlessly (any idea how to fix that?).

Anyway, when I commented out the NtCreateThreadEx and fall back to CreateRemoteThread, problems went away at all crashing applications.

Maybe it solved the problem, but nevertheless I am posting here so you can be aware of the issue. If you'd need anymore testing and reproduction from my side, feel free to ask. I like the library and hope to be using it for hooking specific addresses (can you do that?) and reading variables from the hosting process.