80186 codice macchina + DOS, 91 byte
Versione testuale:
hm j j PPjzjzjgaAAA JSJJ RU Sq ReAA JdJJJ RfiJElK JEiS GtI And she said But that s his
Versione testo, con schede (codice 9) sostituite da 9
e spazi (codice 32) sostituite da *
:
hm9j9j9PPjzjzjgaAAA9JSJJ9RU9Sq9ReAA9JdJJJ9RfiJElK9JEiS*GtI*And*she*said***But*that*s*his***
hexdump:
68 6D 09 6A 09 6A 09 50 50 6A 7A 6A 7A 6A 67 61
41 41 41 09 4A 53 4A 4A 09 52 55 09 53 71 09 52
65 41 41 09 4A 64 4A 4A 4A 09 52 66 69 4A 45 6C
4B 09 4A 45 69 53 20 47 74 49 20 41 6E 64 20 73
68 65 20 73 61 69 64 20 20 20 42 75 74 20 74 68
61 74 20 73 20 68 69 73 20 20 20
Il codice macchina appare in un file con estensione .com
. Quando lo eseguo, stampa il messaggio richiesto e quindi si blocca (eseguendo dati casuali).
Spiegazione di alto livello su ciò che fa:
- Inizializza i registri con valori costanti
- Sostituisce gli spazi nel messaggio con i simboli speciali richiesti (
,'.$
)
- Patch il codice per generare l'
int 21
istruzione, che stampa il messaggio
- Chiama DOS
Codice assembly (può essere compilato con tasm
):
my_bp equ 7ah
my_si equ 7ah
my_di equ 67h
my_msg equ 13bh
.model tiny
.code
.startup
.186
org 100h
push 96dh ; ax (ah = 0; al = don't care, but see below)
push 9 ; cx
push 9 ; dx
push ax ; bx = don't care
push ax ; don't care
push my_bp
push my_si
push my_di
popa
inc cx
inc cx
inc cx
or [bp+si+my_msg-my_bp-my_si+12], cx ; ,
dec dx
dec dx
or [bp+si+my_msg-my_bp-my_si+14], dx ; '
or [bp+di+my_msg-my_bp-my_di+23], dx ; '
or [bp+si+my_msg-my_bp-my_si+30], dx ; '
inc cx
inc cx
or [bp+si+my_msg-my_bp-my_si+29], cx ; .
dec dx
dec dx
dec dx
or [bp+si+my_msg-my_bp-my_si+31], dx ; $
; 0x2049 * 0x4b6c = 0x98301cc
; So this sets cx to 1cc (a temporary constant used to patch code)
imul cx, [bp+si+my_msg-my_bp-my_si-2], 4b6ch
; 0x1cc | 0x2049 = 0x21cd (the instruction which calls DOS int 21)
; Here ah = 9 ("print" mode)
or [bp+si+my_msg-my_bp-my_si-2], cx
; At address 101, there is the constant 96d, which was loaded into ax
; 0x96d * 0x7447 = 0x448013b
; So the following sets dx to 13b (adddress of the message)
imul dx, [bp+di+101h-my_bp-my_di], 7447h
int21:
dw 2049h
db 'And she said But that s his '
end
Utilizza le popa
istruzioni per far apparire tutti i registri, perché regolare pop
non può riempire tutti i registri necessari (ad es. pop di
È un codice operativo proibito).
Gli indirizzi dei byte da correggere sono compresi nell'intervallo 0x100 ... 0x160. Per fortuna, possono essere rappresentati come una somma di 3 byte con valori consentiti:
- 0x7a in
bp
- 0x7a o 0x67 in
si
odi
- Valore immediato
Il patching dei byte nel messaggio funziona in modo logico OR
su 0x20 (carattere spazio) e una piccola costante (4, 7, 12 o 14). La piccola costante si ottiene inizializzando cx
e dx
su 9 (carattere di tabulazione) e facendo INC
o DEC
secondo necessità.
Patch del codice utilizza l' IMUL
istruzione. Ho trovato le costanti necessarie a 16 bit da moltiplicare usando la ricerca della forza bruta.
Infine, l'indirizzo del messaggio (0x13b) viene ottenuto per moltiplicazione. Per risparmiare spazio, ho preso una delle costanti da una delle istruzioni, che contiene un valore immediato 0x96d
. Qui la 9
parte sceglie una funzione di stampa DOS e la 6d
parte è un parametro gratuito. Si scopre che 6d
è l'unica possibilità che può dare 0x13b dopo la moltiplicazione.
Disassemblaggio della parte di codice:
06BA:0100 686D09 PUSH 096D
06BA:0103 6A09 PUSH +09
06BA:0105 6A09 PUSH +09
06BA:0107 50 PUSH AX
06BA:0108 50 PUSH AX
06BA:0109 6A7A PUSH +7A
06BA:010B 6A7A PUSH +7A
06BA:010D 6A67 PUSH +67
06BA:010F 61 POPA
06BA:0110 41 INC CX
06BA:0111 41 INC CX
06BA:0112 41 INC CX
06BA:0113 094A53 OR [BP+SI+53],CX
06BA:0116 4A DEC DX
06BA:0117 4A DEC DX
06BA:0118 095255 OR [BP+SI+55],DX
06BA:011B 095371 OR [BP+DI+71],DX
06BA:011E 095265 OR [BP+SI+65],DX
06BA:0121 41 INC CX
06BA:0122 41 INC CX
06BA:0123 094A64 OR [BP+SI+64],CX
06BA:0126 4A DEC DX
06BA:0127 4A DEC DX
06BA:0128 4A DEC DX
06BA:0129 095266 OR [BP+SI+66],DX
06BA:012C 694A456C4B IMUL CX,[BP+SI+45],4B6C
06BA:0131 094A45 OR [BP+SI+45],CX
06BA:0134 6953204774 IMUL DX,[BP+DI+20],7447
06BA:0139 CD21 INT 21 (after the code patches itself)
Curiosità: normalmente, offset message
invece di 13bh
hardcoded, userei, ma in questo caso, poiché al momento dell'analisi il suo indirizzo è sconosciuto, tasm genera un offset immediato a 16 bit, sprecando 1 byte di codice:
06BA:0131 098A4600 OR [BP+SI+0046],CX