diff options
| author | jvoisin | 2013-01-15 21:31:40 +0100 |
|---|---|---|
| committer | jvoisin | 2013-01-15 21:31:40 +0100 |
| commit | 808069c906a036f3b8c5de51e302245154131584 (patch) | |
| tree | c8e046626973ee28a793c24faba312ace286c8c1 | |
First commit with an ugly makefile !
| -rw-r--r-- | Makefile | 26 | ||||
| -rw-r--r-- | crash/10123.c | 32 | ||||
| -rw-r--r-- | crash/header_screwer.c | 65 | ||||
| -rw-r--r-- | detect/gdb.c | 99 | ||||
| -rw-r--r-- | detect/gdb.h | 13 | ||||
| -rw-r--r-- | detect/main.c | 72 | ||||
| -rw-r--r-- | detect/various.c | 46 | ||||
| -rw-r--r-- | detect/various.h | 7 |
8 files changed, 360 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7933f7e --- /dev/null +++ b/Makefile | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | OUTPUT_DIR=./bin/ | ||
| 2 | |||
| 3 | CC=gcc | ||
| 4 | CFLAGS=-m32 | ||
| 5 | |||
| 6 | |||
| 7 | all: directory prog | ||
| 8 | |||
| 9 | directory: | ||
| 10 | @mkdir -p $(OUTPUT_DIR) | ||
| 11 | |||
| 12 | prog: detection crash | ||
| 13 | |||
| 14 | crash: header_screwer 10123 | ||
| 15 | |||
| 16 | 10123: | ||
| 17 | $(CC) $(CFLAGS) ./crash/10123.c -o $(OUTPUT_DIR)$@ | ||
| 18 | |||
| 19 | header_screwer: | ||
| 20 | $(CC) $(CFLAGS) ./crash/header_screwer.c -o $(OUTPUT_DIR)$@ | ||
| 21 | |||
| 22 | detection: | ||
| 23 | $(CC) $(CFLAGS) ./detect/*.c -o $(OUTPUT_DIR)$@ | ||
| 24 | |||
| 25 | clean: | ||
| 26 | rm -Rf $(OUTPUT_DIR) | ||
diff --git a/crash/10123.c b/crash/10123.c new file mode 100644 index 0000000..48a9304 --- /dev/null +++ b/crash/10123.c | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /* | ||
| 2 | *Excerpt of the bug's description: | ||
| 3 | GDB fails to interrupt the program being debugged if the program is blocking SIGINT. | ||
| 4 | |||
| 5 | When using the sigwait function to retrieve signals, the program is expected to block them. SIGINT is a commonly handled signal. Any | ||
| 6 | program using sigwait to retrieve signals and handling SIGINT this way will not be interruptible by GDB. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <stddef.h> | ||
| 10 | #include <stdio.h> | ||
| 11 | #include <unistd.h> | ||
| 12 | #include <signal.h> | ||
| 13 | |||
| 14 | int main(){ | ||
| 15 | sigset_t sigs; | ||
| 16 | sigfillset(&sigs); | ||
| 17 | sigprocmask(SIG_SETMASK, &sigs, NULL); | ||
| 18 | |||
| 19 | if(fork()){ | ||
| 20 | sleep(1); // to be sure that | ||
| 21 | kill(getppid(), SIGINT); | ||
| 22 | _exit(0); | ||
| 23 | } | ||
| 24 | while(1){ | ||
| 25 | pause(); | ||
| 26 | printf("[*] No GBD detected\n"); | ||
| 27 | /* | ||
| 28 | * Put your code here | ||
| 29 | */ | ||
| 30 | } | ||
| 31 | return 0; | ||
| 32 | } | ||
diff --git a/crash/header_screwer.c b/crash/header_screwer.c new file mode 100644 index 0000000..735aecd --- /dev/null +++ b/crash/header_screwer.c | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | /* | ||
| 2 | * Elf header screwer, based on an idea of svenka's crackme, named Thellurik (http://crackmes.de/users/svenka/thellurik/) | ||
| 3 | * Unfortunately for me, ioactive was quicker than me : http://blog.ioactive.com/2012/12/striking-back-gdb-and-ida-debuggers.html | ||
| 4 | * Kudos to them ! | ||
| 5 | * | ||
| 6 | */ | ||
| 7 | |||
| 8 | |||
| 9 | #include <stdio.h> | ||
| 10 | #include <sys/mman.h> | ||
| 11 | #include <unistd.h> | ||
| 12 | #include <stdlib.h> | ||
| 13 | #include <elf.h> | ||
| 14 | #include <sys/stat.h> | ||
| 15 | #include <sys/types.h> | ||
| 16 | #include <sys/procfs.h> | ||
| 17 | #include <fcntl.h> | ||
| 18 | |||
| 19 | |||
| 20 | int main(int argc, char** argv){ | ||
| 21 | int f; | ||
| 22 | static Elf32_Ehdr* header; | ||
| 23 | |||
| 24 | printf(".: Elf corrupt :.\n"); | ||
| 25 | |||
| 26 | if(argc < 2){ | ||
| 27 | printf("Usage: %s file", argv[0]); | ||
| 28 | return 1; | ||
| 29 | } | ||
| 30 | |||
| 31 | if((f = open(argv[1], O_RDWR)) < 0){ | ||
| 32 | perror("open"); | ||
| 33 | return 1; | ||
| 34 | } | ||
| 35 | |||
| 36 | //MAP_SHARED is required to actually update the file | ||
| 37 | if((header = (Elf32_Ehdr *) mmap(NULL, sizeof(header), PROT_READ | PROT_WRITE, MAP_SHARED, f, 0)) == MAP_FAILED){ | ||
| 38 | perror("mmap"); | ||
| 39 | close(f); | ||
| 40 | return 1; | ||
| 41 | } | ||
| 42 | |||
| 43 | printf("[*] Current header values:\n"); | ||
| 44 | printf("\te_shoff:%d\n\te_shnum:%d\n\te_shstrndx:%d\n", | ||
| 45 | header->e_shoff, header->e_shnum, header->e_shstrndx); | ||
| 46 | |||
| 47 | header->e_shoff = 0xffff; | ||
| 48 | header->e_shnum = 0xffff; | ||
| 49 | header->e_shstrndx = 0xffff; | ||
| 50 | |||
| 51 | printf("[*] Patched header values:\n"); | ||
| 52 | printf("\te_shoff:%d\n\te_shnum:%d\n\te_shstrndx:%d\n", | ||
| 53 | header->e_shoff, header->e_shnum, header->e_shstrndx); | ||
| 54 | |||
| 55 | if(msync(NULL, 0, MS_SYNC) == -1){ | ||
| 56 | perror("msync"); | ||
| 57 | close(f); | ||
| 58 | return 1; | ||
| 59 | } | ||
| 60 | |||
| 61 | close(f); | ||
| 62 | munmap(header, 0); | ||
| 63 | printf("You should no more be able to run \"%s\" inside GDB\n", argv[1]); | ||
| 64 | return 0; | ||
| 65 | } | ||
diff --git a/detect/gdb.c b/detect/gdb.c new file mode 100644 index 0000000..53a0311 --- /dev/null +++ b/detect/gdb.c | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | /* | ||
| 2 | * Various tricks to detect GDB or any related GNU tools | ||
| 3 | * | ||
| 4 | */ | ||
| 5 | |||
| 6 | |||
| 7 | #include <signal.h> | ||
| 8 | #include <stdio.h> | ||
| 9 | #include <stdlib.h> | ||
| 10 | #include <string.h> | ||
| 11 | #include <sys/ptrace.h> | ||
| 12 | |||
| 13 | |||
| 14 | #define check_strings(str_buff) (strstr(str_buff, "gdb") || strstr(str_buff, "ltrace") || strstr(str_buff, "strace")) | ||
| 15 | |||
| 16 | /* | ||
| 17 | * This is an old well known bug (#7912) | ||
| 18 | * | ||
| 19 | * GDB leaks 2 file descriptors when it opens a program to be debugged. | ||
| 20 | * Both file descriptors are pointing to the file being debugged. | ||
| 21 | */ | ||
| 22 | int dbg_file_descriptor(){ | ||
| 23 | FILE* fd = fopen("/", "r"); | ||
| 24 | int nb_fd = fileno(fd); | ||
| 25 | fclose(fd); | ||
| 26 | |||
| 27 | return (nb_fd > 3); | ||
| 28 | } | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Detect GDB by the mean of /proc/$PID/cmdline, which should no be "gdb" | ||
| 32 | */ | ||
| 33 | int dbg_cmdline(){ | ||
| 34 | char buff [24], tmp [16]; | ||
| 35 | FILE* f; | ||
| 36 | |||
| 37 | snprintf(buff, 24, "/proc/%d/cmdline", getppid()); | ||
| 38 | f = fopen(buff, "r"); | ||
| 39 | fgets(tmp, 16, f); | ||
| 40 | fclose(f); | ||
| 41 | |||
| 42 | return check_strings(tmp); | ||
| 43 | } | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Classic self ptrace trick: a program can only be ptraced by ONE other. | ||
| 47 | */ | ||
| 48 | int dbg_ptrace(){ | ||
| 49 | if(ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) | ||
| 50 | return 1; | ||
| 51 | //TODO : detach ptrace | ||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | /* | ||
| 56 | * GDB handle SIGTRAP, if we raise one under GDB, it will not reach our handler. | ||
| 57 | * FIXME | ||
| 58 | */ | ||
| 59 | unsigned int no_dbg = 1; | ||
| 60 | static void handler(int signum){no_dbg = 0;} | ||
| 61 | int dbg_sigtrap(){ | ||
| 62 | no_dbg = 1; | ||
| 63 | signal(SIGTRAP, handler); | ||
| 64 | raise(SIGTRAP); | ||
| 65 | signal(SIGTRAP, SIG_IGN); | ||
| 66 | return no_dbg; | ||
| 67 | } | ||
| 68 | |||
| 69 | /* | ||
| 70 | * Scan memory for breakpoints | ||
| 71 | * TODO | ||
| 72 | */ | ||
| 73 | int dbg_check_bp(){ | ||
| 74 | unsigned char* start; | ||
| 75 | size_t size; | ||
| 76 | size_t i; | ||
| 77 | |||
| 78 | for(i = 0; i < size; i++){ | ||
| 79 | if(start[i] == 0xCC || start[i] == 0xCD) | ||
| 80 | return 1; | ||
| 81 | } | ||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | /* | ||
| 86 | * Check the parent's name | ||
| 87 | */ | ||
| 88 | int dbg_getppid_name(){ | ||
| 89 | char buff1[24], buff2[16]; | ||
| 90 | FILE* f; | ||
| 91 | |||
| 92 | snprintf(buff1, 24, "/proc/%d/status", getppid()); | ||
| 93 | f = fopen(buff1, "r"); | ||
| 94 | fgets(buff2, 16, f); | ||
| 95 | fclose(f); | ||
| 96 | |||
| 97 | return check_strings(buff2); | ||
| 98 | } | ||
| 99 | |||
diff --git a/detect/gdb.h b/detect/gdb.h new file mode 100644 index 0000000..c899cf2 --- /dev/null +++ b/detect/gdb.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #ifndef _GDB_ | ||
| 2 | #define _GDB_ | ||
| 3 | |||
| 4 | #define check_strings(str_buff) (strstr(str_buff, "gdb") || strstr(str_buff, "ltrace") || strstr(str_buff, "strace")) | ||
| 5 | |||
| 6 | int dbg_file_descriptor(); | ||
| 7 | int dbg_cmdline(); | ||
| 8 | int dbg_ptrace(); | ||
| 9 | int dbg_sigtrap(); | ||
| 10 | int dbg_check_bp(); | ||
| 11 | int dbg_getppid_name(); | ||
| 12 | |||
| 13 | #endif | ||
diff --git a/detect/main.c b/detect/main.c new file mode 100644 index 0000000..09e7515 --- /dev/null +++ b/detect/main.c | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | #include <signal.h> | ||
| 2 | #include <stdio.h> | ||
| 3 | #include <stdlib.h> | ||
| 4 | #include <string.h> | ||
| 5 | #include <sys/ptrace.h> | ||
| 6 | |||
| 7 | #include "gdb.h" | ||
| 8 | #include "various.h" | ||
| 9 | |||
| 10 | |||
| 11 | int main(int argc, char** argv){ | ||
| 12 | unsigned int res = 0; | ||
| 13 | |||
| 14 | printf(".: GDB detector :.\n\n"); | ||
| 15 | |||
| 16 | if(res += dbg_file_descriptor()) | ||
| 17 | printf("[x] file descriptor\n"); | ||
| 18 | else | ||
| 19 | printf("[ ] file descriptor\n"); | ||
| 20 | |||
| 21 | if(res += dbg_cmdline()) | ||
| 22 | printf("[x] /proc/PID/cmdline\n"); | ||
| 23 | else | ||
| 24 | printf("[ ] /proc/PID/cmdline\n"); | ||
| 25 | |||
| 26 | if(res += dbg_sigtrap()) | ||
| 27 | printf("[x] SIGTRAP\n"); | ||
| 28 | else | ||
| 29 | printf("[ ] SIGTRAP\n"); | ||
| 30 | |||
| 31 | if(res += dbg_getppid_name()) | ||
| 32 | printf("[x] getppid name\n"); | ||
| 33 | else | ||
| 34 | printf("[ ] getppid name\n"); | ||
| 35 | |||
| 36 | if(res += dbg_ptrace()) | ||
| 37 | printf("[x] ptrace\n"); | ||
| 38 | else | ||
| 39 | printf("[ ] ptrace\n"); | ||
| 40 | |||
| 41 | if(res) | ||
| 42 | printf("\n[*] GDB detected\n"); | ||
| 43 | else | ||
| 44 | printf("\n[ ] No GDB detected\n"); | ||
| 45 | |||
| 46 | |||
| 47 | res = 0; | ||
| 48 | printf("\n\n"); | ||
| 49 | printf(".: Various tricks detector :.\n\n"); | ||
| 50 | |||
| 51 | if(res += various_ldpreload()) | ||
| 52 | printf("[x] LD_PRELOAD\n"); | ||
| 53 | else | ||
| 54 | printf("[ ] LD_PRELOAD\n"); | ||
| 55 | |||
| 56 | if(res += various_ldpreload_custom_getenv()) | ||
| 57 | printf("[x] hidden LD_PRELOAD\n"); | ||
| 58 | else | ||
| 59 | printf("[ ] hidden LD_PRELOAD\n"); | ||
| 60 | |||
| 61 | if(res += various_rdtsc()) | ||
| 62 | printf("[x] Something is slowing the process...\n"); | ||
| 63 | else | ||
| 64 | printf("[ ] Everything is running well\n"); | ||
| 65 | |||
| 66 | if(res) | ||
| 67 | printf("\n[*] Something is wrong\n"); | ||
| 68 | else | ||
| 69 | printf("\n[ ] Everything seems fine\n"); | ||
| 70 | |||
| 71 | return 0; | ||
| 72 | } | ||
diff --git a/detect/various.c b/detect/various.c new file mode 100644 index 0000000..3689a8a --- /dev/null +++ b/detect/various.c | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * Detection of various tricks | ||
| 3 | * | ||
| 4 | */ | ||
| 5 | |||
| 6 | |||
| 7 | #include <stdio.h> | ||
| 8 | #include <stdlib.h> | ||
| 9 | #include <string.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | |||
| 12 | |||
| 13 | /* | ||
| 14 | * Dead simple try to detect the LD_PRELOAD trick by looking | ||
| 15 | * into environnement variables of the program. | ||
| 16 | */ | ||
| 17 | int various_ldpreload(){ | ||
| 18 | return (getenv("LD_PRELOAD") != NULL); | ||
| 19 | } | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Try to detect the LD_PRELOAD trick when used with a custom | ||
| 23 | * gentenv() function. Feel free to expand it using the same principe. | ||
| 24 | */ | ||
| 25 | int various_ldpreload_custom_getenv(){ | ||
| 26 | if(!various_ldpreload()){ | ||
| 27 | putenv("LD_PRELOAD=hello"); | ||
| 28 | return (strcmp(getenv("LD_PRELOAD"), "hello")); | ||
| 29 | } | ||
| 30 | return 1; | ||
| 31 | } | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Timiming attack, useful for detecting breakpoints | ||
| 35 | */ | ||
| 36 | int various_rdtsc(){ | ||
| 37 | clock_t t = clock(); | ||
| 38 | |||
| 39 | int i; //Time-consuming crap | ||
| 40 | for(i=2; i<7137001; i++) | ||
| 41 | if (7137001 % i == 0) | ||
| 42 | break; | ||
| 43 | |||
| 44 | return (clock() - t > 0xffff); //adjust this | ||
| 45 | } | ||
| 46 | |||
diff --git a/detect/various.h b/detect/various.h new file mode 100644 index 0000000..321c9c8 --- /dev/null +++ b/detect/various.h | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | #ifndef _VARIOUS_ | ||
| 2 | #define _VARIOUS_ | ||
| 3 | int various_ldpreload(); | ||
| 4 | int various_ldpreload_custom_getenv(); | ||
| 5 | int various_rdtsc(); | ||
| 6 | #endif | ||
| 7 | |||
