Raw socket TCP/IP sous Windwos XP

Résolu
cs_MaximeH Messages postés 11 Date d'inscription dimanche 6 juillet 2003 Statut Membre Dernière intervention 14 juillet 2005 - 14 juil. 2005 à 00:53
cs_MaximeH Messages postés 11 Date d'inscription dimanche 6 juillet 2003 Statut Membre Dernière intervention 14 juillet 2005 - 14 juil. 2005 à 13:07
Bonjour à tous,
J'aimerais savoir pourquoi ce code ne marche pas (il n'es pas de moi, c'est sensé être un exemple ...) :

###code

// SheepTCP->SYN Hawaien

//----------------------

// Utilisation des Raw Sockets

// Construction du paquet IP -> RFC - 791

// Construction du paquet TCP -> RFC - 793

// Flag SYN : 0x02 -> Syn

//-----------------------------

// http://www.sheep-team.org

//-----------------------------


#include <stdio.h>
#include<winsock2.h>

// ------- Déclaration des fonctions ----------------

int InitWinsock(void); // Initialisation de la Socket

SOCKET CreateSocket(void); // Vreation de la Raw socket

unsigned short in_cksum(u_short * addr, int len); // Calcul du checksum


// ------- Structure IP ----------------------------

typedef struct iphdr {
unsigned char ver_len:8; // version d'IP + longeur d'en tète

unsigned char tos:8; // type of service

unsigned short tot_len:16;// longueur totale du datagramme

unsigned short id:16; // identification

unsigned short offset:16; // décalage

unsigned char ttl:8; // time to live

unsigned char protocol:8; // protocol

unsigned short checksum:16; // somme de contrôle

unsigned int source:32; // adresse IP source

unsigned int destination:32; // adresse IP destination

} IP_HDR;

// ------- Structure TCP ---------------------------

typedef struct tcphdr
{
unsigned short psource:16; // port source

unsigned short pdest:16; // port de destination

unsigned int seq:32; // numéro de séquence

unsigned int ack:32; // accusé de réception TCP

unsigned char doffset:8; // Le data offset

unsigned char flags:8; // Les flags

unsigned short win:16; // La fenêtre d'echange

unsigned short checksum:16; // Le checksum

unsigned short urgp:16; // Le pointeur de données urgentes

} TCP_HDR;

// ------- Structure de calcul checksum ------------

struct fauxhdr
{
unsigned long saddr;
unsigned long daddr;
char useless;
unsigned char protocol;
unsigned short length;
struct tcphdr tcp;
};

// ----------------------------------------------------

int main(){

// ------- Déclarations -------------------------------

unsigned short ip_v, ip_len; // version d'IP + longueur -> En-tete IP

struct iphdr *ip; // structure IP -> En-tete IP

struct tcphdr *tcp; // structure TCP -> En-tete TCP

struct fauxhdr *fhdr; // structure de calcul checksum

char *packet NULL, *ptr NULL; // paquet -> Creation du paquet

struct sockaddr_in sin; // -> Envoi du paquet


// ------- Initialisation/Creation de la socket -------

InitWinsock(); // WinSock

int sock=CreateSocket(); // Raw Socket


// ------- En-tete IP ---------------------------------

// malloc pour la structure IP

ip = (struct iphdr *)malloc(sizeof(struct iphdr));
// mise à 0

memset(ip, 0x0, sizeof(struct iphdr));
// longueur de l'en tête IP

ip_len 5; // Par défaut, il est égal à 5 (20 octets), cependant, avec les options de l'entête IP, il peut être compris entre 6 et 15.> sizeof(struct iphdr) / sizeof(unsigned long);

// version d'IPv4

ip_v = 4;
// remplissage de la structure IP

ip->ver_len = (ip_v << 4) | ip_len;
ip->tos = 0; // -> calculé par windows

ip->tot_len = htons (sizeof (struct iphdr) + sizeof (struct tcphdr)); // taille du paquet -> calculé par windows

ip->id = 1;
ip->offset = 0;
ip->ttl = 255; // time to live

ip->protocol = IPPROTO_TCP; // Proto TCP

ip->source = inet_addr("80.119.222.105"); // adresse IP source

ip->destination = inet_addr("66.102.11.104"); // adresse IP de destination

ip->checksum = 0; // on met le champ checksum à 0 avant l'appel de la fonction calculant le checksum

ip->checksum = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); // calcul du checksum avec la fonction

//-> calculé par windows


// ------- En-tete TCP --------------------------------

// malloc pour la structure TCP

tcp = (struct tcphdr *)malloc(sizeof(struct tcphdr));
// mise à 0

memset(tcp, 0x0, sizeof(struct tcphdr));
// remplissage de la structure TCP

tcp->psource = htons(1025);
tcp->pdest = htons(80) ;
tcp->seq = htonl(1337);
tcp->ack = htonl(0);
tcp->doffset = (5) << 4;
tcp->flags 0x02; // 0x02 flag syn

tcp->win = htons(1337);
tcp->checksum = 0;
tcp->urgp = 0;

// ------- Faux Header ---------------------------------

// malloc pour la structure

fhdr = (struct fauxhdr *)malloc(sizeof(struct fauxhdr));
// mise à 0

memset(fhdr, 0x0, sizeof(struct fauxhdr));
// remplissage de la structure

fhdr->saddr = ip->source; // IP source

fhdr->daddr = ip->destination; // IP de destination

fhdr->useless = 0; // null

fhdr->protocol = IPPROTO_TCP; // protocol TCP (6)

fhdr->length = htons(sizeof(struct tcphdr)); // longueur TCP_HDR

fhdr->tcp = *tcp; // structure TCP

// ------- END/Faux Header- ----------------------------


// Maintenant nous pouvons calculer le checksum de notre paquet

tcp->checksum = in_cksum((unsigned short *)fhdr, sizeof(struct fauxhdr));

// ------------------ Creation du paquet --------------

packet = (char *) malloc((sizeof(struct iphdr) + sizeof(struct tcphdr)));
memset(packet, 0x0, (sizeof(struct iphdr) + sizeof(struct tcphdr)));
ZeroMemory(packet, sizeof(packet)); //mise à zero

ptr = packet;
memcpy(ptr, ip, sizeof(struct iphdr));
ptr += sizeof(struct iphdr);
memcpy(ptr, tcp, sizeof(struct tcphdr));
ptr += sizeof(struct tcphdr);

// ------------------ Envoi du paquet -----------------

// remplissage de la structure sockaddr_in

sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip->destination;

// Et voili, il ne reste plus qu'à envoyer le paquet

if(sendto(sock, packet, (sizeof(struct iphdr) + sizeof(struct tcphdr)), 0x0, (struct sockaddr *)&sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
printf("[Error] . Fonction sendto(). Code d'erreur : %d\n", WSAGetLastError());
free(ip);
free(tcp);
free(fhdr);
WSACleanup();
}
free(ip);
free(tcp);
free(fhdr);
WSACleanup();
}
// Function : Initialise WinSock

int InitWinsock(void){
WSADATA WSAData; // structure WSADATA définie dans winsock.h

int err;
// Initialise winsock

// Permet à notre application de spécifier la version de Winsock requise et de recevoir les détails des ces spécifications.

// Version : 2.0

if((err = WSAStartup(MAKEWORD(2,0), &WSAData)) != 0) {
// Si la valeur retournée est différente de zéro c'est qu'il y a un problème.

printf("Impossible d'initialiser l'API Winsock\n");
return(-1); // on quitte

}
return(0); // on quitte

}
// Function : Creation de la Raw Socket

SOCKET CreateSocket(void){
int optval = 1;
SOCKET socket; // déclaration de notre socket

// Protocol IP en mode RAW

if ((socket WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0,0)) INVALID_SOCKET){
printf("[Error] . Function() Raw Socket : %d\n", WSAGetLastError());
WSACleanup();
exit(-1);
}
// Specification de la socket

if (setsockopt(socket, IPPROTO_IP, 2, (char *)&optval, sizeof(optval)) == SOCKET_ERROR) {
printf("[Error] . Function setsockopt() : %d\n", WSAGetLastError());
WSACleanup();
exit(-1);
}
return(socket); // retourne la socket prête à l'emploi

}
// Function : Calcul de checksum

// -> Pas de moi cette function, glané sur le net - pas d'auteur

// Explication de la rfc :

// Complément à un sur 16 bits de la somme des compléments à un du message ICMP

unsigned short in_cksum(u_short * addr, int len){

register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;

while (nleft > 1) {
sum += *w++;
nleft -= 2;
}

if (nleft == 1) {
*(u_char *) (&answer) = *(u_char *) w;
sum += answer;
}

sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;

return (answer);
}


###code

Voilà, quand je lance, ça me donne : "[Error] . Function() Raw Socket : 10004".
A savoir que je compile sous dev-c++, que j'ai bien inclu la librairie libws2_32.a et que 80.119.222.105 était mon ip lors de mes test et 66.102.11.104 une ip prise au harsard.
Chose currieuse, si l'on remplace tous le IPPROTO_TCP par des IPPROTO_ICMP ou IPPROTO_UDP ça marche (mais avec un packet corrompu bien sûr).
Meci.
M.H.

1 réponse

cs_MaximeH Messages postés 11 Date d'inscription dimanche 6 juillet 2003 Statut Membre Dernière intervention 14 juillet 2005 1
14 juil. 2005 à 13:07
Merci quand même, le fait est, qu'en fait les RAW SOCKET sont supprimés sous XP SP2 (pour le TCP et partiellement pour le UDP). Plus de détails à :
http://www.microsoft.com/technet/prodtechnol/winxppro/maintain/sp2netwk.mspx.
M.H.
3
Rejoignez-nous