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!