📄 bnpcap.c
字号:
l = (len-(datap-data)); eventlog(eventlog_level_debug,__FUNCTION__,"filling up header (adding %d to %d to get %d)",l,off,packet_get_header_size(p)); memcpy(packet_get_raw_data(p,off),datap,l); datap = datap + l; off = off + l; } else { unsigned int l = (packet_get_size(p)-off); if ((len-(datap-data)) < l) l = (len-(datap-data)); eventlog(eventlog_level_debug,__FUNCTION__,"filling up packet (0x%04x:%s) (adding %d to %d to get %d)",packet_get_type(p),packet_get_type_str(p,bnpcap_conn_get_dir(c,&s,&d)),l,off,packet_get_size(p)); memcpy(packet_get_raw_data(p,off),datap,l); datap = datap + l; off = off + l; } if ((off>=packet_get_header_size(p))&&(off>=packet_get_size(p))) { /* packet is complete */ eventlog(eventlog_level_debug,__FUNCTION__,"packet is complete"); bp = (t_bnpcap_packet *) malloc(sizeof(t_bnpcap_packet)); /* avoid warning */ if (!bp) { eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno)); return -1; } if ((off != packet_get_size(p))&&(bnpcap_dodebug)) { eventlog(eventlog_level_warn,__FUNCTION__,"packet size differs (%d != %d) (offset=0x%04x)",off,packet_get_size(p),datap-data); hexdump(stderr,data,len);/* memcpy(packet_get_raw_data(p,0),data,packet_get_size(p)); */ } bp->dir = bnpcap_conn_get_dir(c,&s,&d); bp->p = p; bp->id = current_packet_id++; memcpy(&bp->tv,&packettime,sizeof(struct timeval)); bnpcap_conn_add_packet(c,bp); if (packet_get_size(p)==0) datap = data + len; /* if size is invalid, drop the rest of the stream packet */ p = NULL; off = 0; } } /* while */ /* write back saved state */ if ((off>0)&&(bnpcap_dodebug)) { eventlog(eventlog_level_debug,__FUNCTION__,"saving %d bytes in packet buffer (p=0x%08lx)",off,(long)p); } if (bnpcap_conn_get_dir(c,&s,&d)==packet_dir_from_client) { c->clientpkt = p; c->clientoff = off; } else { c->serverpkt = p; c->serveroff = off; } } /* !always_complete */ return 0; } return 0;}/************************************************************************//******************************** LAYERS ********************************//********************************* TCP **********************************/static int bnpcap_tcp2tcp(t_tcp_header * d, t_tcp_header_raw const * s){ d->sport = htons(s->sport); d->dport = htons(s->dport); d->seqno = htonl(s->seqno); d->ackno = htonl(s->ackno); d->doffset = (htons(s->stuff) & 0xF000) >> 12; d->flags = (htons(s->stuff) & 0x0FFF); d->window = htons(s->window); d->checksum = htons(s->checksum); d->urgp = htons(s->urgp); return 0;}static int bnpcap_process_tcp(t_ip_header const * ip, unsigned char const *data, unsigned int len){ t_tcp_header_raw const *raw; t_tcp_header h; raw = (t_tcp_header_raw const *) data; /* avoid warning */ bnpcap_tcp2tcp(&h,raw); if (h.doffset < 5) { eventlog(eventlog_level_warn,__FUNCTION__,"tcp header too small (%u 32-bit words)",h.doffset); return 1; } else { char fstr[32] = ""; if (h.flags & TCP_URG) strcat(fstr,"U"); if (h.flags & TCP_ACK) strcat(fstr,"A"); if (h.flags & TCP_PSH) strcat(fstr,"P"); if (h.flags & TCP_RST) strcat(fstr,"R"); if (h.flags & TCP_SYN) strcat(fstr,"S"); if (h.flags & TCP_FIN) strcat(fstr,"F"); eventlog(eventlog_level_debug,__FUNCTION__,"tcp: sport=%u dport=%u seqno=0x%08x ackno=0x%08x window=0x%08x len=%d (%s)",h.sport,h.dport,h.seqno,h.ackno,h.window,((signed)len-(h.doffset*4)),fstr); if (((signed)len-(h.doffset*4))<=0) { eventlog(eventlog_level_info,__FUNCTION__,"empty packet (%d)",((signed)len-(h.doffset*4))); /* handle sync packets */ if (h.flags & TCP_SYN) { t_bnpcap_addr s,d; s.ip=ip->src; s.port=h.sport; d.ip=ip->dst; d.port=h.dport; if (h.flags & TCP_ACK) { t_bnpcap_conn *c = bnpcap_conn_find(&s,&d); if (c) { if (c->tcpstate==tcp_state_syn) c->tcpstate=tcp_state_ack; } } else { if (!bnpcap_conn_find(&s,&d)) { t_bnpcap_conn *c; c = bnpcap_conn_new(&s,&d); c->tcpstate = tcp_state_syn; list_append_data(conns,c); eventlog(eventlog_level_debug,__FUNCTION__,"created new connection with SYN"); } else { eventlog(eventlog_level_debug,__FUNCTION__,"got SYN in connection"); } } } } else if (((h.sport!=listen_port)&&(h.dport!=listen_port)) && ((h.sport!=6200)&&(h.dport!=6200))) { eventlog(eventlog_level_info,__FUNCTION__,"other packet (%d)",((signed)len-(h.doffset*4))); } else { eventlog(eventlog_level_info,__FUNCTION__,"valid packet (%d)",((signed)len-(h.doffset*4))); bnpcap_conn_packet(ip->src,h.sport,ip->dst,h.dport,data+(h.doffset*4),len-(h.doffset*4)); } return 0; }}/************************************ UDP ********************************/static int bnpcap_udp2udp(t_ip_udp_header *d, t_ip_udp_header_raw const *s){ d->sport = ntohs(s->sport); d->dport = ntohs(s->dport); d->len = ntohs(s->len); d->checksum = ntohs(s->checksum); return 0;}static int bnpcap_process_udp(unsigned char const *data, unsigned int len){ t_ip_udp_header_raw const *raw; t_ip_udp_header h; t_bnpcap_packet *bp; raw = (t_ip_udp_header_raw const *) data; /* avoid warning */ bnpcap_udp2udp(&h,raw); bp = (t_bnpcap_packet *) malloc(sizeof(t_bnpcap_packet)); /* avoid warning */ if (!bp) { eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno)); return -1; } if (h.dport==listen_port || h.dport==6200) { bp->dir = packet_dir_from_client; } else { bp->dir = packet_dir_from_server; } eventlog(eventlog_level_debug,__FUNCTION__,"sport=%u dport=%u len=%u(%d)",h.sport,h.dport,h.len,len); bp->id = current_packet_id++; memcpy(&bp->tv,&packettime,sizeof(struct timeval)); bp->p = packet_create(packet_class_udp); if (!bp->p) { eventlog(eventlog_level_error,__FUNCTION__,"packet_create failed"); return -1; } packet_set_size(bp->p,h.len-sizeof(t_ip_udp_header_raw)); memcpy(packet_get_raw_data(bp->p,0),data+sizeof(t_ip_udp_header_raw),h.len-sizeof(t_ip_udp_header_raw)); eventlog(eventlog_level_error,__FUNCTION__,"id=%u ",bp->id); list_append_data(udppackets,bp); return 0;}/************************************ IP *********************************/static int bnpcap_ip2ip(t_ip_header * d, t_ip_header_raw const * s){ d->version = ((s->versionihl & 0xf0) >> 4); d->ihl = s->versionihl & 0x0f; d->tos = s->tos; d->len = ntohs(s->len); d->id = ntohs(s->id); d->offset = ntohl(s->flagsoffset); d->flags = ((d->offset & 0xE000)>>13); d->offset = ((d->offset & 0x1FFF)); d->ttl = s->ttl; d->protocol = s->protocol; d->checksum = ntohs(s->checksum); d->src = ntohl(s->src); d->dst = ntohl(s->dst); return 0;}static int bnpcap_process_ip(unsigned char const *data, unsigned int len){ /* FIXME: handle IP fragmentation */ /* FIXME: use identification field to pass the datagram in the right order */ t_ip_header_raw const *raw; t_ip_header h; raw = (t_ip_header_raw const *) data; /* avoid warning */ bnpcap_ip2ip(&h,raw); if (h.version != 4) { eventlog(eventlog_level_warn,__FUNCTION__,"ip version %u not supported (ihl=%u, raw=0x%02x)",h.version,h.ihl,raw->versionihl); return 1; } else if (h.ihl < 5) { /* an IP header must be at least 5 words */ eventlog(eventlog_level_warn,__FUNCTION__,"ip header to small (%u 32-bit words)",h.ihl); return 1; } else if (h.len > len) { eventlog(eventlog_level_warn,__FUNCTION__,"ip len larger than packet (%d > %d)",h.len,len); return 1; } else { char fstr[32] = ""; if (h.flags & IP_DF) strcat(fstr,"D"); if (h.flags & IP_MF) strcat(fstr,"M"); eventlog(eventlog_level_debug,__FUNCTION__,"ip: len=%u(%u) src=%08x dst=%08x protocol=%u offset=0x%08x id=0x%08x (%s)",h.len,len,h.src,h.dst,h.protocol,h.offset,h.id,fstr); if (h.protocol==6) { /* This is TCP */ return bnpcap_process_tcp(&h,data+(h.ihl*4),h.len-(h.ihl*4)); } else if (h.protocol==17) { /* This is UDP */ return bnpcap_process_udp(data+(h.ihl*4),h.len-(h.ihl*4)); } } return 0;}/************************************* ETHERNET ******************************/static int bnpcap_process_ether(unsigned char const *data, unsigned int len){ /* Well, first parse the ethernet header (I hope you use Ethernet_II :) ... */ t_ether_raw const *raw; raw = (t_ether_raw const *) data; /* avoid warning */ if (ntohs(raw->type)==0x0800) { /* This is IP */ return bnpcap_process_ip(data+sizeof(t_ether_raw),len-sizeof(t_ether_raw)); } else { eventlog(eventlog_level_warn,__FUNCTION__,"unsupported protocol 0x%04x",ntohs(raw->type)); return 1; }}/* If you want to use other hardware protocols like PPP add them here ... *//**************************** PACKET/PCAP *********************************/static void bnpcap_process_packet(u_char * private, const struct pcap_pkthdr * p, u_char const * data){ unsigned int pl = p->len; if(private) private = NULL; // hack to eliminate compiler warning memcpy(&packettime,&p->ts,sizeof(struct timeval)); eventlog(eventlog_level_debug,__FUNCTION__,"packet: len=%d caplen=%d",p->len,p->caplen); /* FIXME: check if it's ethernet */ bnpcap_process_ether(data,pl);}/**************************************************************************/static void bnpcap_usage(void) { printf("BNPCAP - A tool to convert pcap battle.net dumps to a human-readable format.\n"); printf("Version " PVPGN_VERSION " --- Copyright (c) 2001 Marco Ziech (mmz@gmx.net)\n"); printf("This software makes use of libpcap.\n\n"); printf("Usage: bnpcap [-d] [-v] [-p PORT] <pcap-filename>\n"); printf(" -d Print out debugging information\n"); printf(" -v Be more verbose\n"); printf(" -p PORT Specify port to process (Default: 6112)\n\n");}/******************************* MAIN *************************************/int main (int argc, char **argv) { t_elem * currconn; t_elem * currudp; int c; while ((c=getopt(argc,argv,"dvp:"))!=-1) { switch (c) { case 'p': str_to_uint(optarg, &listen_port); break; case 'd': bnpcap_dodebug = 1; break; case 'v': bnpcap_beverbose = 1; break; case '?': printf("unrecognized option '%c'\n",optopt); break; default: printf("getopt returned \'%c\'\n",c); } } if (optind < argc) { filename = argv[optind]; } else { bnpcap_usage(); return 1; } pc = pcap_open_offline(filename,ebuf); if (!pc) { fprintf(stderr,"pcap_open_offline: %s\n",ebuf); return -1; } eventlog_set(stderr); eventlog_clear_level(); if (bnpcap_dodebug) eventlog_add_level("debug"); if (bnpcap_beverbose||bnpcap_dodebug) eventlog_add_level("info"); eventlog_add_level("warn"); eventlog_add_level("error"); eventlog_add_level("fatal"); conns = list_create(); udppackets = list_create(); pcap_dispatch(pc,0,bnpcap_process_packet,NULL); printf("### This packet dump was created by bnpcap.\n"); LIST_TRAVERSE(conns,currconn) { t_bnpcap_conn *c; char cstr[64]; char sstr[64]; t_elem * currpacket; c = elem_get_data(currconn); snprintf(cstr,64,"%u.%u.%u.%u:%u",((c->client.ip & 0xFF000000)>>24),((c->client.ip & 0x00FF0000)>>16),((c->client.ip & 0x0000FF00)>>8),((c->client.ip & 0x000000FF)),c->client.port); snprintf(sstr,64,"%u.%u.%u.%u:%u",((c->server.ip & 0xFF000000)>>24),((c->server.ip & 0x00FF0000)>>16),((c->server.ip & 0x0000FF00)>>8),((c->server.ip & 0x000000FF)),c->server.port); printf("## %s connection: client=%s server=%s\n",(c->incomplete?"incomplete":"complete"),cstr,sstr); LIST_TRAVERSE(c->packets,currpacket) { t_bnpcap_packet * bp; bp = elem_get_data(currpacket); printf("# %u packet from %s: type=0x%04x(%s) length=%d class=%s\n",bp->id/*bp->tv.tv_sec*/,(bp->dir==packet_dir_from_client?"client":"server"),packet_get_type(bp->p),packet_get_type_str(bp->p,bp->dir),packet_get_size(bp->p),packet_get_class_str(bp->p)); hexdump(stdout,packet_get_raw_data(bp->p,0),packet_get_size(bp->p)); printf("\n"); } } printf("## udp packets\n"); LIST_TRAVERSE(udppackets,currudp) { t_bnpcap_packet *bp; bp = elem_get_data(currudp); printf("# %u packet from %s: type=0x%04x(%s) length=%d class=%s\n",bp->id/*bp->tv.tv_sec*/,(bp->dir==packet_dir_from_client?"client":"server"),packet_get_type(bp->p),packet_get_type_str(bp->p,bp->dir),packet_get_size(bp->p),packet_get_class_str(bp->p)); hexdump(stdout,packet_get_raw_data(bp->p,0),packet_get_size(bp->p)); printf("\n"); } pcap_close(pc); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -