What does ENV (“_”) do for anti-debugging?
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.
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).