sábado, 28 de junho de 2014

Detectando Debugger no linux

Usando códigos simples é possível detectar quando a aplicação esta sendo rodada por um debugger , fiz o teste com strace (programa que intercepta as system calls) e com o gdb e funcionou =).

Código>
#include <stdio.h>
#include <sys/ptrace.h>

int main(){
        if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
                printf("DEBUGGING... Bye\n");
                return 1;
        }
        printf("Hello\n");
        return 0;
}

Testando com gdb>
$ gdb ./a.out
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /tmp/a.out...(no debugging symbols found)...done.
(gdb) run
Starting program: /tmp/a.out 
DEBUGGING... Bye
[Inferior 1 (process 3422) exited with code 01]
(gdb) quit

Testando com strace>
$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 31 vars */]) = 0
brk(0)                                  = 0x811b000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb774b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=121789, ...}) = 0
mmap2(NULL, 121789, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb772d000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/i386-linux-gnu/i686/cmov/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240o\1\0004\0\0\0"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1441960, ...}) = 0
mmap2(NULL, 1456504, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb75c9000
mprotect(0xb7726000, 4096, PROT_NONE)   = 0
mmap2(0xb7727000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15d) = 0xb7727000
mmap2(0xb772a000, 10616, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb772a000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb75c8000
set_thread_area({entry_number:-1 -> 6, base_addr:0xb75c88d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
mprotect(0xb7727000, 8192, PROT_READ)   = 0
mprotect(0xb776a000, 4096, PROT_READ)   = 0
munmap(0xb772d000, 121789)              = 0
ptrace(PTRACE_TRACEME, 0, 0x1, 0)       = -1 EPERM (Operation not permitted)
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb774a000
write(1, "DEBUGGING... Bye\n", 17DEBUGGING... Bye

O único problema mesmo seria detectar o strace quando o programa já esta rodando , por exemplo:
$ strace -p [pid]

O codigo foi tirado de um paper de 1999>
http://vxheavens.com/lib/vsc04.html

Esse outro paper contem mais tecnicas ainda de anti-debugger, foi feito em 2006>
http://www.stonedcoder.org/~kd/lib/14-61-1-PB.pdf

Nenhum comentário:

Postar um comentário