__ ______ __ __ __ _ ___ __ _ _ _ _\_ _ _ \ / \ / \ \ \ \ _ \ \ .\ | |/ / / / / _ / /.\ \ .- - / /\ \/ /\ \-\_\ \_\\_\-\_/ ----| < /_/-/_//_/\/__/ \- ------. : \ \ \__/ / / |_|\_\ \ \ : , \/ \/ \ \ | : \ \ . . 11.10 Comment sender des packets RAW sous windows 2k/XP\ \ ! . aka \ \ . ; ginette ginette, laisse moi entrer dans ton socket \ \ : : \ \ : '-- ----- - -------- --- --------- - -- ------------- --- -\ \-' \____ _ _\ ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© © AVERTISSEMENT © ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© ¤ Cet article est destiné à ceux et celles qui savent déjà ¤ © utiliser les sockets, qui ont une bonne base en TCP/IP © ¤ qui connaissent les principes des raw sockets de base et ¤ © le language C. © ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© ------------------------------------------------------------ ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© © INTRODUCTION © ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© Bonjour, si vous avez continué à lire malgré le petit avertissement, c'est signe que vous savez déjà l'utilité des raw sockets au delà du simple SYN flood. Je vais donc vous épargner l'intro et commencer tout de suite le côté intéressant. Dans cet article je ne vais pas parler des autres possibilités avec les raw sockets, comme par exemple de pouvoir "sniffer" les packets qui entrent et sortent d'une box. Je vais me concentrer sur l'envoi de packets raw. ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© © LE SOCKET LUI-MÊME © ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© Pour commencer, vous devez absolument être administrateur sur la box où vous voudrez faire des raw sockets. Seul l'admin a les droits pour les utiliser. À moins de créer une clé dans votre registre, qui permettrait à tout les utilisateurs de s'en servir. Créez la clé ci-dessous et settez sa valeur qui est de type DWORD à 1. HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Afd\Parameters\DisableRawSecurity Vous aurez aussi besoin d'un header "custom" pour setter vos header TCP et IP. J'en ai inclus un à la fin de l'article sous le chapitre "HEADER À UTILISER". Je tient toutefois à mentionner que je n'ai PAS programmé le header. Il a été fait par "ziss". Les autres headers dont vous aurez besoin sont et . N'oubliez pas d'inclure la librairie de winsock2 "ws2_32.lib". Personellement je suggère, si vous utilisez MS visual C++, d'utiliser la petite commande: #pragma comment(lib, "ws2_32.lib"); La déclaration d'un socket "normal" ou de type SOCK_STREAM ou SOCK_DGRAM est simple: SOCKET sock; socket(AF_INET, SOCK_STREAM, 0); Pour la déclaration d'un raw socket, quelques petites choses diffèrent. Voici un exemple: SOCKET sock; socket(AF_INET, SOCK_RAW, IPPROTO_RAW); J'attire votre attention sur le SOCK_RAW, qui est le type de socket, et sur IPPROTO_RAW qui est le protocole qui sera utilisé par le socket. Il est important de configurer notre socket pour qu'il soit "vraiment" raw. Nous faisons ça de cette façon: BOOL bOpt = TRUE; setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt)); Votre socket est maintenant raw et prêt à être utilisé. Notez que pour utiliser IP_HDRINCL, vous devez absolument être en administrateur ou bien avoir mit la petite clé que j'ai mentionnée plus haut. ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© © LES HEADERS TCP/IP © ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© Je ne vais pas m'attarder à l'explication des headers TCP/IP puisque je crois que pas mal tout le monde ont déjà lu sur le sujet. Un packet contient toute les informations qu'il à besoin pour se diriger sur l'internet. Il contient l'adresse du destinataire, celle de l'envoyeur et autre choses comme la version IP, la grandeur du packet, le checksum, le port de l'envoyeur et du destinataire, etc. Si vous êtes intéressés à en savoir plus sur les headers TCP/IP ou sur le TCP/IP lui-même, je vous suggère de jeter un oeil attentif sur le rfc1180. Les headers TCP/IP seront facilement configurable avec la librairie "tcpip.h" fournie à la fin de cet article. Pour vous donner une idée, je vais faire les headers TCP et IP. IP_HDR ipHeader; ipHeader.ip_checksum = 0; ipHeader.ip_id = 1; ipHeader.ip_offset = 0; ipHeader.ip_protocol = IPPROTO_TCP; ipHeader.ip_tos = 0; ipHeader.ip_totallength = htons(iSize); // iSize = sizeof(ipHeader) + sizeof(tcpHeader); ipHeader.ip_ttl = 128; // Time to live (en hops) généralement 128 // parfois 48, dependant de vos besoins ipHeader.ip_verlen = (4 << 4) | iIPSize; // iIPSize = sizeof(ipHeader) / sizeof(unsigned long); ipHeader.ip_destaddr = inet_addr("127.0.0.1"); // addresse de destination ipHeader.ip_srcaddr = inet_addr("7.7.7.7"); // source Avec des noms de variables aussi clairs que ça, je ne crois pas avoir besoin d'expliquer chaque chose ;). J'ai pris soin de mettre les variables en commentaire où elles sont utilisées, pour avoir une idée de ce que vous faites vraiment. Maintenant allons y pour le TCP. Un des avantages des raw sockets, est que vous pouvez vous même choisir la provenance du packet. C'est à dire qu'en changeant le IP_HDR.ip_srcaddr pour un autre ip que le vôtre, (7.7.7.7 dans ce cas-ci), la personne qui va recevoir le packet pensera qu'il viens de ce ip. C'est d'ailleurs comme ça que les smurfs marchent. Ils envoient un ping à une liste de serveurs, les serveurs, eux, vont tous répondre à la "victime" en même temps ce qui va causer sa déconnection, tout dépendant de plusieurs facteurs. Assez parlé de smurf, et continuons avec le TCP. TCP_HDR tcpHeader; tcpHeader.acknum = 0; tcpHeader.DataOffset = (5) << 4; tcpHeader.Flags = SYN; tcpHeader.seqnum = htonl(7777); // n'importe quoi tcpHeader.Windows = htons(7777); // n'importe quoi tcpHeader.Checksum = 0; tcpHeader.UrgPointer = 0; tcpHeader.sport = htons(7777); // le port source, // ce que vous voulez ;) tcpHeader.dport = htons(80); // le port de la destination C'est assez simple ici aussi, je ne pense pas que quelqu'un ne comprenne pas quelque chose. Lors d'une connexion TCP/IP, l'hôte génère un "numéro de séquence initiale" (Initial sequence number (ISN)). Ce numéro est utilisé pour garder la trace sur les paquets envoyés et pour être certain que la connexion continue bel et bien. Dans notre situation, avec des sockets raw, on ne se sert pas vraiment de ça, vous pouvez donc marquer ce que vous voulez à "tcpHeader.seqnum". De même pour "tcpHeader.Windows". Maintenant, on va avoir besoin d'un pseudo-header pour faire le checksum de notre header TCP. C'est très semblable au TCP_HDR en fait, voici comment on procède: PS_HDR psHeader; psHeader.placeholder = 0; psHeader.protocol = IPPROTO_TCP; psHeader.tcp_length = htons(sizeof(tcpHeader)); psHeader.source_address = inet_addr("7.7.7.7"); //comme dans le IP_HDR psHeader.dest_address = inet_addr("127.0.0.1");//même chose ici aussi memcpy(&psHeader.tcp, &tcpHeader, sizeof(tcpHeader)); Voilà, on a créé notre pseudo header et pouvons maintenant procéder au checksum : tcpHeader.Checksum = checksum((usigned short *)&psHeader, sizeof(psHeader)); Ceci conclus le chapitre. ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© © EXAMPLE DE CODE © ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© /************************************************************/ #include #include #include #include #include "tcpip.h" #pragma comment(lib, "ws2_32.lib") int CreatePacket(int, int, int, char[]); int SendPacket(int, int, int); int main() { int destPort = 80; // le port de destination int destIP = inet_addr("127.0.0.1"); // Addresse de destination int srcIP = inet_addr("19.13.2.7"); // Provenance (ce que vous voulez) // envoi de 5 packets for(int a = 0; a < 5; a++) SendPacket(destPort, destIP, srcIP); return 0; } int CreatePacket(int dport, int destIP, int srcIP, char buf[]) { // Déclaration des headers TCP IP et Pseudo header IP_HDR ipHeader; TCP_HDR tcpHeader; PS_HDR psHeader; int iSize, // Grosseur totale du packet ( + sizeof(autre_buffer) ) iIPVersion, // La version, dans notre cas IPv4 iIPSize; // La grosseur du IP char *cPtr = NULL; iSize = sizeof(ipHeader) + sizeof(tcpHeader); iIPVersion = 4; iIPSize = sizeof(ipHeader) / sizeof(int); // Configuration des headers // Header IP ipHeader.ip_checksum = 0; ipHeader.ip_id = 1; ipHeader.ip_offset = 0; ipHeader.ip_protocol = IPPROTO_TCP; ipHeader.ip_tos = 0; ipHeader.ip_totallength = htons(iSize); ipHeader.ip_ttl = 128; ipHeader.ip_verlen = (4 << 4) | iIPSize; ipHeader.ip_destaddr = destIP; // addresse de destination ipHeader.ip_srcaddr = srcIP; // source // Header TCP tcpHeader.acknum = 0; tcpHeader.DataOffset = (5) << 4; tcpHeader.Flags = SYN; tcpHeader.seqnum = htonl(7777); tcpHeader.Windows = htons(7777); tcpHeader.Checksum = 0; tcpHeader.UrgPointer = 0; tcpHeader.dport = htons(80); // destination tcpHeader.sport = htons(7777); // source // Pseudo Header psHeader.placeholder = 0; psHeader.protocol = IPPROTO_TCP; psHeader.tcp_length = htons(sizeof(tcpHeader)); memcpy(&psHeader.tcp,&tcpHeader, sizeof(tcpHeader)); psHeader.dest_address = destIP; // destination psHeader.source_address = srcIP; // source // Calcul du checksum tcpHeader.Checksum = checksum((USHORT *)&psHeader, sizeof(psHeader)); // Préparation du buffer memset(buf, 0, sizeof(buf)); cPtr = buf; memcpy(cPtr, &ipHeader, sizeof(ipHeader)); cPtr = cPtr + sizeof(ipHeader); memcpy(cPtr, &tcpHeader, sizeof(tcpHeader)); cPtr = cPtr + sizeof(tcpHeader); return 0; } int SendPacket(int destPort, int destIP, int srcIP) { WSADATA WSAData; SOCKET sock; BOOL bOpt =true; struct sockaddr_in sin; char buf[40]; WSAStartup(MAKEWORD(2,2), &WSAData); sock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0,0); setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt)); sin.sin_family = AF_INET; sin.sin_port = htons(1); sin.sin_addr.s_addr = destIP; // Envoi de 1 packet CreatePacket(destPort,destIP,srcIP, buf); sendto(sock, buf, sizeof(buf), 0, (SOCKADDR *)&sin, sizeof(sin)); // Cleaning up... closesocket(sock); WSACleanup(); return 0; } /************************************************************/ ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© © HEADER À UTILISER © ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© J'ai trouvé ce petit header déjà programmé par "ziss". J'en ai vu beaucoup d'autres, mais j'ai trouvé que celui-ci était le mieux construit avec des noms de variables appropriés. J'ai donc choisi de l'inclure dans cet article. /*************************** TCPIP.H ********************************/ /************************** by: ziss *******************************/ #ifndef _TCPIP_H_ #define _TCPIP_H_ // Standard TCP flags #define URG 0x20 #define ACK 0x10 #define PSH 0x08 #define RST 0x04 #define SYN 0x02 #define FIN 0x01 // Our tcp header struct typedef struct tcp_hdr { unsigned short sport; unsigned short dport; unsigned int seqnum; unsigned int acknum; unsigned char DataOffset; unsigned char Flags; unsigned short Windows; unsigned short Checksum; unsigned short UrgPointer; }TCP_HDR; // Our ip header struct typedef struct ip_hdr { unsigned char ip_verlen; // IP version & length unsigned char ip_tos; // IP type of service unsigned short ip_totallength; // Total length unsigned short ip_id; // Unique identifier unsigned short ip_offset; // Fragment offset field unsigned char ip_ttl; // Time to live unsigned char ip_protocol; // Protocol(TCP, UDP, etc.) unsigned short ip_checksum; // IP checksum unsigned int ip_srcaddr; // Source address unsigned int ip_destaddr; // Destination address } IP_HDR; // Our pseudo header struct typedef struct ps_hdr { unsigned int source_address; unsigned int dest_address; unsigned char placeholder; unsigned char protocol; unsigned short tcp_length; struct tcp_hdr tcp; }PS_HDR; // Standard TCP/UDP checksum function. USHORT checksum(USHORT *buffer, int size) { unsigned long cksum=0; while (size > 1) { cksum += *buffer++; size -= sizeof(USHORT); } if (size) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } #endif /********************** END TCPIP.H *************************************/ ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© © CONCLUSION © ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© Il y a beaucoup à faire avec les raw sockets. Je vous suggère fortement de lire plus sur le sujet si vous êtes intéressé. Les possibilités sont infinies, mais ceci n'est que la poignée de la porte. J'espère toutefois que vous aurez appris un peu, ceci conclus ce court article sur les raw sockets 2k/XP. ¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤©¤© ___ ___ .----/ /----------- ---------- --------- - -- - - --- -----------/ / | / / / /| : / / / / : | / / alice514@hotmail.com / / | |/ / / / | /___/-- ---------- ----- ----------------- - ------- -- --- -/___/----'