Forum: PC-Programmierung DOS 16Bit: Interrupt 0xF0, hat jemand eine Idee was das ist?


von cppbert3 (Gast)


Lesenswert?

folgenden Code haben ich in dem Loader eines DOS 16Bit Spiel gefunden
der Großteil des Loader Codes ist mir klar (das Spiel selber habe ich 
noch nicht angeschaut) - nur ist hier ein Happen der mit absolut gar 
nichts sagt

der Loader ist in Assembler geschrieben das Spiel selbst in Turbo C 
(laut IDA)

der Loader erstellt aus n Dateien eine Exe im Speicher die dann als 
Sub-Prozess gestartet wird
1
  xor ax, ax
2
  mov es, ax
3
  assume es:nothing
4
  ; es = 0
5
  lds si, es:0x3C0      ; 0:0x3C0 => Interrupt-Vektor-Table[0xF0]
6
  mov ax, ds
7
  or  ax, si          ; warum hier das or?
8
  jz  short loc_809
9
  mov cx, [si+2]
10
  mov dx, [si+4]
11
  cmp cx, 4649h
12
  jnz short loc_809
13
  cmp dx, 4D47h
14
  jnz short loc_809
15
  mov ah, 0Eh
16
  int 0F0h            ; Info von IDA Pro: used by BASIC while in interpreter
17
18
loc_809: 
19
  xor al, al
20
  mov ah, 4Ch
21
  int 21h

in dem restlichen Loader Code gibt es keine Stelle wo der 0xF0 Interrupt 
gesetzt wird - das Spiel ist kein TSR - hat jemand eine Idee was das 
sein könnte?

Für mich sieht es danach aus als wenn Segment/Offset vom 0xF0-Interrupt 
als so eine Art Flag genutzt werden - und dann wird der 0xF0 mit ah=0x0E 
aufgerufen??, oder ist das irgendein ganz alter Hardware-Test oder 
sowas?

Jemand eine Idee?

von cppbert3 (Gast)


Lesenswert?

hier noch der leicht kommentierte Original opcode

ganz vergessen:
-das ist der Shutdown/Exit Code des Loaders
-in der Ralph Brown Interrupt List habe ich zu dem 0xF0 Interrupt nichts 
gefunden
-16Bit Realmode - kein 32Bit oder Protected Mode, ganz alter Kram
-der Code hat teilweise extra Support für DOS 2 - also alles ein wenig 
alt
1
shutdown_loader:
2
  0x0000000000000000:  32 E4             xor       ah, ah
3
; hier wird der originale video mode aktiviert
4
  0x0000000000000002:  2E A0 06 02       mov       al, byte ptr cs:[0x206]
5
  0x0000000000000006:  CD 10             int       0x10
6
  0x0000000000000008:  2E 8B 1E BD 01    mov       bx, word ptr cs:[0x1bd]
7
  0x000000000000000d:  B4 50             mov       ah, 0x50
8
; das original psp segment gesetzt
9
  0x000000000000000f:  CD 21             int       0x21
10
  0x0000000000000011:  06                push      es
11
  0x0000000000000012:  1E                push      ds
12
  0x0000000000000013:  33 C0             xor       ax, ax
13
  0x0000000000000015:  8E C0             mov       es, ax
14
  0x0000000000000017:  2E C5 06 BF 01    lds       ax, ptr cs:[0x1bf]
15
; hier wird der original interrupt 1 wieder herstellt
16
  0x000000000000001c:  26 A3 04 00       mov       word ptr es:[4], ax
17
  0x0000000000000020:  26 8C 1E 06 00    mov       word ptr es:[6], ds
18
  0x0000000000000025:  1F                pop       ds
19
  0x0000000000000026:  07                pop       es
20
  0x0000000000000027:  06                push      es
21
  0x0000000000000028:  1E                push      ds
22
  0x0000000000000029:  33 C0             xor       ax, ax
23
  0x000000000000002b:  8E C0             mov       es, ax
24
  0x000000000000002d:  8C C8             mov       ax, cs
25
  0x000000000000002f:  8E D8             mov       ds, ax
26
  0x0000000000000031:  FC                cld       
27
  0x0000000000000032:  8D 36 C3 01       lea       si, [0x1c3]
28
; hier werden die originalen Interrupts 151-155 wieder hergestellt
29
  0x0000000000000036:  BF 5C 02          mov       di, 0x25c
30
  0x0000000000000039:  B9 14 00          mov       cx, 0x14
31
  0x000000000000003c:  F3 A4             rep movsb byte ptr es:[di], byte ptr [si]
32
  0x000000000000003e:  26 C5 36 C0 03    lds       si, ptr es:[0x3c0]
33
  0x0000000000000043:  8C D8             mov       ax, ds
34
  0x0000000000000045:  0B C6             or        ax, si
35
  0x0000000000000047:  74 16             je        0x5f --> label1
36
  0x0000000000000049:  8B 4C 02          mov       cx, word ptr [si + 2]
37
  0x000000000000004c:  8B 54 04          mov       dx, word ptr [si + 4]
38
  0x000000000000004f:  81 F9 49 46       cmp       cx, 0x4649
39
  0x0000000000000053:  75 0A             jne       0x5f --> label1
40
  0x0000000000000055:  81 FA 47 4D       cmp       dx, 0x4d47
41
  0x0000000000000059:  75 04             jne       0x5f --> label1
42
  0x000000000000005b:  B4 0E             mov       ah, 0xe
43
  0x000000000000005d:  CD F0             int       0xf0
44
label1:
45
  0x000000000000005f:  1F                pop       ds
46
  0x0000000000000060:  07                pop       es
47
  0x0000000000000061:  32 C0             xor       al, al
48
  0x0000000000000063:  B4 4C             mov       ah, 0x4c
49
  0x0000000000000065:  CD 21             int       0x21

von cppbert3 (Gast)


Lesenswert?

Es wird geprüft ob ab dem  2. byte des Interrupt 0xF0 Procs
'IFGM' (0x4946474d) steht

sagt das jemanden etwas?

von Content B. (Firma: Da) (contentblocker_da)


Lesenswert?

0x0F ist der Interrupvector vom Parallelport. Dongle fürs Spiel?

Edit: http://manmrk.net/tutorials/DOS/PSBOOK/book2/intlist.htm

: Bearbeitet durch User
von cppbert3 (Gast)


Lesenswert?

Content B. schrieb:
> 0x0F ist der Interrupvector vom Parallelport. Dongle fürs Spiel?
>
> Edit: http://manmrk.net/tutorials/DOS/PSBOOK/book2/intlist.htm

hatte ich auch schon gesehen, aber:

-es gibt kein Dongle in der Originalfassung - aber vielleicht war der 
vorgesehen?

-warum den Dongle nur so kurz vor dem Programende nur 1 mal ansprechen?
sonst wird der F0 Interrupt nirgends im Loader aufgerufen oder sonst wie 
angesprochen

mysteriös ...

von cppbert3 (Gast)


Lesenswert?

Content B. schrieb:
> 0x0F ist der Interrupvector vom Parallelport. Dongle fürs Spiel?
> Edit: http://manmrk.net/tutorials/DOS/PSBOOK/book2/intlist.htm

Du hast dich verguckt (ist mir auch gerade erst aufgefallen) es ist 0xF0 
nicht 0x0F

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

Sieht so aus wie ein Test, ob irgend ein bestimmtes Programm-Modul unter 
INT F0h läuft. Zumindest das OR oben kann ich erklären, das setzt das 
Zero-Flag für den nachfolgenden Sprung. Aber wozu oder welches Programm 
da erwartet wird... keine Ahnung, das sind die Freiheiten von x86 
Assembler auf einem frühen Betriebssystem. Da konnte man machen was man 
will...

IGFM könnten Initialen sein. Der Code bei loc_809 ist auch aus irgend 
einem Compiler entstanden, ein Mensch hätte MOV AX,4c00h genutzt.

Für Shutdown_Loader gilt das Gleiche, das hat kein Mensch geschrieben. 
Bspw. wird DS auf den Stack geladen und wiederhergestellt, obwohl es gar 
nicht verändert wird. Oder die Kombination MOV AX,CS MOV DS,AX - 
Menschen haben gerne PUSH CS POP DS genutzt, weil zwei Byte kürzerer 
Code. Genau wie das REP MOVSB mit fester gerade Länge (CX=14h), ein 
Mensch nimmt dafür REP MOVSW mit CX=14h/2.

: Bearbeitet durch User
von Content B. (Firma: Da) (contentblocker_da)


Lesenswert?

Könnte es eventuell ein Teil eines Viruses sein, der sich an das 
Programm geheftet hatte? Es gibt ja welche mit Stealth-Mode und 
selbstveränderlichen Code

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

Sehr unwahrscheinlich. Ich will nicht ausschließen, daß irgend jemand 
sowas programmiert haben könnte, aber meine TSR-Stealthviren haben sich 
einfach in den DOS-Interrupt reingehängt.

Zum Verständnis, die Funktionsweise davon ist ziemlich einfach, im 
Grunde entsteht eine lange Kette von allen geladenen Programmen, durch 
die INT-Aufrufe hindurchgehen bis irgend ein Programm was damit anfangen 
kann. Der DOS-Kern wurde zuerst geladen, also steht er ganz am Ende 
dieser Kette. Der Virus steht irgendwo davor, sprich bevor ein 
INT-Aufruf z.B. eines Virenscanners zum Öffnen einer Datei zu DOS 
durchdringt, kann der (später geladene) Virus diesen Aufruf untersuchen 
und ggf. Maßnahmen ergreifen. Ein Stealth-Virus kann z.B. beim Öffnen 
einer Datei schauen, ob das ein infiziertes Programm ist. Wenn ja, wird 
der anhängende Virencode entfernt bevor der INT-Aufruf an DOS 
weitergereicht wird. Beim Schließen der Datei wird das Programm dann 
wieder neu infiziert. Dadurch bekommt der Virenscanner nur "saubere" 
Programmdateien zu sehen.

von cppbert3 (Gast)


Lesenswert?

Ben B. schrieb:
> das hat kein Mensch geschrieben.

Ich bin schon sehr oft auf handgeschriebenen Assembler Code gestossen 
den ein Kompiler so nicht erzeugt hätte :)

Der Loader Code ist definitiv in Assembler geschrieben weil er Teile 
seines eigenen Codes zum speichersparen mit geladenen Dateien 
ueberschreibt, sowas laesst sich schwer in C, Pascal oder anderen 
Kompilern aus der Zeit realisieren

von cppbert3 (Gast)


Lesenswert?

Content B. schrieb:
> Könnte es eventuell ein Teil eines Viruses sein, der sich an das
> Programm geheftet hatte? Es gibt ja welche mit Stealth-Mode und
> selbstveränderlichen Code

Nein definitiv nicht, die Arbeitsweise des Loaders ist mir 98% klar, hab 
den ganzen Code reversed und bin dabei den nach C zu portieren, da ist 
nichts stealthiges im Code :)

Ich finde aber leider absolut gar nichts zu diesem Interrupt 0xF0 und 
Basic im Internet, ist wohl sehr sehr alt

von Ben B. (Firma: Funkenflug Industries) (stromkraft)


Lesenswert?

Das ist ein Software-Interrupt, Du kannst da so ziemlich alles 
draufschmeißen was Du möchtest. Man hätte auch genau so gut einen 
anderen höchstwahrscheinlich unbenutzten Interrupt nehmen können.

Und ich glaube immer noch nicht, daß das ein Mensch geschrieben hat. 
Noch ein weiterer Anhaltspunkt - das Programm lädt oben CX und DX mit 
[SI+2] und [SI+4]. Ein Mensch hätte nur eines der Register benutzt und 
das zweite MOV erst nach dem ersten CMP/JNZ ausgeführt weil's erst dort 
interessant wird. Spart ein Register (die waren beim frühen x86 oft 
Mangelware, jeder ernstzunehmende Assembler-Programmierer war bestrebt, 
so viel wie möglich davon einzusparen) und eine Anweisung falls der 
erste Sprung ausgeführt wird. Das sieht aus wie ein 32Bit-Compare aus 
einem Compiler, nicht wie handgeschriebener Assemblercode. Oder der Typ 
der das geschrieben hat war ein Noob ohne Ahnung von solchen 
Optimierungen.

von cppbert3 (Gast)


Lesenswert?

habs mit dem Dosbox Debugger durch debuggt

wenn ich den Loader starte und gleich wieder beende (ohne Grafik-Karte 
wählen und Spiel-Start) dann steht in der Interrupt-Tabelle beim 
Interrupt 0xF0 nur Nullen und der Interrupt 0xF0 wird nicht aufgerufen

wenn ich aber das Spiel aus dem Loader starte dann wird der 0xF0 
Interrupt vom Spiel selbst gesetzt und hinter der Adresse steht dann 
auch ab Stelle 2 diese Signatur

also wird der Interrupt vom Spiel auf diesen Code verbogen
1
  jmp     short loc_D
2
3
aIfgmAdlib db 'IFGM ADLIB',0
4
5
loc_D:
6
  push    ds
7
  push    es
8
  push    si
9
  push    di
10
  push    bx
11
  push    cx
12
  push    bp
13
  cld
14
  mov     bx, cs
15
  mov     ds, bx
16
  xor     bx, bx
17
  mov     bl, ah
18
  call    cs:off_EFF[bx]
19
  pop     bp
20
  pop     cx
21
  pop     bx
22
  pop     di
23
  pop     si
24
  pop     es
25
  pop     ds
26
  iret

wenn jetzt noch jemand eine Idee hat zu dem C-String "IFGM ADLIB" :)

von cppbert3 (Gast)


Lesenswert?

Ben B. schrieb:
> Das sieht aus wie ein 32Bit-Compare aus
> einem Compiler, nicht wie handgeschriebener Assemblercode. Oder der Typ
> der das geschrieben hat war ein Noob ohne Ahnung von solchen
> Optimierungen.

ich hab schon ein paar Games disassembliert und es gibt einige bei denen 
der Game-Code in C geschrieben ist und der Grafik-Engine/Sound Code in 
Assembler - das sieht man relativ deutlich wenn plötzlich Calls nur noch 
mit Registern arbeiten (kein Watcom) oder nur noch globale Variablen 
verwendet werden und alles voll ist mit Dead-Code Schnipseln, 
Far-Pointer pushen und dann als Segment doch hart DS verwenden usw. - 
Kompiler machen so was nicht

von cppbert3 (Gast)


Lesenswert?

cppbert3 schrieb:
> "IFGM ADLIB"

ADLIB ist ein Soundkarten-Hersteller aus der Zeit - aber was bedeutet 
IFGM? Chipkennung oder sowas?

von cppbert3 (Gast)


Lesenswert?

IFM - Internal Frequency Modulation - aber wofür das G?

von Nils Pipenbrinck (Gast)


Lesenswert?

100% Spekulation, aber:

IFGM ADLIB klingt sehr nach einem Soundkarten Treiber. "Interface 
General Midi Adlib" würde Sinn machen. Vielleicht findest Du im Code ja 
auch irgendwo den String "IFGM MPU401" oder "IFGM MPU-401". Dann wäre 
die Sache klar.

Ansonsten probiere doch einfach mal den Programmierer zu kontaktieren.

von honko (Gast)


Lesenswert?

cppbert3 schrieb:
> int 0F0h            ; Info von IDA Pro: used by BASIC while in
> interpreter

Naja offenbar weiß IDA es schon,
das Programm ist in basic geschrieben und er prüft ob er im Interpreter 
läuft und verhält sich dann anders (zB debug-Infos ausgeben oder 
dergleichen)
Beim Kompilierten Programm (ja es gab compiler) überspringt er dann 
bestimmte Abschnitte

von cppbert3 (Gast)


Lesenswert?

honko schrieb:
> cppbert3 schrieb:
>> int 0F0h            ; Info von IDA Pro: used by BASIC while in
>> interpreter
>
> Naja offenbar weiß IDA es schon,
> das Programm ist in basic geschrieben und er prüft ob er im Interpreter
> läuft und verhält sich dann anders (zB debug-Infos ausgeben oder
> dergleichen)
> Beim Kompilierten Programm (ja es gab compiler) überspringt er dann
> bestimmte Abschnitte

ich hab vor 1h 
(Beitrag "Re: DOS 16Bit: Interrupt 0xF0, hat jemand eine Idee was das ist?") 
geschrieben das der Interrupt durch das Spiel verbogen wird - das ist 
kein Basic mehr, z.B. die Dosbox implementiert das gar nicht mehr, die 
IDA Information ist veraltet oder hier nicht passend

der Interrupt wird für die Soundausgabe des Spiel zweckentfremdet

von cppbert3 (Gast)


Lesenswert?

Nils Pipenbrinck schrieb:
> 100% Spekulation, aber:
>
> IFGM ADLIB klingt sehr nach einem Soundkarten Treiber. "Interface
> General Midi Adlib" würde Sinn machen. Vielleicht findest Du im Code ja
> auch irgendwo den String "IFGM MPU401" oder "IFGM MPU-401". Dann wäre
> die Sache klar.

das klingt plausibel

> Vielleicht findest Du im Code ja...

erstmal muss ich den Loader noch in ein Tool portieren der mir das "im 
Speicher Exe erzeugen" in eine echte Exe auf Platte ersetzt die der IDA 
dann lieber mag :) - (und nein ich will kein Image des Memories dumpen)

> Ansonsten probiere doch einfach mal den Programmierer zu kontaktieren.

das mache ich immer erst dann wenn ich gar nicht weiterkomme
oft können die sich selbst nicht daran erinnern weil das irgendjemand 
anderes programmiert hat

von Ida O. (keil-er)


Lesenswert?

cppbert3 schrieb:
> das mache ich immer erst dann wenn ich gar nicht weiterkomme
> oft können die sich selbst nicht daran erinnern weil das irgendjemand
> anderes programmiert hat

Ich letztes Jahr irgendwann, auf gut Glück, an eine E-Mail Adresse aus 
dem Text-File eines Shareware Programms von 1993 geschrieben und nach 
Code gefragt.
Die Mail kam an, das war auch der Gewünschte. Der konnte sich aber nicht 
mehr an das Programm erinnern. Paar Tage später kam ein zip-Datei mit 
dem Vermerk, dass Disketten wohl langlebiger als Gehirne seien :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.