;GB-SCAN Virus Scanner ;(C) 1995 American Eagle Publications, Inc., All Rights Reserved. .model tiny .code ;Equates DBUF_SIZE EQU 16384 ;size of data buffer for scanning ;These are the flags used to identify the scan strings and what they are for. BOOT_FLAG EQU 00000001B ;Flags a boot sector MBR_FLAG EQU 00000010B ;Flags a master boot sector EXE_FLAG EQU 00000100B ;Flags an EXE file COM_FLAG EQU 00001000B ;Flags a COM file RAM_FLAG EQU 00010000B ;Search RAM END_OF_LIST EQU 00100000B ;Flags end of scan string list ORG 100H GBSCAN: mov ax,cs mov ds,ax mov ah,19H ;get current drive number int 21H mov BYTE PTR [CURR_DR],al ;and save it here mov ah,47H ;get current directory mov dl,0 mov si,OFFSET CURR_DIR int 21H mov bx,5CH mov al,es:[bx] ;get drive letter from FCB or al,al ;was one specified? jnz GBS1 ;yes, go adjust as necessary mov ah,19H ;no, get current drive number int 21H inc al GBS1: dec al ;adjust so A=0, B=1, etc. mov BYTE PTR [DISK_DR],al ;save it here mov dl,al mov ah,0EH ;and make this drive current int 21H push cs pop es mov di,OFFSET PATH ;set up path with drive letter mov al,[DISK_DR] add al,'A' mov ah,':' stosw mov ax,'\' stosw mov dx,OFFSET HELLO ;say "hello" mov ah,9 int 21H call SCAN_RAM ;is a virus in RAM? jc GBS4 ;yes, exit now! cmp BYTE PTR [DISK_DR],2 ;is it drive C:? jne GBS2 ;no, don't mess with master boot record call SCAN_MASTER_BOOT GBS2: cmp BYTE PTR [DISK_DR],2 ;is it drive D: or higher? jg GBS3 ;yes, don't mess with boot sector call SCAN_BOOT GBS3: mov dx,OFFSET ROOT ;go to root directory mov ah,3BH int 21H call SCAN_ALL_FILES GBS4: mov dl,[CURR_DR] ;restore current drive mov ah,0EH int 21H mov dx,OFFSET CURR_DIR ;restore current directory mov ah,3BH int 21H mov ax,4C00H ;exit to DOS int 21H ;This routine scans the Master Boot Sector. ;The drive to scan is supplied in dl. SCAN_MASTER_BOOT: mov WORD PTR [FILE_NAME],OFFSET MBR_NAME push ds ;first read the boot sector pop es mov bx,OFFSET DATA_BUF ;into the DATA_BUF mov ax,201H mov cx,1 mov dh,0 mov dl,[DISK_DR] cmp dl,2 jc SMB1 add dl,80H-2 SMB1: int 13H mov ax,201H ;duplicate read int 13H ;in case disk change jc SMBR ;exit if error mov cx,512 ;size of data to scan mov ah,MBR_FLAG and 255 ;scan for boot sector viruses call SCAN_DATA ;go scan the data SMBR: ret ;This routine scans the boot sector for both floppy disks and hard disks. ;For hard disks, the master boot sector must be in the data buffer when ;this is called, so it can find the boot sector. SCAN_BOOT: mov WORD PTR [FILE_NAME],OFFSET BOOT_NAME mov cx,1 ;assume floppy parameters mov dh,0 mov dl,[DISK_DR] cmp BYTE PTR [DISK_DR],2 jc SB2 ;go handle floppies if so mov si,OFFSET DATA_BUF + 1BEH SBL: cmp BYTE PTR [si],80H ;check active flag je SB1 ;active, go get it add si,10H ;else try next partition cmp si,1FEH ;at the end of table? jne SBL ;no, do another ret ;yes, no active partition, just exit SB1: mov dx,[si] ;set up dx and cx for read mov cx,[si+2] SB2: mov bx,OFFSET DATA_BUF push ds pop es mov ax,201H int 13H ;read boot sector mov cx,512 mov ah,BOOT_FLAG call SCAN_DATA ;and scan it ret ;This routine systematically scans all RAM below 1 Meg for resident viruses. ;If a virus is found, it returns with c set. Otherwise c is reset. SCAN_RAM: mov WORD PTR [FILE_NAME],OFFSET RAM_NAME xor ax,ax mov es,ax mov bx,ax ;set es:bx=0 SRL: mov ah,RAM_FLAG ;prep for scan mov cx,8010H ;scan this much in a chunk call SCAN_DATA ;scan ram pushf mov ax,es ;update es for next chunk add ax,800H mov es,ax popf jc SREX ;exit if a virus was found or ax,ax ;are we done? jnz SRL ;nope, get another chunk clc ;no viruses, return nc SREX: ret ;This routine scans all EXEs and COMs on the current disk looking for viruses. ;This routine is fully recursive. SCAN_ALL_FILES: push bp ;build stack frame mov bp,sp sub bp,43 ;space for file search record mov sp,bp mov dx,OFFSET SEARCH_REC ;set up DTA mov ah,1AH int 21H call SCAN_COMS ;scan COM files in current directory call SCAN_EXES ;scan EXE files in current directory mov dx,bp ;move DTA for directory search mov ah,1AH ;this part must be recursive int 21H mov dx,OFFSET ANY_FILE mov ah,4EH ;prepare for search first mov cx,10H ;dir file attribute int 21H ;do it SAFLP: or al,al ;done yet? jnz SAFEX ;yes, quit cmp BYTE PTR [bp+30],'.' je SAF1 ;don't mess with fake subdirectories test BYTE PTR [bp+21],10H jz SAF1 ;don't mess with non-directories lea dx,[bp+30] mov ah,3BH ;go into subdirectory int 21H call UPDATE_PATH ;update the PATH viariable push ax ;save end of original PATH call SCAN_ALL_FILES ;search all files in the subdirectory pop bx mov BYTE PTR [bx],0 ;truncate PATH variable to original mov dx,bp ;restore DTA, continue dir search mov ah,1AH int 21H mov dx,OFFSET UP_ONE ;go back to this directory mov ah,3BH int 21H SAF1: mov ah,4FH ;search next int 21H jmp SAFLP ;and continue SAFEX: add bp,43 mov sp,bp pop bp ;restore stack frame and exit ret ;This routine scans all EXE files in the current directory looking for viruses. SCAN_EXES: mov BYTE PTR [FFLAGS],EXE_FLAG and 255 mov WORD PTR [FILE_NAME],OFFSET SEARCH_REC + 30 ;where file name is mov dx,OFFSET EXE_FILE jmp SCAN_FILES ;This routine scans all COM files in the current directory looking for viruses. SCAN_COMS: mov BYTE PTR [FFLAGS],COM_FLAG mov WORD PTR [FILE_NAME],OFFSET SEARCH_REC + 30 ;where file name is mov dx,OFFSET COM_FILE SCAN_FILES: mov ah,4EH ;prepare for search first mov cx,3FH ;any file attribute int 21H ;do it SCLP: or al,al ;an error? jnz SCDONE ;if so, we're done call SCAN_FILE ;scan the file mov ah,4FH ;search for next file int 21H jmp SCLP ;and go check it SCDONE: ret ;all done, exit ;This routine scans a single file for viruses. The @ of the file name is assumed ;to be at ds:[FILE_NAME]. The flags to use in the scan are at ds:[FFLAGS] SCAN_FILE: mov dx,WORD PTR [FILE_NAME] mov ax,3D00H ;open file int 21H jc SFCLOSE ;exit if we can't open it mov bx,ax SF1: mov ah,3FH ;read file mov cx,DBUF_SIZE mov dx,OFFSET DATA_BUF int 21H cmp ax,16 ;did we actually read anything? jle SFCLOSE ;nope, done, go close file mov cx,ax ;size of data read to cx push bx ;save file handle mov bx,OFFSET DATA_BUF push ds pop es mov ah,[FFLAGS] call SCAN_DATA pop bx ;restore file handle jc SFCL2 ;if a virus found, exit with c set mov ax,4201H ;move file pointer relative to current mov cx,-1 ;back 16 bytes mov dx,-16 ;so we don't miss a virus at the int 21H ;buffer boundary jmp SF1 SFCLOSE:clc ;exit when no virus found, c reset SFCL2: pushf ;save flags temporarily mov ah,3EH ;close file int 21H popf ret ;This routine scans data at es:bx for viruses. The amount of data to ;scan is put in cx, and the flag mask to examine is put in ah. SCAN_DATA ;will return with c set if a scan string was found, and nc if not. SCAN_DATA: mov WORD PTR [DSIZE],cx mov si,OFFSET SCAN_STRINGS ;si is an index into the scan strings SD1: lodsb ;get flag byte push ax and al,END_OF_LIST ;end of list? pop ax jnz SDR ;yes, exit now and al,ah ;no, so is it a string of proper type? jz SDNEXT ;no, go do next string mov dx,bx add dx,[DSIZE] ;dx = end of search buffer mov di,bx ;di = start of search buffer SD2: mov al,[si] ;get 1st byte of string xor al,0AAH cmp di,dx ;end of buffer yet? je SDNEXT ;yes, go do next string cmp al,es:[di] ;compare with byte of buffer je SD3 ;equal, go check rest of string inc di ;else check next byte in buffer jmp SD2 SD3: push si ;check for entire 16 byte string push di ;at es:di mov cx,16 SD4: lodsb ;ok, do it xor al,0AAH ;decrypt inc di cmp al,es:[di-1] loopz SD4 pop di pop si pushf inc di popf jne SD2 ;not equal, go try next byte mov di,si ;else calculate the index for this sub di,OFFSET SCAN_STRINGS+1;virus to display its name on screen mov ax,di mov di,17 xor dx,dx div di mov di,ax call DISP_VIR_NAME ;go display its name stc ;set carry ret ;and exit SDNEXT: add si,16 ;go to next scan string jmp SD1 SDR: clc ;clear carry, no virus found ret ;and exit ;This routine updates the variable PATH to reflect a new directory. It also ;returns a pointer to the end of the old path in ax. It is used only in ;conjunction with SCAN_ALL_FILES. UPDATE_PATH: lea di,[bp+30] ;update PATH variable mov si,OFFSET PATH SAF01: lodsb ;find end of existing PATH or al,al jnz SAF01 dec si mov dx,si ;save end here push cs pop es xchg si,di SAF02: lodsb ;move new directory to PATH stosb or al,al jnz SAF02 dec di mov ax,'\' ;terminate path with backslash stosw mov ax,dx ret ;This routine displays the virus name indexed by di. If di=0 then this ;displays the first ASCIIZ string at NAME_STRINGS, if di=1 then it displays ;the second, etc. DISP_VIR_NAME: mov si,OFFSET PATH FV00: lodsb or al,al jz FV01 mov ah,0EH int 10H jmp FV00 FV01: mov si,[FILE_NAME] FV02: lodsb or al,al jz FV05 mov ah,0EH int 10H jmp FV02 FV05: mov si,OFFSET NAME_STRINGS FV1: or di,di jz DISP_NAME push di FV2: lodsb cmp al,'$' jnz FV2 pop di dec di jmp FV1 DISP_NAME: push si mov dx,OFFSET INFECTED mov ah,9 int 21H pop dx mov ah,9 int 21H mov dx,OFFSET VIRUS_ST mov ah,9 int 21H ret HELLO DB 'GB-SCAN Virus Scanner Ver. 1.00 (C) 1995 American ' DB 'Eagle Publications Inc.',0DH,0AH,24H INFECTED DB ' is infected by the $' VIRUS_ST DB ' virus.',0DH,0AH,24H MBR_NAME DB 'The Master Boot Record',0 BOOT_NAME DB 'The Boot Sector',0 RAM_NAME DB 7,7,7,7,7,'ACTIVE MEMORY',0 EXE_FILE DB '*.EXE',0 COM_FILE DB '*.COM',0 ANY_FILE DB '*.*',0 ROOT DB '\',0 UP_ONE DB '..',0 SCAN_STRINGS DB (COM_FLAG or EXE_FLAG) and 255 ;MINI-44 virus DB 1EH,0E4H,10H,8CH,0ABH,67H,8BH,0D8H,0B6H,12H,0ABH,97H DB 10H,34H,0AAH,67H DB BOOT_FLAG ;Kilroy-B virus (live) DB 12H,0ABH,0A8H,11H,0AAH,0AFH,13H,0ABH,0AAH,10H,0ABH,0AAH DB 67H,0B9H,12H,0ABH DB COM_FLAG ;Kilroy-B virus (dropper) DB 12H,0ABH,0A8H,11H,0AAH,0AFH,13H,0ABH,0AAH,10H,0ABH,0AAH DB 67H,0B9H,12H,0ABH DB (EXE_FLAG or RAM_FLAG) and 255 ;The Yellow Worm DB 0FAH,0A4H,0B5H,26H,0ACH,86H,0AAH,12H,0AAH,0BCH,67H,85H DB 8EH,0D5H,96H,0AAH DB END_OF_LIST ;end of scan string list NAME_STRINGS DB 'MINI-44$' DB 'Kilroy-B$' DB 'Kilroy-B dropper$' DB 'Yellow Worm$' PATH DB 80 dup (?) CURR_DIR DB 64 dup (?) DSIZE DW ? SEARCH_REC DB 43 dup (?) CURR_DR DB ? ;current disk drive DISK_DR DB ? ;drive to scan FFLAGS DB ? ;flags to use in scan FILE_NAME DW ? ;address of file name in memory DATA_BUF DB DBUF_SIZE dup (?) END GBSCAN