EasyHook / EasyHook

EasyHook - The reinvention of Windows API Hooking
https://easyhook.github.io
MIT License
3.03k stars 654 forks source link

System.AccessViolationException: STATUS_ACCESS_DENIED: Unable to open service control manager. Check for administrator privileges! (Code: 5) #368

Open wangruoyi1996 opened 3 years ago

wangruoyi1996 commented 3 years ago

StackTrace: at EasyHook.NativeAPI.Force(Int32 InErrorCode) at EasyHook.NativeAPI.RtlInstallService(String InServiceName, String InExePath, String InChannelName) at EasyHook.ServiceMgmt.Install() at EasyHook.ServiceMgmt.Inject(Int32 InHostPID, Int32 InTargetPID, Int32 InWakeUpTID, Int32 InNativeOptions, String InLibraryPath_x86, String InLibraryPath_x64, Boolean InRequireStrongName, Object[] InPassThruArgs) at EasyHook.RemoteHooking.InjectEx(Int32 InHostPID, Int32 InTargetPID, Int32 InWakeUpTID, Int32 InNativeOptions, String InLibraryPath_x86, String InLibraryPath_x64, Boolean InCanBypassWOW64, Boolean InCanCreateService, Boolean InRequireStrongName, Object[] InPassThruArgs) at EasyHook.RemoteHooking.Inject(Int32 InTargetPID, String InLibraryPath_x86, String InLibraryPath_x64, Object[] InPassThruArgs)

My system is Windows10 x64 This exception only occurs when inject a specific 32-bit program

wangruoyi1996 commented 3 years ago

I did some debugging.

Not running as Administrator: RemoteHooking.InjectEx -> NativeAPI.RhInjectLibraryEx -> NativeAPI_x64.RhInjectLibrary -> OpenProcess (this method return null and GetLastError() == ERROR_ACCESS_DENIED, then THROW(STATUS_ACCESS_DENIED, L"Unable to open target process. Consider using a system service.")) -> ServiceMgmt.Inject (Because of the last bug, you started trying to use system services) -> ServiceMgmt.Install -> NativeAPI.RtlInstallService -> NativeAPI_x64.RtlInstallService -> OpenSCManagerW (this method return null then you THROW(STATUS_ACCESS_DENIED, L"Unable to open service control manager. Check for administrator privileges!"))

I think the first error is the same as the second one, which is the lack of administrator rights, so I tried to run as administrator.

Running as Administrator: RemoteHooking.InjectEx -> NativeAPI.RhInjectLibraryEx -> NativeAPI_x64.RhInjectLibrary -> if(!Is64BitTarget) THROW(STATUS_WOW_ASSERTION, L"It is not supported to directly hook through the WOW64 barrier.") -> WOW64Bypass.Inject -> WOW64Bypass.m_Interface.InjectEx -> I don't know what happened, just got an exception "STATUS_INTERNAL_ERROR: Unknown error in injected C++ completion routine. (Code: 15)" RemoteStackTrace
at EasyHook.NativeAPI.Force(Int32 InErrorCode) at EasyHook.RemoteHooking.InjectEx(Int32 InHostPID, Int32 InTargetPID, Int32 InWakeUpTID, Int32 InNativeOptions, String InLibraryPath_x86, String InLibraryPath_x64, Boolean InCanBypassWOW64, Boolean InCanCreateService, Boolean InRequireStrongName, Object[] InPassThruArgs) at EasyHook.HelperServiceInterface.InjectEx(Int32 InHostPID, Int32 InTargetPID, Int32 InWakeUpTID, Int32 InNativeOptions, String InLibraryPath_x86, String InLibraryPath_x64, Boolean InCanBypassWOW64, Boolean InCanCreateService, Boolean InRequireStrongName, Object[] InPassThruArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs) at System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage msg) Exception rethrown at [0]:

justinstenning commented 3 years ago

Please share a simple version of your code

wangruoyi1996 commented 3 years ago
        EasyHook.RemoteHooking.IpcCreateServer<HelperServiceInterface>(ref channelName, System.Runtime.Remoting.WellKnownObjectMode.Singleton, communication);

        injectionLibrary = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "Stardew Valley Mod.dll");

        int pid;
        if(!int.TryParse(pidBox.Text, out pid))
        {
            IntPtr hwnd = FindWindow(null, "Stardew Valley");
            if (hwnd != IntPtr.Zero)
            {
                GetWindowThreadProcessId(hwnd, out pid);
            }
            else
            {
                return;
            }
        }
        try
        {
            EasyHook.RemoteHooking.Inject(pid, injectionLibrary, injectionLibrary, channelName);
            EasyHook.HelperServiceInterface.BeginInjection(pid);
        }
        catch (Exception ex)
        {
            InjectionMSG.AddAMSG("inject fail");
        }
justinstenning commented 3 years ago

Is your .dll that you are injecting a .NET assembly compiled with AnyCPU?

wangruoyi1996 commented 3 years ago

Is your .dll that you are injecting a .NET assembly compiled with AnyCPU?

yes

justinstenning commented 3 years ago

Not sure sorry, perhaps the target is implementing some other protection mechanisms that result in a access denied message.

wangruoyi1996 commented 3 years ago

I don’t think it’s because of the target. I tested it on another computer, and the injection procedure and target are the same. But the result is completely different.

Not running as Administrator: RemoteHooking.InjectEx -> NativeAPI.RhInjectLibraryEx -> NativeAPI_x64.RhInjectLibrary -> if(!Is64BitTarget) THROW(STATUS_WOW_ASSERTION, L"It is not supported to directly hook through the WOW64 barrier.") -> WOW64Bypass.Inject -> WOW64Bypass.m_Interface.InjectEx -> No Exception! and successfully injected.

I did not run as administrator but still got permission. In addition, WOW64Bypass.m_Interface.InjectEx was also successfully executed. I think the difference between the two computers in some settings caused this result, but I don’t know the underlying operating mechanism of EasyHook, so I can’t analyze the reason.