user-0 提问: 关于自制嗅探器实现TCP嗅探/c、c++

回复:
user: user-1
content: 仿照tcpdump做了个linux下的小demo,你可以参考一下  #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h>  #include <net/if.h> #include <netinet/in.h> #include <linux/if_ether.h> #include <linux/tcp.h>  #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h>   #include <errno.h>  ////////////////////////////////////////////////////////////////////////////// #define TARGET_INTERFACE "enp2s0"  typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef unsigned long long int uint64_t;  //////////////////////////////////////////////////////////////////////////////  typedef enum _tcpFlag { 	TH_FIN	= 0x01, /* finish, no more data from sender(Last package from sender) */ 	TH_SYN	= 0x02, /* Synchronize sequence numbers */ 	TH_RST	= 0x04, /* Reset the connection */  	TH_PUSH = 0x08, /* Push function, Asks to push the buffered data to the receiving application */  	TH_ACK	= 0x10, /* indicates that the ACKnowledgment field is significant (Sometimes abbreviated by tcpdump as ".") */  	TH_URG	= 0x20, /* ndicates that the URGent pointer field is significant */  	TH_ECE	= 0x40, /* ECN Echo */ 	TH_CWR	= 0x80, /* ECN Cwnd Reduced */ }tcpFlag_t;  /* Structure of an Ethernet header.*/ typedef struct _eth_hdr { 	uint8_t 	dstmac[6];	/* dest mac addr */ 	uint8_t 	srcmac[6];	/* source mac addr */ 	uint16_t	type;		/* Ethernet type */ } eth_hdr;  /* Structure of an internet header, naked of options */ typedef struct _ip_hdr { #ifdef LITTLE_ENDIAN 	uint8_t 	ip_hlen:4;	/* Internet Header Length(means the count of 32bit words) */ 	uint8_t 	ip_ver:4;	/* version */ #else /* LITTLE_ENDIAN */ 	uint8_t 	ip_ver:4;	/* version */ 	uint8_t 	ip_hlen:4;	/* Internet Header Length */ #endif /* LITTLE_ENDIAN */ 	uint8_t 	ip_tos; 	/* type of service */ 	uint16_t	ip_len; 	/* total length */ 	uint16_t	ip_id;		/* identification */ 	uint16_t	ip_off; 	/* fragment offset field */ 	uint8_t 	ip_ttl; 	/* time to live */ 	uint8_t 	ip_p;		/* protocol */ 	uint16_t	ip_sum; 	/* checksum */ 	uint32_t	ip_src; 	/* source address */ 	uint32_t	ip_dst; 	/* dest address */ 	uint8_t 	options[0]; /* ip options */ } ip_hdr;  /* Structure of an TCP header */ typedef struct _tcp_hdr { 	uint16_t	th_sport;	/* source port */ 	uint16_t	th_dport;	/* destination port */ 	uint32_t	th_seq; 	/* sequence number */ 	uint32_t	th_ack; 	/* acknowledgement number */ #ifdef LITTLE_ENDIAN 	uint8_t 	th_rsvd:3;	/* reversed */ 	uint8_t 	th_ns:1;	/* ns flag */ 	uint8_t 	th_oft:4;	/* data offset */ #else  /* LITTLE_ENDIAN */ 	uint8_t 	th_oft:4;	/* data offset */ 	uint8_t 	th_rsvd:3;	/* reversed */ 	uint8_t 	th_ns:1;	/* ns flag */ #endif /* LITTLE_ENDIAN */ 	uint8_t 	th_flags;	/* tcp flag */ 	uint16_t	th_win; 	/* window */ 	uint16_t	th_sum; 	/* checksum */ 	uint16_t	th_urp; 	/* urgent pointer */ 	uint8_t 	options[0]; /* tcp options */ } tcp_hdr;  /* Structure of an TCP session, used for calc relative seq and ack */ typedef struct _tcp_sess_hash { 	struct _tcp_sess_hash* next; 	uint64_t ip; 	uint32_t seq; 	uint32_t ack; 	uint8_t* data; 	uint16_t data_len; } tcp_sess_hash_t;  #define TCP_SESS_HASH_COUNT (1000) static tcp_sess_hash_t tcp_sess_hash_bucket[TCP_SESS_HASH_COUNT];  typedef struct _tcp_show { 	uint8_t direction; 	uint8_t optlen; /* tcp option lenght */ 	uint16_t length; /* real data length */ 	uint32_t seq; /* relative seq */ 	uint32_t ack; /* relative ack */ 	uint32_t abs_seq; /* orgin seq */ 	uint32_t abs_ack; /* orgin ack */ } tcp_show_t;  /* these two macros for print mac address */ #define PNTMAC(mac) \ 	((unsigned char*)&mac)[0], \ 	((unsigned char*)&mac)[1], \ 	((unsigned char*)&mac)[2], \ 	((unsigned char*)&mac)[3], \ 	((unsigned char*)&mac)[4], \ 	((unsigned char*)&mac)[5] #define PNTMAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"  /* these two macros for print ipv4 address */ #define NIPQUAD(addr) \ 	((unsigned char *)&addr)[0], \ 	((unsigned char *)&addr)[1], \ 	((unsigned char *)&addr)[2], \ 	((unsigned char *)&addr)[3] #define NIPQUAD_FMT "%u.%u.%u.%u"  ///////////////////////////////////////////////////////////////////////////// int setPromiscuous(int sock, char* ethx); void procPacket(char* buf, ssize_t len);  ////////////////////////////////////////////////////////////////////////////// int main(void) { 	int sock; 	ssize_t sRet = 0; 	char buf[4096];  	//create a PACKET socket 	sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 	if (sock < 0) { 		perror("socket failed"); 		exit(EXIT_FAILURE); 	}  	//set promiscuous mode,if you are root 	sRet = setPromiscuous(sock, TARGET_INTERFACE); 	if (sRet < 0) { 		close(sock); 		perror("ioctl failed"); 		exit(EXIT_FAILURE); 	}  	//receive packet 	while (1) { 		sRet = recv(sock, buf, sizeof(buf), 0); 		if (sRet < 0) { 			perror("recv failed"); 			break; 		} 		else if(0 == sRet) { 			printf("peer point performed an shutdown\n"); 			break; 		} 		else { 			procPacket(buf, sRet); 		} 	} 	 	close(sock);  	return 0; }   ////////////////////////////////////////////////////////////////////////////// int setPromiscuous(int sock, char* ethx) {	 	uid_t uid = 0; 	struct ifreq ethreq;  	uid = getuid(); 	if (uid != 0) { 		printf("You are not root, can't change %s to Promiscuous Mode\n", ethx); 		return 0; 	}  	strncpy(ethreq.ifr_name, ethx, IFNAMSIZ); 	 	if (ioctl(sock, SIOCGIFFLAGS, ðreq) < 0) { 		return -1; 	} 	 	ethreq.ifr_flags |= IFF_PROMISC; 	if( ioctl(sock, SIOCSIFFLAGS, ðreq) < 0) { 		return -2; 	}  	return 0; }  ////////////////////////////////////////////////////////////////////////////// static char* getTcpFlags(uint8_t flag) { 	static char buf[32];  	memset(buf, 0x00, sizeof(buf)); 	if (flag & TH_FIN)	strcat(buf, "F"); 	if (flag & TH_SYN)	strcat(buf, "S"); 	if (flag & TH_RST)	strcat(buf, "R"); 	if (flag & TH_PUSH)	strcat(buf, "P"); 	if (flag & TH_URG) 	strcat(buf, "U"); 	if (flag & TH_ECE)	strcat(buf, "E"); 	if (flag & TH_CWR)	strcat(buf, "W"); 	if (flag & TH_ACK)	strcat(buf, "."); 	 	return buf; }   static char* getTcpOptions(uint8_t* option, tcp_show_t* show) {  	uint8_t i = 0; 	uint8_t loop = 0; 	int loop_flag = 1; 	uint8_t count = 0; 	uint32_t s,e; 	char tmp[32]; 	static char buf[128];  	if (show->optlen == 0) { 		return ","; 	}  	memset(buf, 0x00, sizeof(buf)); 	strcpy(buf, ", options ["); 	while (loop_flag) {  		if (loop > show->optlen) { 			goto FINISH; 		}  		switch (option[loop]) { 		case 0: /* EOL : End of Option List */ 			loop_flag = 0; 			break; 		 		case 1: /* NOP : No-Operation */ 			strcat(buf, "nop,"); 			loop++; 			break; 			 		case 2: /* MSS : Maximum Segment Size */ 			sprintf(tmp, "mss %u,", ntohs(*(uint16_t*)(option + loop + 2))); 			strcat(buf, tmp); 			loop += option[loop + 1]; 			break; 			 		case 3: 			sprintf(tmp, "wscale %u,", (*(uint8_t*)(option + loop + 2))); 			strcat(buf, tmp); 			loop += option[loop + 1]; 			break; 			 		case 4: 			strcat(buf, "sackOK,"); 			loop += option[loop + 1]; 			break; 			 		case 5: 			count = (option[loop + 1] - 2) / 8; 			sprintf(tmp, "sack %d ", count); 			strcat(buf, tmp); 			for (i = 0; i < count; i++) { 				s = ntohl(*(uint32_t*)(option + loop + 2 + i * 8)); 				e = ntohl(*(uint32_t*)(option + loop + 6 + i * 8)); 	 				if (show->direction) { 					sprintf(tmp, "{%u,%u}", s - show->abs_seq, e - show->abs_seq); 				} else { 					sprintf(tmp, "{%u,%u}", s - show->abs_ack, e - show->abs_ack); 				} 				strcat(buf, tmp); 			} 			strcat(buf, ","); 			loop += option[loop + 1]; 			break; 			 		case 8: 			strcat(buf, "TSOPT,"); 			loop += option[loop + 1]; 			break;  		default: 			loop += option[loop + 1]; 			break; 		} 	}  FINISH: 	strcpy(buf + strlen(buf) - 1, "],"); 	return buf; }   int procSession(ip_hdr* ip, tcp_hdr* tcp, tcp_show_t* show) { 	tcp_sess_hash_t* sess = NULL; 	uint64_t ip_combine = 0; 	uint32_t hash = 0; 	 	static char buf[128] = {0};  	show->seq = ntohl(tcp->th_seq); 	show->ack = ntohl(tcp->th_ack); 	 	if (tcp->th_sport > tcp->th_dport) { 		show->direction = 1; 		hash = ((uint32_t)tcp->th_dport << 16 + tcp->th_sport) % TCP_SESS_HASH_COUNT; 		ip_combine = (uint64_t)ip->ip_dst << 32 + ip->ip_src; 	} 	else { 		show->direction = 0; 		hash = ((uint32_t)tcp->th_sport << 16 + tcp->th_dport) % TCP_SESS_HASH_COUNT; 		ip_combine = (uint64_t)ip->ip_src << 32 + ip->ip_dst; 	}  	for (sess = &tcp_sess_hash_bucket[hash]; sess->next; sess = sess->next) { 		if (sess->ip == ip_combine) { 			break; 		} 	}  	if (!sess->next || (tcp->th_flags & TH_SYN)) { 		if (!sess->next) { 			sess->next = (tcp_sess_hash_t*)calloc(1, sizeof(tcp_sess_hash_t)); 			if (!sess->next) { 				printf("<ERROR> calloc failed\n"); 				return -1; 			} 		}  		sess->ip = ip_combine; 		if (show->direction) { 			sess->seq = show->ack - 1; 			sess->ack = show->seq; 		} else { 			sess->seq = show->seq; 			sess->ack = show->ack - 1; 		} 	} else { 		if (show->direction) { 			show->seq -= sess->ack; 			show->ack -= sess->seq; 		} else { 			show->seq -= sess->seq; 			show->ack -= sess->ack; 		} 	}  	show->length = ntohs(ip->ip_len)- (ip->ip_hlen + tcp->th_oft) * 4; 	show->optlen = (tcp->th_oft - 5) * 4; 	show->abs_ack = sess->ack; 	show->abs_seq = sess->seq;  	sess->data_len += show->length;  	return 0; }  void procPacket(char* buf, ssize_t len) { 	eth_hdr* eth = (eth_hdr*)buf; 	ip_hdr* ip = (ip_hdr*)(buf + sizeof(eth_hdr)); 	tcp_hdr* tcp = (tcp_hdr*)((void*)ip + sizeof(ip_hdr)); 	tcp_show_t show;   	/* just process the IPv4 TCP packet */ 	if ((ip->ip_p != IPPROTO_TCP) || (ip->ip_ver != 4)){ 		return; 	} 	procSession(ip, tcp, &show); 	printf("[TCP] "NIPQUAD_FMT".%d > "NIPQUAD_FMT".%d: Flags [%s], seq %u, ack %u, win:%u%s length %u\n", \ 		NIPQUAD(ip->ip_src), ntohs(tcp->th_sport), \ 		NIPQUAD(ip->ip_dst), ntohs(tcp->th_dport), \ 		getTcpFlags(tcp->th_flags),  \ 		show.seq, show.ack, ntohs(tcp->th_win), \ 		getTcpOptions(tcp->options, &show), \ 		show.length); }

user: user-2
content: 仅供参考：//循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef _MSC_VER     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef _MSC_VER     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef _MSC_VER void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX; CRITICAL_SECTION cs_BBB; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             Log("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef _MSC_VER     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef _MSC_VER     pthread_exit(NULL); #endif } int main() { #ifdef _MSC_VER     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX);     InitializeCriticalSection(&cs_BBB); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef _MSC_VER     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef _MSC_VER     DeleteCriticalSection(&cs_BBB);     DeleteCriticalSection(&cs_HEX);     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }

user: user-3
content: 没事贴代码~

user: user-0
content: 求助啊，求助啊