⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qqmonitor.c

📁 QQ嗅探源码
💻 C
字号:
/* * OICQ Simple sniffer programme for UNIX. * Author <missanda@hotmail.com>  QQ 8907673 * **/#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <string.h>#include <signal.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdarg.h>#include <errno.h>#include <fcntl.h>#include <net/if.h>#include <arpa/inet.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/udp.h>#include <netinet/tcp.h>#include <netinet/if_ether.h>#include <linux/sockios.h>void usage(void);void usage(void){	fprintf(stderr,"qqmonitor usage:\n");	fprintf(stderr,"qqmonitor <NetworkInterfaceDevice>\n");	fprintf(stderr,"example:\n");	fprintf(stderr,"1. qqmonitor eth0\n");	return;}static int sniffer_fd = 0;void sniffer_exit(int signo);void sniffer_exit(int signo){	printf("sniffer signal %d recvied exiting ...\n",signo);	close(sniffer_fd);	exit(0);}#define BUFFER_SIZE	65536	/*64K*/static unsigned char buff[BUFFER_SIZE];#define HWADDR(addr) \    ((unsigned char *)&addr)[0], \    ((unsigned char *)&addr)[1], \    ((unsigned char *)&addr)[2], \    ((unsigned char *)&addr)[3], \    ((unsigned char *)&addr)[4], \    ((unsigned char *)&addr)[5]#define NIPQUAD(addr) \    ((unsigned char *)&addr)[0], \    ((unsigned char *)&addr)[1], \    ((unsigned char *)&addr)[2], \    ((unsigned char *)&addr)[3]void parse_packet(unsigned char*buff,int len);void parse_packet_arp(unsigned char*buff,int len);void parse_packet_ip(unsigned char*buff,int len);void parse_qq_login(unsigned char*buff,int len,int direction);void parse_qq_login_token(unsigned char*buff,int len,int direction);void parse_qq_unknown(unsigned char *buff,int len,int direction);void parse_qq_login_token(unsigned char*buff,int len,int direction){	unsigned char*p = NULL;	int i = 0;	uint32_t tmp32 = 0;	if(!buff||len==0){		return;	}	p = buff;	printf("qq login token data %d bytes:\n",len);	for(i=0;i<len;i++){		printf("%02X ",p[i]);		if(i&&((i%8)==0))			printf("\n");	}	printf("\n");	if(direction == 1){		printf("reply data:\n");		printf("request token %s\n",p[0]==0?"succeed":"failed");		if(p[0] == 0x00){			printf("token length %d bytes\n",p[1]);			printf("login token : ");			for(i=0;i<p[1];i++){				printf("%02X ",p[i+1]);			}		}	}	else	{		printf("request data:\n");		tmp32 = ntohl(*((uint32_t*)&p[0]));		printf("request QQ %d\n",tmp32);	}	return ;}void parse_packet_ip(unsigned char*buff,int len){	struct iphdr *ip = (struct iphdr *)buff;	struct in_addr in;	unsigned char *p = NULL;	int data_len = 0;	uint16_t cmd = 0;	uint16_t seq = 0;	uint16_t ver = 0;	uint32_t id = 0;	int port = 0;	int direction = 0; /*1 = server -> client  0 = client -> server*/	int i = 0;#if 0	printf("ip protocol\n");	printf("version : %d\n",ip->version);	printf("header length : %d bytes\n",ip->ihl*4);	printf("tos : 0x%02X\n",ip->tos);	printf("total length : %d\n",ntohs(ip->tot_len));	printf("identification : %d\n",ntohs(ip->id));	printf("flags: %02X %02X\n",((unsigned char*)&ip->frag_off)[0],((unsigned char*)&ip->frag_off)[1]);	printf("ttl :  %d\n",ip->ttl);	printf("protocol : %d\n",ip->protocol);	printf("checksum : 0x%02X%02X\n",((unsigned char*)&ip->check)[0],((unsigned char*)&ip->check)[1]);#endif	//printf("ip->protocol = %d\n",ip->protocol);	switch(ip->protocol){		case IPPROTO_TCP:			/*TCP data*/			p = buff + sizeof(struct iphdr) + sizeof(struct tcphdr);			data_len = len - sizeof(struct iphdr) - sizeof(struct tcphdr);			port = ((struct tcphdr*)(buff+sizeof(struct iphdr)))->source;			port = ntohs(port);		case IPPROTO_UDP:			/*UDP data.*/			p = buff + sizeof(struct iphdr) + sizeof(struct udphdr);			data_len = len - sizeof(struct iphdr) - sizeof(struct udphdr);			port = ((struct udphdr*)(buff+sizeof(struct iphdr)))->source;			port = ntohs(port);			break;		default:			//printf("unknow protocol.\n");			return;			break;	}//	printf("data_len = %d p[0] = %02x  p[%d] = %02x\n",data_len,p[0],data_len-1,p[data_len-1]);		if(p[0]!=0x02 || p[data_len-1]!=0x03){		//not oicq data.		return;	}	printf("oicq data %s :\n",(ip->protocol==IPPROTO_TCP)?"tcp":"udp");	printf("*source      ip address : %d.%d.%d.%d:%d\n",NIPQUAD(ip->saddr),port);	printf("*destination ip address : %d.%d.%d.%d:%d\n",NIPQUAD(ip->daddr));		// oicq 7 bytes header.	ver = ntohs(*((uint16_t*)&p[1]));	cmd = ntohs(*((uint16_t*)&p[3]));	seq = ntohs(*((uint16_t*)&p[5]));		printf("oicq version  : 0x%04x\n",ver);	printf("oicq command  : 0x%04x\n",cmd);	printf("oicq sequence : 0x%04x\n",seq);	printf("data length   : %d\n",data_len);	if(ver == 0x0100 || ver == 0x0000){		direction = 1; /*server to client*/	}	else	{		direction = 0; /*client to server*/	}	p = &p[7];	switch(cmd){		//pre-login command -- high verion		case 0x0062:			printf("* login token %d bytes\n",data_len);			parse_qq_login_token(p,data_len,direction);			break;		//logout command		case 0x0001:			printf("* logout\n");			id = ntohl(*((uint32_t*)&p[0]));			printf("  %d logouted \n",id);			printf("  server address %d.%d.%d.%d\n",NIPQUAD(ip->daddr));			printf("  client address %d.%d.%d.%d:%d\n\n",NIPQUAD(ip->saddr),port);			break;		//login command		case 0x0022:			printf("* login\n");			parse_qq_login(p,data_len,direction);			break;		case 0x0002:			printf("* keep alive\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0004:			printf("* modify information\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0005:			printf("* search onlines\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0006:			printf("* get user information\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0009:			printf("* add friend\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x000A:			printf("* delete friend\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x000B:			printf("* add friend authorize\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x000D:			printf("* change status\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0012:			printf("* ACK : system message\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0016:			printf("* IM send\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0017:			printf("* IM recv\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x001C:			printf("* delete me.\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x001D:			printf("* request key.\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0021:			printf("* ????1\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0026:			printf("* get friends list\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0027:			printf("* get online friends list\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0029:			printf("* ????2\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0030:			printf("* group command\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0031:			printf("* test.\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x003C:			printf("* group name command.\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x003D:			printf("* group members upload command.\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x003E:			printf("* friends remark command.\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0058:			printf("* group members upload command.\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x005C:			printf("* get level\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0080:			printf("* system message\n");			parse_qq_unknown(p,data_len,direction);			break;		case 0x0081:			printf("* friend change status\n");			parse_qq_unknown(p,data_len,direction);			break;		default:			printf("qq cmd = 0x%04x %d bytes\n",cmd,data_len);			parse_qq_unknown(p,data_len,direction);			break;	}	return ;}void parse_qq_unknown(unsigned char *buff,int len,int direction){	int i = 0;	if(!buff||len == 0)		return;		printf("dump data direction = %s:\n",direction?"s -> c":"c -> s");	for(i=0;i<len;i++){		printf("%02X ",buff[i]);		if(i&&(i%16 == 0))			printf("\n");	}	printf("\n");	return ;}void parse_qq_login(unsigned char*buff,int len,int direction){	uint32_t id = 0;	unsigned char tea_key[16];	unsigned char*p = NULL;	unsigned char x[1];	unsigned char data[65535];	int len2 = 0;	int e = -1;	bzero(data,sizeof(data));	if(len%4){		return;	}	p = buff;	if(direction == 0){		//client to server		printf("  login request data.\n");		// 4 bytes qq id		id = ntohl(*((uint32_t*)&p[0]));		printf("  id = \"%d\"\n",id);		// 16 bytes TEA key		bcopy(&p[4],tea_key,16);		x[0] = p[20];		printf("  TEA key %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",tea_key[0],tea_key[1],tea_key[2],tea_key[3],tea_key[4],tea_key[5],tea_key[6],tea_key[7],tea_key[8],tea_key[9],tea_key[10],tea_key[11],tea_key[12],tea_key[13],tea_key[14],tea_key[15]);		len2 =  len - 4 - 16;	}	else	{		printf("  login respond data.\n");	}	return ;}void parse_packet_arp(unsigned char*buff,int len){	struct ether_arp *arp = (struct ether_arp *)buff;#if 0	printf("arp packet - time = %u\n",time(0));	printf("hardware type :  %d\n", ntohs(arp->arp_hrd));	printf("protocol type : %02X-%02X\n", ((unsigned char*)&arp->arp_pro)[0],((unsigned char*)&arp->arp_pro)[1]);	printf("hardware address length : %d\n", arp->arp_hln);	printf("protocol address length : %d\n", arp->arp_pln);	printf("operation code : %d\n", ntohs(arp->arp_op));	printf("request hardware address : %02X:%02X:%02X:%02X:%02X:%02X\n",HWADDR(arp->arp_sha));	printf("request ip       address : %d.%d.%d.%d", NIPQUAD(arp->arp_spa));	printf("target  hardware address : %02X:%02X:%02X:%02X:%02X:%02X\n",HWADDR(arp->arp_tha));	printf("target  ip       address : %d.%d.%d.%d\n",NIPQUAD(arp->arp_tpa));#endif	return;}void parse_packet(unsigned char*buff,int len){	struct ethhdr *eth = (struct ethhdr *)buff;#if 0	/*DEBUG only*/	printf("MAC header\n");   	printf("destination : %02X:%02X:%02X:%02X:%02X:%02X\n",HWADDR(eth->h_dest));    	printf("source      : %02X:%02X:%02X:%02X:%02X:%02X\n",HWADDR(eth->h_source)); 	printf("protocol    : %02X-%02X\n",((unsigned char*)&eth->h_proto)[0],((unsigned char*)&eth->h_proto)[1]);#endif	switch(ntohs(eth->h_proto)){		case ETH_P_IP:			/*QQ data in it.*/			//printf("ip protocol.\n");			parse_packet_ip(&buff[sizeof(struct ethhdr)],len - sizeof(struct ethhdr));			break;		case ETH_P_ARP:			/*ARP request.*/			//printf("arp protocol.\n");			parse_packet_arp(&buff[sizeof(struct ethhdr)],len - sizeof(struct ethhdr));			break;		default:			//printf("unknow protocol.\n");			return;	}	return;}int main(int argc,char**argv){		char ch = 0;	int e = -1;	int len = 0;	char ifdev[256];	struct ifreq ifr;	if(argc!=2){		usage();		exit(-1);	}	if(getuid()!=0){		fprintf(stderr,"only root can open SOCK_PACKET - frame type 0x800\n");		exit(-1);	}	signal(SIGINT,sniffer_exit);	signal(SIGTERM,sniffer_exit);	signal(SIGCHLD,SIG_IGN);		bzero(ifdev,sizeof(ifdev));	bcopy(argv[1],ifdev,strlen(argv[1]));		//only monitor local ethernet work	//sniffer_fd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));	/*set NIC to promisc mode.*/	sniffer_fd = socket(AF_INET, SOCK_PACKET, htons(0x800));	if(sniffer_fd<0){		fprintf(stderr,"failed to create socket - PF_PACKET %0x\n",0x800);		return -EFAULT;	}	bzero(&ifr,sizeof(ifr));	sprintf(ifr.ifr_name,ifdev);#if 1	e = ioctl(sniffer_fd, SIOCGIFFLAGS, &ifr);	if(e){		fprintf(stderr,"failed to ioctl - SIOCGIFFLAGS - \"%s\"\n",ifdev);		close(sniffer_fd);		return -EFAULT;	}	ifr.ifr_flags |= IFF_PROMISC;	e = ioctl(sniffer_fd, SIOCSIFFLAGS, &ifr);	if(e){		fprintf(stderr,"failed to ioctl - SIOCGIFFLAGS - \"%s\" - IFF_PROMISC\n",ifdev);		close(sniffer_fd);		return -EFAULT;	}#endif	printf("oicq packet sniffer is starting ...\n");	while(1){		bzero(buff,BUFFER_SIZE);		//len = recv(sniffer_fd,buff,BUFFER_SIZE,0); 		len = read(sniffer_fd,buff,BUFFER_SIZE); 		if(len<=0){			continue;		}		//printf("==>> %d bytes recevied.\n",len);				parse_packet(buff,len);	}		/*maybe never run to here. but make gcc happy.*/	close(sniffer_fd);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -