#include #include #include #ifdef WIN32 #pragma pack(1) #endif struct EthernetHeader { u_char etherDestMac[6]; u_char etherSrcMac[6]; u_short etherProtoType; // 0x0800 IP }; #ifdef WIN32 #pragma pack(1) #endif struct IPheader { u_char versionHeadLen; // 0x45 u_char diffServField; // 0 u_short totLen; // 190 for resp u_short id; // 0 u_char flags; // 0 u_char fragOffset; // 0 u_char ttl; // 63 u_char proto; // UDP - 0x11 u_short headChkSum; u_int ipsrc; u_int ipdst; }; #ifdef WIN32 #pragma pack(1) #endif struct TCPheader { u_short srcPort; // u_short dstPort; // 0 u_int seqNum; u_int ackNum; u_char offset; u_char flags; u_short checksum; u_short urgpoint; }; #ifdef WIN32 #pragma pack(1) #endif struct TCPPacket { EthernetHeader ethHead; IPheader ipHead; TCPheader tcpHead; } ; //****************************************************************************// //* // //* Copyright (C) 2003, James Antognini, antognini@mindspring.com. // //* // //****************************************************************************// /**************************************************************************************************/ /* */ /* Calculate TCP checksum, based on TCP datagram (TCP header + data) and pseudo-header. */ /* */ /* Derived in part from from RFC 1071, section 4.1, p 7, and in part from DDK \e100bex\offload.h. */ /* */ /* Notes: */ /* */ /* 1) This routine is written for a little-endian environment (eg, x86). It has been tested */ /* and used in WinXP user- and kernel-space environments. */ /* */ /* 2) This routine assumes the checksum field in the TCP header has been set to 0, in order */ /* to compute the checksum. */ /* */ /* 3) This routine, as is, cannot be used to check a checksum, because checking a checksum */ /* involves getting the one's complement sum over the TCP datagram, with the checksum */ /* included (see RFC 1071, p 1), but this routine does that summing and then returns the */ /* one's complement of that sum. That is, this routine will, if a checksum is correct, */ /* yield 0xffff in the folding statement below but then will return the one's complement */ /* of 0xffff, which is 0. */ /* */ /**************************************************************************************************/ u_short GetTCPChecksum( u_short* pTCPFd, // Pointer to TCP datagram (header + data). u_short* pSrcAddr, // Address of source IP address (in network format). u_short* pDestAddr, // Address of destination IP address (in network format). u_short usTCPFd // Length of TCP datagram (header + data). ) { #define JADrvNm "jaNDISpassthru" #define JADrvRtnsName "GetTCPChecksum" #define JADrvRtnsVer "1.01" #define lnPseudoHdr 12 // Size of pseudo-header. char PseudoHdrArr[lnPseudoHdr]; // Pseudo-header. u_short usPsHdr = lnPseudoHdr; // Length of pseudo-header. u_short* pPseudoHdr = (u_short*)PseudoHdrArr; // Pointer to pseudo-header. ULONG sum = 0; // Note: The one's complement addition done for the TCP datagram and for the pseudo-header is effected // with little-endian u_short* variables. Because of the associativity of addition, that produces // a good result except that the bytes have to be swapped in the return statement. (The data // being checked-summed are, as always, in network (big-endian) order; eg, if the length of the // TCP datagram used in the pseudo-header is 0x95, the value is stored as 0x0095 in memory, not // as 0x9500.) // Build the pseudo-header field. memcpy(PseudoHdrArr, pSrcAddr, 4); // Copy source IP address. memcpy(PseudoHdrArr+4, pDestAddr, 4); // Copy destination IP address. PseudoHdrArr[8] = 0; // Set to 0. PseudoHdrArr[9] = IPPROTO_TCP; // Set to TCP protocol constant. pPseudoHdr[5] = // Put length of entire TCP datagram into pseudo-header. (u_short)(((usTCPFd&0xFF00)>>8) + ((usTCPFd&0x00FF)<<8)); // Do one's complement addition of pseudo-header. while(usPsHdr > 0) { sum += *pPseudoHdr++; usPsHdr -= 2; } // Do one's complement addition of TCP field, except for the last byte if the field length is odd. while(usTCPFd > 1) { sum += *pTCPFd++; usTCPFd -= 2; } // Add left-over byte, if any. if(usTCPFd > 0) sum += *(PUCHAR)pTCPFd; // Fold 32-bit sum to 16 bits (form per offload.h in DDK \e100bex). sum = (((sum >> 16) | (sum << 16)) + sum) >> 16; // Return one's complement (in little-endian form, by the way). return (u_short)~sum; } // End GetTCPChecksum(). //ip header checksum unsigned short cksum(unsigned short *ip, int len){ long sum = 0; /* assume 32 bit long, 16 bit short */ while(len > 1){ sum += *(ip)++; if(sum & 0x80000000) /* if high order bit set, fold */ sum = (sum & 0xFFFF) + (sum >> 16); len -= 2; } if(len) /* take care of left over byte */ sum += (unsigned short) *(unsigned char *)ip; while(sum>>16) sum = (sum & 0xFFFF) + (sum >> 16); return (unsigned short)~sum; } //find offset for ip header (link layer header length) u_int getIpOffset(pcap_t* interf) { //Get datalink type and corresponding header lengths //see http://www.manpagez.com/man/7/pcap-linktype/ int type = pcap_datalink(interf); if (type == DLT_EN10MB) return 14; else if (type == DLT_RAW) return 0; else if (type == DLT_LOOP) return 4; else if (type == DLT_LINUX_SLL) return 16; else return 14; } //main thread function; int main(int argc, const char** argv){ bool openports[65536]; for(int i = 0; i < 65536; i++) //assume all true openports[i]=true; pcap_t* openinterface; pcap_if_t * alldevs; int i = 0; if (pcap_findalldevs(&alldevs, NULL) == -1 || alldevs == NULL) { return -1; } if(argc < 2){ printf("%s %s",argv[0], " interfint ...\n"); while(alldevs != NULL){ printf("%d %s %s\n",i,alldevs->name, alldevs->description); i++; alldevs = alldevs->next; } return 0; } int interfint = atoi(argv[1]); for(int i = 0; i < interfint; i++) alldevs = alldevs->next; if(alldevs==NULL) return 1; printf("opening %d %s %s\n",i,alldevs->name, alldevs->description); //close ports (usually like ftp; open on other systems) int port; for(int i = 2; i < argc; i++) if ((port = atoi(argv[i])) < 65535 && port >= 0) openports[port] = false; if ((openinterface = pcap_open_live(alldevs->name, 65536, 0, 100, NULL)) == NULL) return -1; int offset = getIpOffset(openinterface); struct bpf_program fp; //on some versions of pcap, pcap_compile takes a char* and not a const char*. Cast. if (pcap_compile(openinterface, &fp, "tcp", 0, 0) == -1 || pcap_setfilter(openinterface, &fp) == -1) printf("error compiling or setting filter"); //Main Loop struct pcap_pkthdr *header; const u_char *pkt_data; //u_char * replyPack = (u_char*)malloc(offset + 40); u_char replyPack[54]; u_char basePack[40]={ 0x45,0x00,0x00,0x28,//ip, header len 20, total len 40 0x01,0x13,//id 0x40,0x00,0x80,0x06,//ttl 128, tcp 0x00,0x00, //head chksm 0x00,0x00,0x00,0x00,//src 0x00,0x00,0x00,0x00,//dst //tcp 0x00,0x00, //srcport 0x00,0x00, //dstport 0x13,0x37,0xd0,0x0d,//seq 0x00,0x00,0x00,0x00,//ack 0x50,0x12, //header len and flags (SYN ACK) 0x16,0x22, //window 0x00,0x00, //chksm 0x00,0x00 }; memcpy(replyPack + offset,basePack,40); while(true){ if (pcap_next_ex(openinterface, &header, &pkt_data) != 1) continue; if ( pkt_data[offset + 33] != 0x02) continue; u_short dstport = *(u_short*)&pkt_data[offset + 22]; dstport = (dstport & 0xFF) << 8 | (dstport & 0xFF00) >> 8; if(openports[dstport] != true) continue; //send synack memcpy(replyPack,pkt_data + 6, 6); //copy syn sender mac memcpy(replyPack + 6,pkt_data, 6); //copy our mac memcpy(replyPack + 12,pkt_data + 12, 2); //copy ip memcpy(replyPack + offset + 12, pkt_data + offset + 16,4);//srcip (ours) memcpy(replyPack + offset + 16, pkt_data + offset + 12,4);//dst ip (theirs) memcpy(replyPack + offset + 20, pkt_data + offset + 22,2);//src port (our src) memcpy(replyPack + offset + 22, pkt_data + offset + 20,2);//dst port (our dest) u_int sqacknum = *((u_int*) &pkt_data[offset + 24]); sqacknum = (sqacknum & 0xFF)<<24 | (sqacknum & 0xFF00)<<8 | (sqacknum & 0xFF0000)>>8 | (sqacknum & 0xFF000000)>>24; sqacknum++; sqacknum = (sqacknum & 0xFF)<<24 | (sqacknum & 0xFF00)<<8 | (sqacknum & 0xFF0000)>>8 | (sqacknum & 0xFF000000)>>24; *((u_int*) &replyPack[offset + 28]) = sqacknum; TCPPacket* tcpPack = (TCPPacket*)replyPack; tcpPack->ipHead.headChkSum = 0; tcpPack->ipHead.headChkSum = cksum((u_short*)&(tcpPack->ipHead),sizeof(tcpPack->ipHead)); tcpPack->tcpHead.checksum = 0; tcpPack->tcpHead.checksum = GetTCPChecksum((u_short*)&(tcpPack->tcpHead), (u_short*)&(tcpPack->ipHead.ipsrc),(u_short*)&(tcpPack->ipHead.ipdst), 20); //Sleep(200); pcap_sendpacket(openinterface, replyPack, 54); //printf("replied to %d\n",dstport); //skip what we just sent //pcap_next_ex(openinterface, &header, &pkt_data); } }