This article covers both the techniques behind protecting programs and data and the ways to actually do it in practice. If you're an experienced programmer, you will no doubt find the explanations interesting - any comments or additional suggestions to the usual address. But even if you have little or no experience of programming, the practical methods outlined are perfectly usable - just skip over the technical bits and grab the sample listings instead! But please don't everyone start adding massive protection routines to their PD programs, unless there's a very good reason for it, because it is often useful for people learning programming to look through other peoples' coding, as well as the fact we might need to make a few modifications occasionally - D.G.S. How to protect your BASIC programs By M.T.Farnworth (with a bit of help from DGS) One of the simplest ways of protecting your program is to make the computer disable output to the screen. This is not as difficult as it may sound. It is achieved by making the computer print ASCII character 21. To do this you can use a REM statement at the beginning of the program with the character in it. What I normally do is to insert the line: 10 REM . I then use a memory editor to find the full stop which has the ASCII code 46 and replace the number 46 with 21 using ?address=21. For those of you who do not feel competent enough to do that yourselves the program below will do it for you. 10 C%=PAGE+&100 20 !C%=&70A000D 30 C%!8=&D1520F4 40 I."Please enter filename of program to protect:"file$ 50 OSCLI"LOAD "+file$+" "+STR$~(C%+7) 60 PAGE=C%:END If you now attempt to list your program it will print the line 10 REM and then stop. The computer will appear to have hung up but if you type VDU 6 the prompt will reappear. You may save the program in this form in the normal way. The only problem with this protection is that anyone who knows about it will spot it rapidly, and just type LIST 20, instead of LIST, so that the ASCII code 21 will not be printed by the computer. [Alternatively they could delete whichever line contained the control code, or even load the program into a text editor to see what was going on - D.G.S. ] Because of this, this protection technique is better used in a more subtle way. The first variation I will explain is that shown to me by Daniel. [Though to be honest I probably stole the idea from someone else - D.G.S.] His idea was to insert a sufficient number of character codes to result in the following appearing on the screen when the LIST command is given: Bad Program > This would make the innocent hacker (?) think that it was in fact a piece of machine code, and give up without realising that all that need to be done is delete the first line of the program. To do this a REM statement is used at both beginning and end. The one at the beginning is used to print the message "Bad Program" and switch off the screen output, and the one at the end to switch screen output back on again. In order that the game is not given away by the computer printing 10 REM before it prints "Bad program", we must overwrite the 10 REM after it has been printed by moving the cursor back using control codes in the second REM statement. One of the easiest ways to insert the necessary codes is to use the Master Text Editor, as a program to insert them automatically would have to be quite complex. Pressing CTRL-U while EDITing a BASIC program would insert ASCII code 21 (disable VDU output), CTRL-H would insert ASCII 8 (Backspace), CTRL-F would insert ASCII 6 (enable VDU output) and CTRL-J gives ASCII 10 (Cursor Down/Line feed. Therefore you would have something like: 10 REM CTRL-H CTRL-H SPC SPC CTRL-J CTRL-H CTRL-H Bad program CTRL-J > CTRL-U 20 ... 30 ...Program here 40 ... 50 REM CTRL-H CTRL-F (Don't include all the spaces, just the ones marked by SPC). You would have to use more spaces and CTRL-H in line 10 than this, until you achieve an exact replica of the real "Bad program" message. The CTRL-H in line 50 is to move the cursor back so that the computer prints its own prompt (">") over the top of the one we have inserted - otherwise two prompts would appear, and the hacker would know something was up! The way we have inserted a prompt, and made the cursor appear to the right of it while the screen is disabled is one of the best things about this technique, because it makes it unlikely that the hacker will think the computer is busy listing something - the prompt and cursor make it seem that the computer is in fact awaiting input! (For those of you that don't know, simply use "EDIT" to enter Master EDIT from BASIC while you have the program loaded and SHIFT-f4 to leave). Bear in mind that you could also use other control codes, say to clear the screen, go into MODE 2 and print up a big message to the prospective hacker! This method works by fooling the hacker into thinking there is no BASIC program there to hack. If, however, your opponent is wise to this technique - or has noticed that the load/execution addresses are characteristic of a BASIC program - then again they could simply delete line 10. This could be got round by using, for example, RENUMBER 5200,1. Now that your program is renumbered they will never be able to find the first line in order to delete it. They could still, of course, load the file into BASIC IV and then EDIT it, or even *TYPE it, since *TYPE, unlike *PRINT, does not send control codes (such as 21) to the screen. ******* A variation on this technique is to hide only certain sections of the coding - this can be accomplished in two different ways. The first is to place REM statements in the listing around the section of code you wish to conceal, and then insert the necessary codes for output enable and disable (i.e. ASCII 21 and 6 respectively). The problem with that is that if like myself you very rarely use REM statements they stick out like a sore thumb when you do insert them to hide things. So for this reason I developed another method. Take the line: 10 PRINT".":IF dummy$="HELLO" VDU6:PROCcheat ELSE PRINT"." If the first full stop is replaced by character 21 and the second replaced by 6 the result is that when listed the line appears as: 10 PRINT"" When the program is RUN, if the statement is true the VDU6 reverses the action of the first PRINT command and if it is false the other PRINT command reverses the action, so that your protection techniques don't start switching off the VDU output while your program is running! [ M.T.F. once sent me a program protected in this way, without telling me about the hidden lines - but I wanted to alter what was PRINTed, which led me to discover that something was up! No protection technique is totally foolproof - D.G.S. ] One important thing to remember when hiding sections of coding is to hide smallish sections, as otherwise the delay which occurs as the computer attempts to print the hidden bits to screen becomes noticeable. That concludes our look at character codes, but you might consider their use for other things, such as making sure that every time you list the program the text is yellow and the background blue. ******* The next technique that we will discuss is a very simple one which turns a program into a real "Bad Program", but still allows you to run it. This technique works because of the way a BASIC program is stored in memory. The last two bytes of the program are &0D and &FF (i.e. 13 and 255) respectively. If these two bytes are changed the program is then classed as a "Bad program" but the program can still be RUN. Our friendly hacker will receive a "Bad program" message as soon as he loads the program, and whenever he attempts to LIST it. He might not even try to RUN it at all, assuming that it won't work. Changing the last two bytes is simple; all that it requires is the command !(TOP-2)=&1234. To restore the program to normal use the command !TOP=&FF0D To run a program which is protected in this way it must be LOADed and then RUN. It is not necessary to restore the program in order to RUN it, but it will help if the last line of the program to be protected contains a REM statement as it may be corrupted. N.B. CHAIN will not work on a program altered in this way. Note that once you have entered the command !(TOP-2)=&1234 the normal SAVE command will not work and you must use OSCLI"SAVE "+STR$~PAGE+" "+STR$~(TOP+2) That concludes our look at protecting a program by changing the last two bytes. ******** The final technique which I will explain is that of using the Exclusive OR operation, which is normally known as EOR. This need not only be used on BASIC programs. EOR Truth Table Inputs ! Output ===========!========= 0 0 ! 0 0 1 ! 1 1 0 ! 1 1 1 ! 0 It is probably not immediately obvious from the table above but ((x EOR y) EOR y)=x This result may appear pointless at first but it is in fact a way of scrambling data and an ideal way to protect your program. Consider: z=(x EOR y) where x,y, and z, are each 1 byte long. It is possible to get x from z, but only if you know what y is. If this is done to every byte in the program the result is an unusable piece of data. If however the data is then EORed with y again the result is the original program. In other words, you scramble program X by EORing it with byte Y, and can then unscramble it by EORing it with the same thing again. The above technique is probably the most common way of scrambling files. There are two different ways it can be used. 1) Use a routine to unscramble the program without any user input. 2) Have a program which requests the code be entered and then uses it to unscramble the program. The later is probably one of the best ways of protecting your program with a password as no record of the password is kept within the program and as a result it is not so susceptible to hackers. Below is an example program which will both scramble and unscramble a program, or indeed any file. (Remember the same routine will do both as you do the same thing to the data to scramble and unscramble it.) 10 INPUT"Source Filename:"sfile$ 20 INPUT"Destination Filename:"dfile$ 30 X=OPENINsfile$ 40 Y=OPENOUTdfile$ 50 INPUT"Scramble to what number (1-255):"num% 60 REPEAT 70 BPUT#Y,(BGET#X EOR num%) 80 UNTIL EOF#X 90 CLOSE#X:CLOSE#Y 100 PRINT"Process Complete." N.B. The number 0 is excluded as when you EOR with 0 you get what you started with. This routine is all right but there are only 255 different possibilities and it would not take particularly long to go through them all if you were determined enough. [And we are - D.G.S.] In addition the first byte of a BASIC program is always the same, so you could work out which number had been used to scramble with. This is where the RND function comes in. In reality it does not produce truly random numbers, it simply uses a complex equation, and as a result you can do what is called SEEDING. You then know that the order of the numbers produced by RND will always be the same, and that the scramble code will be harder to crack as there are over 2 billion combinations. The program now becomes: 10 INPUT"Source Filename:"sfile$ 20 INPUT"Destination Filename:"dfile$ 30 X=OPENINsfile$ 40 Y=OPENOUTdfile$ 50 INPUT"What is seed number:"num% 55 dummy=RND(-num%):REM Seeding RND function 60 REPEAT 70 BPUT#Y,(BGET#X EOR RND(256)) 80 UNTIL EOF#X 90 CLOSE#X:CLOSE#Y 100 PRINT"Process Complete." The above routine is also useful because even if you leave a copy of both the scrambled and unscrambled versions about it is still difficult to find the random numbers seed whereas when using the first of the two routines all you have to do is EOR the source file and destination file to get the code number. Both the above routines could be used with the number to EOR with already in the program but then they really need to be in machine code as otherwise the hacker would load the BASIC unscrambler program and use it to unscramble the data. When it is machine code you have the double hope that a) he cannot do machine code, or b) he will not have a disassembler on him. The second of the two programs is somewhat hard to put into machine code but the first is very easy. Another technique which I often use instead of them is to EOR each number with a value one greater than the one before it. The only problem with that is when going over a group of zero bytes the sequence is obvious when looked at as it goes 0,1,2,3,4,5,etc.. This is also true of the first routine as it would go 72,72,72,72,etc.. (72 is just an example value, it would be whatever code number you used.) That concludes this article on BASIC program protection techniques. I hope it has been useful. N.B. There is a BASIC program on the disk under the filename ":2.SCRAM" (or accessible via the software menu) which automatically scrambles/unscrambles files when you load or save them using LOAD, SAVE, *LOAD, or *SAVE (but NOT *RUN or *). If you wish to contact me directly please write to: M.T.Farnworth Or else write to me via the 8BS messaging system (which is cheaper on postage but a lot slower!)