Подтвердить что ты не робот

Процесс приостановки в С#

Как приостановить весь процесс (например, Process Explorer, когда я нажимаю Suspend) на С#.

Я запускаю процесс с Process.Start и на определенном событии, я хочу приостановить процесс, чтобы иметь возможность провести некоторое расследование по его "снимку".

4b9b3361

Ответ 1

Здесь мое предложение:

 [Flags]
    public enum ThreadAccess : int
    {
      TERMINATE = (0x0001),
      SUSPEND_RESUME = (0x0002),
      GET_CONTEXT = (0x0008),
      SET_CONTEXT = (0x0010),
      SET_INFORMATION = (0x0020),
      QUERY_INFORMATION = (0x0040),
      SET_THREAD_TOKEN = (0x0080),
      IMPERSONATE = (0x0100),
      DIRECT_IMPERSONATION = (0x0200)
    }

    [DllImport("kernel32.dll")]
    static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
    [DllImport("kernel32.dll")]
    static extern uint SuspendThread(IntPtr hThread);
    [DllImport("kernel32.dll")]
    static extern int ResumeThread(IntPtr hThread);
    [DllImport("kernel32", CharSet = CharSet.Auto,SetLastError = true)]
    static extern bool CloseHandle(IntPtr handle);


private static void SuspendProcess(int pid)
{
  var process = Process.GetProcessById(pid);

  if (process.ProcessName == string.Empty)
    return;

  foreach (ProcessThread pT in process.Threads)
  {
    IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);

    if (pOpenThread == IntPtr.Zero)
    {
      continue;
    }

    SuspendThread(pOpenThread);

    CloseHandle(pOpenThread);
  }
}

public static void ResumeProcess(int pid)
{
  var process = Process.GetProcessById(pid);

  if (process.ProcessName == string.Empty)
    return;

  foreach (ProcessThread pT in process.Threads)
  {
    IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);

    if (pOpenThread == IntPtr.Zero)
    {
      continue;
    }

    var suspendCount = 0;
    do
    {
      suspendCount = ResumeThread(pOpenThread);
    } while (suspendCount > 0);

    CloseHandle(pOpenThread);
  }
}

Ответ 2

Благодаря Магнусу

После включения флагов я немного изменил код, чтобы быть методом расширения в моем проекте. Теперь я могу использовать

var process = Process.GetProcessById(param.PId);
process.Suspend();

Вот код для тех, кто может быть заинтересован.

public static class ProcessExtension
{
    [DllImport("kernel32.dll")]
    static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
    [DllImport("kernel32.dll")]
    static extern uint SuspendThread(IntPtr hThread);
    [DllImport("kernel32.dll")]
    static extern int ResumeThread(IntPtr hThread);

    public static void Suspend(this Process process)
    {
        foreach (ProcessThread thread in process.Threads)
        {
            var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
            if (pOpenThread == IntPtr.Zero)
            {
                break;
            }
            SuspendThread(pOpenThread);
        }
    }
    public static void Resume(this Process process)
    {
        foreach (ProcessThread thread in process.Threads)
        {
            var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
            if (pOpenThread == IntPtr.Zero)
            {
                break;
            }
            ResumeThread(pOpenThread);
        }
    }
}

У меня есть утилита, которую я использую, чтобы вообще приостановить/убить/перечислить процесс. Полный источник на Git

Ответ 3

Подробное решение с использованием Win32 p/invoke можно найти на CodeProject.

Ответ 4

Итак, как выглядит другой ответ, это приостановка потока в процессе, нет способа действительно приостановить процесс (т.е. в одном вызове)....

Немного другого решения было бы фактически отладить целевой процесс, который вы начинаете, см. блог Майка Столла для некоторых советов для реализации этого из управляемого контекста.

Если вы реализуете отладчик, вы сможете сканировать память или какой-либо другой щелчок, который вам нужен.

Однако я хотел бы отметить, что технически, теперь есть способ действительно сделать это. Даже если вы выполняете debugbreak с помощью целевого процесса debuggee, другой процесс в вашей системе может вставлять поток, и ему будет предоставлена ​​возможность выполнять код независимо от состояния целевого процесса (пусть даже скажем, если он попал в точку останова из-за нарушения доступа), если у вас есть все потоки, приостановленные до супервысокой суммы приостановки, в настоящее время находятся в точке останова в основном потоке процесса и в любом другом таком предполагаемом замороженном состоянии, все еще возможно, чтобы система ввела другой поток в этот процесс и выполнить некоторые инструкции. Вы также можете решить проблему изменения или замены всей точки входа, которую обычно вызывает ядро ​​ и т.д., Но теперь вы ввели вязкая раса MALWARE;)...

В любом случае использование управляемых интерфейсов для отладки кажется "намного проще, чем p/invoke'ng много встроенного вызова API, который будет плохо работать над тем, что вы, вероятно, действительно хотите делать... используя debug api;)

Ответ 5

См. эту статью CodeProject для основ win32: http://www.codeproject.com/KB/threads/pausep.aspx. Этот пример кода использует библиотеку ToolHelp32 из SDK, поэтому я бы рекомендовал превратить этот образец кода в неуправляемую библиотеку С++/CLI с помощью простого интерфейса, например "SuspendProcess (uint processID).

Process.Start вернет вам объект Process, из которого вы можете получить идентификатор процесса, а затем передайте это в свою новую библиотеку на основе вышеописанного.

Dave