O primeiro que precisamos é unha aplicación base cun faio de segmentación:
#include <stdio.h> #include <stdlib.h> // Produce segfault void fail(){ int *asd = NULL; *asd = 7; } int main(int argc, char **argv){ fail(); return 0; }
E, claramente, faia...
Agora ímos cazar o sinal do erro, pero só amosaremos unha mensaxe e sairemos, para isto usamos a función signal:
#include <stdio.h> #include <stdlib.h> #include <signal.h> void segfault_handler(int signal){ printf("Faio de segmentación!\n"); abort(); } // Produce segfault void fail(){ int *asd = NULL; *asd = 7; } int main(int argc, char **argv){ signal(SIGSEGV, segfault_handler); fail(); return 0; }
Ímos entón a amosa-la traza, para isto tiraremos da familia de funcións backtrace:
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <execinfo.h> #define BUFFER_SIZE 128 void show_backtrace(){ void *buffer[128]; char **symbols; int ptr_num = backtrace(buffer, BUFFER_SIZE); int i; symbols = backtrace_symbols(buffer, ptr_num); if (symbols == NULL){ perror("backtrace_symbols"); return; } for(i = 0; i < ptr_num; i++){ printf("%i:\t %s\n", i, symbols[i]); } free(symbols); } void segfault_handler(int signal){ printf("Faio de segmentación, amosando traza:\n\n"); show_backtrace(); abort(); } // Produce segfault void fail(){ int *asd = NULL; *asd = 7; } int main(int argc, char **argv){ signal(SIGSEGV, segfault_handler); fail(); return 0; }
Nota: sempre podemos obter máis información se compilamos cos flags -g -rdynamic.
Nomes de funcións... xa é algo máis, pero a opción sinxela é simplemente delegar nun debugger, se témo-lo PID do proceso podemos facerlle attach por exemplo dende GDB, e podemos facerlle o que sexa :
#include <stdio.h> #include <stdlib.h> #include <signal.h> void segfault_handler(int signal){ printf("Faio de segmentación, preme [enter] para finalizar\n"); printf("pid: %i\n", getpid()); getchar(); abort(); } // Produce segfault void fail(){ int *asd = NULL; *asd = 7; } int main(int argc, char **argv){ signal(SIGSEGV, segfault_handler); fail(); return 0; }
ps: Para quen lle interese, fío en StackOverflow sobre o backtrace co glib.
Espero que resulte útil, saúdos.
Interesante! Ocurreseme algún uso para facer hooking grazas tamén a LD_Preload e con isto saber por onde veñen posibeis ataques. Sería viábel?
ResponderEliminarUn saúdo!
Oh, certamente sería algo moi práctico, o detalle sería a que función facerllo (pódese facer a todo o programa?).
ResponderEliminarOu seguindo con esa idea quizais se poda facer un programa "envoltorio" que prepare as sinais de despois faga execve e deixe paso o código final, pero non teño claro se esta accion limpará os sinais ou a función de trazado.
Parece unha posibilidade que compre explorar, grazas polo alimento para o cerebro ;)
Boas de novo, pois a min a primeira idea que me viñera á cabeza era a de hookear por exemplo strcpy para detectar posibles overflows, fopen para detectar determinadas intromisións e así con calqueira idea bizarra. O de programa envoltorio tampouco sei moi ben como funcionaría, eu con estes temas aínda son e serei un eterno newbie.
ResponderEliminarUn saúdo!