Discussion:
Interrupt verbiegen
(zu alt für eine Antwort)
p***@web.de
2006-08-13 20:10:20 UTC
Permalink
Hallo,

Ich habe Probleme mit folgendem Programm, das ich zum Experimentieren
geschrieben habe:

--------------------------------------------------------------------------------------
Code Segment
Assume cs:code
Org 100h



Begin: jmp Install ;TSR installieren
int 20h




Tsr PROC FAR
Assume cs:code
jmp indosx
indos dw 0,0
hallo db "dsad$"
indosx:


mov ax, word ptr indos ;lese indos byte aus
mov es,ax
mov bx, word ptr indos+1
cmp byte ptr es:[bx],0
jne ende

mov ah,9h
mov dx, offset hallo
cli
int 21h
sti

ende:
iret
Tsr ENDP



Install PROC NEAR
Assume cs:code,ds:code

;adresse des indosflag kopieren
mov ah,34h
int 21h
mov word ptr indos,es
mov word ptr indos+1,bx

mov ah,25h ; int 13h auf die eigene Routine verbiegen
mov al,13h
mov dx,offset tsr
cli
int 21h
sti

mov dx,offset Install ;speicherresident beenden
int 27h
Install ENDP



Code ENDS
END Begin

------------------------------------------------------------------------------------------------------


Es verbiegt den Int13h auf die eigene Routine(, das Aufrufen der
ursprünglichen Routine habe ich noch nicht implementiert)


Soweit klappt auch alles; wie vorauszusehen war, sind keine Zugriffe
auf die Festplatte mehr möglich, allerdings ist das Indos Byte
immer(!) ungleich 0, das heißt, es ist momentan schon ein Interrupt
aktiv, der nicht gestört werden will.

Folgende Varianten habe ich ausprobiert:
- Ausführen des Int 10 innerhalb des TSR statt des INT21:
funktioniert, da es sich um einen BIOS Interrupt handelt.
- Ausführen des Int 21 innerhalb des TSR ohne Indosbyte Überprüfung:
Programmcrash.
- Ausführen des Programmes mit Indosbyte Überprüfung: Indos Byte ist
immer <> 0, d.h. kein Int21 ausführbar...


Wie kann ich trotzdem "irgendwie" den Int21 innerhalb des verbogenen
Interrupts aufrufen? Hat die Tatsache, dass das Indosbyte immer
ungleich 0 ist, etwas damit zu tun, dass ich gerade den Int13 verbogen
habe?

MfG,
baser
Sebastian Biallas
2006-08-13 20:37:59 UTC
Permalink
Post by p***@web.de
Soweit klappt auch alles; wie vorauszusehen war, sind keine Zugriffe
auf die Festplatte mehr möglich, allerdings ist das Indos Byte
immer(!) ungleich 0, das heißt, es ist momentan schon ein Interrupt
aktiv, der nicht gestört werden will.
Das Indos-Byte bedeutet, dass ein DOS-Interrupt aktiv ist -- nicht dass
/irgendein/ Interrupt aktiv ist. Und warum verwundert Dich das so? Wer
(außer DOS) soll denn da großartig mit der Festplatte diskutieren?

IdR läuft das doch so:
- Anwendung sagt "open file" an DOS
- DOS setzt Indos-Byte
- DOS sagt "Lesen von Festplatte" an BIOS (int 13)
- BIOS macht IN/OUT oder DMA oder so.
- wiederhole: bis Datei gefunden
- DOS löscht indos-Byte
- Anwendung bekommt file-handle

Wenn Du den int 13 wie dargestellt abfängst und wiederum "open file"
machst, bringst Du die globalen Variablen von DOS gehörig durcheinander.
Post by p***@web.de
Wie kann ich trotzdem "irgendwie" den Int21 innerhalb des verbogenen
Interrupts aufrufen? Hat die Tatsache, dass das Indosbyte immer
ungleich 0 ist, etwas damit zu tun, dass ich gerade den Int13 verbogen
habe?
Nicht direkt, aber indirekt schon (siehe oben). Was willst Du denn
machen? Text ausgeben kannst Du auch ohne DOS.
--
Gruß,
Sebastian
http://pagetable.com
Sebastian Biallas
2006-08-13 20:42:00 UTC
Permalink
Post by p***@web.de
mov ax, word ptr indos ;lese indos byte aus
mov es,ax
mov bx, word ptr indos+1
BTW, das fällt mir gerade auf: Es muss hier und an den weiteren Stellen
indos+2 heißen. Was Deine "cli"s vor den Interrupts sollen, verstehe ich
auch nicht ganz.
--
Gruß,
Sebastian
http://pagetable.com
Heiko Nocon
2006-08-13 20:53:12 UTC
Permalink
Post by p***@web.de
Es verbiegt den Int13h auf die eigene Routine(, das Aufrufen der
ursprünglichen Routine habe ich noch nicht implementiert)
Soweit klappt auch alles; wie vorauszusehen war, sind keine Zugriffe
auf die Festplatte mehr möglich, allerdings ist das Indos Byte
immer(!) ungleich 0, das heißt, es ist momentan schon ein Interrupt
aktiv, der nicht gestört werden will.
Auch das ist ja wohl vorhersehbar. Überlege doch einfach mal, warum wohl
ein Int13-Aufruf erfolgen könnte. Meinst du nicht auch, daß dafür unter
DOS in der Regel der Aufruf einer Int21-File-Operation die Ursache sein
dürfte?

Du hast einfach die Bedeutung des "Indos"-Flags falsch verstanden. Es
hat keinesfalls die Bedeutung deiner Interpretation, daß "ein Interrupt
aktiv ist, der nicht gestört werden will". Nein, es bedeutet, daß ein
Int21-Aufruf läuft und daß deshalb der Aufruf von Int21-Funktionen zu
vermeiden ist. Und nichtmal das stimmt wirklich. Einiges läßt sich trotz
gesetztem Flag gefahrlos aufrufen, allerdings variiert von DOS-Version
zu DOS-Version, was genau das ist. Also ruft man am besten überhaupt
keine Int21-Funktionen auf.
Post by p***@web.de
funktioniert, da es sich um einen BIOS Interrupt handelt.
Genau.
Post by p***@web.de
Wie kann ich trotzdem "irgendwie" den Int21 innerhalb des verbogenen
Interrupts aufrufen?
Wie schon gesagt: Am besten garnicht. Wenn du unbedingt Int21-Funktionen
brauchst, dann mußt du einen Delay-Mechanismus einbauen. D.h.: Im
Int13-Hook beschaffst du nur die Daten für das, was du tuen willst und
speicherst sie in einem reservierten Datenbereich im TSR. Zusätzlich
hookst du z.B. Timer- und/oder Tastatur-Interrupt und führst erst in
diesen Hooks die gewünschte Funktion aus, aber auch nur dann, wenn das
Indos-Flag "frei" anzeigt. Wenn nicht, dann eben erst beim nächsten
Auftreten des Interrupts. Irgendwann klappt's schon, daß gerade keine
DOS-Funktion läuft. Dann tust du, was du tuen willst und löschst dann
den "Job" aus dem Datenbereich des TSR.


Aber was mir gerade auffällt: Wer zum Teufel interessiert sich
heutzutage noch für DOS-TSRs? Das Thema ist doch seit zehn Jahren
abgegessen.
p***@web.de
2006-08-13 21:12:11 UTC
Permalink
Hallo,

Vielen Dank für die schnellen Antworten!
Post by Sebastian Biallas
Nicht direkt, aber indirekt schon (siehe oben). Was willst Du denn
machen? Text ausgeben kannst Du auch ohne DOS.
Also, eigentlich will ich Dateien suchen, öffnen und etwas
hineinschreiben. Das wird ohne int21 wahrscheinlich etwas umständlich.
Post by Sebastian Biallas
BTW, das fällt mir gerade auf: Es muss hier und an den weiteren Stellen
indos+2 heißen. Was Deine "cli"s vor den Interrupts sollen, verstehe ich
auch nicht ganz.
Danke für den Tipp mit dem +2.
Die Cli's sollen verhindern, dass ein anderer Int zugreift. Bin aber
noch Assembler Anfänger und habe das nur in einem Tutorial gelesen....
Post by Sebastian Biallas
Wie schon gesagt: Am besten garnicht. Wenn du unbedingt Int21-Funktionen
brauchst, dann mußt du einen Delay-Mechanismus einbauen. D.h.: Im
Int13-Hook beschaffst du nur die Daten für das, was du tuen willst und
speicherst sie in einem reservierten Datenbereich im TSR. Zusätzlich
hookst du z.B. Timer- und/oder Tastatur-Interrupt und führst erst in
diesen Hooks die gewünschte Funktion aus, aber auch nur dann, wenn das
Indos-Flag "frei" anzeigt. Wenn nicht, dann eben erst beim nächsten
Auftreten des Interrupts. Irgendwann klappt's schon, daß gerade keine
DOS-Funktion läuft. Dann tust du, was du tuen willst und löschst dann
den "Job" aus dem Datenbereich des TSR.
Danke für diese Idee... Das klingt interessant. Werde ich mich mal
einarbeiten.
Post by Sebastian Biallas
Aber was mir gerade auffällt: Wer zum Teufel interessiert sich
heutzutage noch für DOS-TSRs? Das Thema ist doch seit zehn Jahren
abgegessen.
Da hast du eigentlich recht ;-)
Bin nur gerade dabei, mich in Assembler einzuarbeiten. Ausserdem
interessiere ich mich für alte DOS Viren, ich hoffe dass ich endlich
die alten Quelltexte der DOS Viren verstehen kann.

Bin aber selbst kein Virenprogrammierer, nur hat mich die Idee eines
sich selbst verbreitenden Programmcodes schon immer fasziniert.

Hat dieser Mangel an Relevanz vielleicht auch damit zu tun, dass dies
de.comp.lang.assembler.x86 regelrecht ausblutet? ;-)

MfG,
baser
Sebastian Biallas
2006-08-13 22:02:20 UTC
Permalink
Post by p***@web.de
Hallo,
Vielen Dank für die schnellen Antworten!
Bitte verschmische nach Möglichkeit keine direkten Zitate aus
unterschiedlichen Postings in Deiner Antwort. Du hast Heiko geantwortet
aber teilweise mich zitiert.
Post by p***@web.de
Post by Sebastian Biallas
Nicht direkt, aber indirekt schon (siehe oben). Was willst Du denn
machen? Text ausgeben kannst Du auch ohne DOS.
Also, eigentlich will ich Dateien suchen, öffnen und etwas
hineinschreiben. Das wird ohne int21 wahrscheinlich etwas umständlich.
Nunja, vielleicht geht es, vielleicht nicht. Im schlimmsten Fall
zerstörst Du damit Dein Dateisystem. Erfahrungsgemäß geht es relativ
gut ;) Aber es ist lang her, dass ich mich damit beschäftigt habe.
Post by p***@web.de
Post by Sebastian Biallas
BTW, das fällt mir gerade auf: Es muss hier und an den weiteren Stellen
indos+2 heißen. Was Deine "cli"s vor den Interrupts sollen, verstehe ich
auch nicht ganz.
Danke für den Tipp mit dem +2.
Die Cli's sollen verhindern, dass ein anderer Int zugreift.
cli ist genausowenig reentrant wie DOS. Soll heißen: Wenn der Interrupt
selber wieder sti aufruft, nützt das nichts.

Was mir aber noch aufgefallen ist: Du rufst int 21h/ah=9 auf, aber setzt
ds nicht. Du stellst nach dem int 13h die Register nicht wieder her, ja
Du rufst int 13 ja nichtmal auf. Wenn also der Nutzer vom int 13 danach
irgendwelche definierten Werte in den Registern erwartet, ist es kein
Wunder, dass es kracht.
--
Gruß,
Sebastian
http://pagetable.com
p***@web.de
2006-08-16 10:03:49 UTC
Permalink
Post by Heiko Nocon
Wie schon gesagt: Am besten garnicht. Wenn du unbedingt Int21-Funktionen
brauchst, dann mußt du einen Delay-Mechanismus einbauen. D.h.: Im
Int13-Hook beschaffst du nur die Daten für das, was du tuen willst und
speicherst sie in einem reservierten Datenbereich im TSR. Zusätzlich
hookst du z.B. Timer- und/oder Tastatur-Interrupt und führst erst in
diesen Hooks die gewünschte Funktion aus, aber auch nur dann, wenn das
Indos-Flag "frei" anzeigt. Wenn nicht, dann eben erst beim nächsten
Auftreten des Interrupts. Irgendwann klappt's schon, daß gerade keine
DOS-Funktion läuft. Dann tust du, was du tuen willst und löschst dann
den "Job" aus dem Datenbereich des TSR.
Hallo,
nochmal eine Frage zu deiner Idee mit dem Timer Interrupt( Int 1c):
Kann ich den genauso verbiegen wie den Int21/13? Sind irgendwelche
Nebenwirkungen zu befürchten? Wir rufe ich den richtigen Timer
Interrupt nach meiner Routine auf?

Ich hoffe, du kannst nochmal helfen,

MfG,
baser
Heiko Nocon
2006-08-16 16:49:30 UTC
Permalink
Post by p***@web.de
Kann ich den genauso verbiegen wie den Int21/13?
Ja klar, das kann man mit jedem Interrupt machen.
Post by p***@web.de
Sind irgendwelche
Nebenwirkungen zu befürchten?
Die sind unter DOS immer zu befürchten, weil es schließlich keine
zentrale Verwaltungsinstanz für diesen Kram gibt. Seiteneffekte sind
also immer möglich, sobald auch ein anderes Programm Interrupts hooked,
um darin irgendwas zu erledigen. Besonders kompliziert wird die Sache,
wenn das TSR auch wieder zu stoppen und aus dem Speicher zu entfernen
sein soll.
Post by p***@web.de
Wir rufe ich den richtigen Timer
Interrupt nach meiner Routine auf?
Nun genau so, wie das bei allen anderen Interrupts auch funktioniert.
Bevor du deinen eigenen Vektor setzt, mußt du auf jeden Fall den
Originalvektor in den Datenbereich deines TSR retten, das ist die
Grundvoraussetzung.

Im einfachsten Fall kannst du alles für dich Nötige in deinem Hook
erledigen, bevor die originale ISR abläuft. Dann mußt du am Ende deiner
eigenen Interruptroutine eigentlich bloß den gesicherten Originalvektor
mit einem indirekten far jump anspringen.

Etwas komplizierter wird es, wenn die eigenen Aktionen erst nach der
Originalroutine ablaufen sollen oder gar sowohl vor als auch nach der
Orignalroutine was gepfuscht werden muß.

Ich hänge mal als Beispiel ein paar Auszüge aus einem alten Projekt von
mir an. Damals ging's darum, einen Kommandozeilen-MP3-Player mit einer
"graphischen" Oberfläche zu versehen. Dazu mußte ich u.a. Timer und
Keyboard hooken. Der Timerhook konnte alles Nötige vor der
Originalroutine erledigen, der Keyboardhook hingegen durfte erst nach
Durchlaufen der Originalroutine wirklich aktiv werden. Was die Handler
tatsächlich gemacht haben, ist in diesem Zusammenhang irrelevant und ich
hab's deswegen durch "..." ersetzt.

OldInt1c:
dd 0
OldInt9:
dd 0

insttimerhook:
mov ah,035
mov al,01c
int 021
jnc storeint1c
jmp ps_error2
storeint1c:
lea si,OldInt1c
mov [si],bx
mov [si+2],es
mov ah,025
mov al,01c
push cs
pop ds
lea dx,timerhook
int 021
push cs
pop ds
jnc instkeyhook
jmp ps_error2

instkeyhook:
mov ah,035
mov al,9
int 021
jnc storeint9
jmp ps_error3
storeint9:
lea si,OldInt9
mov [si],bx
mov [si+2],es
mov ah,025
mov al,9
push cs
pop ds
lea dx,keyhook
int 021
push cs
pop ds
jnc ps_callplayer
jmp ps_error3

timerhook:
...
cs jmp d[OldInt1c]

keyhook:
pushf
push cs
push retint9
cs jmp d[OldInt9]
retint9:
...
iret
p***@web.de
2006-08-17 11:23:48 UTC
Permalink
Post by Heiko Nocon
Post by p***@web.de
Kann ich den genauso verbiegen wie den Int21/13?
Ja klar, das kann man mit jedem Interrupt machen.
Post by p***@web.de
Sind irgendwelche
Nebenwirkungen zu befürchten?
Die sind unter DOS immer zu befürchten, weil es schließlich keine
zentrale Verwaltungsinstanz für diesen Kram gibt. Seiteneffekte sind
also immer möglich, sobald auch ein anderes Programm Interrupts hooked,
um darin irgendwas zu erledigen. Besonders kompliziert wird die Sache,
wenn das TSR auch wieder zu stoppen und aus dem Speicher zu entfernen
sein soll.
Post by p***@web.de
Wir rufe ich den richtigen Timer
Interrupt nach meiner Routine auf?
Nun genau so, wie das bei allen anderen Interrupts auch funktioniert.
Bevor du deinen eigenen Vektor setzt, mußt du auf jeden Fall den
Originalvektor in den Datenbereich deines TSR retten, das ist die
Grundvoraussetzung.
Im einfachsten Fall kannst du alles für dich Nötige in deinem Hook
erledigen, bevor die originale ISR abläuft. Dann mußt du am Ende deiner
eigenen Interruptroutine eigentlich bloß den gesicherten Originalvektor
mit einem indirekten far jump anspringen.
Etwas komplizierter wird es, wenn die eigenen Aktionen erst nach der
Originalroutine ablaufen sollen oder gar sowohl vor als auch nach der
Orignalroutine was gepfuscht werden muß.
Ich hänge mal als Beispiel ein paar Auszüge aus einem alten Projekt von
mir an. Damals ging's darum, einen Kommandozeilen-MP3-Player mit einer
"graphischen" Oberfläche zu versehen. Dazu mußte ich u.a. Timer und
Keyboard hooken. Der Timerhook konnte alles Nötige vor der
Originalroutine erledigen, der Keyboardhook hingegen durfte erst nach
Durchlaufen der Originalroutine wirklich aktiv werden. Was die Handler
tatsächlich gemacht haben, ist in diesem Zusammenhang irrelevant und ich
hab's deswegen durch "..." ersetzt.
dd 0
dd 0
mov ah,035
mov al,01c
int 021
jnc storeint1c
jmp ps_error2
lea si,OldInt1c
mov [si],bx
mov [si+2],es
mov ah,025
mov al,01c
push cs
pop ds
lea dx,timerhook
int 021
push cs
pop ds
jnc instkeyhook
jmp ps_error2
mov ah,035
mov al,9
int 021
jnc storeint9
jmp ps_error3
lea si,OldInt9
mov [si],bx
mov [si+2],es
mov ah,025
mov al,9
push cs
pop ds
lea dx,keyhook
int 021
push cs
pop ds
jnc ps_callplayer
jmp ps_error3
...
cs jmp d[OldInt1c]
pushf
push cs
push retint9
cs jmp d[OldInt9]
...
iret
Danke für die Mühe, vor allem mit dem Beispielprogramm!
Werde es durcharbeiten und schauen, was ich am besten bei mir
verwende..

Mit freundlichem Gruss,
baser

Dirk Wolfgang Glomp
2006-08-16 17:19:48 UTC
Permalink
Post by p***@web.de
Post by Heiko Nocon
Wie schon gesagt: Am besten garnicht. Wenn du unbedingt Int21-Funktionen
brauchst, dann mußt du einen Delay-Mechanismus einbauen. D.h.: Im
Int13-Hook beschaffst du nur die Daten für das, was du tuen willst und
speicherst sie in einem reservierten Datenbereich im TSR. Zusätzlich
hookst du z.B. Timer- und/oder Tastatur-Interrupt und führst erst in
diesen Hooks die gewünschte Funktion aus, aber auch nur dann, wenn das
Indos-Flag "frei" anzeigt. Wenn nicht, dann eben erst beim nächsten
Auftreten des Interrupts. Irgendwann klappt's schon, daß gerade keine
DOS-Funktion läuft. Dann tust du, was du tuen willst und löschst dann
den "Job" aus dem Datenbereich des TSR.
Hallo,
Kann ich den genauso verbiegen wie den Int21/13? Sind irgendwelche
Nebenwirkungen zu befürchten? Wir rufe ich den richtigen Timer
Interrupt nach meiner Routine auf?
Der Timer Interrupt wird gewöhnlich auf 18,2/sek gestellt(PIC),
damit die Uhr nicht alzu falsch geht.
Also anders als ein Softint, wird dieser IRQ ständig aufgerufen.

Wenn dieser Timer Interrupt also umgeleitet, noch zusäztliche
Nebenjobs untergeschoben bekommt, ist darauf zu achten das der
Job nicht zu zeitaufwändig wird und nicht vorher schon
erneut aufgerufen sich selber unterbricht.

Dirk
Lesen Sie weiter auf narkive:
Loading...