/* Namescan, DNS mapping system v1.2
Bloodmask 1998 */
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <setjmp.h>
#define CHILD_NAME "namescan"
#define ROOTTIMEOUT 120
#define USLEEP 100000
#define DEFTIMEOUT 15
#define DEFCONNECTIONS 5
#define FILENAME "%s.query"
#define MERGENAME "%s.scan"
#define DEEPNAME "deep"
#define MAXSYSBUF 128
#define MAXFILEBUF 80
#define MAXDOMAINBUF 80
#define TEMPDIR "/var/tmp/"
#define TEMPSIZE 8
#define OK 1
#define FAILED 0
#ifdef PASSWORD_PROTECTED
#ifndef EXECPASSWORD
#define EXECPASSWORD "ZFsZvwzEp7oBc"
#endif
#endif
#define COASTCLEAR 120
int options;
#define F_TIMEOUT 0x002
#define F_PARANOID 0x004
#define F_BACKGROUND 0x008
#define F_DEEPSCAN 0x010
#define F_HOSTNAMES 0x020
#define HASADDRESS "has address "
int quite;
int timeout;
jmp_buf env;
void handleargs(int argc, char **argv, char *hostname);
int paranoid_coastclear(void);
int paranoid_lookout(void);
int findslot(int pid);
void free_children(void);
void sigchld_handler(int sig);
void sigalrm_handler(int sig);
void ignore_signals(void);
char *Strip(char *String);
int QueryDomain(char *Domain, char *Filename, int maxtimeout);
int ElaborateSCAN(char *Filename, int argc, char **argv);
long GetRandom(long Minimum, long Maximum);
char *GetTemp(void);
void Clean(char *String, int bytes);
void usage(void);
int Format(char *Filename_src, char *Filename_dst, int mode);
#ifdef PASSWORD_PROTECTED
int VerifyKEY(char *Accesskey);
#endif
void go_background(void);
int Linkregions(int argc, char **argv);
int addip(char *ip, char *Filename);
struct regionlist {
struct regionlist *next, *last;
char *region;
} *rootregion = NULL;
struct tree_node {
char *string;
struct tree_node *left;
struct tree_node *right;
};
int dump_tree(struct tree_node *tree, FILE *dump);
int insert_string(struct tree_node **tree, char *string);
int free_tree(struct tree_node **tree);
long jump;
int *pids;
int free_slots, connections;
int paranoid_secs;
int main(int argc, char **argv)
{
int Count;
int option;
int runloop;
char *Sysbuf;
char *Filename;
char *password;
char *Domainlist;
FILE *Resultsfp;
FILE *Domainlistfp;
struct regionlist *loop_region;
timeout = DEFTIMEOUT;
connections = DEFCONNECTIONS;
options = quite = runloop = jump = 0;
#ifdef PASSWORD_PROTECTED
password = getpass("Password: ");
if(!VerifyKEY(password)) exit(0);
#endif
while( (option = getopt(argc, argv, "P:j:c:t:D:HMBQh")) != EOF)
switch(option) {
case 'H' : options |= F_HOSTNAMES;
break;
case 'j' :
jump = atol(optarg);
if(jump < 1) {
fprintf(stderr,
"Error: %s Invalid number of systems\n",
optarg);
exit(1);
}
break;
case 't' :
timeout = atoi(optarg);
if(timeout < 1) {
fprintf(stderr, "Error: %s invalid timeout\n",
optarg);
exit(1);
}
options |= F_TIMEOUT;
break;
case 'c' :
connections = atoi(optarg);
if(connections < 1) {
fprintf(stderr, "Error: %s invalid connections\n",
optarg);
}
break;
case 'D' :
Domainlist = (char *) malloc(strlen(optarg)+1);
strcpy(Domainlist, optarg);
options |= F_DEEPSCAN;
break;
case 'Q' :
quite++;
break;
case 'B' :
options |= F_BACKGROUND;
break;
case 'P' :
options |= F_PARANOID;
paranoid_secs = atoi(optarg);
break;
default : usage();
}
if( options & F_BACKGROUND ) {
go_background();
quite = 2;
}
Filename = (char *) malloc(MAXFILEBUF);
if( options & F_DEEPSCAN ) {
ElaborateSCAN(Domainlist, argc, argv);
exit(0);
}
argc -= optind;
argv += optind;
if(argc < 1)
usage();
Linkregions(argc, argv);
argc += optind;
argv -= optind;
for(loop_region = rootregion; loop_region != NULL;
loop_region = loop_region -> next) {
sprintf(Filename, FILENAME, loop_region -> region);
if(!QueryDomain(loop_region -> region, Filename, ROOTTIMEOUT)) {
if( quite < 2 )
fprintf(stderr, "Error: Couldn't lookup root domain [%s]\n",
loop_region -> region);
continue;
} else if( quite < 2 )
fprintf(stderr, "Successfully looked up root domain [%s]\n",
loop_region -> region);
if(!ElaborateSCAN(Filename, argc, argv)) continue;
if( quite < 2 )
fprintf(stderr, "Finished querying root domain [%s]\n",
loop_region -> region);
}
}
int Linkregions(int argc, char **argv)
{
int Count;
struct regionlist *loop_region;
struct regionlist *tmpregion;
for(Count = 0; Count<argc; Count++) {
tmpregion = (struct regionlist *) malloc(sizeof(struct regionlist));
tmpregion -> region = (char *) malloc(MAXDOMAINBUF);
strncpy(tmpregion -> region, argv[Count], MAXDOMAINBUF - 1);
tmpregion -> next = rootregion;
if(rootregion != NULL)
rootregion -> last = tmpregion;
tmpregion -> last = NULL;
rootregion = tmpregion;
}
return OK;
}
char *Strip(char *String)
{
char *S_CH;
if((S_CH = strchr(String, (int) '\r')) != NULL) *S_CH = '\0';
if((S_CH = strchr(String, (int) '\n')) != NULL) *S_CH = '\0';
return String;
}
long GetRandom(long Minimum, long Maximum)
{
long RandomNumber;
struct timeb tp;
ftime(&tp);
srand(tp.millitm);
RandomNumber = Minimum + (long)
( (float) (Maximum - Minimum) * random()/(RAND_MAX+1.0) );
return RandomNumber;
}
char *GetTemp(void)
{
int Count;
char *Filename, *Directory;
char *O_Ch, *D_Ch;
Filename = (char *) malloc(80);
bzero((char *)Filename, 80);
sprintf(Filename, "%s", TEMPDIR);
O_Ch = Filename + strlen(Filename);
for( Count = 0; Count<TEMPSIZE; Count++) {
usleep(GetRandom(10, 20) * 10);
switch(GetRandom(1, 3)) {
case 1 : *O_Ch = GetRandom( (int) 'a', (int) 'z' );
O_Ch++;
break;
case 2 : *O_Ch = GetRandom( (int) 'A', (int) 'Z' );
O_Ch++;
break;
case 3 : *O_Ch = GetRandom( (int) '0', (int) '9' );
O_Ch++;
break;
}
}
return Filename;
}
void Clean(char *String, int bytes)
{
bzero((char *)String, bytes);
}
int QueryDomain(char *Domain, char *Filename, int maxtimeout)
{
int pid, child_pid, child_status;
char *Temp = GetTemp();
struct stat dummy;
if(!(pid = fork())) {
freopen(Temp, "w", stdout);
freopen("/dev/null", "w", stderr);
execl("/usr/bin/host", "/usr/bin/host", "-l", Domain, NULL);
fclose(stdout);
exit(1);
} else
if( pid != -1 ) {
signal(SIGALRM, sigalrm_handler);
alarm(maxtimeout);
if(!setjmp(env)) {
for(;;) {
if(stat(Temp, &dummy) < 0) continue;
if(dummy.st_size > 0) break;
if((child_pid = waitpid(pid, &child_status, WNOHANG)) != -1 )
if( WIFEXITED(child_status) || WIFSIGNALED(child_status) ) break;
usleep(USLEEP);
}
alarm(0);
} else {
unlink(Temp);
kill(pid, 9);
waitpid(pid, &child_status, 0);
return FAILED;
}
waitpid(pid, &child_status, 0);
Format(Temp, Filename, 1);
unlink(Temp);
free(Temp);
return OK;
}
if(quite < 2)
fprintf(stderr, "Error: Couldn't fork\n");
return FAILED;
}
void usage(void)
{
fprintf(stderr,
"usage: namescan [-options] root-domain[s]\n"
"Options:\n"
"\t-Q\t\t\tQuite mode\n"
"\t-B\t\t\tSnap into background\n"
"\t-P paranoid_secs\t\tSet delay between paranoid lookouts\n"
"\t-t timeout\t\tDNS Timeout\n"
"\t-c connections\t\tConnections per batch\n"
"\t-j entries\t\tNumber of entries to jump\n"
"\t-D domain.scan\t\tScan previous results one level deeper\n");
exit(1);
}
void go_background(void)
{
if(fork()) exit(0);
}
int ElaborateSCAN(char *Filename, int argc, char **argv)
{
int i, ploop, Count;
int pid, slot;
long line_number;
char *Domain, *Results, *F_CH;
char *Mergename;
FILE *Resultsfp;
Mergename = (char *) malloc(MAXDOMAINBUF);
Results = (char *) malloc(MAXDOMAINBUF);
Domain = (char *) malloc(MAXDOMAINBUF);
Domain[MAXDOMAINBUF - 1] = '\0';
pids = (int *) malloc(connections*sizeof(int));
for(i = 0; i<connections; i++) pids[i] = -1;
free_slots = connections;
if( !(Resultsfp = fopen(Filename, "rt")) ) {
if( quite < 2 )
fprintf(stderr, "Error: unable to read from `%s'\n", Filename);
return FAILED;
}
strcpy(Mergename, Filename);
strcpy(Results, FILENAME);
F_CH = strstr(Mergename, &Results[2]);
if(F_CH != NULL) {
strcpy(Results, MERGENAME);
sprintf(F_CH, "%s", &Results[2]);
} else strcat(Mergename, DEEPNAME);
for(Count = 0; Count<jump; Count++)
if( fgets(Domain, MAXDOMAINBUF - 1, Resultsfp) == NULL ) {
fprintf(stderr, "Error: Jump parameters out of bounds\n");
exit(0);
}
ploop = line_number = 0;
signal(SIGCHLD, sigchld_handler);
while( fgets(Domain, MAXDOMAINBUF - 1, Resultsfp) != NULL ) {
line_number++;
Strip(Domain);
#ifdef DEBUG
fprintf(stderr, "DEBUG: Handling `%s' from domainlist\n", Domain);
#endif
if(inet_addr(Domain) != -1) {
addip(Domain, Mergename);
continue;
}
repeat:
while( !free_slots ) {
#ifdef DEBUG
fprintf(stderr, "DEBUG: In the while loop, free_slots = %d\n",
free_slots);
#endif
free_children();
usleep(USLEEP);
if( options & F_PARANOID )
if(!(ploop = (ploop+1)%((paranoid_secs*1000000)/USLEEP))) {
if(paranoid_lookout()) {
line_number -= connections;
rewind(Resultsfp);
for(i = 0; i<line_number; i++)
if(!fgets( Domain, MAXDOMAINBUF - 1, Resultsfp )) break;
}
}
}
if((slot = findslot(-1)) < 0) goto repeat;
switch((pid = fork())) {
case 0 : ignore_signals();
handleargs(argc, argv, Domain);
if(!QueryDomain(Domain, Mergename, timeout) && quite < 1)
fprintf(stderr, "Failed querying domain [%s]\n", Domain);
else
if(quite < 1)
fprintf(stderr, "Successfully queried domain [%s]\n", Domain);
exit(getpid() & 0xFF);
default :
free_slots--;
pids[slot] = pid;
#ifdef DEBUG
fprintf(stderr, "DEBUG: new_proc, pid %d, domain %s\n",
pid, Domain);
#endif
}
}
#ifdef DEBUG
fprintf(stderr, "DEBUG: Finished extending domains\n");
#endif
while( free_slots < connections ) {
free_children();
sleep(USLEEP);
if( options & F_PARANOID )
if(!(ploop = (ploop+1)%((paranoid_secs*1000000)/USLEEP)))
paranoid_lookout();
}
fclose(Resultsfp);
Clean(Domain, MAXDOMAINBUF); free(Domain);
Clean((char *)pids, sizeof(int) * connections); free(pids);
unlink(Filename);
Format(Mergename, Filename, 0);
unlink(Mergename);
return OK;
}
void free_children(void)
{
int slot, child_pid, child_status;
for(slot = 0; slot<connections; slot++) {
if(pids[slot] != -1)
if((child_pid = waitpid(pids[slot], &child_status, WNOHANG)) != -1)
if((WIFEXITED(child_status) &&
WEXITSTATUS(child_status) == (pids[slot] & 0xFF)) ||
(WIFSIGNALED(child_status) && WTERMSIG(child_status) == SIGKILL) ) {
free_slots++;
#ifdef DEBUG
fprintf(stderr, "DEBUG: free_slots = %d\n", free_slots);
fprintf(stderr, "DEBUG: free'd pid %d\n", pids[slot]);
#endif
pids[slot] = -1;
}
}
}
int Format(char *Filename_src, char *Filename_dst, int mode)
{
char *Line, *Address, *Pointer;
FILE *SRC, *DST;
struct tree_node *tree = NULL;
Line = (char *) malloc(80);
Address = (char *) malloc(80);
bzero((char *)Address, sizeof(Address));
bzero((char *)Line, sizeof(Line));
if(!(SRC = fopen(Filename_src, "rt"))) return FAILED;
if(!(DST = fopen(Filename_dst, "at"))) return FAILED;
while( fgets(Line, 79, SRC) != NULL ) {
if( mode && (Pointer = strstr(Line, HASADDRESS)) != NULL ) {
Pointer += strlen(HASADDRESS);
sscanf(Pointer, "%s", Address);
} else sscanf(Line, "%s", Address);
if(!mode) Strip(Address);
insert_string(&tree, Address);
}
dump_tree(tree, DST);
free_tree(&tree);
free(Line);
free(Address);
fclose(DST);
fclose(SRC);
}
int insert_string(struct tree_node **tree, char *string)
{
int rc;
struct tree_node *tmp;
if(*tree == NULL) {
tmp = (struct tree_node *)malloc(sizeof(struct tree_node));
bzero((struct tree_node *)tmp, sizeof(struct tree_node));
tmp->string = (char *)malloc(strlen(string)+1);
strcpy(tmp->string, string);
*tree = tmp;
return OK;
}
rc = strcmp(string, (*tree)->string);
if(rc<0)
insert_string(&((*tree)->left), string);
else if(rc>0) insert_string(&((*tree)->right), string);
return OK;
}
int dump_tree(struct tree_node *tree, FILE *WRITE)
{
if(tree != NULL ) {
dump_tree(tree -> left, WRITE);
fprintf(WRITE, "%s\n", tree -> string);
dump_tree(tree -> right, WRITE);
}
return OK;
}
int free_tree(struct tree_node **tree)
{
if( *tree != NULL ) {
free_tree(&(*tree)->left);
free_tree(&(*tree)->right);
free((*tree)->string);
free(*tree);
}
}
int addip(char *IP, char *Filename)
{
FILE *WRITE;
if(!(WRITE = fopen(Filename, "at"))) return FAILED;
fprintf(WRITE, "%s\n", IP);
fclose(WRITE);
return OK;
}
void sigalrm_handler(int sig)
{
signal(SIGALRM, SIG_IGN);
alarm(0);
longjmp(env, 1);
}
void sigchld_handler(int sig)
{
int slot, child_pid, child_status;
if((child_pid = wait(&child_status)) != -1) {
if( (WIFEXITED(child_status) &&
WEXITSTATUS(child_status) == (child_pid & 0xFF)) ||
(WIFSIGNALED(child_status) && WTERMSIG(child_status) == SIGKILL)) {
waitpid(child_pid, &child_status, WNOHANG);
if( (slot = findslot(child_pid)) != -1 ) {
free_slots++;
pids[slot] = -1;
}
#ifdef DEBUG
fprintf(stderr, "DEBUG: caught sigchld from pid %d, free_slots = %d\n",
child_pid, free_slots);
#endif
}
}
signal(SIGCHLD, sigchld_handler);
}
void ignore_signals(void)
{
int i;
for( i = 1; i<=31; i++ ) signal(i, SIG_IGN);
}
int findslot(int pid)
{
int i;
for(i = 0; i<connections; i++)
if(pids[i] == pid) return i;
return -1;
}
void handleargs(int argc, char **argv, char *Hostname)
{
int i = 1;
if( !(options & F_PARANOID) )
sprintf(argv[0], "%s (%s)", CHILD_NAME, Hostname);
else i = 0;
for(; i<argc; i++) argv[i][0] = '\0';
}
int paranoid_coastclear(void)
{
struct stat dummy;
char *filename;
const char *cpa, *cpb;
const char tty[] = "/dev/tty";
const char pty[] = "pqrS";
const char order[] = "0123456789abcdef";
filename = alloca(strlen(tty) + 3);
strcpy(filename, tty);
filename[strlen(tty) + 1] = '\0';
/* check console terminals */
for(cpa = order; *cpa; cpa++) {
filename[strlen(tty)] = *cpa;
if( stat(filename, &dummy) < 0 ) break;
if( (time(NULL) - dummy.st_atime) < COASTCLEAR ) return 0;
}
/* check non-consoles */
filename[strlen(tty) + 2] = '\0';
for(cpa = pty; *cpa; cpa++) {
filename[strlen(tty)] = *cpa;
for(cpb = order; *cpb; cpb++) {
filename[strlen(tty) + 1] = *cpb;
if( stat(filename, &dummy) < 0 ) break;
if( (time(NULL) - dummy.st_atime) < COASTCLEAR ) return 0;
}
}
return 1;
}
int paranoid_lookout(void)
{
int i;
#ifdef DEBUG
fprintf(stderr, "DEBUG: paranoid_lookout called\n");
#endif
if(!paranoid_coastclear()) {
#ifdef DEBUG
fprintf(stderr, "DEBUG: PARANOID mode activated\n");
#endif
for(i = 0; i<connections; i++)
if(pids[i] != -1) kill(pids[i], SIGKILL);
while(free_slots < connections) {
usleep(USLEEP);
free_children();
}
sleep(COASTCLEAR);
while( !paranoid_coastclear() ) {
#ifdef DEBUG
fprintf(stderr, "DEBUG: coastclear returned 0, staying stealthy\n");
#endif
sleep(paranoid_secs);
}
#ifdef DEBUG
fprintf(stderr, "DEBUG: PARANOID mode deactivated\n");
#endif DEBUG
return 1;
}
return 0;
}
#ifdef PASSWORD_PROTECTED
int VerifyKEY(char *Accesskey)
{
int rv;
char *CryptKEY, *CryptCODE;
char Salt[2];
CryptKEY = EXECPASSWORD;
Salt[0] = CryptKEY[0];
Salt[1] = CryptKEY[1];
CryptCODE = crypt(Accesskey, Salt);
rv = strncmp(CryptKEY, CryptCODE, 13);
if( !rv )
return OK;
return FAILED;
}
#endif
TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH