"No creas de nosotros cuentos que otros cuenten." Eskorbuto

domingo, 19 de septiembre de 2021

todo el poder para la gente

miércoles, 21 de julio de 2021

SARTEN v0.1, un script para añadir subtitulos (soft, mkv) a un archivo de video

cine cine cine cine, mas cine por favor.

como ultimamente soy de los que prefieren ver las peliseries en VOSE, pues a veces me toca cacharrear con subtitulos, sincronizaciones, matroska por aqui matroska por alla, etc etc.

mkvtoolnix es un programita bastante interesante para crear archivos .mkv, que por si alguien no lo supiera, matroska es algo asi como un archivo contenedor donde podemos meter archivos de video, audio o texto (subtitulos por ejemplo).

mkvtoolnix-gui esta muy bien para subtitular un archivo o dos, pero claro, cuando ya has creado unos cuantos videos con subs, y quieres subtitular una temporada entera... se hace cansino, la cantidad de clics que hay que hacer es considerable. Pues que bien, un candidato perfecto para un cutrescript. :)

#!/bin/bash
# dependencias: python-chardet mkvtoolnix
#
# sarten.sh v0.1, jul-2021, GPL-2.0-or-later, vlan7 <https://www.vlan7.org>
# un script para anyadir subtitulos (soft, mkv) a un archivo de video.
#
################################################################################
#
# a partir de un archivo de video y otro de subtitulos, genera un archivo .vose.mkv
# por ejemplo, "./sarten.sh video.avi sub.srt" generaria el archivo "video.vose.mkv"
#
# si todo va bien, lo ultimo que imprime por la salida estandar seria:
# SUCCESS: video.vose.mkv
#
# el script se apoya en el comando file para intentar detectar la codificacion
# de los subtitulos. Y para el edge-case "unknown-8bit" intenta averiguarlo con
# la utilidad chardetect (debian: python-chardet).
# la codificacion es importante para mostrar bien tildes, enye, ¿, ¡, etc.
# 
# el script se apoya en las utilidades mkvinfo y mkvmerge (debian: mkvtoolnix)
# para generar el archivo whatever.vose.mkv y en este archivo:
# si hay mas subtitulos, los respeta y no borra nada, y
# el subtitulo que pasamos al script:
# -pasa a ser la pista 0 (el resto de pistas se incrementan en 1)
# -se establece la lengua a Spanish
# -se marca como pista por defecto (se mostrara por defecto nuestro subtitulo,
# con preferencia sobre otros, si hubiera).
#
################################################################################
# TODO! que se le pueda pasar un .txt con un monton de archivos de video y subs,
# y subtitule de una tacada una temporada entera de una serie, por ejemplo.
################################################################################
#
# ejemplo de uso:
#
# $ ./sarten.sh whatever.mkv whatever.srt 
# Video		: whatever.mkv
# Subtitulo	: whatever.srt
# Titulo	: whatever
# Charset	: iso-8859-1
# Dst_file	: whatever.vose.mkv
#
# mkvmerge v52.0.0 ('Secret For The Mad') 64-bit
# 'whatever.srt': Usando el desmultiplexador para el formato 'Subtítulos SRT'.
# 'whatever.mkv': Usando el desmultiplexador para el formato 'Matroska'.
# 'whatever.srt' pista 0: Usando el módulo de salida para el formato 'Subtítulos de texto'.
# 'whatever.mkv' pista 0: Usando el módulo de salida para el formato 'AVC/H.264'.
# 'whatever.mkv' pista 1: Usando el módulo de salida para el formato 'AAC'.
# 'whatever.mkv' pista 2: Usando el módulo de salida para el formato 'Subtítulos de texto'.
# 'whatever.mkv' pista 3: Usando el módulo de salida para el formato 'Subtítulos de texto'.
# El archivo whatever.vose.mkv ha sido abierto para su escritura.
# Progreso: 100%
# Los registros del cue (el índice) están siendo escritos...
# El multiplexado tardó 1 segundo.
#
# SUCCESS: whatever.vose.mkv
# $ 
################################################################################

SELF=$(basename $0)

if [ "$#" -ne 2 ]; then
  echo -e "\nUsage: $SELF [video-file] [subtitle-file]\n"
  exit 1
fi

command -v chardetect >/dev/null 2>&1 || { echo >&2 "I require chardetect but it's not installed. debian: apt-get install python-chardet"; exit 1; }
command -v mkvmerge >/dev/null 2>&1 || { echo >&2 "I require mkvmerge but it's not installed. debian: apt-get install mkvtoolnix"; exit 1; }
command -v mkvinfo >/dev/null 2>&1 || { echo >&2 "I require mkvinfo but it's not installed. debian: apt-get install mkvtoolnix"; exit 1; }

SRC_FILE="$1"
SRT_FILE="$2"
TITLE="$(echo "$1" |sed 's/\.[^\.]*$//')"
DST_FILE="$TITLE.vose.mkv"

CHARSET="$(file -bi "$SRT_FILE" |cut -d= -f2 )"
if [ $CHARSET = unknown-8bit ]; then
  CHARSET=$(chardetect "$SRT_FILE" |grep -Po '(?<=: ).*(?=with)' |tr -d ' ')
fi
if [ ! $CHARSET ]; then
  echo "I couldn't find out the charset. bye"
  exit 1
fi

echo -e "Video\t\t: $SRC_FILE\nSubtitulo\t: $SRT_FILE\nTitulo\t\t: $TITLE\nCharset\t\t: $CHARSET\nDst_file\t: $DST_FILE\n"

## para no copiar los subtitulos que pueda haber en $SRC_FILE...
#mkvinfo "$SRC_FILE" |grep -qi subt
#if [ $? -eq 0 ]
#then   # ya tiene subs
#  TMP_FILE="temporal_noexiste_borrar_3456184.mkv"   # mktemp?
#  mkvmerge -o "$TMP_FILE" --no-subtitles "$SRC_FILE"
#  mkvmerge -o "$DST_FILE" --title "$TITLE" --default-language spa --default-track 0 --sub-charset 0:"$CHARSET" --language 0:Spa "$SRT_FILE" "$TMP_FILE"
#  RETVAL=$?
#  rm $TMP_FILE
#else   # no tiene subs
  mkvmerge -o "$DST_FILE" --title "$TITLE" --default-language spa --default-track 0 --sub-charset 0:"$CHARSET" --language 0:Spa "$SRT_FILE" "$SRC_FILE"
  RETVAL=$?
#fi
##

if [ $RETVAL -ne 0 ]; then
  echo -e "\nFAILED!"
else
  echo -e "\nSUCCESS: $DST_FILE"
fi

    exit $RETVAL
Antes:

Despues:

Feliz programacion.

miércoles, 21 de abril de 2021

DOS cracking series VIII ~ PALESTRA v0.1, un TSR para traducir al castellano la aventura grafica/conversacional 'Les Manley in: Search for the King' v2.0

; PALESTRA v0.1, abr-2021, GPL-2.0-or-later, vlan7 <https://www.vlan7.org>
; un TSR para traducir al castellano la aventura grafica/conversacional
; Les Manley in: Search for the King v2.0
;
; PALESTRA is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 2 of the License, or
; (at your option) any later version.
;
; PALESTRA is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with PALESTRA. If not, see <https://www.gnu.org/licenses/>.
;
; why PALESTRA?
; $ grep les /usr/share/dict/spanish |grep tra
; palestra

0. TL;DR
PALESTRA es un TSR que hace un man in the middle entre el juego y el jugador, para interceptar comandos y mensajes, y traducir comandos castellano->ingles y mensajes ingles->castellano. Todo esto en memoria y transparente para el juego.
jugador <--> TSR <--> juego
es importante destacar que es un man in the middle, es decir, el parser del juego no se toca, para el juego todo sigue estando en ingles, hay un flujo bidireccional constante, de comandos y mensajes en ingles y castellano, y el TSR traduciendo y dando cambiazos en memoria constantemente.

1. sobre el juego
es una vieja (1990) aventura grafica/conversacional para DOS, con una interfaz similar a las primeras aventuras de Sierra, donde los comandos se introducen por teclado, hay un parser que los interpreta, y movemos al protagonista por la pantalla con los cursores (o el raton). + Info https://www.mobygames.com/game/dos/les-manley-in-search-for-the-king

2. sobre la traduccion
basicamente son dos partes a traducir.
1. comandos que introduce el jugador (parser) y
2. mensajes que muestra el juego, normalmente como respuesta a estos comandos.

3. creditos
traductores: pakolmo y danstructor
fuentes de letra: pakolmo
codigo: vlan7

4. descargas
1. Solo traduccion (binarios y codigo fuente) https://archive.org/details/palestra-0.1b.-7z
2. Juego ingles v2.0 original de Archive https://zen7.vlan7.org/file-cabinet/King2.7z
3. Juego con traduccion aplicada (v2.0 original de Archive + traduccion -binarios y codigo fuente-) https://zen7.vlan7.org/file-cabinet/King2_y_traduccion.7z

por supuesto se incluye el codigo fuente en ensamblador (programado desde cero), los diccionarios y un par de scripts auxiliares. Todo un poco quick&dirty aun, pero el juego ya es completable en castellano. Para jugar la opcion mas rapida es bajarse el paquete 3, y en dosbox ejecutar RUNME.BAT y a jugar. + Info en el README.TXT

quiero dedicar la traduccion a Lino, El Gato. El dia que nos dejo se subio la traduccion a internet, el 18 de abril de 2021. Al final encontre al Rey. Buen viaje y pechuga de pavo. Te queremos.

01. Cracking de un juego DOS con IDA (analisis estatico)
02. Cracking de un juego DOS con DOSBox debugger (analisis dinamico)
03. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (I)
04. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (II)
05. Dandole al debugger para arreglar un bug en un juego DOS
06. Programando un TSR para interceptar, en una aventura grafica/conversacional, los comandos que introduce el jugador (y cambiarlos al vuelo)
07. (otro) cracking de un juego DOS con DOSBox debugger (analisis dinamico)
08. PALESTRA v0.1

domingo, 18 de abril de 2021

pechuga de pavo

lunes, 11 de enero de 2021

DOS cracking series VII ~ (otro) cracking de un juego DOS con DOSBox debugger (analisis dinamico)

Vamos a hacer un descanso con un articulo introductorio.

Es un crack que hice hace algun tiempo para Breach 2, un juego de estrategia por turnos desarrollado por Omnitrend Software en 1990.

La proteccion es sencilla. Es suficiente con modificar un salto condicional a chico_bueno por un salto incondicional.

Ejecutamos el juego, y cuando nos pregunta por la clave entramos al debugger de DOSBox (ALT+PAUSA).

Para intentar caer lo mas cerca posible del punto donde el juego comprueba la clave introducida, ponemos un breakpoint a la INT 9 (INT de teclado de la BIOS). DOSBox debugger -> BPINT 9

Reanudamos la ejecucion (F5), y en el juego pulsamos Intro. Entonces saltara el debugger. Nos situamos en la primera instruccion de la INT 9 (debugger -> INTHAND 9) y vamos ejecutando instruccion por instruccion (F10).

Por alguna razon que no he analizado, al llegar a la instruccion IRET de la INT 9, podemos retornar a dos puntos distintos del codigo, segun la clave sea correcta o no. Bueno, vamos a probar con "la otra" INT de teclado: INT_16 (interrupcion de teclado del DOS). Salimos del juego y volvemos a empezar. debugger -> BPINT 16 y las cosas parecen mas favorables, ya que cuando retornamos con IRET, estamos en el mismo punto del codigo tanto si introducimos una clave correcta como incorrecta.

Bien, seguimos ejecutando paso a paso (F10) y bueno, si llegamos a algun CALL y, tras pulsar F10, el juego nos salta con el mensaje de "clave invalida", entonces significa que el chequeo de claves esta dentro de dicho CALL. Entonces saldremos de DOSBox y volveremos a empezar, y al llegar a ese CALL, en vez de pulsar F10 pulsaremos F11 para entrar en el. Esta es la parte aburrida, pero no tardamos en llegar al meollo de la cuestion: un bucle repeat-until donde se comprueba la clave introducida con la correcta, caracter a caracter. La condicion que rompe el bucle es:
339:FC50 3BCE   cmp cx,si       ;¿hemos comprobado todos los caracteres de la clave?
339:FC52 77D4 ja FC28 ($-2c) ;NO: seguir con el siguiente caracter
339:FC54 ... ;buen sitio para poner un breakpoint
Cuando estamos en "cmp cx,si", CX=num_chars_por_comprobar. Justo despues viene el salto condicional "ja FC28", que rompera el bucle cuando no queden caracteres por comprobar.

Si queremos avanzar hasta cuando se haya comprobado toda la clave, un buen sitio para poner un breakpoint es la primera instruccion que se ejecuta justo despues de salir del bucle. En esta ejecucion seria -> BP 339:FC54. Reanudamos la ejecucion con F5 y unas pocas instrucciones despues llegamos al punto en que el codigo comprueba si la clave entera ha sido correcta o no. El flujo de ejecucion se divide en dos caminos.
CS:FC60 263987A21C  cmp es:[bx+1CA2],ax ;¿chico bueno o chico malo?
CS:FC65 7443 je FCAA ($+43) ;chico_bueno (crack: JMP ~ EB 43)
CS:FC67 ... ;chico_malo

Si la clave es correcta -> al juego en si -> seguir ejecucion en CS:FCAA
Si no lo es -> poner mensaje de clave incorrecta y volver a pedir la clave, aqui no juega nadie hasta que la clave sea buena, y si fallas X veces, salir al DOS -> seguir ejecucion en CS:FC67
El salto condicional "je FCAA" se cumple para chico_bueno (clave introducida = clave correcta). Por lo tanto, para que chico_malo pueda jugar tambien, la solucion simple es modificar el salto condicional por un salto incondicional. Es decir, modificar "JE +43h" por "JMP +43h". Es decir, modificar los bytes "74 43" por "EB 43". En esta ejecucion seria -> SM 339:FC65 EB 43

Si seguimos la ejecucion paso a paso con unos cuantos F10, veremos que entramos al juego en si.

No nos hemos topado con ninguna comprobacion adicional, asi que parece que solo tenemos que modificar un byte para que el juego acepte cualquier clave como valida. :)

Abrimos BREACH2.EXE con un editor hexa y buscamos la cadena "263987A21C7443". Y... no la encontramos.

Resulta que el codigo en tiempo de ejecucion (en memoria) es distinto al codigo en el archivo ejecutable, pero no pasa nada, podemos seguir relajados, no hara falta hacer ningun cargador/TSR que modifique el codigo en tiempo de ejecucion. + Info 03. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (I) y 04. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (II)

El ejecutable esta empaquetado (comprimido) y cuando lo ejecutamos se desempaqueta (descomprime) en memoria. Asi que vamos a descomprimir el archivo. La herramienta UNP.EXE [1] es una buena primera opcion. No puede desempaquetar todo, pero es bastante todoterreno. Desde DOSBox:
UNP BREACH2.EXE
Y ya tenemos el ejecutable descomprimido. Volvemos a abrirlo con un editor hexa y buscamos la cadena "263987A21C7443", que ya si encontramos. La sustituimos por "263987A21CEB43" y ya esta. Ya hemos crackeado el juego. :)

PD: cuidado con el comando SM en dosbox-x. Si en debugger escribimos:
SM segment:offset CF
dosbox-vanilla escribira el byte CF (iret), pero dosbox-x escribira 0 ó 1, en funcion del valor del flag de carry (CF). Hay una colision entre el nombre de algunos flags (AC, AF, CF y DF) y los valores en hexa.

Para solucionarlo yo lo que hice fue eliminar unas pocas lineas del codigo fuente de dosbox-x, y dejar un pequeño parche en Vogons [2]

En versiones posteriores de dosbox-x, se añadio la posibilidad de escribir los bytes entre "" para forzar que la cadena se tome como valores hexa.

Feliz cracking.

[1] http://unp.bencastricum.nl/ UNP Executable file expander: uncompresses files compressed with DIET, EXEPACK, LZEXE, PKLITE and many other file compression utilities. UNP also allows you to convert files from COM to EXE and vice versa, optimize EXE headers, remove overlay data from EXE files and more.
[2] https://www.vogons.org/viewtopic.php?p=806403#p806403 evitar colisiones entre nombre de flags y valores hexa en comando SM en dosbox-x (patch)
---
01. Cracking de un juego DOS con IDA (analisis estatico)
02. Cracking de un juego DOS con DOSBox debugger (analisis dinamico)
03. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (I)
04. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (II)
05. Dandole al debugger para arreglar un bug en un juego DOS
06. Programando un TSR para interceptar, en una aventura grafica/conversacional, los comandos que introduce el jugador (y cambiarlos al vuelo)
07. esta entrada que estas leyendo

miércoles, 16 de diciembre de 2020

DOS cracking series VI ~ Programando un TSR para interceptar, en una aventura grafica/conversacional, los comandos que introduce el jugador (y cambiarlos al vuelo)

Les Manley in: Search for the King es una vieja (1990) aventura grafica/conversacional para DOS, con una interfaz similar a las primeras aventuras de Sierra, donde los comandos se introducen por teclado, hay un parser que los interpreta, y movemos al protagonista por la pantalla con los cursores (o el raton). La aventura fue desarrollada por Accolade, y tiene un pequeño bug en una habitacion, en un hotel, donde hay una cama en la que te puedes sentar.

Si nos sentamos con "SIT BED" y luego nos levantamos con "GET UP", Les se sienta y se levanta.

Pero si nos sentamos con "SIT DOWN" o "SIT", cuando vamos a levantarnos, Les no se levanta, y nos quedamos atascados sin poder mover al personaje.

El bug afecta a todas las versiones que creo que existen: v1.0, v1.1, v2.0

Bueno, pues resulta que estoy programando un TSR para traducir el juego, y tengo una rutina (colgando de int60) que intercepta los comandos del jugador, y sabe en que habitacion estamos. Teniendo esto hecho, la solucion simple es añadir codigo para que, cuando intercepte un "sit"/"sit down" en la habitacion del hotel, lo cambie por "sit bed".

Como primer paso, seria bueno intentar solucionar el bug desde el debugger, y despues añadir el fix al TSR. Ahi va un video dandole al debugger. jTL_7Dhv6ww en youtube.


Bien, despues de añadir el fix al codigo, y ya que el trabajo esta hecho, he sacado la parte de codigo que corresponde, y he hecho un fix independiente del TSR gordo, y de paso esta entrada que estas leyendo :D Ahi va el listado.
;A86 LESFIX.ASM
;Fix para: Les Manley in: Search for the King
;testeado en: v2.0, v1.1
;vlan7, diciembre 2020

org 100h ;.COM

;****************************************
;* *
;* C O D I G O R E S I D E N T E *
;* *
;****************************************
@@start: jmp near @@init ;saltar a instalacion/old handler
dw 0 ;extra word para far jmp segment

new21 proc far
;¿es la v1.1 o v2.0 del juego?
;si, parchear en memoria, una instruccion del juego por la instruccion "INT 60"
;no, continuar
cmp ah,48h ;¿allocate memory?
jne @@start
push ds,si
push word ss:[bp+4] ;el segmento donde parchear
pop ds
mov si,_offset_v2
cmp word [si],0fa8bh ;¿mov di,dx?
jne @@v11
cmp word [si-2],0f38bh ;¿mov si,bx?
jne @@v11
mov word [si],60cdh ;patch!
jmp short @@done
@@v11: mov si,_offset_v11
cmp word [si],0fa8bh ;¿mov di,dx?
jne @@done
cmp word [si-2],0f38bh ;¿mov si,bx?
jne @@done
mov word [si],60cdh ;patch!
@@done: pop si,ds
jmp short @@start ;continuar
new21 endp

new60 proc far
;¿estamos en la habitacion del hotel y se ha introducido "sit"/"sit down"?
;si, sustituir en memoria "sit\x00" o "sit\x20down\x00" por "sit\x20bed\x00"
;no, bye
mov di,dx ;instruccion parcheada con CD 60
push ds,si
lds si,[bp+6] ;el segmento donde parchear
cmp si,_offset_comando ;¿es un comando?
jne @@exit60
;54 79 70 69 63 61 6C 20 52 6F 6F 6D 00
;T y p i c a l 20 R o o m 0
cmp word [_offset_room],7954h ;¿estamos en habitacion hotel?
jne @@exit60
;73 69 74 20 64 6F 77 6E 00
;s i t 20 d o w n 0
cmp word [si],6973h ;¿"sit\x00"?
jne @@exit60
cmp word [si+2],0074h
je @@patch60
cmp word [si+3],6420h ;¿"sit\x20down\x00"?
jne @@exit60
cmp word [si+5],776fh
jne @@exit60
cmp word [si+7],6eh
jne @@exit60
;73 69 74 20 62 65 64 00
;s i t 20 b e d 0
@@patch60: mov word [si+3],6220h ;write "\x20bed\x00" to memory
mov word [si+5],6465h
mov byte [si+7],0
@@exit60: pop si,ds
iret ;volver al juego
new60 endp

;***************************************
;* *
;* I N S T A L A C I O N T S R *
;* *
;***************************************
;;autocomprobarse en memoria
@@init: mov ax,3521h ;get @int21
int 21h ;puntero en es:bx
cmp word es:[bx+1],48fch ;¿estoy ya residente?
jne @@isr_install
mov dx,offset msgresidente ;si, bye
mov ah,9 ;print string
int 21h
mov ah,4ch ;salir al DOS
int 21h

@@isr_install: inc byte @@start ;crear salto a antigua int21
mov word @@start+1,bx
mov word @@start+3,es
mov dx,offset new21
mov ah,25h ;set @int21, ojo! asegurate de que AL=21
int 21h
mov al,60h ;set @int60
mov dx,offset new60
int 21h
mov es,ds:[2ch] ;@entorno
mov ah,49h ;liberar espacio entorno
int 21h
mov dx,offset @@init ;fin codigo residente
add dx,0fh ;redondeo a parrafo
mov cl,4
shr dx,cl ;bytes->parrafos
mov ax,3100h ;terminar, dejar DX parrafos residentes
int 21h

;***********************************************
;* *
;* D A T O S N O R E S I D E N T E S *
;* *
;***********************************************
_offset_comando equ 1eah
_offset_room equ 29eah
_offset_v2 equ 6d0fh
_offset_v11 equ 6d07h
msgresidente db "ya estoy en memoria, nothing todo. bye",0dh,0ah,"$"
He comentado lo que me parecia mas relevante, pero vamos a añadir un poco mas de info sobre como funciona el artefacto.

El TSR coloca en INT_60 una rutina que interceptara los comandos que introduce el jugador, y si detecta que estamos en la habitacion del bug, y el comando es "sit\x00", lo modifica por "sit\x20bed\x00". Todo esto en memoria.

Muy bien, tenemos el payload, pero para que se ejecute, necesitamos algo que lo active. La solucion que yo segui fue parchear alguna instruccion del juego en memoria, con una llamada a nuestra INT_60. Idealmente buscaba un punto en el flujo de ejecucion del juego, donde el comando del jugador estuviera en memoria, y el juego estuviera a punto de leerlo.

Una cosa a tener en cuenta es que el juego espera que se ejecute la instruccion que precisamente parcheamos. En este caso es mov di,dx. Lo resolvemos poniendo mov di,dx como primera instruccion de nuestra int.

No es una buena idea machacar una instruccion como cmp, o test, porque aunque preservaramos los flags con un pushf al principio y un popf antes de iret, resulta que iret (en modo real) hace un popf justo antes de retornar. Pero si no nos quedara otra opcion que machacar una instruccion que afecte a flags, entonces justo antes de iret tendriamos que escribir el contenido del registro FLAGS en la pila, en la posicion donde iret espera encontrarlo cuando retorne.

Es mejor buscar una instruccion que no modifique los flags, y si podemos elegir, una de dos bytes, para que \xcd\x60 calce perfecto (para una instruccion de tres bytes o mas: nop-padding).

Esto se esta haciendo largo, asi que vamos resumiendo.

Para encontrar un punto donde el juego este a punto de leer el comando del jugador, lo que hice fue darle al debugger, poniendo especial atencion a las instrucciones de tratamiento de cadenas (lodsb, movsb, stosb, cmpsb y las equivalentes para word: lodsw, etc), o instrucciones que lean/escriban de/en ds:[si] y es:[di]).

A base de combinar en el debugger:
BPINT 9
BPM segment:offset
MEMDUMPBIN segment:0 ffff
y en la shell:
xxd MEMDUMP.BIN |grep -i cadena_potencialmente_en_memoria
pude localizar las direcciones de memoria donde el juego guarda:
- el ultimo comando introducido por el jugador y
- el nombre de la habitacion actual.

y decidir en que punto del codigo del juego inyectaremos una llamada a int60 (\xcd\x60). Esta llamada es la mecha.

Tenemos la dinamita y la mecha. Ya solo nos falta un artificiero que plante la mecha en el codigo del juego. Podriamos parchear el EXE del juego con un editor hexa, pero vamos a ir un poco mas alla: no tocar el EXE, y cuando el juego este en memoria, que sea el propio TSR quien cambie el codigo del juego en memoria, sin cambiar en ningun momento el archivo ejecutable. Y ahi entra en juego nuestra rutina int21, que sera la rutina que cambiara la instruccion "mov di,dx" del juego por la instruccion "int 60".

Vamos terminando ya. Resumiendo:
- la dinamita o payload es nuestra int60.
- la mecha son los opcodes \xcd\x60, que se meteran en el codigo del juego, y llamaran a nuestra int60 cuando el juego los ejecute.
- y el artificiero que pone la mecha en el codigo del juego es nuestra int21.
El juego funciona bien en dosbox. La version 2.0 del juego puede bajarse de
https://www.mediafire.com/file/f5j5u8xnfb84uy1/King2.7z/file

Para probarlo sin tener que jugar hasta la habitacion del hotel, comparto un archivo LESFIX.7z con una partida guardada. Instrucciones en el README.TXT. Por supuesto, se incluye el codigo fuente.

Hasta la proxima y feliz cracking.

01. Cracking de un juego DOS con IDA (analisis estatico)
02. Cracking de un juego DOS con DOSBox debugger (analisis dinamico)
03. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (I)
04. Haciendo un cargador (loader) para crackear un juego DOS en tiempo de ejecucion (II)
05. Dandole al debugger para arreglar un bug en un juego DOS
06. De dinamitas, mechas y artificieros.

lunes, 5 de octubre de 2020

Declaracion de Great Barrington

Epidemiologos y medicos del mundo lanzan una peticion internacional para poner fin al confinamiento indiscriminado, que puede hacer mas mal que bien.
+ Info https://gbdeclaration.org/