I'm reading some PPT and it says ENV("_") can be used for anti-debugging in Linux

enter image description here

Does anyone know what it means?

  • 20
    Automatic typographers quotes should be disabled by people who talk about code in their slides.
    – joojaa
    Jun 20, 2018 at 12:45
  • 24
    @joojaa No please, that's one of those telltale signs for "don't take this presentation too serious".
    – Voo
    Jun 20, 2018 at 13:22
  • 3
    @Voo Unfortunately the writer doesn't always get a choice. Jun 20, 2018 at 21:03
  • 11
    That's the program's 'face' when it realized that it's being debugged.
    – user64742
    Jun 21, 2018 at 2:33
  • Whoever made that slide is delusional. Please post the full PPT, I expect more hilarity.
    – Navin
    Jun 23, 2018 at 3:50

2 Answers 2


In this context, the _ environment variable will typically contain the path to the debugger that started the program rather than the program itself. The program trying to detect the debugger can then read that variable and behave differently if it sees the debugger (perhaps by looking for known debugger names like gdb or by comparing it to argv[0]).

Here's an example that shows this variable in action and how it differs from argv[0]:

C code:

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
    char *path = getenv("_");
    printf("%s\n", argv[0]);
    printf("%s\n", path);
    return 0;

Shell output:

$ gcc -o main main.c
$ ./main
$ gdb main
(gdb) r
Starting program: /home/user/tmp/main
[Inferior 1 (process 21694) exited normally]

NOTE: This is not unique to Linux, you can do it on macOS and probably other POSIX systems too.

ALSO NOTE: The is a really cheap trick that is really easy to bypass and has a high chance of not working as intended (both false positives and false negatives).

  • 4
    Recent GDB seems to reset _. When running on Ubuntu 16.04 (gdb 7.11.1-0ubuntu1~16.5), even though show environment _ prints /usr/bin/gdb, the program itself just prints its own path twice.
    – muru
    Jun 20, 2018 at 4:28
  • 16
    Nothing to do with the kernel, it's purely a thing some shells do. Sometimes. It's so unreliable even if the user isn't trying to do anything about it that it's completely pointless. Jun 20, 2018 at 6:23

Bash sets the environment variable _ to the path to the command that is being executed. So do zsh and pdksh. But other shells, such as fish and dash (which is the default scripting shell on many Linux distributions) don't do it. ATT ksh sets it to a value which includes the path to the command.

The idea is that a program can check the value of the environment variable _ to see what invoked it, I guess. Except that this is extremely unreliable even if the user isn't doing anything to change it. If the program is launched from a GUI or via a script, _ could be empty or could have some completely unrelated value, and that's perfectly legitimate and very common. And of course if the user does want to change it, it's absolutely trivial — just run env -u _ myprogram or env myprogram.

As “anti-debugging” measures go, this one is pretty ridiculous. Not only is it spoofable with zero effort, it wouldn't actually work in normal use. If some reading material touts it as an anti-debugging measure, I would recommend against this material as very unreliable.

  • fish 2.7.1 doesn't do it for me. ksh93 also includes its pid (or ppid sometimes) in there. Jun 20, 2018 at 14:57
  • @StéphaneChazelas Fish 2.2.0 on Debian jessie: ls; echo $_ls. I don't consider ksh93 a major interactive shell. Jun 20, 2018 at 16:44
  • That's another usage of $_ (also done by bash) which is different from the one described here. Try printenv _ instead which would output /usr/bin/printenv in bash/zsh, and nothing in fish (not even /usr/bin/fish if you had started fish from zsh or bash) Jun 20, 2018 at 16:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .