80186 code machine + DOS, 91 octets
Version texte:
hm j j PPjzjzjgaAAA JSJJ RU Sq ReAA JdJJJ RfiJElK JEiS GtI And she said But that s his
Version textuelle, avec tabulations (code 9) remplacées par 9
et espaces (code 32) remplacées par *
:
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
Le code machine apparaît dans un fichier avec une extension .com
. Lorsque je l'exécute, il imprime le message requis, puis se bloque (en exécutant des données aléatoires).
Explication de haut niveau sur ce qu'il fait:
- Initialise les registres avec des valeurs constantes
- Remplace les espaces dans le message par les symboles spéciaux requis (
,'.$
)
- Corrige le code pour générer l'
int 21
instruction, qui imprime le message
- Appelle le DOS
Code d'assemblage (peut être compilé avec 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
Il utilise l' popa
instruction pour faire apparaître tous les registres, parce que regular pop
ne peut pas remplir tous les registres nécessaires (par exemple, pop di
est un opcode interdit).
Les adresses d'octets à corriger sont dans la plage 0x100 ... 0x160. Par chance, ils peuvent être représentés par une somme de 3 octets avec les valeurs autorisées:
- 0x7a dans
bp
- 0x7a ou 0x67 dans
si
oudi
- Valeur immédiate
La correction des octets dans le message fonctionne de manière logique OR
sur 0x20 (caractère espace) et une petite constante (4, 7, 12 ou 14). La petite constante est obtenue en initialisant cx
et dx
à 9 (caractère de tabulation) et en faisant INC
ou DEC
au besoin.
La correction du code utilise l' IMUL
instruction. J'ai trouvé les constantes 16 bits nécessaires pour se multiplier à l'aide de la recherche par force brute.
Enfin, l'adresse du message (0x13b) est obtenue par multiplication. Pour économiser de l'espace, j'ai pris l'une des constantes de l'une des instructions, qui contient une valeur immédiate 0x96d
. Ici, la 9
pièce choisit une fonction d’impression DOS et la 6d
pièce est un paramètre libre. Il s’avère que 6d
c’est la seule possibilité qui puisse donner 0x13b après la multiplication.
Démontage de la partie code:
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)
Anecdote: Normalement, j'utiliserais offset message
le code codé en dur 13bh
, mais dans ce cas, car au moment de l'analyse de son adresse est inconnue, tasm génère un décalage immédiat de 16 bits, gaspillant un octet de code:
06BA:0131 098A4600 OR [BP+SI+0046],CX