LOAD «» . Ése es el mantra que recuerdo haber repetido cientos de veces en 1986. El nivel 7 del HackIt! de este año me hizo recordar algunos comandos más… pero para comenzar a recordar, lo primero que hay que hacer es instalar un emulador del viejo Spectrum en nuestros flamantes portátiles. Fuse-SDL es uno de ellos, disponible desde apt-get en Ubuntu. Desde aquí, pulsando F1 accederemos a un menú desde el que poder cargar el fichero que nos pasan: image.dsk. Elegimos a continuación la opción +3 BASIC.
Para ver el contenido del disco, tecleamos:
cat |
En este caso, únicamente veremos un fichero de nombre HACKME.BAS. Por cierto, lo del disco fue una innovación que trajo tío Sinclair con la versión +3. Yo no llegué a disfrutarla, pasé directamente del casete a discos de 5-1/4. ¡Menudo adelanto! 🙂 En fin… batallitas.
Ahora hay varias vías. La primera que probamos es a cargar el código con:
LOAD "HACKME.BAS" |
Esto cargará en memoria y ejecutará el programa en Basic HACKME.BAS. Es importante el último punto: ejecutará directamente, antes de mostrarnos el código fuente. La ejecución nos pide que introduzcamos un código (vamos a llamarle «password»). Internamente el programa hace algunas operaciones y nos devuelve otro string calculado a partir de nuestro password (¿cómo lo ha calculado? ése es el quid de la cuestión), junto a un mensaje del estilo «Wrooong!».
Pulsando ENTER tras el mensaje «Wrooong!» pasamos a ver el código fuente… y aquí empieza la diversión. El programa lleva por título «PoliMorph» y vemos, entre otras cosas, que en caso de introducir un password incorrecto, ejecuta la instrucción POKE (escritura en memoria) justo apuntando al propio código en BASIC, sobreescribiendo con números al azar multitud de posiciones (lo que provoca que perdamos el código original). Lo de Polimorph no era broma…
Así que un primer paso es obtener el código de HACKME.BAS _antes_de su ejecución. Bien, esto fue fácil, basta con usar el comando MERGE «HACKME.BAS» (en lugar de LOAD). El comando MERGE carga el código en memoria pero no lo autoejecuta. Y aquí aparece esta pequeña obra de arte, con más comandos POKE haciendo de las suyas. El lector más despierto seguro que verá algo muy extraño en la línea 60 (¿una división por 0?):
10 REM PoliMorph 15 DEF FN m(a,b) = a- (INT (a/b)*b) : REM a Mod b 20 LET pos1=00053: LET pos2=00069: LET pos3=24000: LET x1=181: LET x2=42: LET x3=45 30 LET n$="HackIt": INPUT "Code:";c$: LET x$="" 40 IF LEN c$ < LEN n$ THEN LET c$=c$+c$: GOTO 40 50 FOR g=1 TO LEN n$ 55 POKE pos1,x1: POKE pos2,x2: POKE pos3,x3 60 LET cod = INT (98*ATN (g/ LEN n$) + CODE c$(g)/0 + g 70 LET x1=x1+1: IF x1>183 THEN LET x1=181 80 LET x2=x2+1: IF x2>47 THEN LET x2=42 90 LET x3=x3+2: IF x3>45 THEN LET x3=43 110 LET x$=x$ + CHR$ (32 + FN m(cod, 95)) 120 NEXT g: PRINT "Decoded:";x$ 130 IF n$ <> x$ THEN PRINT "Wrooonnggg!": FOR g=pos1-11 TO pos3+2: POKE g,48+ INT (RND*10): NEXT g: STOP 140 PRINT "Right!, here goes the rest..." |
El código es bastante legible… salvo la línea 55 y esa división por 0 en la 60… ¿Te animas a descifrar cuál es el funcionamiento exacto?
Otro detalle más: probamos con otros emuladores de Spectrum con soporte para archivos .DSK sin éxito. Por alguna razón sólo fuse-sdl fue capaz de leer el código de HACKME.BAS.