Les Forums

Les Forums

Les forums sont fermés. Ils restent présent pour consultation et archivage.
Vous pouvez désormais poser vos questions directement dans les commentaires en bas de chaque page du site.
Alors n'hésitez pas à participer

Serveur RAW

Bonjour,

Je suis actuellement en train de tester frameip et je voudrais faire un serveur qui reagirais a l'arriver d'un SYN et qui pourrait m'afficher l'entete TCP.
Tout d'abord je ne sais pas si c'est faisable pour 2 raison
-> Windows risque de rejeter mon SYN avant que mon serveur ne le receptionne. (a me confirmer; et si oui, à par un hook de la pile y aurait il une solution pour recevoir le syn?)
-> J'utilise windows SP2 et je code mon serveur avec winsock2. (si je n'ai pas le choix je passerais a la lib pcap)

voila un extrait de mon code :[code:1:3ee67a9357]
int main(void){

WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2,2);
char buf[512];
sockaddr_in addr_r;
sockaddr addr_r2;
int total;
int size=sizeof(struct sockaddr);
WSAStartup(wVersionRequested,&wsaData);

SOCKET s=socket(AF_INET,SOCK_RAW,IPPROTO_RAW);//IPPROTO_TCP);
if(s==INVALID_SOCKET)
printf("Socket Invalide\n");

memset(&addr_r,0,sizeof(struct sockaddr_in));
addr_r.sin_family=AF_INET;
addr_r.sin_port=htons(70);
addr_r.sin_addr.s_addr=htonl(INADDR_ANY);


if(bind(s,(struct sockaddr *)&addr_r,sizeof(struct sockaddr_in))==(-1))
printf("Erreur Bind : %d\n",WSAGetLastError());

total=recvfrom(s,buf,512,0,&addr_r2,&size);
if(total==-1)
printf("Erreur recfrom\n");
printf("la trame(%d octets):\n-",total);
for(int k=0;k<r;++k)
{
printf("%c",buf[k]);
}
printf("-\nVoila c est recu\n");
system("pause");
closesocket(s);
WSACleanup();
}[/code:1:3ee67a9357]

Si quelqu'un pouvait m'eclairer
Decize
Lu decize,

Comme tu utilise le mode RAW, je pense que tu verras le SYN apparaitre. Par contre, le port n'atant pas placé en listen ni par toi, ni par quelqu'un d'autre, ton OS répondra très certainement un RST ACK.

En Raw, ton firewall passe avant et il faudra donc qu'il autorise ce SYN à entrée.

Si tu veux te mettre avant le Firewall, il te faut passer en Libpcap.


@+
_SebF - Sébastien FONTAINE
Salut _sebf,

Tout d'abord merci de ta reponse rapide.



Effectivement je devais un peu loucher pour ne pas avoir vu qu'il manquais le listen. 🙄

Je rajoute donc a mon code:
(ligne 27)
[code:1:4a74f71b28]+ listen(s,2);[/code:1:4a74f71b28]

Par contre je pense qu'il faut que j'evite de mettre un accept sinon je vais rater mon syn n'est il pas ?

Je desactive mon firewall et....
c est toujours le black out dans ma console, pas de reaction du serveur a l'envoie du packet.

(commande de frameip = FrameIp.exe -interface 1 -tcp_port_destination 70 -ip_destination 192.168.1.2)
Re decize,

J'ai pas dit qu'il fallait mettre un Listen, j'ai dit que s'en lui l'OS renverra un RST ACK.

Je pense pas que tu en ai besoin. Et je pense pas que le fait de rajouter un accept te ferait louper la trame (sauf si c'est le même process qui gère l'écoute).

Je test ton code et je reviens

@+
_SebF - Sébastien FONTAINE
Pas évident de reprendr el code de quelqu'un d'autre 😉
(Au passage, essai de ne pas faire de quick and dirty, c'est pas cool pour les lecture)

Voici un extrait de mon code TCPPING.exe. C'est la procédure de recption qui fonctionne et qui recoit bien toutes les trames.

En t'en inspirant, tu va trouver :
([url=http://www.frameip.com/tcpping/]Le complet[/url])

void reception_de_la_trame()
{
WSADATA initialisation_win32;
SOCKADDR_IN information_sur_la_source;
SOCKET id_de_la_socket_ecoute;
DWORD lpcbBytesReturned;
int tampon; // Variable temporaire
int duree_de_la_boucle;
BOOL sortie_de_la_boucle;
int nombre_de_caractere_recu;
char buffer_de_reception[65535];
double temps_de_reponse; // Variable indiquant le temps écoulé entre l'envoi et la reception

// ********************************************************
// Initialisation de la Socket
// ********************************************************
if (WSAStartup(MAKEWORD(2,2),&initialisation_win32)!=0)
gestion_des_erreurs(1,"WSAStartup",1,1);

// ********************************************************
// Ouverture d'une Socket
// ********************************************************
id_de_la_socket_ecoute=socket(AF_INET,SOCK_RAW,IPPROTO_IP);
if (id_de_la_socket_ecoute==INVALID_SOCKET)
gestion_des_erreurs(1,"socket",1,1);

// ********************************************************
// Lien entre la socket et l'IP d'écoute
// ********************************************************
information_sur_la_source.sin_family=AF_INET;
information_sur_la_source.sin_addr.S_un.S_addr=entete_ipv4.ip_source;
if (bind( id_de_la_socket_ecoute,(SOCKADDR *)&information_sur_la_source, sizeof(information_sur_la_source))==SOCKET_ERROR)
gestion_des_erreurs(1,"bind",1,1);

// ********************************************************
// Choix du mode de la socket
// ********************************************************
tampon=1;
// if (WSAIoctl(id_de_la_socket_ecoute,SIO_RCVALL,&tampon,sizeof(tampon),NULL,0,&lpcbBytesReturned,NULL,NULL)==SOCKET_ERROR)
// gestion_des_erreurs(1,"wsaioctl",1,1);

// ********************************************************
// Passage de la socket en mode non bloquant
// ********************************************************
tampon=1;
// La commande recv attend 1 (on) ms avant de rendre la main
if (setsockopt(id_de_la_socket_ecoute,SOL_SOCKET,SO_RCVTIMEO,(char *)&tampon,sizeof(tampon))!=0)
gestion_des_erreurs(1,"setsockopt",1,1);

// ********************************************************
// Création de la boucle d'attente
// ********************************************************
QueryPerformanceFrequency((LARGE_INTEGER *)&cpu_frequence);
duree_de_la_boucle=GetTickCount();
sortie_de_la_boucle=FALSE;
while (sortie_de_la_boucle==false)
{
nombre_de_caractere_recu=recv(id_de_la_socket_ecoute,buffer_de_reception,65535,0);
if (GetTickCount()-duree_de_la_boucle>(unsigned)(timeout*1000))
{
sortie_de_la_boucle=TRUE;
printf("Timeout, sorry, but I didn't receive the answer SYN/ACK or RST/ACK.\n");
}
else if (nombre_de_caractere_recu!=-1)
{
// ********************************************************
// Extraction et des valeurs recues
// ********************************************************
entete_ipv4_reception=(struct ipv4 *)buffer_de_reception;
entete_tcp_reception=(struct tcp *)(buffer_de_reception+20);

if (entete_ipv4_reception->ip_source==entete_ipv4.ip_destination)
if (entete_ipv4_reception->ip_destination==entete_ipv4.ip_source)
if (entete_ipv4_reception->type==6)
if (entete_tcp_reception->port_source==entete_tcp.port_destination)
if (entete_tcp_reception->port_destination==entete_tcp.port_source)
if (entete_tcp_reception->flag_ack==1)
if ( (entete_tcp_reception->flag_syn==1) || (entete_tcp_reception->flag_rst==1) )
{
sortie_de_la_boucle=TRUE;

// ********************************************************
// Arrêt du chrono
// ********************************************************
QueryPerformanceCounter((LARGE_INTEGER *)&temps_de_reponse2);

// ********************************************************
// Calcul du temps de réponse
// ********************************************************
temps_de_reponse=( (double) ( (temps_de_reponse2.QuadPart - temps_de_reponse1.QuadPart) * (double) 1000.0 / (double) cpu_frequence.QuadPart) );

// ********************************************************
// Affichage du résultat
// ********************************************************
printf("Time : %.2f ms",temps_de_reponse);
if (entete_tcp_reception->flag_syn==1)
printf(" - SYN ACK received from %s",convertion_ip(entete_ipv4_reception->ip_source));
else
printf(" - RST ACK received from %s",convertion_ip(entete_ipv4_reception->ip_source));
printf(" to %s",convertion_ip(entete_ipv4_reception->ip_destination));
printf("\n");
// printf(" %d Octets",nombre_de_caractere_recu-40);
// printf(" ttl : %d\n",entete_ipv4_reception->ttl);
}
}
}
}

@+
_SebF - Sébastien FONTAINE
Yup,

Desole pour le manque de commentaire dans mon code, dans un premier temps je voulais faire un essai rapide(cela dit j'aurais pu le commenter avant de poster ...).
Merci pour le bout de code de ton TCPping :). J'ai deja une idee de ce qu'il me manque. Je fais des essais et je reviens.
Alors apres quelques essais non fructeux de modification de mon code, je me suis decide a repartire de 0.
Je remonte mes manches je lance ethereal , et je me decide a faire des essaies avec TCP ping, (j ai desactiver mon firewall) je fais un premier essai : pas de RST ni SYN /ACK recu.
(ligne de commande : TcpPing.exe -interface 1 -ip_destination 192.168.10.9 -tcp_port_destination 81)
Bon je regarde le resultat de la capture :


No. Time Source Destination Protocol Info
16 4.750743 192.168.10.8 192.168.10.9 TCP [TCP segment of a reassembled PDU]

Frame 16 (69 bytes on wire, 69 bytes captured)
Ethernet II, Src: EdimaxTe_4b:1f:09 (00:50:fc:4b:1f:09), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol, Src: 192.168.10.8 (192.168.10.8), Dst: 192.168.10.9 (192.168.10.9)
Version: 4
Header length: 20 bytes
Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
Total Length: 55
Identification: 0x7913 (30995)
Flags: 0x00
Fragment offset: 0
Time to live: 100
Protocol: TCP (0x06)
Header checksum: 0x484c [correct]
Source: 192.168.10.8 (192.168.10.8)
Destination: 192.168.10.9 (192.168.10.9)
Transmission Control Protocol, Src Port: 16958 (16958), Dst Port: 81 (81), Seq: 0, Len: 15
Source port: 16958 (16958)
Destination port: 81 (81)
Sequence number: 0 (relative sequence number)
Next sequence number: 15 (relative sequence number)
Header length: 20 bytes
Flags: 0x0002 (SYN)
0... .... = Congestion Window Reduced (CWR): Not set
.0.. .... = ECN-Echo: Not set
..0. .... = Urgent: Not set
...0 .... = Acknowledgment: Not set
.... 0... = Push: Not set
.... .0.. = Reset: Not set
.... ..1. = Syn: Set
.... ...0 = Fin: Not set
Window size: 16384
Checksum: 0xbecb [correct]
TCP segment data (15 bytes)


Pas de reponse, aucune autre trame n'est presente dans la capture (que j ai laisse tourner 1 bonne min) (je precise que la machine 192.168.10.8 est bien la machine depuis laquelle j'emet la trame et 192.168.10.9 est bien une machine de mon reseau dont le port 81 est ferme).

Bon je fais un essai avec Framip : ligne de commande (FrameIp.exe -interface 1 -tcp_port_destination 70 -ip_destination 192.168.10.9)
Et la aucune trame TCP de capturer dans ethereal. Est ce que je m'y prend mal ? (Ce post aurait pu ce trouver dans le forum Outils mais il fait suite a mes essais de prog)
Lu decize,

Pourquoi ton adresse MAC de destination est 000...
_SebF - Sébastien FONTAINE
Re _Sebf,

Effectivement c'est etrange, je viens de refaire le test avec une autre machine cible et j'obtient encore une adresse mac destination de 00.. , je vais tester chez moi ce soir en reinstallant winpcap.

[i:676b9d10cf]

Bon sinon j ai trouve pourquoi ca ne fonctionnais pas avec frameip, il me manquais d'activer l'option -ip_type 6, du coup je capture bien une trame mais dans ce cas l adresse mac destination est ffffff...

a suivre ...
Re _SebF

Bon alors voila j ai fais le test sur un autre réseau(je capture les trames à l'aide d'ethereal et je lance TCPping sur une machine éxistante du réseau)

Et la je capture ma trame syn avec une adresse mac destination = 0000..
Hum je cherche une trame ARP, et la je vois une trame ARP provenant de ma machine mais qui recherche l'adresse mac de 192.168.10.254.
(Je precise que le TCP syn par bien en direction de ma machine cible 192.168.1.3)
J ai regarder un peu dans le source de TCPping (d ailleur la version n'est pas à jour dans le source ;))
[code:1:ba9eedaa8d]
strcpy(ip_destination,"192.168.101.254");
entete_ipv4.ip_destination=resolution_de_nom(TRUE,ip_destination);[/code:1:ba9eedaa8d]

un peu plus loin
[code:1:ba9eedaa8d]
if ( (strcmp(strlwr(argv[i]),"-ip_destination")==0) || (strcmp(strlwr(argv[i]),"/ip_destination")==0) )
entete_ipv4.ip_destination=(unsigned long)resolution_de_nom(FALSE,argv[i+1]);
[/code:1:ba9eedaa8d]
or la resolution est sur FALSE.
Comme je ne retrouve l'adresse ip 192.168.101.254 a aucun autre endroit du code je suppose que c'est liee a cette fonction.
ne faudrait-il pas la passer a True ?
Lu decize,

Le premier argument de la fonction resolution_de_nom() n'est utile que dans les interfaces graphique. Cela permet d'indiquer qu'il faut, pendant l'execution de cette fonction, rendre la main régulièrement à l'interface.
Dans ton cas qui utilise tcpping, tu es en ligne de commande, donc l'argument n'a pas d'intérêt et devrait être à FALSE. J'ai fait la modif dans mon code et cela sera pris en compte dans la prochaine compilation.

Si tu as vu une requete ARP cherchant l'adresse 192.168.101.254, c'est alors que tu n'a pas spécifié l'argument -ip_destination car en cas d'absence, la veleur par defaut est :

strcpy(ip_destination,"192.168.101.254");
entete_ipv4.ip_destination=resolution_de_nom(TRUE,ip_destination);

@+
_SebF - Sébastien FONTAINE
Re _sebf,

Ok merci pour l'info sur la fonction.
Mais en fait ce que j ai explique dans mon poste precedent c'est que la requete ARP cherche 192.168.101.254,
Mais que le Trame Syn part bien en direction de l'adresse ip 192.168.1.3. ( Je viens de reverifie et je confirme 🙄 bisard tout ca ... il y a encore un truc qui m'echappe)
Si tu veux je peut inscrire le resultat des captures d'ethereal.

P.S.: (l'adresse mac destination de la trame Syn restant 000...)
Bon je vais me coucher j ai l'oeil qui a du mal a rester ouvert. La nuit porte conseil ....


[code:1:a223e7c4ae]
initiation_des_variables();
initiation_des_variables_automatiques();
gestion_des_arguments(argc,argv);[/code:1:a223e7c4ae]


au lieu de
[/size:a223e7c4ae]
[code:1:a223e7c4ae]
initiation_des_variables();
gestion_des_arguments(argc,argv);
initiation_des_variables_automatiques();[/code:1:a223e7c4ae]
Lu decize,

Tu as raison, tcpping cherche à résoudre l'adresse MAC de 192.168.101.254 même si tu spécifie une autre adresse de destination.

Le problème est résolut dans la version 2.2.3.10 de Tcpping. J'ai rajouté la copie de l'ip destination saisie dans la variable ip_destination :
strcpy(ip_destination,convertion_ip(entete_ipv4.ip_destination));

Normalement, tout est bon maintenant, merci de me confirmer que ton problème est résolut.

J'en ai profité pour publier la dernière version du code 🙂

@+
_SebF - Sébastien FONTAINE
Lu _Sebf,

Nikel le probleme est regle,merci 🙂 , la requete arp par vers la bonne ip et du coup le champs adress mac destination est bien renseigne dans le tcp syn.
Ethereal capture bien une trame rst/ack en retour. En revanche tcpping ne detect la trame syn/rst de retour je fais d'autres essaies ca vient peut etre de chez moi ;).

Bon WE

P.S.: (le firewall etait bien desactive).
Re,

Je reviens avec une bonne nouvelle, grace a tes informations et les sources trouve ici je suis parvenu a faire fonctionner un serveur en mode RAW bon ca ressemble de tres pres a TCPping pour la partie reception.

Pour ce qui est de TCPping il continue a m'afficher qu'il ne recoit pas de syn/ack ou rst/ack , alors que je capture bien la trame rst/ack avec mon serveur RAW.

Serveur RAW :
[code:1:a5019d6890]
#include <winsock2.h>
#include <string.h>
#include <stdio.h>
const int IP_HDRINCL=2; // Permet d'éviter d'intégrer #include <ws2tcpip.h> qui ne veux plus fonctionner
#include "Mstcpip.h"

#define IP_SRC "192.168.1.2"
#define IP_DST "192.168.1.1"
#define PORT_SRC 70
#define PORT_DST 40

/*---------------------------------------------------------------------------------*/
/* Merci à www.Frameip.com pour les nombreuses informations que j'ai pu y denicher,*/
/* et qui m'ont permis d'avancer dans mon projet */
/*---------------------------------------------------------------------------------*/

/* Le serveur n'affiche les trames que des packet provenant de IP_DST */
/* dont le port du serveur utilise est PORT_SRC */

// **********************************
// Structure entete IP
// **********************************
struct ipv4 // htons pour les ushort et htonl pour les ulong
{
unsigned char ihl:4; // L'ordre des champs ihl et Version est inversé
unsigned char version:4; // L'ordre des champs ihl et Version est inversé
unsigned char tos;
unsigned short length;
unsigned short id;
unsigned short offset:5; // Ajout d'offset2 afin de pouvoir utiliser l'invertion qui se fait de 8 bits en 8 bits et non pas en unsigned short
unsigned short flag_mf:1; // L'ordre des champs offset et flag est inversé
unsigned short flag_df:1; // L'ordre des champs offset et flag est inversé
unsigned short flag_zero:1; // L'ordre des champs offset et flag est inversé
unsigned short offset2:8; // L'ordre des champs offset et flag est inversé
unsigned char ttl;
unsigned char type;
unsigned short checksum;
unsigned long ip_source;
unsigned long ip_destination;
};

// **********************************
// Nouvelle structure entete TCP
// **********************************
struct tcp // htons pour les ushort et htonl pour les ulong
{
unsigned short port_source;
unsigned short port_destination;
unsigned long sequence;
unsigned long accuse;

unsigned short reserved:4; // Reserved est divisé en deux afin d'être directement intégré à la bonne place
unsigned short offset:4;
unsigned short flag_fin:1; // L'ordre des champs sont inversé
unsigned short flag_syn:1; // L'ordre des champs sont inversé
unsigned short flag_rst:1; // L'ordre des champs sont inversé
unsigned short flag_psh:1; // L'ordre des champs sont inversé
unsigned short flag_ack:1; // L'ordre des champs sont inversé
unsigned short flag_urg:1; // L'ordre des champs sont inversé
unsigned short reserved2:2;

unsigned short window;
unsigned short checksum;
unsigned short pointeur;
};

char * convertion_ip(int adresse_ip)
{
SOCKADDR_IN translation;
char *tampon;//[65535];
tampon=(char *)malloc(400*sizeof(char));
// ********************************************************
// Transformation en IP de type xxx.xxx.xxx.xxx
// ********************************************************
translation.sin_addr.s_addr=adresse_ip;
strcpy(tampon,inet_ntoa(translation.sin_addr));
return (tampon);
}

int main(void){

WORD wVersionRequested;
WSADATA wsaData;
DWORD lpcbBytesReturned;
DWORD tampon;
sockaddr_in addr_r,addr_rcp;
struct tcp *TCP_HDR;
struct ipv4 *IP_HDR;
bool flag;
char buf[512];
char *tmpip1,*tmpip2;
int total;
int size=sizeof(struct sockaddr);

// Initialisation de winsock
wVersionRequested = MAKEWORD(2,2);
WSAStartup(wVersionRequested,&wsaData);
// Creation d'une socket RAW afin de recuperer les entetes IP et TCP dans les trames
SOCKET s=socket(PF_INET,SOCK_RAW,IPPROTO_IP);
if(s==INVALID_SOCKET)
printf("Socket s Invalide\n");

/*----------------------------*/
/* Configuration de la socket */
/*----------------------------*/
memset(&addr_r,0,sizeof(struct sockaddr_in));
addr_r.sin_family=AF_INET;
addr_r.sin_addr.s_addr=inet_addr(IP_SRC);
if(bind(s,(struct sockaddr *)&addr_r,sizeof(addr_r))==(-1))
printf("Erreur Bind : %d\n",WSAGetLastError());

// Passage en mode Promiscious
if(WSAIoctl(s,SIO_RCVALL,&tampon,sizeof(tampon),NULL,0,&lpcbBytesReturned,NULL,NULL)==SOCKET_ERROR)
printf("Erreur Promiscious = %d",WSAGetLastError());;

/*-----------------------------------------*/
/* Reception et affichage des trames recus */
/*-----------------------------------------*/
while(1){
while((total=recvfrom(s,buf,512,0,(struct sockaddr *)&addr_rcp,&size))==-1);
// Recuperation des entetes a partire des donnees recus
IP_HDR=(struct ipv4 *)buf;
TCP_HDR=(struct tcp *)(buf+20);
flag=TRUE;
// Si le packet provient de IP_DST et si le port local utiliser est PORT_SRC -> On affiche la trame
if(IP_HDR->ip_source==inet_addr(IP_DST))
printf("IP Source: %s\n",IP_DST);
else
flag=FALSE;
if(TCP_HDR->port_destination==htons(PORT_SRC) && flag==TRUE)
printf("Port %d en reception\n",PORT_SRC);
else
flag=FALSE;
// Affichage
if(flag==TRUE){
printf("la trame(%d octets):\n-",total);
printf("--------- Info structure tcp ipv4 --------\n");
tmpip1=convertion_ip(IP_HDR->ip_destination);
tmpip2=convertion_ip(IP_HDR->ip_source);
printf("IP dest=%s, IP src=%s\n",tmpip1,tmpip2);
printf("PORT tcp de la 2nd structure : %d\n",(int)ntohs(TCP_HDR->port_destination));
printf("type=%d port source=%d flag ack=%d flag rst=%d\n",IP_HDR->type,(int)ntohs(TCP_HDR->port_source),(int)TCP_HDR->flag_ack,(int)TCP_HDR->flag_rst);
printf("donnee :-");
for(int k=20+24;k<total;++k)
printf("%c",buf[k]);
printf("-\nVoila c est recu\n\n\n");
free(tmpip1);
free(tmpip2);
}
}

system("pause");
closesocket(s);
WSACleanup();
}
[/code:1:a5019d6890]

Tu notera que j'ai recupere ta fonction char * convertion_ip(int adresse_ip),
Seulement j'ai note que la fonction alloue de la memoire localement et que cela cree un effet de bord. Cela dit cette fonction n'est certainement pas en cause pour mon probleme de reception.

Je vais tenter de compiler TcpPing et de faire des tests avec chez moi 😉
Lu decize,

Je ne penses pas que le char 65535 fasse un débrdement, car le strcpy va copier dedant. Et le reste lui est de toute facon reservé.

Cependant, en relisant le code, je confirme que c'est moche, j'aurais du faire un char * puis un malloc de 16 et un memcpy d'une longueur de 16. J'ai appris au fure et à mesure et ca se voit quand tu ressort de vieilles fonctions 🙂

@+ et n'hésite pas.
_SebF - Sébastien FONTAINE