
Open = -30
Close = -36
Read = -42
Write = -48
SetFunction = -420
AllocMem = -198
FreeMem = -210
OldOpenLibrary = -408
OpenLibrary = -552
CloseLibrary = -414
DisplayAlert = -90
Examine = -102
ExNext = -108
Lock = -84
Unlock = -90
ParentDir = -210


MODE_OLD = 1005
MODE_NEW = 1006

 ; Link Virus Killer V1.0
 ;
 ; Written by Oliver Siebenhaar in 5/89,
 ; using the Kick-Ass Assembler
 ;

 lea Path(pc),a1           ; Drivepath kopieren
 subq.l #1,d0
 beq.s No_Paars
 moveq #3,d0
C_Drive: cmp.b #$0A,(a0)           ; Linefeed ?
 beq.s No_Paars
 move.b (a0)+,(a1)+
 dbra d0,C_Drive

No_Paars: cmp.b #':',-(a1)
 bne Early_End
 move.l $4,a6
 move.l #260*4,d0          ; Speicher für Fileinfoblock
 move.l #$10002,d1         ; reservieren
 jsr AllocMem(a6)
 beq Early_End
 move.l d0,fileinfo

 move.l #10000,d0          ; Speicher für Ablage der Namen
 move.l #$10002,d1         ; reservieren
 jsr AllocMem(a6)
 beq Early_End
 move.l d0,N_Buffer

 move.l #100000,d0         ; Speicher für Ablage des Files
 move.l #$10002,d1         ; reservieren
 jsr AllocMem(a6)
 beq Early_End
 move.l d0,F_Buffer

 lea intlib(pc),a1
 moveq #0,d0
 jsr OpenLibrary(a6)       ; intuition library öffnen
 move.l d0,intbase         ; Basis retten

 lea doslib(pc),a1
 moveq #0,d0
 jsr OpenLibrary(a6)       ; dos library öffnen
 move.l d0,dosbase         ; Basis retten

 ; Virus im Speicher  ?

 cmp.w #$00F0,OldOpenLibrary+2(a6) ; Zeiger verändert ?
 bpl.s Not_in_Memory        ; nein, dann alles OK
 move.l intbase(pc),a6      ; Basis Adresse der intuition library
 moveq #0,d0                ; Alertnummer = 0
 moveq #50,d1               ; Höhe = 50
 lea Alert_Mem(pc),a0
 jsr DisplayAlert(a6)       ; Alert anzeigen
 tst.l d0                   ; Virus inaktivieren ?
 bne.s Not_in_Memory        ; nein, dann weiter

 ; Kick it out !

 move.l OldOpenLibrary+2(a6),a0
 move.l 18(a0),d0          ; hier steht der alte Vektor
 move.l $04,a6
 move.l #OldOpenLibrary,a0
 move.l $04,a1
 jsr SetFunction(a6)       ; alten Vektor setzen
 clr.l 550(a6)             ; KickTagPtr löschen

Not_in_Memory: move.l dosbase(pc),a6

 ; Diskette untersuchen

 move.l N_Buffer(pc),a5    ; Anfang der Namenliste
 lea Stack-4(pc),a4        ; eigenen Stack initialisieren
 bsr.s Get_Fnames          ; Namen holen
 bsr Check_Files           ; Files testen
 bra Ende


Init_Path: move.l dosbase(pc),a6
 move.l #Path,d1
 moveq #-2,d2
 jsr Lock(a6)
 moveq #0,d6
 tst.l d0
 bne.s No_Open_Error
 moveq #-1,d6
No_Open_Error: move.l d0,locksav
 move.l d0,d1
 move.l fileinfo(pc),d2
 jsr Examine(a6)
 clr.l (a4)
 rts

Get_Fnames: bsr.s Init_Path
 tst.l d6                 ; Fehler beim LOCKen ?
 bpl.s Check_on_Disk
 rts                      ; wenn ja, dann Ende
Check_on_Disk: move.l dosbase(pc),a6
 move.l locksav(pc),d1
 move.l fileinfo(pc),d2
 jsr ExNext(a6)
 tst.l d0
 bne.s Check_it
 move.l Path_End(pc),a1
Seek_Begin: cmp.b #'/',-(a1)
 beq.s Seek_End
 cmp.b #':',(a1)
 beq.s Seek_End
 bra.s Seek_Begin
Seek_End: move.l a1,Path_End
 addq.l #1,a1
 clr.b (a1)

 move.l locksav(pc),d1
 move.l locksav(pc),d5
 jsr ParentDir(a6)          ; ein Directory höher
 tst.l d0
 bne.s No_Root_Dir
 move.l locksav(pc),d1
 jsr Unlock(a6)
 rts

No_Root_Dir: move.l d0,locksav
 move.l d5,d1
 jsr Unlock(a6)

 addq.l #4,a4
 move.l (a4),d5
 subq.l #1,d5
 bsr Init_Path
Get_Position: move.l locksav(pc),d1
 move.l fileinfo(pc),d2
 jsr ExNext(a6)
 addq.l #1,(a4)
 dbra d5,Get_Position

 bra.s Check_on_Disk

Check_it: addq.l #1,(a4)
 move.l fileinfo(pc),a0
 tst.l 4(a0)                 ; Directory ?
 bmi.s No_Dir

 ; Directory gefunden

 move.l locksav(pc),d1
 jsr Unlock(a6)
 lea Path(pc),a1             ; Neuen Pfad anfügen
Seek_Path_End: tst.b (a1)+
 bne.s Seek_Path_End
 subq.l #1,a1
 move.l fileinfo(pc),a0
 lea 8(a0),a0

C_Dir: move.b (a0)+,(a1)+
 tst.b (a0)
 bne.s C_Dir
 move.b #'/',(a1)+
 clr.b (a1)
 subq.l #1,a1
 move.l a1,Path_End
 subq.l #4,a4
 bsr Init_Path

 bra Check_on_Disk

No_Dir: move.l dosbase(pc),a6     ; Basisadresse der dos library nach a6
 move.l a5,a3

 lea Path(pc),a0
C_Path: move.b (a0)+,(a5)+
 tst.b (a0)
 bne.s C_Path
 move.l fileinfo(pc),a0
 lea 8(a0),a0

C_Name: move.b (a0)+,(a5)+         ; Namen kopieren
 tst.b (a0)
 bne.s C_Name
 clr.b (a5)+
 move.l a3,d1               ; Testen ob executable File
 move.l #MODE_OLD,d2
 jsr Open(a6)
 tst.l d0
 beq.s Non_Ex
 move.l fileinfo(pc),a0
 cmp.l #100000,124(a0)      ; File zu lang ?
 bgt.s Non_Ex
 move.l d0,handle
 move.l d0,d1
 move.l F_Buffer(pc),d2
 moveq #4,d3                ; 1 Langwort lesen
 jsr Read(a6)
 tst.l d0
 bmi.s Non_Ex
 move.l handle(pc),d1
 jsr Close(a6)
 move.l F_Buffer(pc),a0
 cmp.l #$000003F3,(a0)      ; Testen ob ausführbar
 beq.s Executable
Non_Ex: clr.b -(a5)                ; fehlerhaften Filenamen
 cmp.l a5,a3                ; löschen
 bne.s Non_Ex
Executable:
 bra Check_on_Disk

 ; Virustestroutine

Check_Files: move.l  N_Buffer(pc),a5

Check_Loop: move.l dosbase(pc),a6
 tst.b (a5)
 beq Check_End
 move.l a5,a4
Filename_On: tst.b (a5)+
 bne.s Filename_On
 move.l F_Buffer(pc),a0
 move.l #500-1,d0
Clr_FBuffer: clr.b (a0)+
 dbra d0,Clr_FBuffer
 move.l a4,d1
 move.l #MODE_OLD,d2
 jsr Open(a6)              ; File suchen
 tst.l d0
 beq.s Check_Loop          ; Error
 move.l d0,d5              ; Filehandle retten
 move.l d0,d1
 move.l F_Buffer(pc),d2    ; Puffer für File nach d2
 move.l #500,d3            ; Anzahl der zu lesenden Byte
 jsr Read(a6)              ; lesen
 move.l d5,d1
 jsr Close(a6)             ; File schließen
 move.l  F_Buffer(pc),a0
 move.l 8(a0),d6
 lsl.l #2,d6                ; feststellen, ob sich der Virus
 cmp.l #$FFFE6100,30(a0,d6) ; im ersten Hunk befindet
 beq.s Virus                ; wenn ja, dann Virus anzeigen
 bra.s Check_Loop

Virus: lea File(pc),a0
 moveq #29,d0
Clr_Buffer: move.b #$20,(a0)+          ; Buffer für Filenamen löschen
 dbra d0,Clr_Buffer
 move.l a4,a0               ; Filename
 lea File(pc),a1
cfile: move.b (a0)+,(a1)+         ; Filenamen in Alert Meldung kopieren
 tst.b (a0)
 bne.s cfile
 move.l intbase(pc),a6      ; Basis Adresse der intuition library
 moveq #0,d0                ; Alertnummer = 0
 moveq #50,d1               ; Höhe = 50
 lea Alert(pc),a0
 jsr DisplayAlert(a6)       ; Alert anzeigen
 tst.l d0                   ; Weitersuchen gewählt ?
 bne Check_Loop             ; ja, dann weiter

Kill: movem.l d0-d7/a0-a6,-(sp)  ; Register retten
 move.l dosbase(pc),a6
 move.l a4,d1
 moveq #-2,d2
 jsr Lock(a6)
 move.l d0,locksav
 move.l d0,d1
 move.l fileinfo(pc),d2
 jsr Examine(a6)
 tst.l d0
 beq Kill_End
 move.l fileinfo(pc),a0
 move.l 124(a0),d7           ; Filelänge nach d7

 move.l locksav(pc),d1
 jsr Unlock(a6)
 move.l a4,d1
 move.l #MODE_OLD,d2
 jsr Open(a6)
 tst.l d0
 beq Kill_End
 move.l d0,handle
 move.l d0,d1
 move.l F_Buffer(pc),d2
 move.l d7,d3
 jsr Read(a6)
 move.l handle(pc),d1
 jsr Close(a6)

 move.l a4,d1               ; Filename
 move.l #MODE_NEW,d2
 jsr Open(a6)               ; File neu öffnen
 tst.l d0
 beq.s Kill_End
 move.l d0,a5               ; Filehandle in a5 speichern
 move.l F_Buffer(pc),a4        ; Filebasis nach a4
 subq.l #1,8(a4)            ; Anzahl der Hunks-1
 subq.l #1,16(a4)           ; letzter Hunk-1
 move.l a5,d1
 move.l a4,d2
 moveq #$14,d3              ; Erste 5 Langworte
 jsr Write(a6)              ; abspeichern
 lea $18(a4),a4             ; Länge des Virus und erste 5
 move.l a5,d1               ; Langworte addieren
 move.l a4,d2
 move.l d6,d3               ; Länge der Hunk Tabelle
 jsr Write(a6)              ; abspeichern
 lea 0(a4,d6),a4            ; Länge der Hunk Tabelle addieren
 lea $444(a4),a4            ; Länge des Virus-Hunks addieren
 move.l a4,a0
 move.l a4,a1
 sub.l d6,d7                ; Länge der Hunk-Tabelle,
 sub.l #$14,d7              ; erste 5 Langworte,
 subq.l #4,d7               ; Länge des Virus in Tabelle
 sub.l #$444,d7             ; und Länge des Virus von ur-
 ;                          sprünglicher PRG Länge abziehen
 lea 0(a1,d7),a1

Seek_Hunk:
 cmp.l #$000003EC,(a0)+     ; in dieser Routine werden
 bne.s Seek_Hunk            ; die Hunknummern der zu

S2: move.l (a0)+,d0            ; korrigierenden Offsets
 beq.s Test_End             ; korrigiert
 subq.l #1,(a0)+
 lsl.l #2,d0
 lea 0(a0,d0),a0
 bra.s S2

Test_End: cmp.l a0,a1
 bgt.s Seek_Hunk

 move.l a5,d1               ; ursprüngliches PRG
 move.l a4,d2
 move.l d7,d3               ; Länge des ursprünglichen PRG's
 jsr Write(a6)              ; abspeichern
 move.l a5,d1
 jsr Close(a6)
Kill_End: movem.l (sp)+,d0-d7/a0-a6
 bra Check_Loop          ; weitersuchen
Check_End: rts

Ende: move.l $4,a6
 move.l dosbase(pc),a1      ; Librarys wieder schließen
 jsr CloseLibrary(a6)
 move.l intbase(pc),a1
 jsr CloseLibrary(a6)
 move.l fileinfo(pc),a1
 move.l #260*4,d0
 jsr FreeMem(a6)            ; Speicher wieder freigeben
 move.l N_Buffer(pc),a1
 move.l #10000,d0
 jsr FreeMem(a6)
 move.l F_Buffer(pc),a1
 move.l #100000,d0
 jsr FreeMem(a6)

Early_End: moveq #0,d0
 rts                        ; Programm beenden


dosbase: dc.l 0
intbase: dc.l 0
handle: dc.l 0
fileinfo: dc.l 0
N_Buffer: dc.l 0
F_Buffer: dc.l 0
Path_End: dc.l 0
locksav: dc.l 0
doslib: dc.b 'dos.library',0
intlib: dc.b 'intuition.library',0

 even
Path: dc.b 'df1:',0              ; Puffer für Pfad
 blk.b 500

 even
 blk.l 50,0                 ; eigener Stack
Stack:

 ; Alertmeldungen

 even
Alert: dc.b 0,220,20,'Link Virus in file '
File: blk.b 30,$20
 dc.b 0,1
 dc.b 0,80,40,'Left mouse = continue           '
 dc.b ' Right mouse = restore file',0,0
Alert_Mem: dc.b 0,220,20,'IRQ Link Virus found in memory '
 dc.b 0,1
 dc.b 0,80,40,'Left mouse = continue           '
 dc.b ' Right mouse = Kick it out !',0,0










