From 808069c906a036f3b8c5de51e302245154131584 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Tue, 15 Jan 2013 21:31:40 +0100 Subject: First commit with an ugly makefile ! --- Makefile | 26 +++++++++++++ crash/10123.c | 32 ++++++++++++++++ crash/header_screwer.c | 65 +++++++++++++++++++++++++++++++++ detect/gdb.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ detect/gdb.h | 13 +++++++ detect/main.c | 72 ++++++++++++++++++++++++++++++++++++ detect/various.c | 46 +++++++++++++++++++++++ detect/various.h | 7 ++++ 8 files changed, 360 insertions(+) create mode 100644 Makefile create mode 100644 crash/10123.c create mode 100644 crash/header_screwer.c create mode 100644 detect/gdb.c create mode 100644 detect/gdb.h create mode 100644 detect/main.c create mode 100644 detect/various.c create mode 100644 detect/various.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7933f7e --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +OUTPUT_DIR=./bin/ + +CC=gcc +CFLAGS=-m32 + + +all: directory prog + +directory: + @mkdir -p $(OUTPUT_DIR) + +prog: detection crash + +crash: header_screwer 10123 + +10123: + $(CC) $(CFLAGS) ./crash/10123.c -o $(OUTPUT_DIR)$@ + +header_screwer: + $(CC) $(CFLAGS) ./crash/header_screwer.c -o $(OUTPUT_DIR)$@ + +detection: + $(CC) $(CFLAGS) ./detect/*.c -o $(OUTPUT_DIR)$@ + +clean: + 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 @@ +/* + *Excerpt of the bug's description: + GDB fails to interrupt the program being debugged if the program is blocking SIGINT. + + When using the sigwait function to retrieve signals, the program is expected to block them. SIGINT is a commonly handled signal. Any + program using sigwait to retrieve signals and handling SIGINT this way will not be interruptible by GDB. + */ + +#include +#include +#include +#include + +int main(){ + sigset_t sigs; + sigfillset(&sigs); + sigprocmask(SIG_SETMASK, &sigs, NULL); + + if(fork()){ + sleep(1); // to be sure that + kill(getppid(), SIGINT); + _exit(0); + } + while(1){ + pause(); + printf("[*] No GBD detected\n"); + /* + * Put your code here + */ + } + return 0; +} 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 @@ +/* + * Elf header screwer, based on an idea of svenka's crackme, named Thellurik (http://crackmes.de/users/svenka/thellurik/) + * Unfortunately for me, ioactive was quicker than me : http://blog.ioactive.com/2012/12/striking-back-gdb-and-ida-debuggers.html + * Kudos to them ! + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int main(int argc, char** argv){ + int f; + static Elf32_Ehdr* header; + + printf(".: Elf corrupt :.\n"); + + if(argc < 2){ + printf("Usage: %s file", argv[0]); + return 1; + } + + if((f = open(argv[1], O_RDWR)) < 0){ + perror("open"); + return 1; + } + + //MAP_SHARED is required to actually update the file + if((header = (Elf32_Ehdr *) mmap(NULL, sizeof(header), PROT_READ | PROT_WRITE, MAP_SHARED, f, 0)) == MAP_FAILED){ + perror("mmap"); + close(f); + return 1; + } + + printf("[*] Current header values:\n"); + printf("\te_shoff:%d\n\te_shnum:%d\n\te_shstrndx:%d\n", + header->e_shoff, header->e_shnum, header->e_shstrndx); + + header->e_shoff = 0xffff; + header->e_shnum = 0xffff; + header->e_shstrndx = 0xffff; + + printf("[*] Patched header values:\n"); + printf("\te_shoff:%d\n\te_shnum:%d\n\te_shstrndx:%d\n", + header->e_shoff, header->e_shnum, header->e_shstrndx); + + if(msync(NULL, 0, MS_SYNC) == -1){ + perror("msync"); + close(f); + return 1; + } + + close(f); + munmap(header, 0); + printf("You should no more be able to run \"%s\" inside GDB\n", argv[1]); + return 0; +} 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 @@ +/* + * Various tricks to detect GDB or any related GNU tools + * + */ + + +#include +#include +#include +#include +#include + + +#define check_strings(str_buff) (strstr(str_buff, "gdb") || strstr(str_buff, "ltrace") || strstr(str_buff, "strace")) + +/* + * This is an old well known bug (#7912) + * + * GDB leaks 2 file descriptors when it opens a program to be debugged. + * Both file descriptors are pointing to the file being debugged. + */ +int dbg_file_descriptor(){ + FILE* fd = fopen("/", "r"); + int nb_fd = fileno(fd); + fclose(fd); + + return (nb_fd > 3); +} + +/* + * Detect GDB by the mean of /proc/$PID/cmdline, which should no be "gdb" + */ +int dbg_cmdline(){ + char buff [24], tmp [16]; + FILE* f; + + snprintf(buff, 24, "/proc/%d/cmdline", getppid()); + f = fopen(buff, "r"); + fgets(tmp, 16, f); + fclose(f); + + return check_strings(tmp); +} + +/* + * Classic self ptrace trick: a program can only be ptraced by ONE other. + */ +int dbg_ptrace(){ + if(ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) + return 1; + //TODO : detach ptrace + return 0; +} + +/* + * GDB handle SIGTRAP, if we raise one under GDB, it will not reach our handler. + * FIXME + */ +unsigned int no_dbg = 1; +static void handler(int signum){no_dbg = 0;} +int dbg_sigtrap(){ + no_dbg = 1; + signal(SIGTRAP, handler); + raise(SIGTRAP); + signal(SIGTRAP, SIG_IGN); + return no_dbg; +} + +/* + * Scan memory for breakpoints + * TODO + */ +int dbg_check_bp(){ + unsigned char* start; + size_t size; + size_t i; + + for(i = 0; i < size; i++){ + if(start[i] == 0xCC || start[i] == 0xCD) + return 1; + } + return 0; +} + +/* + * Check the parent's name + */ +int dbg_getppid_name(){ + char buff1[24], buff2[16]; + FILE* f; + + snprintf(buff1, 24, "/proc/%d/status", getppid()); + f = fopen(buff1, "r"); + fgets(buff2, 16, f); + fclose(f); + + return check_strings(buff2); +} + 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 @@ +#ifndef _GDB_ +#define _GDB_ + +#define check_strings(str_buff) (strstr(str_buff, "gdb") || strstr(str_buff, "ltrace") || strstr(str_buff, "strace")) + +int dbg_file_descriptor(); +int dbg_cmdline(); +int dbg_ptrace(); +int dbg_sigtrap(); +int dbg_check_bp(); +int dbg_getppid_name(); + +#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 @@ +#include +#include +#include +#include +#include + +#include "gdb.h" +#include "various.h" + + +int main(int argc, char** argv){ + unsigned int res = 0; + + printf(".: GDB detector :.\n\n"); + + if(res += dbg_file_descriptor()) + printf("[x] file descriptor\n"); + else + printf("[ ] file descriptor\n"); + + if(res += dbg_cmdline()) + printf("[x] /proc/PID/cmdline\n"); + else + printf("[ ] /proc/PID/cmdline\n"); + + if(res += dbg_sigtrap()) + printf("[x] SIGTRAP\n"); + else + printf("[ ] SIGTRAP\n"); + + if(res += dbg_getppid_name()) + printf("[x] getppid name\n"); + else + printf("[ ] getppid name\n"); + + if(res += dbg_ptrace()) + printf("[x] ptrace\n"); + else + printf("[ ] ptrace\n"); + + if(res) + printf("\n[*] GDB detected\n"); + else + printf("\n[ ] No GDB detected\n"); + + + res = 0; + printf("\n\n"); + printf(".: Various tricks detector :.\n\n"); + + if(res += various_ldpreload()) + printf("[x] LD_PRELOAD\n"); + else + printf("[ ] LD_PRELOAD\n"); + + if(res += various_ldpreload_custom_getenv()) + printf("[x] hidden LD_PRELOAD\n"); + else + printf("[ ] hidden LD_PRELOAD\n"); + + if(res += various_rdtsc()) + printf("[x] Something is slowing the process...\n"); + else + printf("[ ] Everything is running well\n"); + + if(res) + printf("\n[*] Something is wrong\n"); + else + printf("\n[ ] Everything seems fine\n"); + + return 0; +} 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 @@ +/* + * Detection of various tricks + * + */ + + +#include +#include +#include +#include + + +/* + * Dead simple try to detect the LD_PRELOAD trick by looking + * into environnement variables of the program. + */ +int various_ldpreload(){ + return (getenv("LD_PRELOAD") != NULL); +} + +/* + * Try to detect the LD_PRELOAD trick when used with a custom + * gentenv() function. Feel free to expand it using the same principe. + */ +int various_ldpreload_custom_getenv(){ + if(!various_ldpreload()){ + putenv("LD_PRELOAD=hello"); + return (strcmp(getenv("LD_PRELOAD"), "hello")); + } + return 1; +} + +/* + * Timiming attack, useful for detecting breakpoints + */ +int various_rdtsc(){ + clock_t t = clock(); + + int i; //Time-consuming crap + for(i=2; i<7137001; i++) + if (7137001 % i == 0) + break; + + return (clock() - t > 0xffff); //adjust this +} + 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 @@ +#ifndef _VARIOUS_ +#define _VARIOUS_ +int various_ldpreload(); +int various_ldpreload_custom_getenv(); +int various_rdtsc(); +#endif + -- cgit v1.3