[ dns hijacker v1.3 ] pedram amini (pedram@redhive.com) pedram.redhive.com Table of Contents: - Introduction - Uses - Compiling - Command Line Options - The Fabrication Table - Extras - Brief Technical Rundown - How To Remove Ads - How To Use With RRDtool /************************************** * Introduction * **************************************/ 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 and 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 second, and in my opinion, more useful use is to hijack the queries for all the popular ad servers (such as doubleclick.net). That way not only are you alleviating yourself from the ghastly sight 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 7.3 it requires libpcap (www.tcpdump.org) and libnet (www.packetfactory.net), at the time I was using versions 0.7.1 and 1.0.2a respectively. To compile: gcc dnshijacker.c -lpcap -lnet `libnet-config --defines` -o dnshijacker You can optionally compile with -DDEBUG to enable (messy) debug messages. You could also check out the Makefile. /************************************** * Command Line Options * **************************************/ -d 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 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 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 in the standard /etc/hosts format. 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: 17.254.0.91 www.microsoft.com # 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)? ... 17.254.0.91 www.microsoft.com # www.apple.com 208.184.74.98 secure.microsoft.com # www.insecure.org Lastly, say we wanted to redirect .microsoft.com to www.apple.com... 17.254.0.91 microsoft.com # 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 500. 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 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 by one each time (easing the burden of guessing the id). answer_dns <#_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. /************************************** * How To Remove Ads * **************************************/ The default ftable comes with an extensive list of ad servers gleaned from http://www.yoyo.org/~pgl/adservers/. The entries are by default mapped to localhost (127.0.0.1). While this does successfully block advertisements it leaves broken images and causes problems in some browsers (Netscape). The following is a description of the three step approach I took to remove ads from my home network: 1. First you need to alias an unused IP address on one of your interfaces. This will serve as the address that we redirect all ad servers to. I chose 10.0.0.3. 2. Next you need to modify the ftable replacing all 127.0.0.1'1 with 10.0.0.3. 3. Finally you need to setup an Apache virtual host with a mod_rewrite rule that redirects all requests to an image of your choosing. I created a 1x1 transparent GIF for this purpose. Here is a sample virtual host entry to get you started: ServerAdmin admin@my.server.com DocumentRoot /path/to/my/vhost ServerName no-ads.my.server.com ErrorLog /dev/null CustomLog /dev/null common RewriteEngine on RewriteRule ^.* /spacer.gif /************************************** * How To Use With RRDtool * **************************************/ First and foremost you need to create a round robin database to store your statistic values in. I choose to keep one weeks worth of 10 minute samples: rrdtool create dnshijacker.rrd \ --step 600 \ DS:spoofs:COUNTER:1200:U:U \ RRA:AVERAGE:0.5:1:1008 You then need to collect statistics. I use the following perl snippet which is called from cron every ten minutes: #!/usr/bin/perl # # dnshijacker spoof count rrd collector # $print_flag = shift; $num_spoofs = int(`cat /var/log/dnshijacker_spoofs`); if ($print_flag) { print "rrdtool update /rrd/dnshijacker.rrd N:$num_spoofs\n"; } `rrdtool update /rrd/dnshijacker.rrd N:$num_spoofs`; You finally need to graph your statistics. I use the following shell script which is called from cron every hour: #!/bin/bash ### # cron.daily script # recreates daily and weekly dnshijacker spoof statistics graphs. # rrd database location: /rrd/ # rrd graph location: /www/html/rrdgraphs/ rrdtool graph /www/html/rrdgraphs/dnshijacks_daily.gif \ --title "1-day dnshijacks" \ --width 600 \ --color BACK#333333 \ --color SHADEA#000000 \ --color SHADEB#000000 \ --color CANVAS#000000 \ --color GRID#999999 \ --color MGRID#666666 \ --color FONT#CCCCCC \ --color FRAME#333333 \ --start -86400 \ --vertical-label "spoofed answers" \ --no-legend \ --units-exponent 0 \ DEF:ns=/rrd/dnshijacker.rrd:spoofs:AVERAGE \ AREA:ns#0066FF \ LINE1:ns#FF0000 rrdtool graph /www/html/rrdgraphs/dnshijacks_weekly.gif \ --title "1-week dnshijacks" \ --width 600 \ --color BACK#333333 \ --color SHADEA#000000 \ --color SHADEB#000000 \ --color CANVAS#000000 \ --color GRID#999999 \ --color MGRID#666666 \ --color FONT#CCCCCC \ --color FRAME#333333 \ --start -604800 \ --vertical-label "spoofed answers" \ --no-legend \ --units-exponent 0 \ DEF:ns=/rrd/dnshijacker.rrd:spoofs:AVERAGE \ AREA:ns#0066FF \ LINE1:ns#FF0000 #!/bin/bash ### # cron.daily script # recreates daily and weekly dnshijacker spoof statistics graphs. # rrd database location: /rrd/ # rrd graph location: /www/html/rrdgraphs/ rrdtool graph /www/html/rrdgraphs/dnshijacks_daily.gif \ --title "1-day dnshijacks" \ --width 600 \ --color BACK#333333 \ --color SHADEA#000000 \ --color SHADEB#000000 \ --color CANVAS#000000 \ --color GRID#999999 \ --color MGRID#666666 \ --color FONT#CCCCCC \ --color FRAME#333333 \ --start -86400 \ --vertical-label "spoofed answers" \ --no-legend \ --units-exponent 0 \ DEF:ns=/rrd/dnshijacker.rrd:spoofs:AVERAGE \ AREA:ns#0066FF \ LINE1:ns#FF0000 rrdtool graph /www/html/rrdgraphs/dnshijacks_weekly.gif \ --title "1-week dnshijacks" \ --width 600 \ --color BACK#333333 \ --color SHADEA#000000 \ --color SHADEB#000000 \ --color CANVAS#000000 \ --color GRID#999999 \ --color MGRID#666666 \ --color FONT#CCCCCC \ --color FRAME#333333 \ --start -604800 \ --vertical-label "spoofed answers" \ --no-legend \ --units-exponent 0 \ DEF:ns=/rrd/dnshijacker.rrd:spoofs:AVERAGE \ AREA:ns#0066FF \ LINE1:ns#FF0000