Copy Link
Add to Bookmark
Report

dbsnatch 1.0

neat little tool to quickly dig up information on a host and log it in a database for later use. (In our honest opinion #1)

eZine's profile picture
Published in 
In our honest opinion
 · 6 Mar 2024

README

# DB Snatch v1.0 -- ben-z (bentothez@phayze.com) || #og @ undernet.org 

# nice way to log various information about a host.. edit the 'logdir'
# variable to wherever you want dbnsatch to log all its scans to. Each
# host's log file will be saved as the name of the host in your $logdir.
# Also, make sure the binfo-udp binary is in your $PATH somewhere!

# requires:
# dig, whois, traceroute, nc, nmap, and a seedless watermelon

# recommended installation:
# cd dbsnatch-1.0
# gcc -o binfo-udp binfo-udp.c
# ln -s `pwd`/binfo-udp /bin
# ln -s `pwd`/dbsnatch /bin
# mkdir /usr/local/snatch
# cd ..

# syntax: dbsnatch <host>

# written for "IOHO (In Our Honest Opinion) e-zine" ISSUE 1.0@#$!
# http://benz.ath.cx/ioho

binfo-udp.c

/* 
* This code was written by:
* Joshua James Drake (jdrake@pulsar.net)
*
* Published 6/9/98 @ 12:02 AM
*
* The following lines of code are, in a nutshell, written to pry
* some information from a nameserver. The information it gives
* you may or may not be useful. That is for you to decide.
*
* However, it will tell you if the server supports IQUERY and, if
* possible, what version of bind (by Paul Vixie) it is running.
*
*/


/* local type includes */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <sys/errno.h>
/* network type includes */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <netdb.h>

/* bulky shit for printing dnspkts need to link dnspkt.o from dnspkt.c too */
#ifdef DEBUG
#include "dnspkt.h"
#endif

/* prototypes */
int lookup_host(struct sockaddr_in *ra, char *hn, unsigned short rp);
void probe_bind(struct sockaddr_in ra);
int talk(int sd, char *pkt, int pktl, char opc);
int make_keypkt(char *pktbuf, char opc);
void print_ver(char *host, int vul, char *buf);
void handle_alarm(int signum);

/*
* here we simply check arguments, resolve the hostname given and
* if all is well, initialize the radom seed and probe away.
*/

void
main(argc, argv)
int argc;
char *argv[];
{
struct sockaddr_in ra;

if (argc != 2)
{
printf("usage: %s <host>\n", argv[0]);
return;
}
if (!lookup_host(&ra, argv[1], NAMESERVER_PORT))
return;
srand(time(NULL));
probe_bind(ra);
}

/*
* resolve a hostname to a sockaddr_in struct.
* we first try treating it like an ip address in a.b.c.d notation
* then, if that fails, we try to resolve using DNS ways
* if all fails, we return 0. (failed)
* if we get the sockaddr_in struct all filled out, we return 1.
*/

int
lookup_host(ra, hn, rp)
struct sockaddr_in *ra;
char *hn;
unsigned short rp;
{
struct hostent *he;

ra->sin_family = AF_INET;
ra->sin_port = htons(rp);
if ((ra->sin_addr.s_addr = inet_addr(hn)) != -1)
return 1;
if ((he = gethostbyname(hn)) != (struct hostent *)NULL)
{
memcpy(&ra->sin_addr.s_addr, he->h_addr, 4);
return 1;
}
herror("Unable to resolve hostname");
return 0;
}

/*
* here we allocate some space for our packets and make sure it's
* "fullanull". then we attempt to allocate and setup our socket.
* if failure occurs, we shall report error and return.
* the we attempt to reverse our address in the sockaddr_in structure
* passed as the only argument into a dns name, if that fails, we go
* with the ascii ip address representation. then we attempt to
* communicate the remote server, if failure, we return. after we
* have successfully got our packets back, we close the socket and
* print out a summary of what we got.
*/

void
probe_bind(ra)
struct sockaddr_in ra;
{
int sd;
char iquery[512], vquery[512], rname[256];
struct hostent *he;
HEADER *dh = (HEADER *)iquery;

memset(vquery, 0, sizeof(vquery));
memset(iquery, 0, sizeof(iquery));
if (((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) ||
(connect(sd, (struct sockaddr *)&ra, sizeof(ra)) == -1))
{
perror("Unable to connect");
if (sd != -1)
close(sd);
return;
}
if ((he = gethostbyaddr((char *)&ra.sin_addr, sizeof(ra.sin_addr), AF_INET)) == (struct hostent *)NULL)
sprintf(rname, "%s", inet_ntoa(ra.sin_addr));
else
strncpy(rname, he->h_name, sizeof(rname));

if (!talk(sd, iquery, sizeof(iquery), IQUERY))
return;
if (!talk(sd, vquery, sizeof(vquery), QUERY))
return;
close(sd);

/* if dh->rcode == 0, then our iquery request was answered and the remote server
supports iquery */

print_ver(rname, dh->rcode == 0, vquery);
}

/*
* write our packet from pkt, wait for a response and put it in pkt.
* if the alarm goes off or the read fails, we print error
* and return 0. otherwise, our response packet is in pkt and we return 1.
*/

int
talk(sd, pkt, pktl, opc)
int sd, pktl;
char *pkt, opc;
{
int pktlen;

pktlen = make_keypkt(pkt, opc);
if (!write(sd, pkt, pktlen))
{
perror("write failed");
close(sd);
return 0;
}
#ifdef DEBUG
printf("write() success\n");
#endif
siginterrupt(SIGALRM, 1);
signal(SIGALRM, handle_alarm);
alarm(3);
pktlen = read(sd, pkt, pktl);
if (pktlen <= 0)
{
if (errno == EINTR)
errno = ETIMEDOUT;
perror("read failed");
close(sd);
return 0;
}
#ifdef DEBUG
printf("read success\n");
#endif
alarm(0);
return 1;
}

/*
* this forms a valid dns packet based on the op code given by opc.
* only two opcodes are supported because that's all we need to support.
* the packet ends up in pktbuf and the length of the packet is returned.
*/

int
make_keypkt(pktbuf, opc)
char *pktbuf;
char opc;
{
HEADER *dnsh;
char *ptr = pktbuf;
int pktlen = 0;

dnsh = (HEADER *) ptr;
/* fill out the parts of the DNS header that aren't 0 */
dnsh->id = htons(rand() % 65535);
dnsh->opcode = opc;
dnsh->rd = 1;
dnsh->ra = 1;
/* one answer for IQUERY, one question for QUERY */
if (opc == IQUERY)
dnsh->ancount = htons(1);
else if (opc == QUERY)
dnsh->qdcount = htons(1);
pktlen += sizeof(HEADER);
ptr += sizeof(HEADER);

/* we have to make a QUERY, fill out the question section */
if (opc == QUERY)
{
/* version.bind. == elite */
char qstr[] = "\007version\004bind\000";
int qlen = strlen(qstr) + 1;

memcpy(ptr, qstr, qlen);
ptr += qlen;
pktlen += qlen;
PUTSHORT(T_TXT, ptr);
PUTSHORT(C_CHAOS, ptr);
pktlen += sizeof(short) * 2;
}
/* add a resource record for the inverse query */
else if (opc == IQUERY)
{
unsigned long addr = inet_addr("1.2.3.4");
unsigned long ttl = 31337;
unsigned short addrlen = 4;

*(ptr++) = '\0';
pktlen++;
PUTSHORT(T_A, ptr);
PUTSHORT(C_IN, ptr);
PUTLONG(ttl, ptr);
PUTSHORT(addrlen, ptr);
PUTLONG(addr, ptr);
pktlen += (sizeof(short) * 3) + (sizeof(long) * 2);
}
/* if we're debugging, show what we just made */
#ifdef DEBUG
print_dnspkt(pktbuf, pktbuf + pktlen);
#endif
return pktlen;
}

/*
* This function takes a DNS packet in buf, and whether or not it reponds to IQUERY in vul.
* We cast the packet and extract the response as long as there is one.
* If there isn't one, then we assume that the remote server is an old version of bind.
* this is the end of the line.
*/

void
print_ver(host, vul, buf)
char *host, *buf;
int vul;
{
HEADER *dnsh = (HEADER *)buf;
char *ptr, *verstr;
int len;

if (dnsh->rcode != 0)
{
printf("%s's named that %s iquery does not respond to version.bind.\n", host, vul ? "supports" : "errors on");
return;
}
/* So we actually have a response. Lets skip the crap, starting with the header */
ptr = (buf + sizeof(HEADER));
/* then the question section domain name. */
while (*ptr != '\0')
ptr++;
/* then the trailing null and the type/class of the question */
ptr += 1 + (sizeof(short) * 2);
/* now we skip the answer section domain name. (should be the same as the question) */
while (*ptr != '\0')
ptr++;
/* don't forget the trailing null, type, class, and time to live. */
ptr += 1 + (sizeof(long) + (sizeof(short) * 2));
/* Here we are at the resource record data length, extract it */
GETSHORT(len, ptr);
/* avoid the need to decompress the string (treat it as one) */
ptr++;
/* allocate space for and copy the version response txt */
verstr = (char *)malloc(len);
memset(verstr, 0, len);
memcpy(verstr, ptr, len-1);
/* run through the vesion string and replace non-printable and non-whitespace characters
with a '.' */

for (ptr = verstr; ptr - verstr != len - 1; ptr++)
if (!isprint(*ptr) && !isspace(*ptr))
*ptr = '.';
/* print the version and iquery support status, woo hoo */
printf("%s's named that %s iquery is version: %s\n", host, vul ? "supports" : "errors on", verstr);
}

/*
* handle the alarm signal by resetting the alarm timer and
* the signal handler for SIGALRM. This stuff probably isn't needed,
* but I did it anyway. It's good for debugging, ran into some problems with
* alarm() not doing its job.
*/

void
handle_alarm(signum)
int signum;
{
alarm(0);
signal(SIGALRM, SIG_DFL);
#ifdef DEBUG
printf("received alarm\n");
#endif
}

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT