How to detect if the current process is being run by GDB?

The standard way would be the following:

if (ptrace(PTRACE_TRACEME, 0, NULL, 0) == -1)
  printf("traced!\n");

In this case ptrace returns an error if the current process is traced (i.e. running it with gdb or attaching to it).

But there is a serious problem with this: if the call returns successfully, gdb may not attach to it later. Which is a problem since I'm not trying to implement anti-debug stuff. My purpose is to emit an 'int 3' when a contition is met (i.e. an assert fails) and gdb is running (otherwise I get a SIGTRAP which stops the application).

Disabling SIGTRAP and emitting an 'int 3' every time is not a good sollution because the application I'm testing might be using SIGTRAP for some other purpose (in which case I'm still screwed, so it wouldn't matter but it's the principle of the thing :))

Thanks

57
задан Ciro Santilli 新疆改造中心法轮功六四事件 13 June 2015 в 11:21
поделиться

3 ответа

Ранее в качестве комментария: вы могли разветвить дочерний элемент, который попытался бы PTRACE_ATTACH своего родителя (а затем при необходимости отсоединить) и сообщить результат обратно. Хотя это кажется немного неэлегантным.

Как вы упомянули, это довольно дорого. Я думаю, это не так уж плохо, если утверждения терпят неудачу нерегулярно. Возможно, было бы целесообразно сохранить для этого один долго работающий дочерний элемент — совместно использовать два канала между родителем и дочерним элементом, дочерний элемент выполняет свою проверку, когда читает байт, а затем отправляет байт обратно со статусом.

16
ответ дан 7 November 2019 в 06:05
поделиться

Код В итоге я использовал следующее:

int
gdb_check()
{
  int pid = fork();
  int status;
  int res;

  if (pid == -1)
    {
      perror("fork");
      return -1;
    }

  if (pid == 0)
    {
      int ppid = getppid();

      /* Child */
      if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0)
        {
          /* Wait for the parent to stop and continue it */
          waitpid(ppid, NULL, 0);
          ptrace(PTRACE_CONT, NULL, NULL);

          /* Detach */
          ptrace(PTRACE_DETACH, getppid(), NULL, NULL);

          /* We were the tracers, so gdb is not present */
          res = 0;
        }
      else
        {
          /* Trace failed so gdb is present */
          res = 1;
        }
      exit(res);
    }
  else
    {
      waitpid(pid, &status, 0);
      res = WEXITSTATUS(status);
    }
  return res;
}

Несколько моментов:

  • Когда ptrace(PTRACE_ATTACH, ...) завершается успешно, отслеживаемый процесс останавливается и его необходимо продолжить.
  • Это также работает, когда gdb подключается позже.
  • Недостатком является то, что при частом использовании это вызывает серьезное замедление.
  • Также подтверждено, что это решение работает только в Linux. Как упоминалось в комментариях, это не будет работать на BSD.

В любом случае, спасибо за ответы.

19
ответ дан 7 November 2019 в 06:05
поделиться

Если вы просто хотите узнать, работает ли приложение под gdb для отладки Для целей Linux самым простым решением является readlink("/proc//exe") и поиск результата для "gdb".

6
ответ дан 7 November 2019 в 06:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: