80186 Maschinencode + DOS, 91 Bytes
Textversion:
hm j j PPjzjzjgaAAA JSJJ RU Sq ReAA JdJJJ RfiJElK JEiS GtI And she said But that s his
Textversion mit Tabulatoren (Code 9) 9
und Leerzeichen (Code 32) ersetzt durch *
:
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
Der Maschinencode wird in einer Datei mit der Erweiterung angezeigt .com
. Wenn ich es ausführe, druckt es die erforderliche Nachricht und hängt dann (zufällige Daten werden ausgeführt).
Erklärung auf hoher Ebene, was es tut:
- Initialisiert Register mit konstanten Werten
- Ersetzt Leerzeichen in der Nachricht durch die erforderlichen Sonderzeichen (
,'.$
)
- Korrigiert den Code, um die
int 21
Anweisung zu generieren , die die Nachricht druckt
- Ruft DOS auf
Assembler-Code (kann mit kompiliert werden 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
Es benutzt den popa
Befehl, um alle Register zu pop
füllen , da regular nicht alle benötigten Register füllen kann (zB pop di
ist ein verbotener Opcode).
Die Adressen der zu patchenden Bytes liegen im Bereich von 0x100 ... 0x160. Glücklicherweise können sie als Summe von 3 Bytes mit zulässigen Werten dargestellt werden:
- 0x7a in
bp
- 0x7a oder 0x67 in
si
oderdi
- Sofortiger Wert
Das Patchen von Bytes in der Nachricht erfolgt logisch OR
mit 0x20 (Leerzeichen) und einer kleinen Konstante (4, 7, 12 oder 14). Die kleine Konstante wird durch Initialisieren von cx
und dx
auf 9 (Tabulatorzeichen) und Ausführen INC
oder DEC
nach Bedarf erhalten.
Das Patchen von Code verwendet die IMUL
Anweisung. Ich habe die benötigten 16-Bit-Konstanten gefunden, um sie mithilfe der Brute-Force-Suche zu multiplizieren.
Schließlich wird die Adresse der Nachricht (0x13b) durch Multiplikation erhalten. Um Platz zu sparen, habe ich eine der Konstanten aus einer der Anweisungen genommen, die einen unmittelbaren Wert enthält 0x96d
. Hier 9
wählt der Teil eine DOS-Druckfunktion und der 6d
Teil ist ein freier Parameter. Es stellt sich heraus, dass dies 6d
die einzige Möglichkeit ist, die nach der Multiplikation 0x13b ergeben kann.
Demontage des Codeteils:
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)
Unterhaltsame Tatsache: Normalerweise würde ich offset message
anstelle der 13bh
hartcodierten verwenden, aber in diesem Fall generiert tasm, da zum Zeitpunkt der Analyse die Adresse unbekannt ist, einen sofortigen 16-Bit-Offset und verschwendet 1 Codebyte:
06BA:0131 098A4600 OR [BP+SI+0046],CX