;;; a86 CKRYNN.ASM SIZE EQU 1024 ; Este programa y su pila caben en 1 KB OVL segment para 'code' assume cs:OVL, ds:OVL org 100h ; Esto sera un programa .COM START: jmp INITCODE ; Codigo de inicializacion OLDINT16 dw 0,0 ; Espacio para el puntero a INT_16h del sistema NEWINT16 proc far or ah, ah ; Nos llaman para INT_16h funcion 0 ? jnz EXIT ; NO: saltamos a la INT_16h del sistema ;; Necesitamos el segmento donde estan los bytes que queremos parchear push es ; Guardamos ES push ax ; Guardamos AX mov ax, [bp+4h] ; [bp+4h] es cierto CALL hacia atras donde esta el segmento ; que buscamos mov es, ax ; movemos el segmento a ES ;; ;; Ahora comprobamos que valor tienen los bytes del juego en memoria que ; queremos parchear, porque si ya los hemos parcheado en alguna llamada previa a ; INT_16/0, no queremos volver a hacerlo. ; Ojo!! x86 es little endian asi que los bytes van "al reves" cmp Word Ptr es:[0428], 0374h ; ¿ES:[428] = 74 03? (JE ($+3)) jne YAPARCHEADO ; NO: nos vamos sin parchear cmp Word Ptr es:[0443], 0675h ; ¿ES:[443] = 75 06? (JNE ($+6)) jne YAPARCHEADO ; NO: nos vamos sin parchear ;; ;; Si estamos aqui es que aun no hemos parcheado. Vamos a parchear en memoria :) ; ES:[0428] = JMP SHORT mov Byte Ptr es:[0428], 0ebh ; CRACK ~ escribimos el byte EB en ES:[0428] ; ES:[0443] = NOP NOP mov Word Ptr es:[0443], 9090h ; CRACK ~ escribimos 90 90 en ES:[0443] ;; YAPARCHEADO: pop ax ; Restauramos AX pop es ; Restauramos ES EXIT: jmp DWord Ptr cs:[OLDINT16] ; Saltamos a la INT_16h del sistema NEWINT16 endp INITCODE: mov sp, SIZE ; Redefinimos la pila mov bx, SIZE/16 mov ah, 4ah ; Redimensionamos bloque memoria int 21h lea dx, MSG mov ah, 9 ; Escribimos texto por pantalla int 21h xor ah, ah ; Esperamos pulsacion de tecla int 16h mov ax, 3516h ; Queremos el puntero a la INT_16h del sistema int 21h mov OLDINT16[0], bx ; Guardamos puntero a la INT_16h del sistema mov OLDINT16[2], es ; (necesitaremos llamarla despues) push cs pop es ; Necesitaremos ES:BX apuntando a EXEC_INFO mov ax, 2516h ; Sobreescribimos en el vector de interrupciones el ; puntero a INT_16h por lea dx, NEWINT16 ; un puntero a nuestra rutina NEWINT16 proc far int 21h ;; Parameter block lea bx, EXEC_INFO mov DWord Ptr [bx], 0 mov DWord Ptr [bx+2], 80h ; PSP mov Word Ptr [bx+4], cs mov Word Ptr [bx+6], 5ch ; FCB 0 mov Word Ptr [bx+8], cs mov Word Ptr [bx+0ah], 6ch ; FCB 1 mov Word Ptr [bx+0ch], cs ;; lea dx, FILENAME ; ES:BX apuntando a EXEC_INFO ; DS:DX apuntando al nombre ASCIIZ del archivo a ejecutar mov ax, 4b00h int 21h ; cargar y ejecutar programa mov dx, OLDINT16[0] mov ds, OLDINT16[2] mov ax, 2516h ; Restauramos la INT_16h del sistema int 21h push cs pop ds ; DS = CS mov ax, 4c00h ; terminar int 21h FILENAME db "START.EXE",0 ; programa a ejecutar EXEC_INFO db 22 DUP (0) MSG db 0dh,0ah db "Champions of Krynn (1990) crack.",0dh,0ah db "2019, vlan7",0dh,0ah,"$" OVL ends end START