📄 qqmonitor.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*)ð->h_proto)[0],((unsigned char*)ð->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 + -