Skip to content

Instantly share code, notes, and snippets.

@RicardoLara
Created May 31, 2016 01:48
Show Gist options
  • Select an option

  • Save RicardoLara/25cc07e3b547780ad5ec5d904a0be61c to your computer and use it in GitHub Desktop.

Select an option

Save RicardoLara/25cc07e3b547780ad5ec5d904a0be61c to your computer and use it in GitHub Desktop.
#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