Created
May 31, 2016 01:48
-
-
Save RicardoLara/25cc07e3b547780ad5ec5d904a0be61c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <sys/types.h> | |
| #include <sys/ioctl.h> | |
| #include <sys/socket.h> | |
| #include <sys/time.h> | |
| #include <arpa/inet.h> | |
| #include <linux/if_packet.h> | |
| #include <net/if.h> | |
| #include <netinet/ether.h> | |
| #include <netinet/in.h> | |
| #include <fcntl.h> | |
| struct info { | |
| unsigned char IP[4]; | |
| unsigned char MAC[6]; | |
| unsigned char netMask[4]; | |
| unsigned char gatewayIP[4]; | |
| int indice; | |
| }; | |
| int getMACfromIP(const char* argv, unsigned char *MACDestino, struct info mi, int ds); | |
| void enviarTrama(int packet_socket, unsigned char * trama, int size, int indice); | |
| int recibirTrama(int ds, unsigned char tramaResp[1514], struct info mi); | |
| void whoami(struct info *agregar, struct ifreq net, int ds); | |
| void printStruct(struct info mi); | |
| char* GetGatewayForInterface(const char* interface); | |
| void generaHex(unsigned char* trama, int cantidad); | |
| int capsIP(const unsigned char *datos, int size, struct info mi, const unsigned char *MACDestino){ | |
| /*strncpy(resultado + 15, datos, sizeof(datos)); | |
| printf("\n\nResultado\n" ); | |
| for (i = 0; i < 60; i++) | |
| printf("%.2x ", resultado[i]); | |
| //strncpy(stuff, resultado, sizeof(resultado));*/ | |
| return 1; | |
| } | |
| // Envia packete ICMP | |
| // Return -1 = Error | Return >0 = Ms de Respuesta | |
| int enviarEcho(unsigned char *MACDestino, struct info mi, int ds){ | |
| printf("Entre enviar Echo\n"); | |
| unsigned char datosICMP[42] = { | |
| 0x08, 0x00, 0x4d, 0x46, 0x00, 0x01, 0x00, 0x01, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, | |
| 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x61, | |
| 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69 | |
| }; | |
| unsigned char resultado[1514]; | |
| int i; | |
| printf("Sizeof(trama) %ld\n", sizeof(datosICMP)); | |
| bzero(&resultado, 1514); | |
| //generaHex(resultado, 1514); | |
| unsigned char headerIP[] = { | |
| 0x08, 0x00, 0x45, 0x00, 0x00, 0x3c, 0x66, 0x7a, 0x00, 0x00, 0x40, 0x01, 0x66, 0xeb, 0xc0, 0xa8, 0x00, 0xa7, | |
| 0xc0, 0xa8, 0x00, 0x64 | |
| }; | |
| memcpy(resultado, MACDestino, 6); | |
| memcpy(resultado + 6, mi.MAC, 6); | |
| memcpy(resultado + 12, headerIP, sizeof(headerIP)); | |
| memcpy(resultado + 12 + sizeof(headerIP), datosICMP, sizeof(datosICMP)); | |
| for (i = 0; i < sizeof(headerIP) + 12 + sizeof(datosICMP); i++) | |
| printf("%.2x ", resultado[i]); | |
| printf("\n"); | |
| enviarTrama(ds, resultado, sizeof(headerIP) + 12 + sizeof(datosICMP), mi.indice); | |
| unsigned char new[] = { 0x02 }; | |
| memcpy(resultado + 40, new, 1); | |
| enviarTrama(ds, resultado, sizeof(headerIP) + 12 + sizeof(datosICMP), mi.indice); | |
| return 500; | |
| } | |
| int main(int argc, char *argv[]){ | |
| struct ifreq net; | |
| struct info mi; | |
| int i, ms, packet_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); | |
| unsigned char *MACDestino; | |
| struct timeval tv; | |
| tv.tv_sec = 0; /* 30 Secs Timeout */ | |
| tv.tv_usec = 10000; // Not init'ing this can cause strange errors | |
| if (packet_socket == -1) perror("Error en el socket"); | |
| else{ | |
| if (argc < 2) { | |
| printf("Uso: ping destino [interfaz] | eg. ping 8.8.8.8 etho1 \n"); | |
| return 1; | |
| }else if (argc > 2) strcpy(net.ifr_name, argv[2]); | |
| else{ | |
| printf("Introduzca nombre de la interfaz: "); | |
| scanf("%s", net.ifr_name); | |
| } | |
| perror("Abriendo Socket"); | |
| setsockopt(packet_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval)); | |
| whoami(&mi, net, packet_socket); //Obtener Informacion de tarjeta de Red. | |
| //printStruct(mi); // NOTE: Para Debug | |
| printf("\nMAC de %s: ", argv[1]); | |
| if (getMACfromIP(argv[1], MACDestino, mi, packet_socket) < 0) printf("Error al Obtener MAC Destino\n"); | |
| else { | |
| for (i = 0; i < 6; i++) { | |
| printf("%.2x", MACDestino[i]); | |
| if (i != 5) printf(":"); | |
| } | |
| printf("\n"); | |
| ms = enviarEcho(MACDestino, mi, packet_socket); | |
| if (ms < 0) printf("Time Out\n"); | |
| else printf("Respuesta! Tardo %dms\n", ms); | |
| } | |
| close(packet_socket); | |
| } | |
| return 0; | |
| } | |
| // Llena ARG[2] con la MAC de la direccion IP:ARG[1]. Usa ARP | |
| // Return -1 = Error | Return 0 = Correcto | |
| int getMACfromIP(const char* argv, unsigned char *MACDestino, struct info mi, int ds){ | |
| char *IPRecv = strdup(argv), *p, *token, actual[10]; | |
| unsigned char u_IP[4]; | |
| unsigned char tramaOut[1514], tramaIn[1514]; | |
| unsigned char arpData[] = { 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01 }; | |
| struct timeval start, end; | |
| long mtime = 0, seconds, useconds; | |
| int i = 0, numbytes; | |
| token = strtok(IPRecv, "."); | |
| while ( token != NULL ) { | |
| sprintf(actual, "%.2x", atoi(token)); | |
| u_IP[i++] = strtoul(actual, &p, 16); | |
| token = strtok(NULL, "."); | |
| } | |
| bzero(&tramaOut, 1514); | |
| bzero(&tramaIn, 1514); | |
| memcpy(tramaOut + 6, mi.MAC, 6); | |
| memcpy(tramaOut + 12, arpData, 10); | |
| memcpy(tramaOut + 22, mi.MAC, 6); | |
| memcpy(tramaOut + 28, mi.IP, 4); | |
| memcpy(tramaOut + 38, u_IP, 4); | |
| gettimeofday(&start, NULL); | |
| enviarTrama(ds, tramaOut, 60, mi.indice); //Envia ARP | |
| while (mtime < 100) { // Recolecta ARP ó Envia Error si se cumplen 100ms | |
| gettimeofday(&end, NULL); | |
| seconds = end.tv_sec - start.tv_sec; | |
| useconds = end.tv_usec - start.tv_usec; | |
| mtime = ((seconds) * 1000 + useconds / 1000.0) + 0.5; // Time Control | |
| numbytes = recibirTrama(ds, tramaIn, mi); | |
| // IF Checa: Recibir Algo && Que sea ARP && Que sea Respuesta && Que sea la IP que pedi. | |
| if (numbytes > 0 && tramaIn[12] == 0x08 && tramaIn[13] == 0x06 && tramaIn[21] == 0x02 && !memcmp(tramaIn + 28, u_IP, 4)) { | |
| memcpy(MACDestino, tramaIn + 22, 6); | |
| return 0; | |
| } | |
| } | |
| return -1; | |
| } | |
| // Envia ARG[2]:Trama a traves de ARG[1]:Socket. | |
| // Return -1 = Error | Return 0 = Correcto | |
| void enviarTrama(int packet_socket, unsigned char * trama, int size, int indice){ | |
| struct sockaddr_ll interfaz; | |
| memset(&interfaz, 0, sizeof(interfaz)); | |
| interfaz.sll_family = AF_PACKET; | |
| interfaz.sll_protocol = htons(ETH_P_ALL); | |
| interfaz.sll_ifindex = indice; | |
| if (sendto(packet_socket, trama, size, 0, (struct sockaddr *)&interfaz, sizeof(interfaz)) < 0) | |
| perror("Error al enviar"); | |
| } | |
| // Recibe Trama a traves de ARG[1]:Socket y si el destino de la trama es mi.MAC, copia la trama a ARG[2]:Trama | |
| // Return -1 = Error | Return >0 = Numbytes Recibidos | |
| int recibirTrama(int ds, unsigned char tramaResp[1514], struct info mi){ | |
| unsigned char server_reply[1514]; | |
| int i = 0, j = 0, success = 0; | |
| ssize_t numbytes; | |
| numbytes = recvfrom(ds, server_reply, 1514, MSG_DONTWAIT, NULL, NULL); | |
| if (numbytes > 0) { | |
| if (!memcmp(server_reply, mi.MAC, 6)) { | |
| memcpy(tramaResp, server_reply, sizeof(server_reply)); | |
| return numbytes; | |
| } | |
| } | |
| return -1; | |
| } | |
| void generaHex(unsigned char* trama, int cantidad){ | |
| unsigned char random[cantidad]; | |
| int fd = open("/dev/urandom", O_RDONLY); | |
| read(fd, random, cantidad); | |
| memcpy(trama, random, cantidad); | |
| } | |
| // Llena ARG[1] con informacion de tarjeta de red definida en ARG[2]. | |
| void whoami(struct info *agregar, struct ifreq net, int ds){ | |
| if (ioctl(ds, SIOCGIFINDEX, &net) == -1) perror("Error al obtener el indice"); | |
| else agregar->indice = net.ifr_ifindex; | |
| if (ioctl(ds, SIOCGIFHWADDR, &net) == -1) perror("Error al obtener MAC"); | |
| else memcpy(agregar->MAC, net.ifr_hwaddr.sa_data, 6); | |
| if (ioctl(ds, SIOCGIFADDR, &net) == -1) perror("Error al obtener IP"); | |
| else memcpy(agregar->IP, net.ifr_hwaddr.sa_data + 2, 4); | |
| if (ioctl(ds, SIOCGIFNETMASK, &net) == -1) perror("Error al obtener NETMask"); | |
| else memcpy(agregar->netMask, net.ifr_netmask.sa_data + 2, 4); | |
| memcpy(agregar->gatewayIP, GetGatewayForInterface(net.ifr_name), 6); | |
| return; | |
| } | |
| // Imprime toda la informacion de un struct info | |
| void printStruct(struct info mi){ | |
| int i; | |
| printf("IP: "); | |
| for (i = 0; i < 4; i++) { | |
| printf("%d", mi.IP[i]); | |
| if (i != 3) printf("."); | |
| } | |
| printf("\nMAC: "); | |
| for (i = 0; i < 6; i++) { | |
| printf("%.2x", mi.MAC[i]); | |
| if (i != 5) printf(":"); | |
| } | |
| printf("\nnetMask: "); | |
| for (i = 0; i < 4; i++) { | |
| printf("%d", mi.netMask[i]); | |
| if (i != 3) printf("."); | |
| } | |
| printf("\nIndice: %d\n", mi.indice); | |
| } | |
| // Obtiene gateway a partir de ARG[1]:Nombre de la Interfaz | |
| // Return gateway como cadena | |
| char* GetGatewayForInterface(const char* interface) { | |
| char* gateway = NULL; | |
| FILE* fp = popen("netstat -rn", "r"); | |
| char line[256] = { 0x0 }; | |
| while (fgets(line, sizeof(line), fp) != NULL) { | |
| char* destination; | |
| destination = strndup(line, 15); | |
| char* iface; | |
| iface = strndup(line + 73, strlen(interface)); | |
| if (strcmp("0.0.0.0 ", destination) == 0 && strcmp(iface, interface) == 0) | |
| gateway = strndup(line + 16, 15); | |
| free(destination); | |
| free(iface); | |
| } | |
| pclose(fp); | |
| return gateway; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment