[ 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 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 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. Empty lines are ignored and lines starting with a '#" are treated
as comments. 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.

