/* * IP Toolkit * * Simple utility for crafting IP traffic of your choosing. * * Requires: * libnet >= 1.1.x (http://www.packetfactory.net/projects/libnet/) * root * a basic understanding what this tool does * * Compile with something like: * gcc -Wall `libnet-config --defines --cflags` -o ip-tk ip-tk.c `libnet-config --libs` * * This code can be found in its original form here: * * http://spoofed.org/files/ip-tk.c * * * Jon Hart * * Copyright (c) 2003, Jon Hart * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the organization nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #if (SOLARIS || BSD) #include #else #include #endif #include /* for getprotoby*()*/ #define OPT_HELP 0 #define OPT_VERBOSE 1 #define OPT_INTERFACE 2 #define OPT_SRCIP 3 #define OPT_DSTIP 4 #define OPT_SRCETHER 5 #define OPT_DSTETHER 6 #define OPT_PAYLOAD 7 #define OPT_IPID 8 #define OPT_IPTOS 9 #define OPT_IPTTL 10 #define OPT_IPPROTO 11 struct opt { char *name; /* name of this option */ int req; /* required? */ int set; /* Does it have a value? */ }; struct opt opts[] = { {"help", 0, 0}, {"verbose", 0, 0}, {"interface", 1, 0}, {"source IP", 1, 0}, {"destination IP", 1, 0}, {"source ethernet address", 0, 0}, {"destination ethernet address", 0, 0}, {"payload", 1, 0}, {"IP ID number", 1, 0}, {"TOS", 1, 0}, {"TTL", 1, 0}, {"IP Protocol number", 1, 0} }; void usage() { fprintf(stderr, "\tip-tk\n\n\tA simple IP Toolkit\n\tby Jon Hart \n"); fprintf(stderr, "\thttp://spoofed.org/files/ip-tk.c\n\n"); fprintf(stderr, "Usage:\n"); fprintf(stderr, "\tRequired:\n"); fprintf(stderr, "\t-i Specify interface\n"); fprintf(stderr, "\t-d Destination IP\n"); fprintf(stderr, "\n\tOptional:\n\n"); fprintf(stderr, "\tLink Layer:\n"); fprintf(stderr, "\t-e Source ethernet address (default: auto)\n"); fprintf(stderr, "\t-E Destination ethernet address (default: auto)\n"); fprintf(stderr, "\tIP Layer:\n"); fprintf(stderr, "\t-I IP ID number (default: sane)\n"); fprintf(stderr, "\t-p IP Protocol number (default: random)\n"); fprintf(stderr, "\t-s Source IP (default: auto)\n"); fprintf(stderr, "\t-t IP TTL (default: 255)\n"); fprintf(stderr, "\tProtocol Layer:\n"); fprintf(stderr, "\t-c Packet payload (default: NULL)\n"); fprintf(stderr, "\tOther:\n"); fprintf(stderr, "\t-h Help (this message)\n"); fprintf(stderr, "\t-v Be verbose\n"); } void mem_free(void **ptr) { if (*ptr) free(*ptr); *ptr = NULL; } int main(int argc, char *argv[]) { int c, i; libnet_t *libnet; libnet_ptag_t ipv4, ether; struct protoent *protoent; u_long src_ip, dst_ip; u_char ip_ttl, ip_tos, ip_proto; u_short ip_id; /* The source and destination MAC addresses * for the ethernet level */ struct libnet_ether_addr *src_ether; struct libnet_ether_addr *dst_ether; char *interface; struct ether_addr *ether_t; u_char *payload; u_long payload_l; char errbuf[LIBNET_ERRBUF_SIZE]; while ((c = getopt(argc, argv, "i:c:e:s:E:d:p:i:u:I:t:vh")) != EOF) { switch (c) { case 'h': usage(); exit(EXIT_SUCCESS); case 'v': opts[OPT_VERBOSE].set = 1; break; case 'i': interface = optarg; opts[OPT_INTERFACE].set = 1; break; case 'e': if ((ether_t = ether_aton(optarg)) == NULL) { printf("Invalid source ethernet address: %s\n", optarg); return(EXIT_FAILURE); } if ((src_ether = malloc(sizeof(struct libnet_ether_addr))) == NULL) { printf("Couldn't malloc() for src_ether\n"); return(EXIT_FAILURE); } memcpy(src_ether->ether_addr_octet, ether_t, sizeof(struct ether_addr)); opts[OPT_SRCETHER].set = 1; break; case 'E': if ((ether_t = ether_aton(optarg)) == NULL) { printf("Invalid ethernet address: %s\n", optarg); return(EXIT_FAILURE); } if ((dst_ether = malloc(sizeof(struct libnet_ether_addr))) == NULL) { printf("Couldn't malloc() for dst_ether\n"); return(EXIT_FAILURE); } memcpy(dst_ether->ether_addr_octet, ether_t, sizeof(struct ether_addr)); opts[OPT_DSTETHER].set = 1; break; case 's': src_ip = libnet_name2addr4(libnet, optarg, LIBNET_RESOLVE); opts[OPT_SRCIP].set = 1; break; case 'd': dst_ip = libnet_name2addr4(libnet, optarg, LIBNET_RESOLVE); opts[OPT_DSTIP].set = 1; break; case 't': ip_ttl = atoi(optarg); opts[OPT_IPTTL].set = 1; break; case 'c': payload = optarg; payload_l = strlen(payload); opts[OPT_PAYLOAD].set = 1; break; case 'I': ip_id = atoi(optarg); opts[OPT_IPID].set = 1; break; case 'p': ip_proto = atoi(optarg); opts[OPT_IPPROTO].set = 1; break; default: usage(); goto pass; break; } } /* Ensure that an interface is specified */ if (!opts[OPT_INTERFACE].set) { usage(); goto fail; } /* Depending on whether or not they choose to pick their own MACs, * libnet needs to be initialized differently for some reason */ if (opts[OPT_SRCETHER].set || opts[OPT_DSTETHER].set) { if ((libnet = libnet_init(LIBNET_LINK, interface, errbuf)) == NULL) { fprintf(stderr, "libnet_init() failed: %s", errbuf); goto fail; } } else { if ((libnet = libnet_init(LIBNET_RAW4, interface, errbuf)) == NULL) { fprintf(stderr, "libnet_init() failed: %s", errbuf); goto fail; } } libnet_seed_prand(libnet); /* If they didn't set a source ethernet address, figure out */ if (!opts[OPT_SRCETHER].set) { if ((src_ether = libnet_get_hwaddr(libnet)) == NULL) { fprintf(stderr, "libnet_get_hwaddr() failed: %s", errbuf); libnet_destroy(libnet); goto fail; } } /* If they didn't set a destination ethernet address, figure out */ if (!opts[OPT_DSTETHER].set) { if ((dst_ether = libnet_get_hwaddr(libnet)) == NULL) { fprintf(stderr, "libnet_get_hwaddr() failed: %s", errbuf); libnet_destroy(libnet); goto fail; } } /* If they didn't set a source IP, have libnet figure it out */ if (!opts[OPT_SRCIP].set) { src_ip = libnet_get_ipaddr4(libnet); opts[OPT_SRCIP].set = 1; } /* If no IP id is set, pick a random one */ if (!opts[OPT_IPID].set) { ip_id = libnet_get_prand(LIBNET_PRu16); opts[OPT_IPID].set = 1; } /* If no IP TOS is set, pick 0 */ if (!opts[OPT_IPTOS].set) { ip_tos = 0; opts[OPT_IPTOS].set = 1; } /* No payload? Then NULL */ if (!opts[OPT_PAYLOAD].set) { payload = NULL; payload_l = 0; opts[OPT_PAYLOAD].set = 1; } if (!opts[OPT_IPPROTO].set) { ip_proto = libnet_get_prand(LIBNET_PRu16); opts[OPT_IPPROTO].set = 1; } /* If no TTL is set, default to something sly. */ if (!opts[OPT_IPTTL].set) { /* 255 is too high, others are too low. I'll take the midground! */ ip_ttl = 200 + (libnet_get_prand(LIBNET_PR8) % 55); opts[OPT_IPTTL].set = 1; } /* make sure that everything that needs to be set is set... */ for (i = 0; i < 10; i++) { if (opts[i].req && !opts[i].set) { fprintf(stderr, "No %s specified\n\n", opts[i].name); usage(); libnet_destroy(libnet); goto fail; } } ipv4 = libnet_build_ipv4( LIBNET_IPV4_H + payload_l, /* length */ ip_tos, /* TOS */ ip_id, /* ID */ IP_DF, /* Frag */ ip_ttl, /* TTL */ ip_proto, /* Protocol */ 0, /* Sum */ src_ip, /* source IP */ dst_ip, /* destination IP */ payload, /* Payload */ payload_l, /* Payload size */ libnet, 0); if (ipv4 == -1) { fprintf(stderr, "Can't build ipv4: %s\n", libnet_geterror(libnet)); libnet_destroy(libnet); goto fail; } /* If they wish to set their own src/dst ethernet addresses * we need to actually build the ethernet. If they don't, * libnet does it automagically for us. */ if (opts[OPT_SRCETHER].set || opts[OPT_DSTETHER].set) { ether = libnet_build_ethernet( dst_ether->ether_addr_octet, /* Destination ethernet address */ src_ether->ether_addr_octet, /* Source ethernet address */ ETHERTYPE_IP, /* Protocol type */ NULL, /* Payload */ 0, /* Payload size */ libnet, 0); if (ether == -1) { fprintf(stderr, "Can't build ethernet: %s\n", libnet_geterror(libnet)); libnet_destroy(libnet); goto fail; } } if ((c = libnet_write(libnet)) == -1) { fprintf(stderr, "Couldn't write packet to the wire: %s\n", libnet_geterror(libnet)); } else { if (opts[OPT_VERBOSE].set) { if (opts[OPT_SRCETHER].set || opts[OPT_DSTETHER].set) { printf("Link Layer: "); printf("%s -> ", opts[OPT_SRCETHER].set ? ether_ntoa((struct ether_addr *) src_ether->ether_addr_octet) : interface); printf("%s\n", opts[OPT_DSTETHER].set ? ether_ntoa((struct ether_addr *) dst_ether->ether_addr_octet) : "(auto)"); } printf(" IP Layer: %s -> %s\n", libnet_addr2name4(src_ip, LIBNET_DONT_RESOLVE), libnet_addr2name4(dst_ip, LIBNET_DONT_RESOLVE)); printf(" IP Layer: TTL: %d TOS: 0x%X ID: %d ", ip_ttl, ip_tos, ip_id); printf("Protocol: %d (%s)\n", ip_proto, (protoent = getprotobynumber(ip_proto)) != NULL ? protoent->p_name : "unknown"); printf(" App Layer: %ld byte payload\n", payload_l); } } libnet_destroy(libnet); goto pass; fail: if (opts[OPT_SRCETHER].set) { free(src_ether); } if (opts[OPT_DSTETHER].set) { free(dst_ether); } return(EXIT_FAILURE); pass: if (opts[OPT_SRCETHER].set) { free(src_ether); } if (opts[OPT_DSTETHER].set) { free(dst_ether); } return(EXIT_SUCCESS); }