Example #1
0
        public void StartProcessAndWaitForDebugger(IEnumerable <String> args)
        {
            STARTUPINFO         si = new STARTUPINFO();
            PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

            // disable the hook so won't call ourselves recursively
            ImageFileExecutionWrapper.SetupHook(imagePath, false);

            var sargs = String.Join(" ", args);

            sargs = String.Join(" ", "\"" + imagePath + "\"", sargs);
            bool success = NativeMethods.CreateProcess(null, sargs, IntPtr.Zero, IntPtr.Zero,
                                                       false, ProcessCreationFlags.CREATE_SUSPENDED, IntPtr.Zero, null, ref si, out pi);

            // enable the hook again
            ImageFileExecutionWrapper.SetupHook(imagePath, true);

            if (!success)
            {
                throw new Win32Exception();
            }
            var hthread = pi.hThread;

            var failuresCnt       = 0;
            var isDebuggerPresent = false;

            while (!isDebuggerPresent)
            {
                if (failuresCnt > 3)
                {
                    Trace.Write("Too many failures while waiting for the debugger to appear - I give up.");
                    break;
                }
                if (!NativeMethods.CheckRemoteDebuggerPresent(pi.hProcess, ref isDebuggerPresent))
                {
                    failuresCnt++;
                    continue;
                }
                Thread.Sleep(1000); // sleep for 1s before the next check
            }
            // resume the process thread
            NativeMethods.ResumeThread(hthread);
        }
Example #2
0
        static void Main(string[] args)
        {
            var result = CommandLine.Parser.Default.ParseArguments <Options>(args);

            if (result.Errors.Any())
            {
                return;
            }
            if (!IsUserAdmin())
            {
                Console.WriteLine("You need to be an administrator to use this application.");
                return;
            }
            if (result.Value.ShouldInstall && result.Value.ShouldUninstall)
            {
                Console.WriteLine("You need to decide whether you would like to install or uninstall a hook.");
                return;
            }
            if (result.Value.ListHooks)
            {
                ImageFileExecutionWrapper.ListHooks();
                return;
            }

            if (result.Value.Timeout > 0)
            {
                SetServiceTimeout(result.Value.Timeout);
            }
            else
            {
                if (GetServiceTimeout() < 60000)
                {
                    // service will be killed if it does not respond under 1 min.
                    Console.WriteLine("Warning: current ServicePipeTimeout is set under 1 min - this time might not be enough " +
                                      "to attach with the debugger to the service and start debugging it. It's highly recommended to set this " +
                                      "value to at least 4 min (you may use -timeout option for this purpose)");
                }
            }

            var svcpath = result.Value.ServiceExePath;

            if (svcpath == null)
            {
                Console.WriteLine("A path to the service exe file must be provided.");
                return;
            }

            if (result.Value.ShouldInstall)
            {
                ImageFileExecutionWrapper.SetupHook(svcpath, true);
            }
            else if (result.Value.ShouldUninstall)
            {
                ImageFileExecutionWrapper.SetupHook(svcpath, false);
            }
            else
            {
                // here the logic will be a bit more complicated - we will start the process
                // as suspended and then wait for the debugger to appear
                var s = new Suspender(svcpath);
                s.StartProcessAndWaitForDebugger(result.Value.ServiceArgs);
            }
        }