Os adjunto un programa en Python3 que decodifica un programa Basic no protegido. Me he encontrado un documento y no me he podido resistir
No lo he probado mucho, así que algo no esperado pudiera pasar.
Código: Seleccionar todo
fichero = open("bomb.bas", "rb")
bytes = []
try:
bytes = fichero.read()
except:
pass
print (len(bytes))
puntero = 0
basic = bytes[128:] # quitamos la cabecera
print (len(basic))
FIN_LINEA = 0x00
VARI_ENTERO = 0x02 #integer variable definition (defined with "%" suffix)
VARI_STRING = 0x03 #string variable definition (defined with "$" suffix)
VARI_FLOAT = 0x04 #floating point variable definition (defined with "!" suffix)
VALOR_8BIT = 0x19 #8-bit integer decimal value
VALOR_16BIT = 0x1a #16-bit integer decimal value
VALOR_BIN16BIT = 0x1b #16-bit integer binary value (with "0xX" prefix)
VALOR_HEX16BIT = 0x1c #16-bit integer hexadecimal value (with "0xH" or "0x" prefix)
VALOR_STRING = 0x22 #'"', #quoted string value
COMILLAS = '"'
BASIC_PUNTERO = 0x1d #16-bit BASIC program line memory address pointer
BASIC_NUMLIN = 0x1e #: 16-bit integer BASIC line number
VALORES = [VALOR_8BIT, VALOR_16BIT, VALOR_BIN16BIT, VALOR_HEX16BIT, VALOR_STRING]
VARIABLES = [VARI_ENTERO, VARI_STRING, VARI_FLOAT, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d]
PRINTABLE = [0x23,0x7b]
RSX = 0x7c # "|" symbol; prefix for RSX commands
TOKENS = {
0x01: ":", # statement seperator
0x0e: '0', #number constant "0"
0x0f: '1', #number constant "1"
0x10: '2', #number constant "2"
0x11: '3', #number constant "3"
0x12: '4', #number constant "4"
0x13: '5', #number constant "5"
0x14: '6', #number constant "6"
0x15: '7', #number constant "7"
0x16: '8', #number constant "8"
0x17: '9', #number constant "9"
0x18: '10', #number constant "10"
0x1f: '.', #floating point value
0x20: " ", #(space) symbol
0x21: '!', #ASCII "!" symbol
0x80: 'AFTER',
0x81: 'AUTO',
0x82: 'BORDER',
0x83: 'CALL',
0x84: 'CAT',
0x85: 'CHAIN',
0x86: 'CLEAR',
0x87: 'CLG',
0x88: 'CLOSEIN',
0x89: 'CLOSEOUT',
0x8a: 'CLS',
0x8b: 'CONT',
0x8c: 'DATA',
0x8d: 'DEF',
0x8e: 'DEFINT',
0x8f: 'DEFREAL',
0x90: 'DEFSTR',
0x91: 'DEG',
0x92: 'DELETE',
0x93: 'DIM',
0x94: 'DRAW',
0x95: 'DRAWR',
0x96: 'EDIT',
0x97: 'ELSE',
0x98: 'END',
0x99: 'ENT',
0x9a: 'ENV',
0x9b: 'ERASE',
0x9c: 'ERROR',
0x9d: 'EVERY',
0x9e: 'FOR',
0x9f: 'GOSUB',
0xa0: 'GOTO',
0xa1: 'IF',
0xa2: 'INK',
0xa3: 'INPUT',
0xa4: 'KEY',
0xa5: 'LET',
0xa6: 'LINE',
0xa7: 'LIST',
0xa8: 'LOAD',
0xa9: 'LOCATE',
0xaa: 'MEMORY',
0xab: 'MERGE',
0xac: 'MID$',
0xad: 'MODE',
0xae: 'MOVE',
0xaf: 'MOVER',
0xb0: 'NEXT',
0xb1: 'NEW',
0xb2: 'ON',
0xb3: 'ON BREAK',
0xb4: 'ON ERROR GOTO',
0xb5: 'SQ',
0xb6: 'OPENIN',
0xb7: 'OPENOUT',
0xb8: 'ORIGIN',
0xb9: 'OUT',
0xba: 'PAPER',
0xbb: 'PEN',
0xbc: 'PLOT',
0xbd: 'PLOTR',
0xbe: 'POKE',
0xbf: 'PRINT',
0xc0: "'", #symbol (same function as REM keyword)
0xc1: 'RAD',
0xc2: 'RANDOMIZE',
0xc3: 'READ',
0xc4: 'RELEASE',
0xc5: 'REM',
0xc6: 'RENUM',
0xc7: 'RESTORE',
0xc8: 'RESUME',
0xc9: 'RETURN',
0xca: 'RUN',
0xcb: 'SAVE',
0xcc: 'SOUND',
0xcd: 'SPEED',
0xce: 'STOP',
0xcf: 'SYMBOL',
0xd0: 'TAG',
0xd1: 'TAGOFF',
0xd2: 'TROFF',
0xd3: 'TRON',
0xd4: 'WAIT',
0xd5: 'WEND',
0xd6: 'WHILE',
0xd7: 'WIDTH',
0xd8: 'WINDOW',
0xd9: 'WRITE',
0xda: 'ZONE',
0xdb: 'DI',
0xdc: 'EI',
0xdd: 'FILL',
0xde: 'GRAPHICS',
0xdf: 'MASK',
0xe0: 'FRAME',
0xe1: 'CURSOR',
0xe3: 'ERL',
0xe4: 'FN',
0xe5: 'SPC',
0xe6: 'STEP',
0xe7: 'SWAP',
0xea: 'TAB',
0xeb: 'THEN',
0xec: 'TO',
0xed: 'USING',
0xee: '>',
0xef: '=',
0xf0: '>=',
0xf1: '<',
0xf2: '<>',
0xf3: '=<',
0xf4: '+',
0xf5: '-',
0xf6: '*',
0xf7: '/',
0xf8: '^',
0xf9: '\\',
0xfa: 'AND',
0xfb: 'MOD',
0xfc: 'OR',
0xfd: 'XOR',
0xfe: 'NOT'
}
TOKENS2 = { 0x00: 'abs', 0x01: 'asc', 0x02: 'atn', 0x03: 'chr$', 0x04: 'cint', 0x05: 'cos',
0x06: 'creal', 0x07: 'exp', 0x08: 'fix', 0x09: 'fre', 0x0a: 'nkey',
0x0b: 'inp', 0x0c: 'int', 0x0d: 'joy', 0x0e: 'len', 0x0f: 'log',
0x10: 'log10', 0x11: 'lower$', 0x12: 'peek', 0x13: 'remain', 0x14: 'sgn',
0x15: 'sin', 0x16: 'space$', 0x17: 'sq', 0x18: 'sqr', 0x19: 'str$', 0x1a: 'tan',
0x1b: 'unt', 0x1c: 'upper$', 0x1d: 'val',
0x40: 'eof', 0x41: 'err', 0x42: 'himem', 0x43: 'inkey$', 0x44: 'pi',
0x45: 'rnd', 0x46: 'time', 0x47: 'xpos', 0x48: 'ypos',
0x71: 'bin$', 0x72: 'dec$', 0x73: 'hex$', 0x74: 'instr', 0x75: 'left$',
0x76: 'max', 0x77: 'min', 0x78: 'pos', 0x79: 'right$', 0x7a: 'round',
0x7b: 'string$', 0x7c: 'test', 0x7d: 'testr', 0x7e: ' ', 0x7f: 'vpos'
}
def get_valor_puntero():
global basic, puntero
b = basic[puntero]
puntero = puntero + 1
return b
def get_int():
return get_valor_puntero() + get_valor_puntero() * 256
def get_bin(n):
return bin(n).replace('0b','&X')
def get_hex(n):
return hex(n).replace('0x', '&')
def get_variable():
c = 0
var = ''
while c < 128:
c = get_valor_puntero()
#print("var",c)
if c < 128:
var = var + chr(c)
else:
var = var + chr(c - 128)
return var
try:
while puntero < len(basic):
linea = ""
long_linea = get_int()
num_linea = get_int()
linea = linea + ascii(num_linea) + ' '
b = 255
while b != 0:
b = get_valor_puntero()
if b == FIN_LINEA:
pass
elif b == BASIC_PUNTERO or b == BASIC_NUMLIN:
linea = linea + ascii(get_int())
elif PRINTABLE[0] <= b and b <= PRINTABLE[1]:
linea = linea + chr(b)
elif b in TOKENS:
linea = linea + TOKENS[b]
elif b == 0xff:
b = get_valor_puntero()
linea = linea + TOKENS2[b]
elif b in VARIABLES:
longitud_variable = get_valor_puntero() - 4
separador = get_valor_puntero()
linea = linea + get_variable()
if b == VARI_ENTERO:
linea = linea + '%'
elif b == VARI_STRING:
linea = linea + '$'
elif b == VARI_FLOAT:
linea = linea + '!'
elif b in VALORES:
if b == VALOR_8BIT:
linea = linea + get_valor_puntero(b)
elif b == VALOR_16BIT:
n = get_int()
linea = linea + get_int(b)
elif b == VALOR_HEX16BIT:
n = get_int()
linea = linea + get_hex(n)
elif b == VALOR_BIN16BIT:
n = get_int()
linea = linea + get_bin(b)
elif b == VALOR_STRING:
linea = linea + COMILLAS
b = 255
while b != FIN_LINEA and b != VALOR_STRING:
b = get_valor_puntero()
if b == VALOR_STRING:
linea = linea + COMILLAS
else:
linea = linea + chr(b)
elif b == RSX:
linea = linea + '|' + get_variable()
print (linea)
except IndexError:
pass