Citation :
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//#include <sconio.h>
#include "Fingerprint.h"
#include "ip_checksum.h"
#define MAX_PING_PACKET_SIZE (1024 + sizeof(IPHeader))
//////////////////////////// setup_for_ping /////////////////////////////////////////
// // Crée la structure Winsock nécessaire pour envoyer et recevoir des paquets ping.
// l'hôte peut être soit une adresse IP soit un nom de machine.
// ttl c'est le time to live (càd le nombre de rebonds) du paquet.
// Les deux autres paramètres sont les sorties de la fonction.
// Elle renvoie -1 si il y a une erreur.
//
/////////////////////////////////////////////////////////////////////////////////////
int setup_tcp(char* host, SOCKET& sd, sockaddr_in& dest)
{
// Créer la socket
sd = WSASocket(AF_INET, SOCK_RAW, IPPROTO_TCP, 0, 0, 0);
if (sd == INVALID_SOCKET) {
printf("Erreur pendant la création d'un Rawsocket" );
return -1;
}
// Initialise le bloc d'infos pour la machine destinataire
memset(&dest, 0, sizeof(dest));
// Place le premier paramètre passé dans une adresse IP à pinger
unsigned int addr = inet_addr(host);
if (addr != INADDR_NONE) {
// C'était en IPv4 donc on sauve le résultat
dest.sin_addr.s_addr = addr;
dest.sin_family = AF_INET;
}
else {
// C'est pas un IPv4, donc c'est un nom de machine et on le cherche
hostent* hp = gethostbyname(host);
if (hp != 0) {
// Trouvé un nom de machine correspndant donc on sauve l adresse
memcpy(&(dest.sin_addr), hp->h_addr, hp->h_length);
dest.sin_family = hp->h_addrtype;
}
else {
// Le nom de machine n'est pas reconnu
printf("Machine introuvable" );
return -1;
}
}
return 0;
}
/////////////////////////// init_ping_packet ///////////////////////////
//
// Remplit les champs et les zones de données d'un paquet ICMP, le
// remplissant au maximum avec des zéros pour s'adapter avec la taille
// du paquet, en lui donnant la séquence passée en paramètre. // Ceci complète le paquet, ainsi nous pouvons calculer le checksum du
// paquet etle mettre dans le champ approprié.
//
////////////////////////////////////////////////////////////////////////
void init_tcp(TCPHeader* tcp_hdr, int packet_size)
{
tcp_hdr->th_dport=htons(1234);
tcp_hdr->th_sport=htons(1234);
tcp_hdr->th_seq=31337; tcp_hdr->th_ack=0; tcp_hdr->th_lenres=(sizeof(TCPHeader)/4<<4|0); tcp_hdr->th_flag=2;
tcp_hdr->th_win=htons(65535);
tcp_hdr->th_urp=0; tcp_hdr->th_sum=0;
// on remplit le champ de données avec 0xCAFEDECA
const unsigned long int cafedeca = 0xCAFEDECA;
char* datapart = (char*)tcp_hdr + sizeof(TCPHeader);
int bytes_left = packet_size - sizeof(TCPHeader);
while (bytes_left > 0) {
memcpy(datapart, &cafedeca, min(int(sizeof(cafedeca)), bytes_left));
bytes_left -= sizeof(cafedeca);
datapart += sizeof(cafedeca);
}
}
//////////////////////// Envoi de paquet ICMP /////////////////////////////
//
// Envoi un paquet ICMP à l'ordi distant avec la socket sd d'une taille de
// packet_size octets. Ce n'est pas vérifié pour l'authenticité du paquet,
// donc il faut vérifier que la taille est d'au moins sizeof(ICMPHeader).
// Cette fonction retourne -1 si une erreur apparait.
//
///////////////////////////////////////////////////////////////////////////
int send_tcp(SOCKET sd, const sockaddr_in& dest, TCPHeader* send_buf, int packet_size)
{
// Envoi le paquet par le buffer send_buf
int bwrote;
bwrote = sendto(sd, (char*)send_buf, packet_size, 0, (sockaddr*)&dest, sizeof(dest));
if (bwrote == SOCKET_ERROR) {
cerr << "Envoi impossible : " << WSAGetLastError() << endl;
return -1;
}
else printf("PAQUET ENVOYE" );
return 0;
}
/////////////////////////////// Reception paquet ICMP/////////////////////
//
// Reçoit une réponse ICMP sur la socket sd dans le buffer recv_buf et stocke les infos
// de l'envoyeur dans la source.
// Retourne -1 sur erreur ou 0 sinon.
// Notons que le buffer de réception recv_buf doit être plus grand que celui d'émission send_buf
// parce que le paquet incident possède l'entête IP.
// Il peut aussi y avoir des options IP ; donc ça n'est pas suffisant de mettre
// une taille de "sizeof(send_buf) + sizeof(IPHeader)" octets.
// On a réservé une place beaucoup plus large mais c'est pas grave de perdre de la place.
//
///////////////////////////////////////////////////////////////////////////
int recv_tcp(SOCKET sd, sockaddr_in& source, IPHeader* recv_buf, int packet_size, char * host)
{
int df,fromlen,bread;
// On attend la réponse à notre requête
fromlen = sizeof(source);
/* bread = recvfrom(sd,(char*)recv_buf,packet_size + sizeof(IPHeader),0,(sockaddr*)&source, &fromlen);
if (bread == SOCKET_ERROR) {
cerr << "Lecture échouée: ";
if (WSAGetLastError() == WSAEMSGSIZE) {
printf("Tampon trop petit" );
}
else {
cerr << "Erreur #" << WSAGetLastError() << endl;
}
return -1;
}*/
bread = recvfrom(sd, (char*)recv_buf, sizeof(recv_buf), 0, (sockaddr*)&source, &fromlen);
printf("\n==============================================\n" );
printf("==Paquet IP/TCP recu de la machine distante==\n" );
printf("==============================================\n" );
printf("Version : %d\n",recv_buf->version);
printf("Longueur entête : %d\n",recv_buf->h_len);
printf("Type de service : %d\n",recv_buf->tos);
if(recv_buf->flags == 0x40)
df=1;
else
df=0;
printf("DF : %d\n",df);
printf("Protocole : %d\n",recv_buf->proto);
printf("IP SOURCE : %d.%d.%d.%d\n",*(&recv_buf->ttl + 4),*(&recv_buf->ttl + 5),*(&recv_buf->ttl + 6),*(&recv_buf->ttl + 7));
printf("IP DEST : %d.%d.%d.%d",*(&recv_buf->ttl + 8),*(&recv_buf->ttl + 9),*(&recv_buf->ttl + 10),*(&recv_buf->ttl + 11));
return 0;
}
///////////////////////////// Decodade de la réponse /////////////////////////////
//
// Analyse le paquet reçu. Retourne -1 sur une erreur, -2 si l'on doit réessayer
// et 0 si pas de problème
//
//////////////////////////////////////////////////////////////////////////////////
int decode_tcp(IPHeader* reply, int bytes, sockaddr_in* from) {
// Passe directement à l'entête ICMP en zappant l'entête IP
unsigned short header_len = reply->h_len * 4;
TCPHeader* icmphdr = (TCPHeader*)((char*)reply + header_len);
printf("La fenetre TCP est de : %d\n",icmphdr->th_win);
printf("Port source : %d\n",icmphdr->th_sport);
printf("Port dest : %d\n",icmphdr->th_dport);
return 0;
}
/////////////////////////////////////Envoi des paquets/////////////////////
//
// envoie un paquet, le recoit et vérifie sa validité, on lui passe en paramètres les
//paramètres du paquet à envoyer
//retourne 1 si tout s'est bien passé et -1 si il y a un problème
//
///////////////////////////////////////////////////////////////////////////
int test_tcp(char* host, int packet_size, SOCKET& sd, sockaddr_in& dest, sockaddr_in& source,
TCPHeader* send_buf, IPHeader* recv_buf)
{
int i=1,delai=0;
if (setup_tcp(host, sd, dest) < 0) //df et tos variables
{
delete[]send_buf;
delete[]recv_buf;
WSACleanup();
return -1;
}
init_tcp(send_buf, packet_size);
// Envoi le paquet et reçoit la réponse
if (send_tcp(sd, dest, send_buf, packet_size) >= 0)
{
// Boucle de reception jusqu'à avoir une réponse ou une erreur
if (recv_tcp(sd, source, recv_buf, MAX_PING_PACKET_SIZE, host) < 0)
{
// On extrait le numéro de séquence de l'entête ICMP. Si c'est mauvais
// on en tient compte, sinon on abandonne.
unsigned short header_len = recv_buf->h_len * 4;
TCPHeader* icmphdr = (TCPHeader*)
((char*)recv_buf + header_len);
}
if ( (decode_tcp(recv_buf, packet_size, &source) != -2)&&(i))
{
// Réussite ou erreur fatale
i = 0;
}
}
else
printf("Erreur d'envoi du paquet TCP" );
return 1;
}
|