35

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?

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

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
./main
./main
$ gdb main
...
(gdb) r
Starting program: /home/user/tmp/main
/home/user/tmp/main
/usr/bin/gdb
[Inferior 1 (process 21694) exited normally]
(gdb)

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 '18 at 4:28
  • 15
    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. – Gilles Jun 20 '18 at 6:23
42

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. – Stéphane Chazelas Jun 20 '18 at 14:57
  • @StéphaneChazelas Fish 2.2.0 on Debian jessie: ls; echo $_ls. I don't consider ksh93 a major interactive shell. – Gilles Jun 20 '18 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) – Stéphane Chazelas Jun 20 '18 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.