Classic Computer Magazine Archive COMPUTE! ISSUE 73 / JUNE 1986 / PAGE 96

Atari Password

Glenn Anderson

Would you like to protect a diskful of important programs from prying eyes? If so, here's a solution that discourages all but the most determined snoops: a security program that denies access to your disk unless the correct password is entered. Even if someone boots from a different disk and bypasses the security program, your BASIC listings remain unreadable. For all Atari 400/800, XL, and XE computers with at least 24K RAM, a disk drive, and Atari DOS 2.0, 2.5, or 3.0.


Most people at one time or another have felt the need to protect their programs from prying eyes. At first the solution seems simple: When the program starts, it can ask the user to type in a code which is then compared to a password embedded in the program. If the user fails to enter the right password, the program can end with a NEW command, erasing itself from memory.
    This might deflect a rank beginner, but not many other computer users would be fooled. Anyone could obtain the password merely by stopping the program with the BREAK key, typing LIST, and reading through the listing. A password serves no purpose if it can be found so easily.
    To keep people from stopping the program and scanning the listing, you can disable the BREAK key by adding this line:

1 POKE 16,64:POKE 53774,64

Now if the user hits BREAK, nothing happens.
    The next thing a persistent person will do, however, is press the Atari's SYSTEM RESET button. The computer does what is called a warm start, and the program stops. Since the program is still in memory, the user can type LIST and start looking for the password.
    To prevent this from happening, you can add this line:

2 POKE 580,1

Now when SYSTEM RESET is pressed, the computer does a cold start instead of a warm start. It has the same effect as switching the power off and then on again, erasing any program in memory, rebooting the disk operating system (DOS), and loading and running an AUTORUN.SYS file if one is present on the DOS disk. With BREAK and SYSTEM RESET now safely disabled or trapped, the user can't stop your program and discover the secret password.

It's Still Vulnerable
But that assumes your program is running. The user can simply load the program without running it, then type LIST. To prevent this, you could make the BASIC program run automatically on powerup by writing a machine language booter or creating an AUTORUN.SYS file with the autobooting utility included with DOS 2.5. Whenever the computer is booted with this disk, the program automatically runs, and the user must enter the correct password to gain access to the rest of the program.
    This works if the user boots with that disk. But what's to stop people from booting with another disk? They can easily gain control of BASIC, insert your disk, load your program, and find the password.
    What's really needed is a way to save the program so that it can be run but not loaded. A method for this has already been found and published by COMPUTE! Books in Mapping the Atari, and similar solutions have appeared in other publications. To protect a program from being loaded, these two lines must be added:

32766 FOR VARI=PEEK(130)+PEEK(131)
      *256 TO PEEK(132)+PEEK
      (133)*256:POKE VARI,155:NEXT
      VARI
32767 POKE PEEK(138)+PEEK
      (139)*256+2,0:SAVE
      "D:filexame.ext":NEW

    It is important to make these the last two lines in the program. The first line fills the variable name table with RETURN characters. The second line finds the location in memory of the current statement line-line 32767 in this exampleand POKEs the value of zero into the length of that line. Now, when the computer tries to access a statement with a line number higher than 32767, it gets caught at line 32767 when searching for the line.
    This keeps the program from being loaded because of the way Atari BASIC handles an immediate mode command-it treats the immediate mode line as if it were numbered 32768. Since 32768 is higher than 32767, the computer never finds the immediate mode line and never executes it. Therefore, unless the computer is executing the program, the system is effectively crashed because nothing can be done in immediate mode. With this done, the only way to get the program into memory without crashing the system is to run the program at the same time it is loaded from disk: RUN "D.filename.ext".
    To lock and save a program in this manner, you enter GOTO 32766. The routine saves the pro gram with the filename you specified in line 32767. It also erases the program from memory with NEW, so it's a good idea to save an unprotected copy on another disk before protecting it in case the program needs revisions or debugging.

The Keeper Of The Keys
Now we've got the basis of a password program that can be used to keep out unwanted users. And, thanks to the AUTORUN.SYS loader, the program runs automatically when the disk is booted.
    Another idea is to make this autoboot program a menu program that can run other protected programs. This saves the trouble of adding a password procedure to all the protected programs on the disk. To let the other programs know that the user has successfully entered the correct password, the menu program can POKE some arbitrary but predetermined number into any location in an area of memory that is not erased when a new program runs. Then the first line of the new program can check this location for the proper value. If the location does not hold the correct value, the program can stop with a NEW command or rerun the menu program.
    You might also want to make the other programs rerun the menu program when they're finished. If this is done, it's wise to have the menu program check the secret memory location for the desired value again so that it knows whether the password has been successfully entered already. If it has, the menu program can skip over the password procedure.
    "Atari Password," listed below as Program 1, does all this and a little more. It also includes a way to change the password and unprotect the program.
    When typing Program 1, be especially careful with the DATA statements in lines 1-6. They contain information for restoring the variable name table when unprotecting the program.
    The initial password is in line 120: ENTER. Type this line exactly as it appears. If you want to change the password later, do it with the option provided for this purpose when running Atari Password, not by changing line 120.

Creating A Password Disk
When you've finished typing in Program 1, follow these steps before running the program:
    1. LIST at least one copy of Atari Password on a backup disk with the command LIST "D:filename.ext". Retain this copy as your unprotected backup. Use any filename you like except AUTORUN.BAS, because that's the name used by the protected version of Atari Password.
    2. Don't run the program yet. After saving your backup, type NEW to erase it from memory. Then type in Program 2, "Autoboot Maker," and save at least one copy of that program on your backup disk. Don't run this program yet, either.
    3. Type NEW to erase Program 2 from memory. Reload Atari Password (Program 1) from your back up disk with the command ENTER "D:filename.ext". This ensures that the variable name table will be in the proper state so that the program can be unprotected properly.
    4. Now you're ready to create a protected version of Atari Password. Insert a formatted disk that contains Atari DOS 2.0, 2.5, or 3.0. This will be your protected password disk.
    5. Type GOTO 9500 and press RETURN. After a brief pause, Atari Password saves a protected version of itself on the disk with the filename AUTORUN.BAS. When it's done, it erases itself from memory.
    6. Remove the password disk and insert the backup disk. Load Program 2.
    7. Remove the backup disk and insert the password disk. Run Program 2. It creates an AUTO RUN.SYS file on the password disk and informs you when it's done. If you've made a typing mistake in the DATA statements, it notifies you of your error. On power-up, this AUTORUN.SYS file runs a BASIC program named AUTORUN.BAS-the protected version of Atari Password. (Note that if there's already an AUTORUN.SYS file on the disk, it will be replaced by this AUTORUN.SYS. Rename or move the existing AUTORUN.SYS to another disk if you don't want to lose it.)
    8. The password disk is now prepared. To confirm that Atari Password is working properly, turn the power off, then on again to boot the disk. Atari Password should automatically load and run. You should be able to gain access to the program by typing the default password, ENTER, and then pressing the START button (do not press RETURN). Type the password carefully; the actual keys you press are not echoed on the screen, so it's easy to make a typing mistake: The SELECT button backspaces, and OPTION erases the entire input line. If you accidentally hit the CAPS key, the program may not recognize your password; uppercase and lowercase are significant. If the program denies access with a LOCKOUT message, press START to try again or SYSTEM RESET to reboot.

Using Atari Password
Once you've gained access, Atari Password presents a short menu. Press 1, 2, or 3 for your choice:

1 EXIT TO BASIC
2 CHANGE PASSWORD CODE
3 DISK DIRECTORY

    Option 1 exits Atari Password, erases the program from memory, and leaves you in BASIC.
    Option 2 lets you change the password from the default-ENTER-to anything you wish. When using this option, make sure you have the password disk inserted in the drive. It rewrites the part of Atari Password which checks for the code word. You can enter any combination of letters or numbers for the password, but it should be no more than 28 characters long.
    Option 3 calls up a disk directory on the screen. From this directory, you can load and run any BASIC program saved on the disk. To pick a program, move the arrow pointer with the cursor keys (you don't have to hold down CTRL as you normally do when moving the cursor in BASIC). Then press RETURN. If Atari Password can't load and run the program for some reason-perhaps it's not a BASIC program, or it's saved in LIST format-you're informed of this and allowed to pick another program. To return to the main menu, press the SELECT button.

Protecting BASIC Programs
To protect an ordinary BASIC program and make it dependent on Atari Password, follow these steps:

    1. Type in these three lines and LIST them to disk:

0 IF PEEK(1612)<>126 THEN RUN"D:
  AUTORUN.BAS"
32766 FOR VARI=PEEK(130)+PEEK
      (131)*256 TO PEEK(132)+PEEK
      (133)*256:POKE VARI,155:NEXT VARI
32767 POKE PEEK(138)+PEEK(139)*
      256+2,0:SAVE"D:filename.ext"
      :NEW

(Notice line 0; it checks to see whether memory location 1612 contains the value 126. If not, it reruns Atari Password, a protection technique that we mentioned above. If you change Atari Password to put a different number in this location, or if you change the location, be sure to make the change here also.)
    2. Load the BASIC program you want to protect. Be sure it doesn't already contain lines numbered 0, 32766, or 32767. Then merge the above lines with your BASIC program by ENTERing the lines from disk.
    3. Change the filename.ext in line 32767 to whatever name you wish to use for the protected version of your program.
    4. Make sure the password disk is inserted in the drive. Type GOTO 32766 and press RETURN. When the READY prompt reappears, the program is protected. Now it can be run only after the password has been successfully entered with Atari Password.
    Some password-protected programs have what's known as a back door. This is a secret way to bypass the protection. Atari Password doesn't have a back door, but it does have a secret feature that lets you exit the password program to BASIC without erasing the program from memory. When the main menu is on the screen, press the S key and wait. After five or ten seconds, the buzzer sounds. Then press the B key. You'll find yourself in BASIC with the password program intact.

How It Works
Here's a breakdown of Atari Password:

Lines
1-6
These are DATA statements to refill the variable name table.
60-110 Initialization. Note the variables TRUE and FALSE which assign values to Boolean variables.
120 Contains the password. See explanation below for lines 6000-6080.
500 Checks to see whether the program has been previously run. If not, it checks for password. The memory address (1612) and code value (126) in this line can be changed to any free location and value that you would like, but be sure to reflect your change in line 5000 also.
510 The program reaches here only if the correct password has been entered. If so, it jumps to the main menu.
1000-1160 The main loop of the password-checking routine.
1200-1220 Backs up one space if SELECT is pressed while a password is being entered.
1300 Erases the entire input line if OPTION is pressed while a password is being entered.
1500-1510 Checks for the correct password if START is pressed.
1600-1650 Sounds alarm and displays the LOCKOUT message until START is pressed if the incorrect password is entered.
1999 Returns from the password-checking routine.
2000-2010 Fills the screen with inverse spaces.
2500-2600 Gets the actual password code from C$ and puts it in CODE$.
3000-3210 Main menu section.
6000-6080 This routine changes the password code. It does this by opening Atari Password on disk for read and write and searching for the occurrence of the two Z's that can be seen in line 120. When it finds this flag, it writes the new password code to disk. Something to note is the #16 in line 6005; this suppresses the question mark which is the normal INPUT prompt.
7000-7460 This routine calls the disk directory. It prints the directory on the screen along with an arrow-shaped pointer that can be moved to the desired filename. RETURN runs the selected program. If the entire directory cannot fit on the screen, the message <MORE> appears. Press START to see the rest of the directory or SELECT to go back to the main menu. This routine can be removed and used in your own programs, but remember to DIMension the variables DIR$, ENT$, and PR$, and use a GRAPHICS 0 statement, because the routine uses LOCATE to read the filename from the screen.
9000-9030 Restores the program to BASIC with the listing intact. This is done by refilling the variable name table with its original values, which are stored as DATA statements. Then it POKES the correct length into line 9510. For this reason, you shouldn't change any of the variables in this program.
9500-9510 This short routine creates the protected version of the password program on disk.

For instructions on entering these listings,
please refer to "COMPUTEI's Guide to Typing
In Programs" in this issue of COMPUTE!.


Program 1: Atari Password

FD 1 DATA 84,82,85,197,70,65
     ,76,83,197,83,84,65,82,
     212,83,69,76,69,67,212,
     79
PC 2 DATA 80,84,73,79,206,84
     ,82,89,164,67,79,68,69,
     164,67,164,68,73,82,164
MM 3 DATA 69,78,84,164,80,82
     ,164,208,75,69,89,80,82
     ,69,83,83,69,196,67,79
FP 4 DATA 78,B3,79,204,193,2
     01,217,78,67,164,68,79,
     78,197,68,77,65,216,77,
     79
1G 5 DATA 82,197,68,84,79,20
     8,66,79,212,216,68,69,2
     04,79,217,79,216,214,88
     ,67
JP 6 DATA 200,69,216,88,177,
     83,212,76,201,86,65,82,
     201,202
JN A60 OPEN #1,4,0,"K:"
BJ 70 GRAPHICS 0:POKE 82,2
AA 80 POKE 580,1:POKE 16,64:
      POKE 53774,64
LB 90 SETCOLOR 4,10,0:SETCOL
      OR 2,10,0
PJ 100 TRUE=(1=1):FALSE=(1=0
       ):START=6:SELECT=5:OP
       TION=3
CD 110 DIM TRY$(30),CODE$(30
       ),C$(32),DIR$(1235)IE
       NT$(17),PR$(14),NC$(3
       0)
MH 120 C$="ZZENTER**********
       ***************"
GA 500 IF PEEK(1612)<>126 TH
       EN GOSUB 2500:GOSUB 1
       000:POKE 1612,126
JC 510 GOTO 3000
IA 997 END
PM 999 REM GET PASSWORD CODE
LH 1000 POKE 752,1:GOSUB 200
        0:POSITION 2,2:? "{RVS}CO
        DE:{OFF}";:POSITION 7,2
FN 1010 P=0:TRY$=""
NP 1040 P=P+1:KEYPRESSED=FAL
        SE
DM 1045 IF P=30 THEN 1300
CL 1050 IF PEEK(764)<)255 AN
        D PEEK(764)<>154 THE
        N KEYPRESSED=TRUE
FC 1060 CONSOL=PEEK(53279)
0J 1065 IF CONSOL=START THEN
        1500
BE 1070 IF CONSOL=SELECT THE
        N 1200
DD 1075 IF CONSOL=OPTION THE
        N 1300
DG 1100 IF NOT KEYPRESSED T
        HEN 1050
BE 1110 GET #1,A
FJ 1130 TRY$(P)=CHR$(A)
HP 1140 PRINT "{RVS}-{OFF}";
N6 1160 GOTO 1040
DE 1198 REM BACKSPACE
HK 1200 IF P<=1 THEN GOTO 10
        50
EP 1210 P=P-1:TRY*(P)="":? "
        {BELL}{LEFT}{RVS} {OFF}{LEFT}";
ME 1220 GOTO 1050
EH 1298 REM CLEARLINE
EB 1300 POSITION 7,2:FOR I=1
         TO P:? "{RVS} {OFF}";:NEXT I:
        TRY$="":POSITION 7,2
        :P=1:GOTO 1050
DK 1498 REM CHECK ENTERED CO
        DE
FK 1500 PRINT "{ESC}
        {CLR TAB}";:FOR I=1
        TO 200:NEXT 1
CH 1505 IF TRY$<>CODE$ THEN
        1600
NM 1510 GOTO 1999
IB 1598 REM NO GOOD
AM 1600 GOSUB 2000:POSITION
        16,12:? "{RVS}LOCKOUT{OFF}"
HF 1610 SOUND 1,50,10,10:POK
        E 755,2:FOR I=1 TO 5
        0
JH 1620 IF PEEK(53279)<>STAR
        T THEN NEXT I
KB 1630 SOUND 1,100,10,10:PO
        KE 755,0:FOR I=1 TO
        50
NE 1640 IF PEEK(53279)<>STAR
        T THEN NEXT I:GOTO 1
        610
FP 1650 POP :SOUND 1,0,0,0:P
        OKE 755,2:8070 1000
LM 1999 RETURN
HH 2000 ? "{CLEAR}";:FOR Y=1
         TO 23:? "
        {38 {RVS}SPACES{OFF}}";:NEXT Y
KD 2010 RETURN
IN 2500 P=3
HN 2510 IF C$(P,P)="*" THEN
        2600
MJ 2520 CODE$(P-2)=C$(P,P)
AD 2530 P=P+1
MM 2540 GOTO 2510
KI 2600 RETURN
PF 2998 REM MENU
GA 3000 PRINT "{CLEAR}{38 N}
        ";
NK 3010 PRINT "{18 SPACES}ME
        NU"
LP 3020 PRINT "{38 M}";
AI 3040 PRINT " 1 EXIT TO BA
        SIC"
PP 3050 PRINT " 2 CHANGE PAS
        SWORD CODE"
KN 3060 PRINT " 3 DISK DIRE{
        TORY"
OK 3070 PRINT "{38 N}";
GM 3080 GET #1,A
BA 3090 IF A=ASC("S") THEN G
        OSUB 9000
LN 3100 IF A=ASC("B") AND LI
        =-999 THEN GRAPHICS
        0:END
LO 3200 IF A<49 OR A>51 THEN
         3080
CA 3210 ON A-48 8070 5000,60
        00,7000
FL 5000 GRAPHICS 0:POKE 580,
        0:POKE 1612,0:NEW
MB 5999 REM CHANGE CODE WORD
OP 6000 POKE 752,0
NF 6005 ? "{CLEAR}ENTER NEW
        CODE PASSWORD(S)";:I
        NPUT #16,NC$
FJ 6010 OPEN #2,12,0,"D:AUTO
        RUN.BAS"
AG 6020 IF LEN(NC$)>29 THEN
        NC$(29)=""
GL 6030 FOR I-LEN(NC$)+1 TO
        30:NC$(LEN(NC$)+1)="
        *":NEXT I
JI 6040 GET #2,A:IF A=90 THE
        N GET #2,A:IF A=90 T
        HEN 6060
NO 6050 GOTO 6040
NC 6060 FOR I=1 TO 30:PUT #2
        ,ASC(NC$(I,I)):NEXT
        I
JI 6070 CLOSE #2
PM 6075 POKE 752,1
MK 6080 GOTO 3000
KA 6999 REM DIRECTORY ROUTIN
        E
HP 7000 OPEN #5,6,0,"D:*.*"
KI 7010 DIR$(1)=" ":DIR$(123
        5)=" ":DIR$(2)=DIR$
JN 7020 DONE=FALSE
PE 7030 POKE 752,1
II 7040 P=0
AF 7050 P=P+1
ON 7060 INPUT #5,ENT$
MH 7070 IF ENT$(5,8)="FREE"
        THEN DONE=TRUE
MM 7080 IF DONE THEN 7110
PG 7090 DIR$(P*19-18,P*19)=E
        NT$
MN 7100 GOTO 7050
II 7110 CLOSE #5:DMAX=P
BB 7120 P=1:MORE=FALSE:IF DM
        AX>40 THEN MORE=TRUE
FN 7130 DTOP=40:IF NOT MORE
        THEN DTOP=DMAX
GM 7140 POKE 82,2:POKE 83,39
        :PRINT "{CLEAR}
        {13 {RVS}SPACES{OFF}{RVS}DIRECTORY
        {15 {RVS}SPACES{OFF}}"
JL 7150 PRINT DIR$(P,DTOP*19
        );:IF DTOP/2<>INT(DT
        OP/2) THEN PRINT
DA 7160 BOT=PEEK(84)-1
KA 7170 ? " {36 R}";:IF MORE
         THEN POSITION 17,22
        :PRINT "<MORE>";
BK 7180 X=1:Y=1:POSITION X,Y
        :? "{ESC}{RIGHT}"
HI 7190 KEYPRESSED=FALSE
DB 7210 IF PEEK(764)<>255 TH
        EN KEYPRESSED=TRUE
FG 7220 CONSOL=PEEK(53279)
MB 7230 IF CONSOL=START AND
        MORE AND P<>l THEN 7
        120
KC 7240 IF CONSOL=START AND
        MORE THEN P=(DTOP+1)
        *19+1:DTOP=DMAX:GOTO
        7140
BO 7245 IF CONSOL=SELECT THE
        N 3000
FL 7250 IF KEYPRESSED THEN 7
        270
NC 7260 GOTO 7210
IE 7270 OY=Y:OX=X
EN 7280 GET #1,V:IF V=45 THE
        N Y=Y-1:IF Y<l THEN
        Y=1
ME 7290 IF V=61 THEN Y=Y+1:I
        F Y>BOT THEN Y=BOT
HJ 7300 IF V=43 OR V=42 THEN
         XCH=XCH+1:IF XCH/2=
        INT(XCH/2) THEN X=1:
        GOTO 7320
BE 7310 IF V=43 OR V=42 THEN
         X=20
IH 7320 IF V=155 THEN 7350
PN 7330 POSITION OX,OY:? " "
        :POSITION X,Y:? "
        {ESC}{RIGHT}"
NI 7340 GOTO 7190
PP 7350 EX=0:PR$="D:":FOR Xl
        =X+3 TO X+13
ND 7360 LOCATE Xl,Y,V:IF V=3
        2 THEN 7400
BP 7370 PR$(LEN(PR$)+1)=CHR$
        (V)
AF 7380 IF X1=X+10 THEN 7400
NK 7390 GOTO 7430
NO 7400 IF EX=1 THEN EX=0:80
        TO 7420
KL 7410 X1=X+11:LOCATE Xl,Y,
        V:IF V<>32 THEN PR$(
        LEN(PR$)+1)=".":X1=X
        1-1:EX=1:GOTO 7430
NF 7420 GOTO 7440
JG 7430 NEXT X1
ML 7440 TRAP 7450:RUN PR$
EN 7450 POSITION 13,23:? "CA
        NNOT BE RUN";:GET #1
        ,A
NE 7460 GOTO 7120
LO 8990 REM
FN 8991 REM THIS ROUTINE IS
        NOT ON THE MENU
AO 8992 REM IT RESTORES THE
        PROGRAM TO BASIC WIT
        H
HP 8993 REM THE LISTING INTA
        CT
OO 8994 REM TO USE THIS OPTI
        ON PRESS S AT THE ME
        NU
KG 8995 REM AND THEN PRESS B
         WHEN YOU HEAR THE B
        UZZER
MA 9000 ST=PEEK(136)+PEEK(13
        7)*256
BH 9010 LI=PEEK(ST)+PEEK(ST+
        1)R256:IF LI<>9510 T
        HEN ST=ST+PEEK(ST+2)
        :GOTO 9818
KH 9020 IF PEEK(ST+2)=0 THEN
         POKE ST+2,72:RESTOR
        E 1
DI 9030 FOR I=1 TO 115:LI=PE
        EK(130)+PEEK(131)*25
        6+(I-1):READ VARI:PO
        KE LI,VARI:NEXT I:LI
        =-999:? "(BELL)":RET
        URN
DI 9498 REM PROTECT SAVE ROU
        TINE
OG 9500 FOR VARI=PEEK(130)+P
        EEK(131)*256 TO PEEK
        (132)+PEEK(133)*256:
        POKE VARI,155:NEXT V
        ARI
EP 9510 POKE PEEK(138)+PEEK(
        139)*256+2,0:SAVE "D
        :AUTORUN.BAS":NEW


Program 2: Autoboot Maker

PA 10 OPEN 01,8,0,"D:AUTORUN
      .SYS"
PN 20 TRAP 40
BJ 30 READ A:PUT #1,A:CHK=CH
      K+A:GOTO 30
BJ 40 IF CHK<>10833 THEN ? "
      Error in DATA statemen
      ts!":END
PE 50 ? "AUTORUN.SYS file ha
      s been written."
CF 1000 DATA 255,255,0,6,109
        ,6
IN 1010 DATA 169,5,141,197,2
        ,133
BJ 1020 DATA 84,169,49,141,6
        8,3
GI 1030 DATA 169,6,141,69,3,
        169
CF 1040 DATA 0,141,73,3,169,
        61
IG 1050 DATA 141,72,3,169,11
        ,141
PI 1060 DATA 66,3,162,0,32,8
        6
ME 1070 DATA 228,169,0,133,8
        4,133
BE 1080 DATA 85,169,13,141,7
        4,3
DP 1090 DATA 96,71,82,46,49,
        43
DF 1100 DATA 49,54,58,63,35,
        54
FB 1110 DATA 59,34,32,32,32,
        207
FB 1120 DATA 206,197,160,205
        ,207,205
FN 1130 DATA 197,206,212,174
        ,174,174
ED 1140 DATA 34,58,80,79,75,
        69
CO 1150 DATA 32,56,52,50,44,
        49
DN 1160 DATA 50,58,82,85,78,
        34
EO 1170 DATA 68,58,65,85,84,
        79
EH 1180 DATA 82,85,78,46,66,
        65
OK 1190 DATA 83,34,226,2,227
        ,2,0,6