IMA4 2021/2022 EC6 : Différence entre versions

De Wiki d'activités IMA
(Documents Rendus)
(Documents Rendus)
Ligne 44 : Ligne 44 :
  
 
= Documents Rendus =
 
= Documents Rendus =
#include <stdio.h>
+
<p>#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #define DEFAUT_SIZE 300</p>
#include <stdlib.h>
 
#include <string.h>
 
#include <sys/stat.h>
 
#define DEFAUT_SIZE 300
 
  
 +
<p> #include <errno.h> #include <unistd.h> #include <getopt.h> #include <time.h> #include <signal.h> #include <net/if.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/ioctl.h> #include <linux/in.h> #include <linux/if_ether.h> #include <linux/if_packet.h> #include <linux/filter.h></p>
  
 +
<p>#define BUFFER_SIZE 2048 #define MAX_COLUMNS 16 #define ETHER_ADDR_LEN 6</p>
  
struct etherFrame
+
<p>#define MODE_DISPLAY 0 #define MODE_SEND 1</p>
{
 
    char sourceMac[18];
 
    char destMac[18];
 
    char etherType[5];
 
    char nameType[15];
 
    int casePacket;
 
 
 
   
 
};
 
  
struct ipFrame{
+
<p> struct etherFrame { char sourceMac[18]; char destMac[18]; char etherType[5]; char nameType[15]; int casePacket;    };</p>
    char versionIp[2];
 
    char lenghtHeaderIp[2];
 
    char DSCP_ECN[2];
 
    char lenghtIP[4];
 
    char identIp[5];
 
    char flagIp[3];
 
    char TTL[5];
 
     char protocolIP[3];
 
    char CsIP[5];
 
    unsigned char sourceIP[4];
 
    unsigned char destIP[4];
 
};
 
  
const char* filename = "ip4.txt";
+
<p>struct ipFrame{  char versionIp[2];  char lenghtHeaderIp[2];  char DSCP_ECN[2];  char lenghtIP[4];  char identIp[5];  char flagIp[3];  char TTL[5];  char protocolIP[3];  char CsIP[5];  unsigned char sourceIP[4];  unsigned char destIP[4]; char fullHeader[40]; };</p>
char packetChar[DEFAUT_SIZE];
 
int indexPacket=0;
 
  
int get_packet()
+
<p>const char* filename = &quot;temp.txt&quot;; char packetChar[DEFAUT_SIZE]; int indexPacket=0;</p>
//ouverture et récupération du packet dans le fichier choisi
 
{
 
    FILE *in_file = fopen(filename, "r");
 
    if (!in_file) {
 
        perror("fopen");
 
        exit(EXIT_FAILURE);
 
    }
 
  
    struct stat sb;
+
<p> char *ifname=&quot;eth0&quot;; /* Interface reseau a utiliser */ unsigned char broadcast=1; /* Capture ou non des diffusions */ unsigned char unicast=0; /* Capture limitee a une adresse MAC ou non */ char macAddress[ETHER_ADDR_LEN];/* adresse MAC a surveiller */</p>
    if (stat(filename, &sb) == -1) {
 
        perror("stat");
 
        exit(EXIT_FAILURE);
 
    }
 
    // Allocation de la taille de la mémoire en fonction de la taille du texte
 
    char *file_contents = malloc(sb.st_size);
 
   
 
    while (fscanf(in_file, "%[^\n ] ", file_contents) != EOF) {
 
     
 
        strcat(packetChar,file_contents);
 
        //printf(" %s\n", file_contents);  
 
        //packetChar[indexPacket]=file_contents;
 
        //indexPacket++;       
 
    }
 
    printf("\n");
 
    //printf("%s", packetChar);
 
    indexPacket=0;
 
    fclose(in_file);
 
    }
 
   
 
struct etherFrame getMacAddressType(){
 
    struct etherFrame ether1;
 
    int i;
 
    // nettoyage de la chaîne de charactère à cause d'un bug :"G��U48:f1:7f:f0:32:20:" en plus de la mac address des charactère sont présents au début
 
    // Je pense que l'erreur ici est que j'ai alloué une zone mémoire à ma string mais je ne l'ai pas initialisé
 
    strcpy(ether1.destMac,"");
 
    strcpy(ether1.sourceMac,"");
 
    strcpy(ether1.etherType,"");
 
    strcpy(ether1.nameType,"");
 
    // Pour résoudre ça je copie dans ma string un texte vide
 
  
// Récupération de l'addresse mac de destination
+
<p> int openRawEthernetSocket(char *ifname){ struct sockaddr_ll address; int proto=htons(ETH_P_ALL); int result;</p>
    for(i=0;i<12;i=i+2){
 
        strcat(ether1.destMac,":");  
 
        strncat(ether1.destMac,&packetChar[i],1);
 
        strncat(ether1.destMac,&packetChar[i+1],1);
 
             
 
    };
 
  
    printf("Addresse mac de destination%s\n",ether1.destMac);
+
<p> if((result=socket(PF_PACKET,SOCK_RAW,proto))<0){ perror(&quot;openRawEthernetSocket.socket&quot;); exit(1); }  return result;  }</p>
//Récupération de l'addresse mac source
 
    for(i=12;i<24;i=i+2){
 
        strcat(ether1.sourceMac,":");
 
        strncat(ether1.sourceMac,&packetChar[i],1);
 
        strncat(ether1.sourceMac,&packetChar[i+1],1);
 
       
 
    }
 
  
     printf("Addresse mac source%s\n",ether1.sourceMac);
+
<p>     void readPacket(int sock,char *packet,int *size){  *size=recvfrom(sock,packet,*size,0,NULL,NULL);  }</p>
    ;// bug de mémoire des caractères sont ajoutés sans raison (solved)
 
   
 
   
 
// Récupération du type
 
  
    *(ether1.etherType)=*(packetChar+24);
+
<p>int get_packet() //ouverture et r&eacute;cup&eacute;ration du packet dans le fichier choisi {  FILE *in_file = fopen(filename, &quot;r&quot;); if (!in_file) { printf(&quot;test&quot;);  perror(&quot;fopen&quot;); exit(EXIT_FAILURE); }</p>
    *(ether1.etherType+1)=*(packetChar+25);
 
    *(ether1.etherType+2)=*(packetChar+26);
 
    *(ether1.etherType+3)=*(packetChar+27);
 
   
 
    // J'avais ici une erreur dans ma string. Lorsque je rajoutais le nameType la char etherType "récupérait" aussi la valeur IPV4 ce qui me rendait printf(etherType) 0800IPV4
 
    // La lenght de etherType changeait aussi sans raison
 
    // En utilisant autre chose qu'une fonction toute faite comme strcat ou strcpy je n'ai pas ajouté \0 à la fin de ma string. etherType et nameType sont collés dans la mémoire. Alors sans \0 la mémoire considérait que
 
    // etherType s'arretait à \0 de nameType
 
    *(ether1.etherType+4)='\0';
 
   
 
    // Vérification du type etherType
 
    if (strcmp(ether1.etherType,"0800")==0){
 
        strcpy(ether1.nameType,"IPV4");
 
        ether1.casePacket =1;
 
            }
 
    else if (strcmp(ether1.etherType,"0806")==0){
 
        strcpy(ether1.nameType,"ARP");
 
        ether1.casePacket =2;
 
    }
 
    else if (strcmp(ether1.etherType,"86dd")==0){
 
        strcpy(ether1.nameType,"IPV6");      
 
        ether1.casePacket =3;
 
    }
 
    else {
 
        strcpy(ether1.nameType,"UNKNOWNS");
 
    }
 
  
    printf("Type en Hexa: %s/ EtherType:%s\n",ether1.etherType,ether1.nameType);
+
<p> struct stat sb;  if (stat(filename, &amp;sb) == -1) {  printf(&quot;test&quot;);  perror(&quot;stat&quot;);  exit(EXIT_FAILURE);  }  // Allocation de la taille de la m&eacute;moire en fonction de la taille du texte  char *file_contents = malloc(sb.st_size);    while (fscanf(in_file, &quot;%[^\n ] &quot;, file_contents) != EOF) {    strcat(packetChar,file_contents);  //printf(&quot; %s\n&quot;, file_contents);  //packetChar[indexPacket]=file_contents;  //indexPacket++;  }  printf(&quot;\n&quot;);  //printf(&quot;%s&quot;, packetChar);  indexPacket=0;  fclose(in_file);  }  struct etherFrame getMacAddressType(){  struct etherFrame ether1;  int i;  // nettoyage de la cha&icirc;ne de charact&egrave;re &agrave; cause d'un bug :&quot;G&#65533;&#65533;U48:f1:7f:f0:32:20:&quot; en plus de la mac address des charact&egrave;re sont pr&eacute;sents au d&eacute;but  // Je pense que l'erreur ici est que j'ai allou&eacute; une zone m&eacute;moire &agrave; ma string mais je ne l'ai pas initialis&eacute;  strcpy(ether1.destMac,&quot;&quot;);  strcpy(ether1.sourceMac,&quot;&quot;);  strcpy(ether1.etherType,&quot;&quot;);  strcpy(ether1.nameType,&quot;&quot;); // Pour r&eacute;soudre &ccedil;a je copie dans ma string un texte vide</p>
    return ether1;
 
}
 
  
 +
<p>// R&eacute;cup&eacute;ration de l'addresse mac de destination  for(i=0;i<12;i=i+2){  strcat(ether1.destMac,&quot;:&quot;);  strncat(ether1.destMac,&amp;packetChar[i],1);  strncat(ether1.destMac,&amp;packetChar[i+1],1);    };</p>
  
 +
<p> printf(&quot;\nAddresse mac de destination%s\n&quot;,ether1.destMac); //R&eacute;cup&eacute;ration de l'addresse mac source  for(i=12;i<24;i=i+2){  strcat(ether1.sourceMac,&quot;:&quot;);  strncat(ether1.sourceMac,&amp;packetChar[i],1);  strncat(ether1.sourceMac,&amp;packetChar[i+1],1);    }</p>
  
struct ipFrame analyseIP4(struct etherFrame ether1){
+
<p> printf(&quot;Addresse mac source%s\n&quot;,ether1.sourceMac); ;// bug de m&eacute;moire des caract&egrave;res sont ajout&eacute;s sans raison (solved)    // R&eacute;cup&eacute;ration du type</p>
    struct ipFrame ip;
 
    // récupération de la version IP et de la longueur de l'en-tête
 
    //printf("Test");
 
    char *ptr;
 
    strcpy(ip.versionIp,"");
 
    strcpy(ip.lenghtHeaderIp,"");
 
     strcpy(ip.DSCP_ECN,"");
 
    strcpy(ip.lenghtIP,"");
 
    strcpy(ip.identIp,"");
 
    ip.versionIp[0]=*(packetChar+28);
 
    ip.lenghtHeaderIp[0]=*(packetChar+29);
 
  
    int tailleHeader = atoi(ip.lenghtHeaderIp)*4;
+
<p> *(ether1.etherType)=*(packetChar+24); *(ether1.etherType+1)=*(packetChar+25); *(ether1.etherType+2)=*(packetChar+26); *(ether1.etherType+3)=*(packetChar+27);   // J'avais ici une erreur dans ma string. Lorsque je rajoutais le nameType la char etherType &quot;r&eacute;cup&eacute;rait&quot; aussi la valeur IPV4 ce qui me rendait printf(etherType) 0800IPV4  // La lenght de etherType changeait aussi sans raison  // En utilisant autre chose qu'une fonction toute faite comme strcat ou strcpy je n'ai pas ajout&eacute; \0 &agrave; la fin de ma string. etherType et nameType sont coll&eacute;s dans la m&eacute;moire. Alors sans \0 la m&eacute;moire consid&eacute;rait que  // etherType s'arretait &agrave; \0 de nameType  *(ether1.etherType+4)='\0';   // V&eacute;rification du type etherType  if (strcmp(ether1.etherType,&quot;0800&quot;)==0){  strcpy(ether1.nameType,&quot;IPV4&quot;); ether1.casePacket =1;  }  else if (strcmp(ether1.etherType,&quot;0806&quot;)==0){  strcpy(ether1.nameType,&quot;ARP&quot;);   ether1.casePacket =2; }  else if (strcmp(ether1.etherType,&quot;86dd&quot;)==0){  strcpy(ether1.nameType,&quot;IPV6&quot;);   ether1.casePacket =3; }  else {  strcpy(ether1.nameType,&quot;UNKNOWNS&quot;); }</p>
    printf("\nTaille Header %d byte",tailleHeader);
 
   
 
    ip.DSCP_ECN[0]=*(packetChar+30);
 
    ip.DSCP_ECN[1]=*(packetChar+31);
 
   
 
    ip.lenghtIP[0]=*(packetChar+32);
 
    ip.lenghtIP[1]=*(packetChar+33);
 
    ip.lenghtIP[2]=*(packetChar+34);
 
    ip.lenghtIP[3]=*(packetChar+35);
 
   
 
    //printf("%s",ip.lenghtIP);
 
    long taillePaquetIp=strtol(ip.lenghtIP,NULL,16);
 
    printf("\nTaille du paquet IP: %d",taillePaquetIp);
 
   
 
    ip.identIp[0]=*(packetChar+36);
 
    ip.identIp[1]=*(packetChar+37);
 
    ip.identIp[2]=*(packetChar+38);
 
    ip.identIp[3]=*(packetChar+39);
 
    ip.identIp[4]='\0';
 
    printf("\nIdentification %s",ip.identIp);
 
   
 
    ip.flagIp[0]=*(packetChar+40);
 
    ip.flagIp[1]=*(packetChar+41);
 
    ip.flagIp[2]='\0';
 
    printf("\nFlag IP: %s", ip.flagIp);
 
   
 
    ip.TTL[0]=*(packetChar+42);
 
    ip.TTL[1]=*(packetChar+43);
 
    ip.TTL[2]=*(packetChar+44);
 
    ip.TTL[3]=*(packetChar+45);
 
    ip.TTL[4]='\0';
 
    printf("\nTTL: %s", ip.TTL);
 
   
 
    ip.protocolIP[0]=*(packetChar+46);
 
    ip.protocolIP[1]=*(packetChar+47);
 
    ip.protocolIP[2]='\0';
 
    printf("\nProtocole:%s", ip.protocolIP);
 
    ;
 
    ip.CsIP[0]=*(packetChar+48);
 
    ip.CsIP[1]=*(packetChar+49);
 
    ip.CsIP[2]=*(packetChar+50);
 
    ip.CsIP[3]=*(packetChar+51);
 
    ip.CsIP[4]='\0';
 
    printf("\nCS= %s",ip.CsIP);
 
   
 
    printf("\nProtocole:%s\n", ip.protocolIP);
 
    // Récupération de l'ip source
 
    char tempChar[2];   
 
    tempChar[2]='\0';
 
    tempChar[0]=*(packetChar+52);
 
    tempChar[1]=*(packetChar+53);
 
  
    ip.sourceIP[0]= strtol(tempChar,NULL,16);
+
<p> printf(&quot;Type en Hexa: %s/ EtherType:%s\n&quot;,ether1.etherType,ether1.nameType); return ether1; }</p>
   
 
    tempChar[0]=*(packetChar+54);
 
    tempChar[1]=*(packetChar+55);
 
    ip.sourceIP[1]=strtol(tempChar,NULL,16);
 
   
 
    tempChar[0]=*(packetChar+56);
 
    tempChar[1]=*(packetChar+57);
 
    ip.sourceIP[2]= strtol(tempChar,NULL,16);
 
   
 
    tempChar[0]=*(packetChar+58);
 
    tempChar[1]=*(packetChar+59);
 
    ip.sourceIP[3]= strtol(tempChar,NULL,16);
 
   
 
    //Récupération de l'ip dest
 
    tempChar[0]=*(packetChar+60);
 
    tempChar[1]=*(packetChar+61);
 
    ip.destIP[0]= strtol(tempChar,NULL,16);
 
   
 
    tempChar[0]=*(packetChar+62);
 
    tempChar[1]=*(packetChar+63);
 
    ip.destIP[1]= strtol(tempChar,NULL,16);
 
   
 
    tempChar[0]=*(packetChar+64);
 
    tempChar[1]=*(packetChar+65);
 
    ip.destIP[2]= strtol(tempChar,NULL,16);
 
   
 
    tempChar[0]=*(packetChar+66);
 
    tempChar[1]=*(packetChar+67);
 
    ip.destIP[3]= strtol(tempChar,NULL,16);
 
   
 
    printf("Ip source %d.%d.%d.%d\n",ip.sourceIP[0],ip.sourceIP[1],ip.sourceIP[2],ip.sourceIP[3]);
 
    printf("Ip de destination %d.%d.%d.%d\n",ip.destIP[0],ip.destIP[1],ip.destIP[2],ip.destIP[3]);
 
   
 
    for
 
    return ip;
 
}
 
   
 
void main(){
 
get_packet();
 
    struct etherFrame ether2;
 
    //printf("\n%s\n",packetChar);
 
    ether2=getMacAddressType();
 
   
 
    switch(ether2.casePacket){
 
        case 1:
 
            printf("\nCase IPV4:");
 
            struct ipFrame resultIP= analyseIP4(ether2);
 
            printf("%s\n",resultIP.CsIP);
 
            int caseIp = atoi(resultIP.protocolIP);
 
            switch(caseIp){
 
                case 6:
 
                    printf("TCP\n");
 
                    // Case TCP
 
                   
 
                    ;
 
                    break;
 
                case 17:
 
                    // UDP
 
            ;
 
            break;
 
    }}
 
  
   
+
<p>struct ipFrame analyseIP4(struct etherFrame ether1){  struct ipFrame ip;  // r&eacute;cup&eacute;ration de la version IP et de la longueur de l'en-t&ecirc;te  //printf(&quot;Test&quot;);  char *ptr;  strcpy(ip.versionIp,&quot;&quot;);  strcpy(ip.lenghtHeaderIp,&quot;&quot;);  strcpy(ip.DSCP_ECN,&quot;&quot;);  strcpy(ip.lenghtIP,&quot;&quot;);  strcpy(ip.identIp,&quot;&quot;);  ip.versionIp[0]=*(packetChar+28);  ip.lenghtHeaderIp[0]=*(packetChar+29);</p>
}
+
 
 +
<p> int tailleHeader = atoi(ip.lenghtHeaderIp)*4;  printf(&quot;\nTaille Header %d byte&quot;,tailleHeader);    ip.DSCP_ECN[0]=*(packetChar+30);  ip.DSCP_ECN[1]=*(packetChar+31);    ip.lenghtIP[0]=*(packetChar+32);  ip.lenghtIP[1]=*(packetChar+33);  ip.lenghtIP[2]=*(packetChar+34);  ip.lenghtIP[3]=*(packetChar+35);    //printf(&quot;%s&quot;,ip.lenghtIP);  long taillePaquetIp=strtol(ip.lenghtIP,NULL,16);  printf(&quot;\nTaille du paquet IP: %ld&quot;,taillePaquetIp);    ip.identIp[0]=*(packetChar+36);  ip.identIp[1]=*(packetChar+37);  ip.identIp[2]=*(packetChar+38);  ip.identIp[3]=*(packetChar+39);  ip.identIp[4]='\0';  printf(&quot;\nIdentification %s&quot;,ip.identIp);    ip.flagIp[0]=*(packetChar+40);  ip.flagIp[1]=*(packetChar+41);  ip.flagIp[2]='\0';  printf(&quot;\nFlag IP: %s&quot;, ip.flagIp);    ip.TTL[0]=*(packetChar+42);  ip.TTL[1]=*(packetChar+43);  ip.TTL[2]=*(packetChar+44);  ip.TTL[3]=*(packetChar+45);  ip.TTL[4]='\0';  printf(&quot;\nTTL: %s&quot;, ip.TTL);    ip.protocolIP[0]=*(packetChar+46);  ip.protocolIP[1]=*(packetChar+47);  ip.protocolIP[2]='\0';  printf(&quot;\nProtocole:%s&quot;, ip.protocolIP);  ;  ip.CsIP[0]=*(packetChar+48);  ip.CsIP[1]=*(packetChar+49);  ip.CsIP[2]=*(packetChar+50);  ip.CsIP[3]=*(packetChar+51);  ip.CsIP[4]='\0';  printf(&quot;\nCS= %s&quot;,ip.CsIP);  </p>
 +
 
 +
<p> // R&eacute;cup&eacute;ration de l'ip source  char tempChar[2];  tempChar[2]='\0';  tempChar[0]=*(packetChar+52);  tempChar[1]=*(packetChar+53);</p>
 +
 
 +
<p> ip.sourceIP[0]= strtol(tempChar,NULL,16);    tempChar[0]=*(packetChar+54);  tempChar[1]=*(packetChar+55);  ip.sourceIP[1]=strtol(tempChar,NULL,16);    tempChar[0]=*(packetChar+56);  tempChar[1]=*(packetChar+57);  ip.sourceIP[2]= strtol(tempChar,NULL,16);    tempChar[0]=*(packetChar+58);  tempChar[1]=*(packetChar+59);  ip.sourceIP[3]= strtol(tempChar,NULL,16);    //R&eacute;cup&eacute;ration de l'ip dest  tempChar[0]=*(packetChar+60);  tempChar[1]=*(packetChar+61);  ip.destIP[0]= strtol(tempChar,NULL,16);    tempChar[0]=*(packetChar+62);  tempChar[1]=*(packetChar+63);  ip.destIP[1]= strtol(tempChar,NULL,16);    tempChar[0]=*(packetChar+64);  tempChar[1]=*(packetChar+65);  ip.destIP[2]= strtol(tempChar,NULL,16);    tempChar[0]=*(packetChar+66);    tempChar[1]=*(packetChar+67);  ip.destIP[3]= strtol(tempChar,NULL,16);    printf(&quot;\nIp source %d.%d.%d.%d&quot;,ip.sourceIP[0],ip.sourceIP[1],ip.sourceIP[2],ip.sourceIP[3]);  printf(&quot;\nIp de destination %d.%d.%d.%d&quot;,ip.destIP[0],ip.destIP[1],ip.destIP[2],ip.destIP[3]);  // printf(&quot;tes 1 %d\n&quot;,strlen(ip.fullHeader)); // printf(&quot;test 2 %d\n&quot;,sizeof(ip.fullHeader)); //  printf(&quot;\n%d &quot;, tailleHeader); // ip.fullHeader = malloc(tailleHeader); // printf(&quot;test 3 %d\n&quot;,strlen(ip.fullHeader)); // printf(&quot;test 4 %d\n&quot;,sizeof(ip.fullHeader));    int index=0;  int i;    for(i=28;i<28+(tailleHeader*2);i=i+1){ // printf(&quot;%d\n&quot;,strlen(ip.fullHeader)); // printf(&quot;%s&quot;,ip.fullHeader);</p>
 +
 
 +
<p> ip.fullHeader[index]=packetChar[i];  index++;  }  ip.fullHeader[tailleHeader*2]='\0';  printf(&quot;\n%s&quot;,ip.fullHeader);  return ip; }  void displayPacket(FILE *stream,char *packet,int size){ FILE *fileOpen = fopen(filename,&quot;w&quot;); chmod(filename, 777);  int i,count=MAX_COLUMNS;  for(i=0;i<size;i++){  fprintf(stream,&quot;%2.2x&quot;,(unsigned char)packet[i]);  fprintf(fileOpen,&quot;%2.2x&quot;,(unsigned char)packet[i]);  }  fclose(fileOpen);  }  void main(){</p>
 +
 
 +
<p>int sock;  int size;  char buffer[BUFFER_SIZE];  sock=openRawEthernetSocket(ifname);  readPacket(sock,buffer,&amp;size);  displayPacket(stdout,buffer,size); get_packet();  struct etherFrame ether2;  ether2=getMacAddressType();    printf(&quot;\n%c&quot;,buffer[20]);  printf(&quot;\n%1.1x&quot;,buffer[20]);  printf(&quot;\n%d\n&quot;,buffer[20]);      switch(ether2.casePacket){  case 1:  printf(&quot;\nCase IPV4:&quot;);  struct ipFrame resultIP= analyseIP4(ether2); // printf(&quot;%s\n&quot;,resultIP.CsIP); // printf(&quot;%d\n&quot;, sizeof(resultIP.CsIP)); // printf(&quot;%d\n&quot;, strlen(resultIP.CsIP));  int caseIp = atoi(resultIP.protocolIP);  chmod(filename, 777);  switch(caseIp){  case 6:  printf(&quot;TCP\n&quot;);  // Case TCP    ;  break;  case 17:  // UDP  ;  break;  }}</p>
 +
 
 +
<p>  }</p>

Version du 6 septembre 2022 à 22:54

Objectif

Développer un micro utilitaire de type tcpdump pour analyser les paquets TCP/IP.

En vous basant sur les sources du logiciel d'interception des paquets réseau des travaux dirigés du semestre 7, réalisez un analyseur de paquets TCP/IP avec les caractéristiques suivantes :

  • les paquets sont toujours affichés sous leur forme numérique ;
  • les entêtes Ethernet sont affichées en clair (les trois champs que vous connaissez bien) ;
  • si le paquet Ethernet contient un paquet IPv4, les entêtes IPv4 sont affichées en clair et la somme de contrôle est vérifiée ;
  • si le paquet IPv4 contient un paquet UDP, les entêtes UDP sont affichées en clair et l'éventuelle somme de contrôle est vérifiée.

Vous devez documenter vos avancées sur cette page Wiki. Au vu du retard que vous avez pris dans l'épreuve, merci de mettre à jour votre Wiki au moins deux fois par semaine.

Travail réaliser

Pour réaliser ce projet j'ai commencé par récupérer différents paquets ethernet "type" qui me permettront de développer mon programme . Pour cela j'utilise l'utilitaire wireshark Cela me permet de récupérer un exemple de trame ipv4 :

0000   48 f1 7f d0 32 20 78 81 02 31 36 76 86 dd 60 00   H...2 x..16v..`.
0010   00 00 00 21 11 3b 2a 00 14 50 40 07 08 0f 00 00   ...!.;*..P@.....
0020   00 00 00 00 20 02 2a 01 cb 00 0a a2 68 00 7d 7c   .... .*.....h.}|
0030   c5 0a 46 7f fe f6 01 bb d8 4c 00 21 0d c0 40 2e   ..F......L.!..@.
0040   40 71 fe 71 19 9e 41 f3 a7 a0 1c 35 5a 25 73 8b   @q.q..A....5Z%s.
0050   cf 41 11 bb 80 b3 b4                              .A.....

Ainsi que les informations associées:

Frame 680: 87 bytes on wire (696 bits), 87 bytes captured (696 bits) on interface \Device\NPF_{4DB062CB-0742-4EDE-86A1-1CFB3480F3BE}, id 0
Ethernet II, Src: Sercomm_31:36:76 (78:81:02:31:36:76), Dst: IntelCor_d0:32:20 (48:f1:7f:d0:32:20)
Internet Protocol Version 6, Src: 2a00:1450:4007:80f::2002, Dst: 2a01:cb00:aa2:6800:7d7c:c50a:467f:fef6
User Datagram Protocol, Src Port: 443, Dst Port: 55372
Data (25 bytes)

J'ai réalisé le même processus pour une trame UDP. Pour le moment c'est trames sont stockées dans un fichier texte mais l'idéal est d'utiliser directement l'utilitaire ether pour récupérer un paquet J'ai décomposé mon programme en plusieurs routine. Récupération de la trame-> Récupération des en-têtes ethernet -> Sélection du type de protocole -> si c'est un IPV4 affichage de ses en-têtes et vérification de la checksum

Récupération de la trame: Ma première routine me permet de récupérer un paquet complet sous la forme d'un char Exemple 48 f1 7f d0 32 20 78 81 02 31 36 76 86 dd 60 00 00 00 00 21 11 3b 2a 00 14 50 40 07 08 0f 00 00 00 00 00 00 20 02 2a 01 cb 00 0a a2 68 00 7d 7c c5 0a 46 7f fe f6 01 bb d8 4c 00 21 0d c0 40 2e 40 71 fe 71 19 9e 41 f3 a7 a0 1c 35 5a 25 73 8b cf 41 11 bb 80 b3 b4

Je traite cette chaine de caractère avec des boucles for. Je sais que l'adresse mac source et de destination et source sont composées de 6 octets alors il me suffit de récupérer les octets correspondants que je met dans une struct dédiée correspondant aux en-têtes ethernet.

Documents Rendus

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #define DEFAUT_SIZE 300

#include <errno.h> #include <unistd.h> #include <getopt.h> #include <time.h> #include <signal.h> #include <net/if.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/ioctl.h> #include <linux/in.h> #include <linux/if_ether.h> #include <linux/if_packet.h> #include <linux/filter.h>

#define BUFFER_SIZE 2048 #define MAX_COLUMNS 16 #define ETHER_ADDR_LEN 6

#define MODE_DISPLAY 0 #define MODE_SEND 1

struct etherFrame { char sourceMac[18]; char destMac[18]; char etherType[5]; char nameType[15]; int casePacket; };

struct ipFrame{ char versionIp[2]; char lenghtHeaderIp[2]; char DSCP_ECN[2]; char lenghtIP[4]; char identIp[5]; char flagIp[3]; char TTL[5]; char protocolIP[3]; char CsIP[5]; unsigned char sourceIP[4]; unsigned char destIP[4]; char fullHeader[40]; };

const char* filename = "temp.txt"; char packetChar[DEFAUT_SIZE]; int indexPacket=0;

char *ifname="eth0"; /* Interface reseau a utiliser */ unsigned char broadcast=1; /* Capture ou non des diffusions */ unsigned char unicast=0; /* Capture limitee a une adresse MAC ou non */ char macAddress[ETHER_ADDR_LEN];/* adresse MAC a surveiller */

int openRawEthernetSocket(char *ifname){ struct sockaddr_ll address; int proto=htons(ETH_P_ALL); int result;

if((result=socket(PF_PACKET,SOCK_RAW,proto))<0){ perror("openRawEthernetSocket.socket"); exit(1); } return result; }

void readPacket(int sock,char *packet,int *size){ *size=recvfrom(sock,packet,*size,0,NULL,NULL); }

int get_packet() //ouverture et récupération du packet dans le fichier choisi { FILE *in_file = fopen(filename, "r"); if (!in_file) { printf("test"); perror("fopen"); exit(EXIT_FAILURE); }

struct stat sb; if (stat(filename, &sb) == -1) { printf("test"); perror("stat"); exit(EXIT_FAILURE); } // Allocation de la taille de la mémoire en fonction de la taille du texte char *file_contents = malloc(sb.st_size); while (fscanf(in_file, "%[^\n ] ", file_contents) != EOF) { strcat(packetChar,file_contents); //printf(" %s\n", file_contents); //packetChar[indexPacket]=file_contents; //indexPacket++; } printf("\n"); //printf("%s", packetChar); indexPacket=0; fclose(in_file); } struct etherFrame getMacAddressType(){ struct etherFrame ether1; int i; // nettoyage de la chaîne de charactère à cause d'un bug :"G��U48:f1:7f:f0:32:20:" en plus de la mac address des charactère sont présents au début // Je pense que l'erreur ici est que j'ai alloué une zone mémoire à ma string mais je ne l'ai pas initialisé strcpy(ether1.destMac,""); strcpy(ether1.sourceMac,""); strcpy(ether1.etherType,""); strcpy(ether1.nameType,""); // Pour résoudre ça je copie dans ma string un texte vide

// Récupération de l'addresse mac de destination for(i=0;i<12;i=i+2){ strcat(ether1.destMac,":"); strncat(ether1.destMac,&packetChar[i],1); strncat(ether1.destMac,&packetChar[i+1],1); };

printf("\nAddresse mac de destination%s\n",ether1.destMac); //Récupération de l'addresse mac source for(i=12;i<24;i=i+2){ strcat(ether1.sourceMac,":"); strncat(ether1.sourceMac,&packetChar[i],1); strncat(ether1.sourceMac,&packetChar[i+1],1); }

printf("Addresse mac source%s\n",ether1.sourceMac);  ;// bug de mémoire des caractères sont ajoutés sans raison (solved) // Récupération du type

*(ether1.etherType)=*(packetChar+24); *(ether1.etherType+1)=*(packetChar+25); *(ether1.etherType+2)=*(packetChar+26); *(ether1.etherType+3)=*(packetChar+27); // J'avais ici une erreur dans ma string. Lorsque je rajoutais le nameType la char etherType "récupérait" aussi la valeur IPV4 ce qui me rendait printf(etherType) 0800IPV4 // La lenght de etherType changeait aussi sans raison // En utilisant autre chose qu'une fonction toute faite comme strcat ou strcpy je n'ai pas ajouté \0 à la fin de ma string. etherType et nameType sont collés dans la mémoire. Alors sans \0 la mémoire considérait que // etherType s'arretait à \0 de nameType *(ether1.etherType+4)='\0'; // Vérification du type etherType if (strcmp(ether1.etherType,"0800")==0){ strcpy(ether1.nameType,"IPV4"); ether1.casePacket =1; } else if (strcmp(ether1.etherType,"0806")==0){ strcpy(ether1.nameType,"ARP"); ether1.casePacket =2; } else if (strcmp(ether1.etherType,"86dd")==0){ strcpy(ether1.nameType,"IPV6"); ether1.casePacket =3; } else { strcpy(ether1.nameType,"UNKNOWNS"); }

printf("Type en Hexa: %s/ EtherType:%s\n",ether1.etherType,ether1.nameType); return ether1; }

struct ipFrame analyseIP4(struct etherFrame ether1){ struct ipFrame ip; // récupération de la version IP et de la longueur de l'en-tête //printf("Test"); char *ptr; strcpy(ip.versionIp,""); strcpy(ip.lenghtHeaderIp,""); strcpy(ip.DSCP_ECN,""); strcpy(ip.lenghtIP,""); strcpy(ip.identIp,""); ip.versionIp[0]=*(packetChar+28); ip.lenghtHeaderIp[0]=*(packetChar+29);

int tailleHeader = atoi(ip.lenghtHeaderIp)*4; printf("\nTaille Header %d byte",tailleHeader); ip.DSCP_ECN[0]=*(packetChar+30); ip.DSCP_ECN[1]=*(packetChar+31); ip.lenghtIP[0]=*(packetChar+32); ip.lenghtIP[1]=*(packetChar+33); ip.lenghtIP[2]=*(packetChar+34); ip.lenghtIP[3]=*(packetChar+35); //printf("%s",ip.lenghtIP); long taillePaquetIp=strtol(ip.lenghtIP,NULL,16); printf("\nTaille du paquet IP: %ld",taillePaquetIp); ip.identIp[0]=*(packetChar+36); ip.identIp[1]=*(packetChar+37); ip.identIp[2]=*(packetChar+38); ip.identIp[3]=*(packetChar+39); ip.identIp[4]='\0'; printf("\nIdentification %s",ip.identIp); ip.flagIp[0]=*(packetChar+40); ip.flagIp[1]=*(packetChar+41); ip.flagIp[2]='\0'; printf("\nFlag IP: %s", ip.flagIp); ip.TTL[0]=*(packetChar+42); ip.TTL[1]=*(packetChar+43); ip.TTL[2]=*(packetChar+44); ip.TTL[3]=*(packetChar+45); ip.TTL[4]='\0'; printf("\nTTL: %s", ip.TTL); ip.protocolIP[0]=*(packetChar+46); ip.protocolIP[1]=*(packetChar+47); ip.protocolIP[2]='\0'; printf("\nProtocole:%s", ip.protocolIP);  ; ip.CsIP[0]=*(packetChar+48); ip.CsIP[1]=*(packetChar+49); ip.CsIP[2]=*(packetChar+50); ip.CsIP[3]=*(packetChar+51); ip.CsIP[4]='\0'; printf("\nCS= %s",ip.CsIP);

// Récupération de l'ip source char tempChar[2]; tempChar[2]='\0'; tempChar[0]=*(packetChar+52); tempChar[1]=*(packetChar+53);

ip.sourceIP[0]= strtol(tempChar,NULL,16); tempChar[0]=*(packetChar+54); tempChar[1]=*(packetChar+55); ip.sourceIP[1]=strtol(tempChar,NULL,16); tempChar[0]=*(packetChar+56); tempChar[1]=*(packetChar+57); ip.sourceIP[2]= strtol(tempChar,NULL,16); tempChar[0]=*(packetChar+58); tempChar[1]=*(packetChar+59); ip.sourceIP[3]= strtol(tempChar,NULL,16); //Récupération de l'ip dest tempChar[0]=*(packetChar+60); tempChar[1]=*(packetChar+61); ip.destIP[0]= strtol(tempChar,NULL,16); tempChar[0]=*(packetChar+62); tempChar[1]=*(packetChar+63); ip.destIP[1]= strtol(tempChar,NULL,16); tempChar[0]=*(packetChar+64); tempChar[1]=*(packetChar+65); ip.destIP[2]= strtol(tempChar,NULL,16); tempChar[0]=*(packetChar+66); tempChar[1]=*(packetChar+67); ip.destIP[3]= strtol(tempChar,NULL,16); printf("\nIp source %d.%d.%d.%d",ip.sourceIP[0],ip.sourceIP[1],ip.sourceIP[2],ip.sourceIP[3]); printf("\nIp de destination %d.%d.%d.%d",ip.destIP[0],ip.destIP[1],ip.destIP[2],ip.destIP[3]); // printf("tes 1 %d\n",strlen(ip.fullHeader)); // printf("test 2 %d\n",sizeof(ip.fullHeader)); // printf("\n%d ", tailleHeader); // ip.fullHeader = malloc(tailleHeader); // printf("test 3 %d\n",strlen(ip.fullHeader)); // printf("test 4 %d\n",sizeof(ip.fullHeader)); int index=0; int i; for(i=28;i<28+(tailleHeader*2);i=i+1){ // printf("%d\n",strlen(ip.fullHeader)); // printf("%s",ip.fullHeader);

ip.fullHeader[index]=packetChar[i]; index++; } ip.fullHeader[tailleHeader*2]='\0'; printf("\n%s",ip.fullHeader); return ip; } void displayPacket(FILE *stream,char *packet,int size){ FILE *fileOpen = fopen(filename,"w"); chmod(filename, 777); int i,count=MAX_COLUMNS; for(i=0;i<size;i++){ fprintf(stream,"%2.2x",(unsigned char)packet[i]); fprintf(fileOpen,"%2.2x",(unsigned char)packet[i]); } fclose(fileOpen); } void main(){

int sock; int size; char buffer[BUFFER_SIZE]; sock=openRawEthernetSocket(ifname); readPacket(sock,buffer,&size); displayPacket(stdout,buffer,size); get_packet(); struct etherFrame ether2; ether2=getMacAddressType(); printf("\n%c",buffer[20]); printf("\n%1.1x",buffer[20]); printf("\n%d\n",buffer[20]); switch(ether2.casePacket){ case 1: printf("\nCase IPV4:"); struct ipFrame resultIP= analyseIP4(ether2); // printf("%s\n",resultIP.CsIP); // printf("%d\n", sizeof(resultIP.CsIP)); // printf("%d\n", strlen(resultIP.CsIP)); int caseIp = atoi(resultIP.protocolIP); chmod(filename, 777); switch(caseIp){ case 6: printf("TCP\n"); // Case TCP  ; break; case 17: // UDP  ; break; }}

}