;;; a86 GOGO.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 OLDINT10 dw 0,0 ; Espacio para el puntero a la INT_10h del sistema NEWINT10 proc far cmp ax, 0013h ; Nos llaman para INT_10h con AX=0013 ? jnz EXIT ; NO: saltamos a la INT_10h del sistema ;; Necesitamos el segmento donde estan los bytes que queremos parchear push bp ; Guardamos BP mov bp, sp ; BP apunta a la cima de la pila push es ; Guardamos ES push ax ; Guardamos AX ; En este punto, podemos cambiar la vista de datos a SS:BP ; (DOSBox debugger -> "d ss:bp") ; De todos esos valores, de dos en dos bytes, uno es el segmento que buscamos. ; Y no deberia estar muy lejos desde SS:BP ; Pero quizas sea mas rapido hacer una lista de instrucciones tal que asi: ; mov ax,[bp] mov ax,[bp+2h] mov ax,[bp+4h] mov ax,[bp+6h] ... ; Con el debugger ejecutaremos instruccion por instruccion viendo que valor va ; tomando AX. ; Pongamos que estamos buscando el segmento donde estan los bytes 74 03. ; Pongamos que ejecutamos en el debugger mov ax,[bp+12h] y AX=03C0. Ya conocemos ; el desplazamiento, digamos que es 032b, entonces iriamos a 3c0:32b (DOSBox ; debugger -> d ax:32b) y si vemos 7403 enhorabuena, hemos encontrado el ; segmento en la pila, podemos añadir la linea de codigo mov ax,[bp+12h] mov ax, [bp+12h] ; [bp+12h] son unos cuantos CALLs hacia atras ; y ahi tenemos el segmento donde estan los bytes a parchear mov es, ax ; lo movemos 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_10/13, no queremos volver a hacerlo. ; Ojo!! x86 es little endian asi que los bytes van "al reves" cmp Word Ptr es:[032b], 0374h ; ¿ES:[032b] = 74 03? (JE ($+3)) jne YAPARCHEADO ; NO: nos vamos sin parchear cmp Word Ptr es:[034a], 3675h ; ¿ES:[034a] = 75 36? (JNE ($+36)) jne YAPARCHEADO ; NO: nos vamos sin parchear cmp Word Ptr es:[0366], 1a75h ; ¿ES:[0366] = 75 1a? (JNE ($+1a)) jne YAPARCHEADO ; NO: nos vamos sin parchear ;; ;; Si estamos aqui es que aun no hemos parcheado. Vamos a parchear en memoria :) ; ES:[032b] = JMP SHORT mov Byte Ptr es:[032b], 0ebh ; Crack ~ escribimos el byte EB en ES:[032b] ; ES:[034a] = NOP NOP mov Word Ptr es:[034a], 9090h ; Crack ~ escribimos 90 90 en ES:[034a] ; ES:[0366] = NOP NOP mov Word Ptr es:[0366], 9090h ; Crack ~ escribimos 90 90 en ES:[0366] ;; YAPARCHEADO: pop ax ; Restauramos AX pop es ; Restauramos ES pop bp ; Restauramos BP EXIT: jmp DWord Ptr cs:[OLDINT10] ; Saltamos a la INT_10h del sistema NEWINT10 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, 3510h ; Queremos el puntero a la INT_10h del sistema int 21h mov OLDINT10[0], bx ; Guardamos puntero a la INT_10h del sistema mov OLDINT10[2], es ; (necesitaremos llamarla despues) push cs pop es ; Necesitaremos ES:BX apuntando a EXEC_INFO mov ax, 2510h ; Sobreescribimos en el vector de interrupciones el ; puntero a INT_10h por lea dx, NEWINT10 ; un puntero a nuestra rutina NEWINT10 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, OLDINT10[0] mov ds, OLDINT10[2] mov ax, 2516h ; Restauramos la INT_10h del sistema int 21h push cs pop ds ; DS = CS mov ax, 4c00h ; terminar int 21h FILENAME db "OURSTAR.EXE",0 ; programa a ejecutar EXEC_INFO db 22 DUP (0) MSG db 0dh,0ah db "Go! Go! OurStar floppy version crack.",0dh,0ah db "2019, vlan7",0dh,0ah,"$" OVL ends end START