Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 66 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
66
Dung lượng
397,64 KB
Nội dung
current disk. Alternatively, one can specify a drive letter on the command line and GBSCAN will scan that drive instead. GBSCAN can be assembled with MASM, TASM or A86. ;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 The GBCHECK Program The GBCHECK.ASM program is a simple behavior checker that flags: A) attempts to write to Cylinder 0, Head 0, Sector 1 on any disk, B) any attempt by any program to go memory resident using DOS Interrupt 21H, Function 31H, and C) attempts by any program to open a COM or EXE file in read/write mode using DOS Interrupt 21H, Function 3DH. This is simply accomplished by installing hooks for Interrupts 21H and 13H. GBCHECK is itself a memory resident program. Since it must display information and questions while nasty things are happen- ing, it has to access video memory directly. Since it’s more of a demo than anything else, it only works properly in text modes, not graphics modes for Hercules or CGA/EGA/VGA cards. It works by grabbing the first 4 lines on the screen and using them tempo- rarily. When it’s done, it restores that video memory and disap- pears. Since GBCHECK is memory resident, it must also be careful when going resident. If it installs its interrupt hook and goes resident it will flag itself. Thus, an internal flag called FIRST is used to stop GBCHECK from flagging the first attempt to go resident it sees. GBCHECK can be assembled with TASM, MASM or A86 to a COM file. ;GB-Behavior Checker ;(C) 1995 American Eagle Publications, Inc. All Rights Reserved. .model tiny .code ORG 100H START: jmp GO_RESIDENT ;jump to startup code ;*************************************************************************** ;Resident part starts here ;Data area FIRST DB 0 ;Flag to indicate first Int 21H, Fctn 31H VIDSEG DW ? ;Video segment to use CURSOR DW ? ;Cursor position VIDEO_BUF DW 80*4 dup (?) ;Buffer for video memory ;*************************************************************************** ;Interrupt 13H Handler OLD_13H DD ? ;Original INT 13H vector ;The Interrupt 13H hook flags attemtps to write to the boot sector or master ;boot sector. INT_13H: cmp ah,3 ;flag writes jne DO_OLD cmp cx,1 ;to cylinder 0, sector 1 jne DO_OLD cmp dh,0 ;head 0 jne DO_OLD call BS_WRITE_FLAG ;writing to boot sector, flag it jz DO_OLD ;ok’ed by user, go do it stc ;else return with c set retf 2 ;and don’t allow a write DO_OLD: jmp cs:[OLD_13H] ;go execute old Int 13H handler ;This routine flags the user to tell him that an attempt is being made to ;write to the boot sector, and it asks him what he wants to do. If he wants ;the write to be stopped, it returns with Z set. BS_WRITE_FLAG: push ds push si push ax call SAVE_VIDEO ;save a block of video for our use push cs pop ds mov si,OFFSET BS_FLAG call ASK pushf call RESTORE_VIDEO ;restore saved video popf pop ax pop si pop ds ret BS_FLAG DB ’An attempt is being made to write to the boot sector. ’ DB ’Allow it? ’,7,7,7,7,0 ;*************************************************************************** ;Interrupt 21H Handler OLD_21H DD ? ;Original INT 21H handler ;This is the interrupt 21H hook. It flags attempts to open COM or EXE files ;in read/write mode using Function 3DH. It also flags attempts to go memory ;resident using Function 31H. INT_21H: cmp ah,31H ;something going resident? jnz TRY_3D ;nope, check next condition to flag cmp BYTE PTR cs:[FIRST],0 ;first time this is called? jz I21RF ;yes, must allow GBC to go resident it- self call RESIDENT_FLAG ;yes, ask user if he wants it jz I21R ;he wanted it, go ahead and do it mov ah,4CH ;else change to non-TSR terminate jmp SHORT I21R ;and pass that to DOS TRY_3D: push ax and al,2 ;mask possible r/w flag cmp ax,3D02H ;is it an open r/w? pop ax jnz I21R ;no, pass control to DOS push si push ax mov si,dx ;ds:si points to ASCIIZ file name T3D1: lodsb ;get a byte of string or al,al ;end of string? jz T3D5 ;yes, couldnt be COM or EXE, so go to DOS cmp al,’.’ ;is it a period? jnz T3D1 ;nope, go get another lodsw ;get 2 bytes or ax,2020H ;make it lower case cmp ax,’oc’ ;are they “co”? jz T3D2 ;yes, continue cmp ax,’xe’ ;no, are they “ex”? jnz T3D5 ;no, not COM or EXE, so go to DOS jmp SHORT T3D3 T3D2: lodsb ;get 3rd byte (COM file) or al,20H ;make it lower case cmp al,’m’ ;is it “m” jz T3D4 ;yes, it is COM T3D3: lodsb ;get 3rd byte (EXE file) or al,20H ;make lower case cmp al,’e’ ;is it “e” jnz T3D5 ;nope, go to original int 21H T3D4: pop ax ;if we get here, it’s a COM or EXE pop si call RDWRITE_FLAG ;ok, COM or EXE, ask user if he wants it jz I21R ;yes, he did, go let DOS do it stc ;else set carry to indicate failure retf 2 ;and return control to caller T3D5: pop ax ;not COM or EXE, so clean up stack pop si jmp SHORT I21R ;and go to old INT 21H handler I21RF: inc BYTE PTR cs:[FIRST] ;update FIRST flag I21R: jmp cs:[OLD_21H] ;pass control to original handler ;This routine asks the user if he wants a program that is attempting to go ;memory resident to do it or not. If the user wants it to go resident, this ;routine returns with Z set. RESIDENT_FLAG: push ds push si push ax call SAVE_VIDEO ;save a block of video for our use push cs pop ds mov si,OFFSET RES_FLAG call ASK pushf call RESTORE_VIDEO ;restore saved video popf pop ax pop si pop ds ret RES_FLAG DB 7,7,7,’A program is attempting to go resident. Allow’ DB ’ it? ’,0 ;RDWRITE_FLAG asks the user if he wants a COM or EXE file to be opened in read/ ;write mode or not. If he does, it returns with Z set. RDWRITE_FLAG: push ds push si push ax call SAVE_VIDEO ;save a block of video for our use mov si,dx call DISP_STRING ;display file name being opened push cs pop ds mov si,OFFSET RW_FLAG ;and query user call ASK pushf call RESTORE_VIDEO ;restore saved video popf pop ax pop si pop ds ret RW_FLAG DB 7,7,7,’ is being opened in read/write mode. Allow it? ’ DB 0 [...]... virus before DOS loaded Move the Z block up, and adjust the 366 The Giant Black Book of Computer Viruses memory size at 0:413H to get rid of the high memory where the virus was originally resident Finally, move the virus down into its new M-block What conditions should be present before the virus does all of this? Certainly, we don’t want to wipe out some program in the middle of executing! Stealth Techniques... INT 13H) High byte of cylinder number (from cl high bits on INT 13H) Sector Size/Drive/Head (from dh, dl on INT 13H) The head is the low 4 bits, the drive is bit 5, and the sector size is bits 6 to 8 (0A0H is 512 byte sectors with ECC, standard for PCs) Written to, it’s the command to execute (20H=read, 40H=write), read from, it’s the status 1F7 3 56 The Giant Black Book of Computer Viruses This will... disk read? 364 The Giant Black Book of Computer Viruses jc READ_FLOPPY ;no, go handle floppy ;This routine stealths the hard disk It’s really pretty simple, since all it ;has to do is add VIR_SIZE+1 to the sector number being read, provided the ;sector being read is somewhere in the virus That moves a read of the ;master boot sector out to the original master boot record, and it moves ;all other sector... searches the log in memory for a match on the file name To use it, pass the name of the file in fname If a match is found, the function returns true, and FN is set to the index in Log[] which is the proper record If no match is found, the function returns false.} function SearchLog(fname:string;var FN:word):boolean; var j :word; begin fname:=UpString(fname); 344 The Giant Black Book of Computer Viruses. .. at the real boot sector to test it, though? Perhaps the best way is to attempt to read by directly manipulating the i/o ports for the hard disk This approach goes past all of the software in the computer (with an important exception we’ll discuss in a moment) and gets the data directly from the hard disk itself The problem with this approach is that it’s hardware dependent The whole purpose of the. .. ;jump to ROM BIOS disk handler DWORD PTR cs:[OLD_13H] 362 The Giant Black Book of Computer Viruses ;This handles reading from the floppy, which is a bit more complex For one, ;we can’t know where the original boot sector is, unless we first read the ;viral one and get that information out of it Secondly, a multi-sector ;read must return with the FAT in the second sector, etc READ_FLOPPY: cmp cx,1 ;is it... 13H, Function 2, and then look at the data you read? Right? And if you got an exact copy of the original sector back on the read, you’d know there was no infection here Everything’s ok Or is it? Maybe not Look at the following code, which might be implemented as an Interrupt 13H hook: INT_13H: cmp jnz cmp jnz mov cx,1 OLD13 dx,80H OLD13 cx,7 352 The Giant Black Book of Computer Viruses pushf call mov... should be there On a standard 64 0K system, you’ll get a display something like: 65 5, 360 total bytes memory 485 ,64 8 bytes free If the “total bytes memory” is anything other than 65 5, 360 (= 64 0 x 1024) then something’s taken part of your 64 0K memory That’s a dead give-away So how does a boot sector virus avoid sending up this red flag? One thing it could do is to wait until DOS (or perhaps another operating... in the BIOS data area at segment 40H The floppy disk uses the SEEK_STATUS flag at offset 3EH in the BIOS data area How is it that these flags get set and reset though? When a hard or floppy disk finishes the work it has been instructed to do by the BIOS or another program, it generates a hardware interrupt The routine which handles this hardware interrupt sets the appropriate flag to notify the software... you can hook the i/o ports themselves in protected mode Thus, a direct hardware access can even be redirected! The SS-3 86 virus does exactly this.1 We’ll discuss this technique more in two chapters Further Options for Viruses We’ve briefly covered a lot of ground for stealthing boot sector viruses There’s a lot more ground that could be covered, though There are all kinds of combinations of the techniques . 12H,0ABH,0A8H,11H,0AAH,0AFH,13H,0ABH,0AAH,10H,0ABH,0AAH DB 67 H,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 ,67 H,85H DB 8EH,0D5H,96H,0AAH DB END _OF_ LIST ;end of scan string. the log in memory for a match on the file name. To use it, pass the name of the file in fname. If a match is found, the function returns true, and FN is set to the index in Log[] which is the . isn’t there. We’ll break our discussion of stealth up into boot sector viruses and file infectors, since the techniques are very different in these two cases. Let’s consider the case of the boot