The gutted out boot sector, BOOT.ASM which is not a virus, but which forms the core for the Kilroy virus is listed here as an ASM file. Neither HEX listing nor batch files are provided.
;This is a simple boot sector that will load either MS-DOS or PC-DOS. It is not
;self-reproducing, but it will be used as the foundation on which to build a
;virus into a boot sector.
;This segment is where the first operating system file (IBMBIO.COM or IO.SYS)
;will be loaded and executed from. We don’t know (or care) what is there, but
;we do need the address to jump to defined in a separate segment so we can
;execute a far jump to it.
DOS_LOAD SEGMENT AT 0070H ASSUME CS:DOS_LOAD ORG 0
LOAD: DB 0 ;Start of the first os program DOS_LOAD ENDS
MAIN SEGMENT BYTE
ASSUME CS:MAIN,DS:MAIN,SS:NOTHING
;This jump instruction is just here so we can compile this program as a COM
;file. It is never actually executed, and never becomes a part of the boot
;sector. Only the 512 bytes after the address 7C00 in this file become part of
;the boot sector.
ORG 100H START: jmp BOOTSEC
;The following two definitions are BIOS RAM bytes which contain information
;about the number and type of disk drives in the computer. These are needed by
;the virus to decide on where to look to find drives to infect. They are not
;normally needed by an ordinary boot sector.
;
; ORG 0410H
;
;SYSTEM_INFO: DB ? ;System info byte: Take bits 6 & 7 and add 1 to ;get number of disk drives on this system ;(eg 01 = 2 drives)
;
; ORG 0475H
;
;HD_COUNT: DB ? ;Number of hard drives in the system
;
;This area is reserved for loading the first sector of the root directory, when
;checking for the existence of system files and loading the first system file.
ORG 0500H
DISK_BUF: DW ? ;Start of the buffer
;Here is the start of the boot sector code. This is the chunk we will take out
;of the compiled COM file and put it in the first sector on a 360K floppy disk.
;Note that this MUST be loaded onto a 360K floppy to work, because the
;parameters in the data area that follow are set up to work only with a 360K
;disk!
ORG 7C00H
BOOTSEC: JMP BOOT ;Jump to start of boot sector code ORG 7C03H ;Start of data area
DOS_ID: DB ’EZBOOT ’ ;Name of this boot sector (8 bytes) SEC_SIZE: DW 200H ;Size of a sector, in bytes
SECS_PER_CLUST: DB 02 ;Number of sectors in a cluster FAT_START: DW 1 ;Starting sector for the first FAT FAT_COUNT: DB 2 ;Number of FATs on this disk ROOT_ENTRIES: DW 70H ;Number of root directory entries SEC_COUNT: DW 2D0H ;Total number of sectors on this disk DISK_ID: DB 0FDH ;Disk type code (This is 360KB) SECS_PER_FAT: DW 2 ;Number of sectors per FAT SECS_PER_TRK: DW 9 ;Sectors per track for this drive HEADS: DW 2 ;Number of heads (sides) on this drive HIDDEN_SECS: DW 0 ;Number of hidden sectors on the disk DSKBASETBL:
DB 0 ;Specify byte 1 DB 0 ;Specify byte 2
DB 0 ;Wait time until motor turned off, in clk ticks DB 0 ;Bytes per sector (0=128, 1=256, 2=512, 3=1024) DB 12H ;Last sector number (lg enough to handle 1.44M) DB 0 ;Gap length between sectors for r/w operations DB 0 ;Data xfer lgth when sector lgth not specified DB 0 ;Gap lgth between sectors for formatting DB 0 ;Value stored in newly formatted sectors DB 1 ;Head settle time, in milliseconds DB 0 ;Motor startup time, in 1/8 seconds HEAD: DB 0 ;Current head to read from
;Here is the start of the boot sector code
BOOT: CLI ;interrupts off
XOR AX,AX ;prepare to set up segments MOV ES,AX ;set ES=0
MOV SS,AX ;start stack at 0000:7C00 MOV SP,OFFSET BOOTSEC
MOV BX,1EH*4 ;get address of disk LDS SI,SS:[BX] ;param table in ds:si PUSH DS
PUSH SI ;save that address PUSH SS
PUSH BX ;and its address MOV DI,OFFSET DSKBASETBL ;and update default MOV CX,11 ;values to table stored here CLD ;direction flag cleared DFLT1: LODSB
CMP BYTE PTR ES:[DI],0 ;anything non-zero
JNZ SHORT DFLT2 ;not default, so don’t save it
STOSB ;else put default in place JMP SHORT DFLT3 ;and go on to next DFLT2: INC DI
DFLT3: LOOP DFLT1 ;and loop until cx=0 MOV AL,AH ;set ax=0
MOV DS,AX ;set ds=0 so we set disk tbl MOV WORD PTR [BX+2],AX ;to @DSKBASETBL (ax=0 here) MOV WORD PTR [BX],OFFSET DSKBASETBL ;ok, done
STI ;now turn interrupts on INT 13H ;and reset disk drive system ERROR1: JC ERROR1 ;if an error, hang the machine
;Here we look at the first file on the disk to see if it is the first MS-DOS or
;PC-DOS system file, IO.SYS or IBMBIO.COM, respectively.
LOOK_SYS:
MOV AL,BYTE PTR [FAT_COUNT] ;get fats per disk XOR AH,AH
MUL WORD PTR [SECS_PER_FAT] ;multiply by sectors per fat ADD AX,WORD PTR [HIDDEN_SECS] ;add hidden sectors ADD AX,WORD PTR [FAT_START] ;add starting fat sector PUSH AX
MOV WORD PTR [DOS_ID],AX ;root dir, save it MOV AX,20H ;dir entry size MUL WORD PTR [ROOT_ENTRIES] ;dir size in ax MOV BX,WORD PTR [SEC_SIZE] ;sector size ADD AX,BX ;add one sector DEC AX ;decrement by 1
DIV BX ;ax=# sectors in root dir ADD WORD PTR [DOS_ID],AX ;DOS_ID=start of data
MOV BX,OFFSET DISK_BUF ;set up disk buffer @ 0000:0500 POP AX
CALL CONVERT ;convert sec # to bios data MOV AL,1 ;prepare for 1 sector disk read CALL READ_DISK ;go read it
MOV DI,BX ;compare first file on disk MOV CX,11 ;with required file name of MOV SI,OFFSET SYSFILE_1 ;first system file for PC DOS REPZ CMPSB
JZ SYSTEM_THERE ;ok, found it, go load it MOV DI,BX ;compare first file with MOV CX,11 ;required file name of MOV SI,OFFSET SYSFILE_2 ;first system file for MS DOS REPZ CMPSB
ERROR2: JNZ ERROR2 ;not the same - an error, ;so hang the machine
;Ok, system file is there, so load it SYSTEM_THERE:
MOV AX,WORD PTR [DISK_BUF+1CH]
XOR DX,DX ;get size of IBMBIO.COM/IO.SYS DIV WORD PTR [SEC_SIZE] ;and divide by sector size INC AL ;ax=number of sectors to read MOV BP,AX ;store that number in BP MOV AX,WORD PTR [DOS_ID] ;get sector # of start of data PUSH AX
MOV BX,700H ;set disk buffer to 0000:0700 RD_BOOT1: MOV AX,WORD PTR [DOS_ID] ;and get sector to read CALL CONVERT ;convert to bios Trk/Cyl/Sec MOV AL,1 ;read one sector
CALL READ_DISK ;go read the disk SUB BP,1 ;# sectors to read - 1 JZ DO_BOOT ;and quit if we’re done ADD WORD PTR [DOS_ID],1 ;add sectors read to sector to ADD BX,WORD PTR [SEC_SIZE] ;read and update buffer address JMP RD_BOOT1 ;then go for another
;Ok, the first system file has been read in, now transfer control to it DO_BOOT:
MOV CH,BYTE PTR [DISK_ID] ;Put drive type in ch MOV DL,BYTE PTR [DRIVE] ;Drive number in dl POP BX
JMP FAR PTR LOAD ;and transfer control to op sys
;Convert sequential sector number in ax to BIOS Track, Head, Sector
;information. Save track number in DX, sector number in CH, CONVERT:
XOR DX,DX
DIV WORD PTR [SECS_PER_TRK] ;divide ax by sectors per track INC DL ;dl=sector # to start read on MOV CH,DL ;save it here
XOR DX,DX ;al=track/head count DIV WORD PTR [HEADS] ;divide ax by head count MOV BYTE PTR [HEAD],DL ;dl=head number, save it MOV DX,AX ;ax=track number, save it in dx RET
;Read the disk for the number of sectors in al, into the buffer es:bx, using
;the track number in DX, the head number at HEAD, and the sector
;number at CH.
READ_DISK:
MOV AH,2 ;read disk command
MOV CL,6 ;shift upper 2 bits of trk # SHL DH,CL ;to the high bits in dh OR DH,CH ;and put sec # in low 6 bits MOV CX,DX
XCHG CH,CL ;ch (0-5) = sector, ;cl, ch (6-7) = track MOV DL,BYTE PTR [DRIVE] ;get drive number from here MOV DH,BYTE PTR [HEAD] ;and head number from here INT 13H ;go read the disk ERROR3: JC ERROR3 ;hang in case of an error RET
;Move data that doesn’t change from this boot sector to the one read in at
;DISK_BUF. That includes everything but the DRIVE ID (at offset 7DFDH) and
;the data area at the beginning of the boot sector.
MOVE_DATA:
MOV SI,OFFSET DSKBASETBL ;Move boot sec code after data MOV DI,OFFSET DISK_BUF+(OFFSET DSKBASETBL-OFFSET BOOTSEC) MOV CX,OFFSET DRIVE - OFFSET DSKBASETBL
REP MOVSB
MOV SI,OFFSET BOOTSEC ;Move initial jump and sec ID MOV DI,OFFSET DISK_BUF
MOV CX,11 REP MOVSB RET
SYSFILE_1: DB ’IBMBIO COM’ ;PC DOS System file SYSFILE_2: DB ’IO SYS’ ;MS DOS System file ORG 7DFDH
DRIVE: DB 0 ;Disk drive for boot sector BOOT_ID: DW 0AA55H ;Boot sector ID word MAIN ENDS
END START