[ dns hijacker v1.0 ] pedram amini (pedram@redhive.com) www.redhive.com Inspired by an idea I came up with while sitting on the john I set out to write a program that would sniff dns requests aned spoof answers. 800 lines of code and 25 hours later I had given birth to dnshijacker. The following is a run-down on what it can do, and how you can go about doing it. /************************************** * uses * **************************************/ Aside from the tremendous comical value of redirecting your friends to gay porno sites there are a few other (possibly legitimate) uses to dnshijacker. Firstly, sites can be filtered based on keywords in domain names. Of course this can easily be bypassed through the usage of a proxy. The seconde, in my opinion, more useful is to hijack the queries for all the popular ad servers (such as doubleclick). That way not only are you alleviating yourself from the ghastly site of advertisements, but you've also upped your level of privacy a notch or two. Along with the prankster, the blackhat will probably find the most uses for dnshijacker. The possibilities are endless. One could easily mirror a site (hotmail, etrade, online banking, etc) and redirect requests to that mirror for login/password collection. Another target for attack is the auto-update features that most windows applications use. Next time Winamp or AOL Instant Messenger check for an update, the request can be redirected to yourself, an "update available" answer can then be spoofed, and a trojan wrapped executable sent to the victim. /************************************** * compiling * **************************************/ dnshijacker was built and tested on an x86 running redhat linux 6.1 it requires libpcap (www.tcpdump.org) and libnet (www.packetfactory.net), at the time I was using versions 0.4-19 and 1.0 respectively. To compile: gcc dnshijacker.c -lpcap -lnet `libnet-config --defines` -o dnshijacker You can optionally compile with -DDEBUG to enable (messy) debug messages. /************************************** * command line options * **************************************/ -d <ip address> You can set the default answer that dnshijacker will respond with using the -d switch followed by an ip address in normal dotted quad form (xxx.xxx.xxx.xxx). dnshijacker will use the default address in the case that no match is found for the current question in the fabrication table or if no fabrication table is present to begin with. -f <filename> The -f switch is used to point dnshijacker to the location of your custom fabrication table. The file must be readable, see below for a guide to the fabrication table. -i <interface> Specify the interface to work on. Pretty simple. -p The -p switch puts dnshijacker into print only mode. I use this when I just want to take a look at traffic patterns to build my fabrication table. It was also useful during the development/debug stage and I just left it around. -v The -v switch will make dnshijacker print more verbose information, basically this includes all the dnsheader segments. dnshijacker will also accept an optional tcpdump style filter string. The key to this is that the program works only on what it can see. This is best explained by example... Say I want to only watch dns traffic, but I want to watch traffic both to and from dns servers. Well in this case the default "udp dst port 53" is not going to cut it, so we run dnshijacker with: dnshijacker -p udp src or dst port 53 What if we wanted to spoof answers, but also wanted to see traffic from dns servers... dnshijacker -f ftable udp src or dst port 53 dnshijacker is smart enough not to attempt to spoof answers to answers. The more practical usage of the filter however is when you want to only hijack certain peoples questions. Say for example I only want to hijack johnny's (10.0.0.5) questions... dnshijacker -f ftable udp dst port 53 and src 10.0.0.5 On a final note, when the -f and -d switches are used together obviously the -f takes precedence. In the case that a match is not found then dnshijacker will fall back to using the default address. /************************************** * the fabrication table * **************************************/ The fabrication table is where you link spoofed answers to real domains. The first column is the list of domains for which we wish to spoof answers for. The second column is the answer we spoof with. Anything after the second column is considered a comment, I prefer to delimit comments with a '#' just to keep things tidy. Probably the best way to explain the format would be by example. So, say for instance you want hijack all requests for www.microsoft.com and redirect them to www.apple.com (17.254.0.91). The table entry would read: www.microsoft.com 17.254.0.91 # answer = apple.com Remember that anything past the second column is a comment. What if we want to also redirect secure.microsoft.com www.insecure.org (208.184.74.98)? ... www.microsoft.com 17.254.0.91 # www.apple.com secure.microsoft.com 208.184.74.98 # www.insecure.org Lastly, say we wanted to redirect <anything>.microsoft.com to www.apple.com... microsoft.com 17.254.0.91 # www.apple.com This works because our table entries represent the needle, and the dns question is the haystack. So as long as the needle exists somewhere within the haystack a match exists. The maximum number of entries is currently 50. If you need more then that, change the define in the header file and recompile. /************************************** * extras * **************************************/ Also included in the package are 2 programs ask_dns and answer_dns. These were used during development/debugging, but I figured someone may find them useful so I left them in here. ask_dns surprisingly will ask a dns question: ask_dns <source_ip> <port> <destination_ip> <port> <dns_id> answer_dns will write a dns answer. This is actually more useful then ask_dns in that it can be used to spoof an answer to someone not on your lan. Of course you need to be able to guess when the victim is looking up the name that you wish to hijack and what the dns id will be. answer_dns will write <#_packets> packets and increment <dns_id> by one each time (easing the burden of guessing the id). answer_dns <source_ip> <port> <destination_ip> <port> <dns_id> <#_packets> Both programs use static data, that can easily be changed however by using dnshijacker's source as a guide. /************************************** * brief technical rundown * **************************************/ dnshijacker uses the libpcap interface for packet capturing. The program starts off by initializing the capture device through this interface. Once this and other initialization is complete dnshijacker falls into an infinite packet capturing loop. Each captured packet is passed to parse_dns(), which first checks to make sure we can use this packet and then steps through the packet and pulls out all relevant/necessary information. parse_dns() is also responsible for building the payload of the answer we are going to spoof. It does so by first calling search_table(), which will search through the user specified fabrication table and return (if any) the appropriate answer. Armed with this information parse_dns() will complete the construction of the payload. All information generated by parse_dns() is stored in our globally declared structure chewy_center. The next step is to make sure we want to spoof an answer. First we check if the print only flag is on, if not we call spoof_dns() and pass to it the socket on which we wish to write. spoof_dns() will check a few more conditions before attempting to do anything, if the conditions pass then we will begin constructing our spoof packet. This is all done through libnet's raw socket API. spoof_dns() builds the packet headers from information stored in chewy_center, it then tacks on the payload and writes the packet. EOF