From f5f7603a55d4fbe9cda585f3464ace490627a6ed Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Mon, 3 Jun 2024 18:23:28 -0400 Subject: protbas: split off protection functions from unprotbas. --- protbas.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 protbas.c (limited to 'protbas.c') diff --git a/protbas.c b/protbas.c new file mode 100644 index 0000000..e57ead3 --- /dev/null +++ b/protbas.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +#include + +#include "bas.h" + +int protect_vars = 1; +int protect_code = 1; +int shrinktable = 0; +int varname_char = 0x9b; + +/* 32767 END */ +unsigned char badcode[] = { + 0xff, 0x7f, /* line number 32767 */ + 0x00, /* *bad* next-line offset */ + 0x06, /* next-statement offset */ + 0x15, /* END token */ + 0x16, /* end-of-line token */ +}; + +void scramble_vars(void) { + int i; + + if(!vntable_ok()) { + fprintf(stderr, "%s: Program already was variable-protected.\n", self); + exit(2); + } + + if(shrinktable) { + if(verbose) fprintf(stderr, "Shrinking variable name table.\n"); + adjust_vntable_size((vvstart - 1) - vnstart, (codestart - vvstart) / 8); + } + + if(varname_char == -1) srand(time(NULL)); + + for(i = vnstart; i < vvstart - 1; i++) + if(varname_char == -1) + program[i] = (rand() >> 8) & 0xff; + else + program[i] = varname_char & 0xff; + + if(verbose) { + i -= vnstart; + if(i) { + fprintf(stderr, "Replaced %d byte variable name table with ", i); + if(varname_char == -1) + fprintf(stderr, "random characters.\n"); + else + fprintf(stderr, "character $%02x.\n", varname_char); + } else { + fprintf(stderr, "Can't protect variables because there are no variables.\n"); + } + } +} + +/* iterate over all the lines, insert a poisoned line 32767 just + before line 32768 */ +void breakcode(void) { + int pos = codestart, oldpos = 0; + int offset, lineno = -1, tmpno = -1; + + while(pos < filelen) { + lineno = tmpno; + tmpno = getword(pos); + if(tmpno == 32768) { + break; + } else { + offset = program[pos + 2]; + if(!offset) { + fprintf(stderr, "%s: program already was code-protected.\n", self); + exit(2); + } + oldpos = pos; + pos += offset; + } + } + + if(!oldpos) die("Can't protect code because there are no lines of code."); + if(lineno == 32767) die("Can't protect code because there is already a line 32767."); + + /* pos is now the start of line 32768, move it up to make room for + the new line */ + offset = sizeof(badcode); + memmove(program + pos + offset, program + pos, filelen); + + /* insert new line */ + memmove(program + pos, badcode, offset); + + if(verbose) + fprintf(stderr, "Inserted line 32767 with invalid offset at file offset $%04x.\n", pos); + + /* update pointers that would be affected by the code move */ + stmcur += offset; + starp += offset; + filelen += offset; + update_header(); + parse_header(); +} + +void print_help(void) { + fprintf(stderr, "Usage: %s [-v] [-nc|-nv] [-s] [-x[r|NN]] \n", self); + fprintf(stderr, " -v: Verbose.\n"); + fprintf(stderr, " -nc: Don't protect code.\n"); + fprintf(stderr, " -nv: Don't protect variable names.\n"); + fprintf(stderr, " -s: Shrink variable name table to min size.\n"); + fprintf(stderr, "-xNN: Hex code NN for variable names.\n"); + fprintf(stderr, " -xr: Random variable names.\n"); + fprintf(stderr, "Use - as a filename to read from stdin and/or write to stdout.\n"); +} + +void parse_args(int argc, char **argv) { + int opt, xopt_used = 0; + + while( (opt = getopt(argc, argv, "vn:x:s")) != -1) { + switch(opt) { + case 'v': verbose = 1; break; + case 's': shrinktable = 1; break; + case 'n': + switch(optarg[0]) { + case 'c': protect_code = 0; break; + case 'v': protect_vars = 0; break; + default: + die("Invalid argument for -n (must be 'c' or 'v')."); + } + break; + case 'x': + xopt_used = 1; + switch(optarg[0]) { + case 'r': + varname_char = -1; break; + case 0: + die("-x option requires a hex number or 'r'."); break; + default: + { + char *e; + varname_char = (int)strtol(&(*argv)[2], &e, 16); + if(*e != 0 || varname_char > 0xff) + die("Invalid hex value for -x option (range is 0 to ff)."); + } + } + break; + default: + print_help(); + exit(1); + } + } + + if(!protect_code && !protect_vars) { + die("Nothing to do: -nc and -nv both given."); + } + + if(!protect_vars) { + if(xopt_used) + die("-x option not valid with -nv."); + if(shrinktable) + die("-s option not valid with -nv."); + } + + if(optind >= argc) + die("No input file given (use - for stdin)."); + else + open_input(argv[optind]); + + if(++optind >= argc) + die("No output file given (use - for stdout)."); + else + output_filename = argv[optind]; +} + +int main(int argc, char **argv) { + set_self(*argv); + parse_general_args(argc, argv, print_help); + parse_args(argc, argv); + readfile(); + parse_header(); + + if(verbose) { + fprintf(stderr, "Protecting program, "); + if(protect_vars && !protect_code) + fprintf(stderr, "variables only.\n"); + else if(protect_code && !protect_vars) + fprintf(stderr, "code only.\n"); + else + fprintf(stderr, "both code and variables.\n"); + } + if(protect_vars) scramble_vars(); + if(protect_code) breakcode(); + + open_output(output_filename); + writefile(); + return 0; /* TODO: meaningful return status */ +} -- cgit v1.2.3