标准方法如下:
if (ptrace(PTRACE_TRACEME, 0, NULL, 0) == -1)
printf("traced!\n");
在这种情况下,如果当前进程被跟踪(例如,使用GDB运行它或附加到它),ptrace将返回一个错误。
但这里面有一个严重的问题:如果调用成功返回,GDB可能不会连接到它。这是一个问题,因为我不想实现反调试的东西。我的目的是当一个条件被满足(例如,Assert失败)和GDB正在运行时发出一个'int3'(否则我会得到一个SIGTRAP,停止应用程序)。
每次禁用SIGTRAP并发出'int3'不是一个好的解决方案,因为我测试的应用程序可能将SIGTRAP用于其他目的(在这种情况下,我仍然很糟糕,所以这无关紧要,但这是事情的原理:))
8条答案
按热度按时间ds97pgxw1#
在Windows上有一个API IsDebuggerPresent来检查进程是否在调试中。在Linux上,我们可以用另一种方法来检查(效率不高)。
检查"跟踪器Pid"属性的"/进程/自身/状态"。
示例代码:
aelbi1ox2#
我最终使用的代码如下所示:
几件事:
9rygscc13#
你可以fork一个子进程,它会尝试
PTRACE_ATTACH
它的父进程(然后在必要时分离),并将结果传递回来,尽管这看起来有点不优雅。正如你提到的,这是相当昂贵的。我想如果Assert不规则地失败也不是太糟糕。也许保持一个长时间运行的子进程来做这件事是值得的--在父进程和子进程之间共享两个管道,子进程在读取一个字节时进行检查,然后将一个字节连同状态一起发送回来。
k7fdbhmy4#
我也有类似的需求,并提出了以下替代方案
如果调用debug_break函数,则只有在连接调试器时才会中断。
如果你在x86上运行,并且想要一个在调用者中中断的断点(而不是在 raise 中),只需包含下面的头,并使用debug_break宏:
a8jjtwal5#
我发现文件描述符“hack”的修改版本described by Silviocesare和blogged by xorl对我来说工作得很好。
这是我使用的修改过的代码:
g9icjywg6#
如果只是为了调试而想知道应用程序是否在GDB下运行,Linux上最简单的解决方案是
readlink("/proc/<ppid>/exe")
,并搜索"gdb"
的结果。cidc1ykv7#
这与terminal的回答类似,但使用管道进行通信:
在OS X下尝试原始代码,我发现waitpid(在父进程中)总是返回-1,并带有EINTR(系统调用中断),这是由pattach引起的,连接到父进程并中断调用。
不清楚再次调用waitpid是否安全(看起来它在某些情况下可能会出错),所以我只是使用了一个管道来进行通信,这是一个额外的代码,但可能会在更多的平台上可靠地工作。
这段代码已经在OS X v10.9.3(Mavericks)、Ubuntu 14.04(Trusty Tahr)(3.13.0-24-generic)和FreeBSD 10.0上进行了测试。
对于实现进程功能的Linux,此方法仅在进程具有
CAP_SYS_PTRACE
功能时有效,该功能通常在进程以root身份运行时设置。其他实用程序(
gdb
和lldb
)也将此功能设置为其文件系统元数据的一部分。可以通过链接
-lcap
来检测进程是否存在有效的CAP_SYS_PTRACE
。cngwdvgl8#
Sam Liao答案的C++版本(仅限Linux):