"half-open" Port scanning mit SOCK_RAW



  • Hi,

    Ich bin vor kurzem auf Mixter's tutorial (http://mixter.void.ru/rawip.html) zu Raw Sockets gestoßen und wollte mal einen Port Scanner schreiben der ein SYN an einen Port sendet und bei Empfang von SYN/ACK diesen in die verfügbare Liste packt. Der Code unten macht das nur für einen Port da ich den beliebig aktivieren/deaktivieren kann und ich erstmal keinen select() benutzen wollte. Dabei wird aber scheinbar nichtmal das SYN Packet gesendet: Ich bekomme schlichtweg gar keine Antwort ("while (!recvfrom (sockfd, packet2, ip2->ip_len, 0, (struct sockaddr*) to, &addrlen))"). tcpdump gibt nichts aus, könnte aber auch daran liegen das es über das interne interface (also nur auf einem Rechner) läuft. Wäre für jede Hilfe dankbar

    #include <iostream>
    #include <cstdlib>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #define __FAVOR_BSD
    #include <netinet/tcp.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    
    using namespace std;
    
    bool scanport (int sockfd, sockaddr_in* to);
    unsigned short csum (unsigned short* buf, int nwords);
    
    int main(int argc, char argv[])
    {
    
      int sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_TCP);
    
      int yes = 1;
    
      if (setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, &yes, sizeof (int)) == -1)
      {
    
          perror ("setsockopt");
    
          exit (0);
    
      }
    
      sockaddr_in target;
    
      target.sin_family = AF_INET;
      target.sin_port = htons (19867); // x-beliebiger port
      target.sin_addr.s_addr = inet_addr ("127.0.0.1");
    
      if (scanport (sockfd, &target))
          cout << "SYN/ACK" << endl;
    
      return 0;
    
    }
    
    bool scanport (int sockfd, sockaddr_in* to)
    {
    
        char packet[4096];
        ip *iph = (struct ip *) packet;
        tcphdr *tcp = (struct tcphdr *) packet + sizeof (struct ip);
    
        memset (packet, 0, 4096);
    
        iph->ip_hl = 5;
        iph->ip_v = 4;
        iph->ip_tos = 0;
        iph->ip_len = sizeof (struct ip) + sizeof (struct tcphdr);
        iph->ip_id = htonl (54321);
        iph->ip_off = 0;
        iph->ip_ttl = 255;
        iph->ip_p = 6;
        iph->ip_sum = 0;
        iph->ip_dst.s_addr = to->sin_addr.s_addr;
    
        // bin davon ausgegangen das der Kernel iph->ip_src ausfüllt
    
        tcp->th_sport = to->sin_port;
        tcp->th_dport = to->sin_port;
        tcp->th_seq = htonl (random ());
        tcp->th_ack = 0;
        tcp->th_x2 = 0;
        tcp->th_off = 0;
        tcp->th_flags = TH_SYN;
        tcp->th_win = htonl (65535);
        tcp->th_sum = 0;
        tcp->th_urp = 0;
    
        int rnd = tcp->th_seq;
    
        iph->ip_sum = csum ((unsigned short *) packet, iph->ip_len >> 1);
    
        if (sendto (sockfd, packet, iph->ip_len, 0, (struct sockaddr*) to, sizeof (*to)) == -1)
        {
    
             perror ("sendto");
    
             exit (0);
    
        }
        else
        {
    
            char packet2[4096];
    
            ip *ip2 = (struct ip *) packet2;
            tcphdr *tcp2 = (struct tcphdr *) packet2 + sizeof (struct ip);
    
            socklen_t addrlen = sizeof (struct sockaddr);
    
            while (!recvfrom (sockfd, packet2, ip2->ip_len, 0, (struct sockaddr*) to, &addrlen))
    
            ip2 = (struct ip *) packet2;  
    
            tcp2 = (struct tcphdr *) packet2 + sizeof (struct ip);
    
            if (tcp2->th_flags & (TH_SYN | TH_ACK))
            {
    
                cout << rnd << endl << tcp2->th_ack << endl;
    
                return true;
    
            }
            else if (tcp2->th_flags & TH_RST)
            {
    
                return false;
    
            }
    
        }   
    
    }
    
    unsigned short csum (unsigned short *buf, int nwords)
    {
      unsigned long sum;
      for (sum = 0; nwords > 0; nwords--)
        sum += *buf++;
      sum = (sum >> 16) + (sum & 0xffff);
      sum += (sum >> 16);
      return ~sum;
    }
    


  • Hallo Anre,

    also Deine Vermutung scheint richtig zu sein, Dein Code geht auf meinem Rechner lokal auch nicht, zu einem anderen allerdings schon.

    Dabei sind mir noch zwei weitere Dinge aufgefallen:

    in bool scanport(..)

    muss es statt
    tcphdr *tcp = (struct tcphdr 😉 packet + sizeof (struct ip);

    tcphdr *tcp = (struct tcphdr 😉 (packet + sizeof (struct ip));

    lauten, sonst wird der falsche Speicherbereich gefüllt.

    Zweitens füllst Du den TCP-Header nicht vollständig, dass solltest Du auch noch beheben.



  • Dankeschön erstmal,

    Ich werde das gleich mal mit einem anderen Rechner ausprobieren und die Fehler beseitigen versuchen 🙂

    MfG Anre



  • Hmm auch wenn ich ein SYN zu einem anderen Rechner im Netzwerk schickebekomme ich keine Antwort.

    Trotz der Anderungen und der TCP-header ist schon vollständig ausgefüllt


Anmelden zum Antworten