Anti-debugging technology under LinuxJanuary 30, 2014 ⁄ general ⁄ a total of 2669 characters ⁄ font size small medium big ⁄ comments off
Transfer from http://wangcong.org/blog/archives/310
How to prevent your own program from being tracked by the debugger is an interesting topic and an important topic in reverse engineering. Here is a brief introduction to the anti-debugging technology on the Linux platform.
(This paper mainly refer to: http://blog.txipinet.com/2006/10/05/37-tecnicas-anti-debugging-sencillas-para-gnu-linux/.
to be kind, reprint please specify the source! )
I. INT3 directive
Intel software Developer ' s Manual Volume 2 a mentions:
The INT 3 instruction generates a special one byte opcode (CC) that's intended for
Calling the debug exception handler. (This one, byte form is valuable because it can
Used to replace the first byte of any instruction with a breakpoint, including other one
Byte instructions, without over-writing other code).
Int3 is a special interrupt instruction (which is also visible from the name) and is intended for use by the debugger. At this point, it should be easy to think, to counter-debug, just insert Int3 to confuse the debugger. However, will this affect the normal procedure? Yes! Because Int3 will generate sigtrap in the user space. It doesn't matter, we just have to ignore the signal.
#include #include void handler (int signo) {} int main (void) { signal (SIGTRAP, handler); __asm__ ("nop\n\t" " int3\n\t"); printf ("Hello from main!\n"); return 0;}
Two. File descriptors
This is an ingenious approach, but it only works with debuggers such as GDB. Here's how:
#include #include #include int main (void) { if (Close (3) = =-1) { printf ("ok\n"); } else { printf (" Traced!\n "); Exit ( -1); } return 0;}
GDB will open an extra file descriptor to read the executable when debugging the program, which takes advantage of this "weakness". Of course, you should be able to guess that this technique is not valid for strace.
Three. Using Getppid
Similar to the one above, but this is more sophisticated, it uses getppid to detect. We know that on Linux to track a program, it must be its parent process to do so, if the parent process of a program is not expected bash and so on (but gdb,strace), it means that it is tracked. The program code is as follows:
#include #include #include #include #include #include #include #include int get_name_by_pid (pid_t pid, char* Name) { int fd; Char buf[1024] = {0}; snprintf (buf, 1024x768, "/proc/%d/cmdline", PID); if (fd = open (buf, o_rdonly)) = =-1) return-1; Read (FD, buf, 1024x768); strncpy (name, buf, 1023); return 0;} int main (void) { char name[1024]; pid_t ppid = Getppid (); printf ("Getppid:%d\n", ppid); if (Get_name_by_pid (ppid, name)) return-1; if (strcmp (name, "bash") = = 0 | | strcmp (name, "init") = = 0) printf ("ok!\n"); else if (strcmp (name, "gdb") = = 0 | | strcmp (name, "strace") = = 0 | | strcmp (name, "ltrace") = = 0) printf ("traced!\n"); else printf ("unknown! Maybe traced!\n "); return 0;}
The same approach, a simpler way is to use the session ID. We know that the session ID is constant, whether tracked or not, and ppid will change! The following procedure takes advantage of this.
#include #include #include int main (void) { printf ("GetSID:%d\n", GetSID (Getpid ())); printf ("Getppid:%d\n", Getppid ()); if (GetSID (Getpid ()) = Getppid ()) { printf ("traced!\n"); Exit (exit_failure); } printf ("ok\n"); return 0;}
Four. Using Environment variables
Bash has an environment variable called $_, which holds the last parameter of the previous command executed. If the value of this variable is changed in the tracked state (why?) )。 Several scenarios are listed below:
Argv[0] getenv ("_") shell ./test ./teststrace ./test /usr/bin/straceltrace ./test /usr/bin/ltracegdb /home/user/test (NULL)
So we can judge it accordingly.
#include #include #include int main (int argc, char *argv[]) { printf ("getenv (_):%s\n", getenv ("_")); printf ("argv[0]:%s\n", argv[0]); if (strcmp (Argv[0], (char *) getenv ("_"))) { printf ("traced!\n"); Exit ( -1); } printf ("ok\n"); return 0;}
Five. Using Ptrace
It's easy to call PTRACE (Ptrace_traceme ...) If you're being followed. Nature will not succeed.
#include #include #include int main (void) { if (ptrace (ptrace_traceme, 0, 1, 0) < 0) { printf ("traced!\n "); return 1; } printf ("ok\n"); return 0;}
Anti-debugging technology under Linux