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 <filename> "+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 *<filename>).
If you wish to contact me directly please write to:
M.T.Farnworth
27 Hunt St
Atherton
Manchester
M29 9JF
Or else write to me via the 8BS messaging system (which is cheaper on
postage but a lot slower!)