;本程序在Tasm下编译通过 ;CIH文件型病毒检测消除程序 GOFIRST MACRO XOR CX,CX XOR DX,DX MOV AX,4200H INT 21H ;文件指针指到文件首 ENDM ALTERLINE MACRO MOV DL,0DH MOV AH,02H INT 21H ;回车 MOV DL,0AH MOV AH,02H INT 21H ;换行 ENDM COPYHANDLE MACRO PUSH BX MOV AH,45H INT 21H ;复制文件把柄 MOV BX,AX MOV AH,3EH INT 21H ;关闭复制文件 POP BX ENDM DATA SEGMENT PARA PUBLIC 'DATA' EXEFILE DB '*.EXE',00 DIRFILE DB '*.*',00 FILEBZ DB 00 ;文件标志(COM:00;EXE:FF) DISKSGN DB 00 ;检测盘号 CURRDISK DB 00 ;当前盘号 DISKCHA DB 00,3AH,24H DAT DB 256 DUP(24H) ;磁盘传送地址DISK TRANSPORT AREA OVERMSG DB '所有CIH病毒已被清除!!!',0DH,0AH,24H FILESUF DB 2000 DUP(0) ;存放被检测文件部份内容 PE_HEAD DB 4 DUP(0) ;存放PE HEAD指针 VIRSUF DB 1024 DUP(0) ;存放CIH病毒头块程序 VIRPOINT DB 4 DUP(0) ;存放CIH 首块及链表区首指针 SECNUM DB 00,00 ;Number of FILE SECTIONS T_ENTRY DB 4 DUP(0) ; true Entry RVA FILEMSG DB ' ( CIH virus) ',24H CLEAMSG DB ' killed !!',0DH,0AH,24H CL_ZERO DB 1024 DUP(0) ;清零数据 HZSM DB '正在扫描: ',24H BLANK DB 60 DUP(20H),24H ;送空格 INITDIR DB "/",64 DUP(0) ;初始目录 CURRDIR DB "/ PE",00,63 DUP(24H) ;当前目录 UPDIR DB "..",00 ;上一级目录 DIRSUFF DB 4096 DUP(0) ;目录参数保留区 DIRSUFP DB 00,00 ;目录参数保留区指针 DIRNUM DB 01,00 ;盘中目录文件个数 EXENUM DB 00,00 ;盘中EXE文件个数 VIREXE DB 00,00 ;感染病毒EXE文件个数 DIRMSG DB "subdirectory number:",24H EXEMSG DB "*.EXE numbers:",24H ERRMSG DB "; which affected:",24H DECSUF DB 11 DUP(0) ;二进制->十进制数存放区 TITL DB "CIH CLEAN ASM SOURCECODE TESTING",0dh,0ah DB "kuibing kuibing@163.com",0DH,0AH,0dh,0ah DB "The virus is a Parastic Virus which infects Windows 95/98 .EXE files",0DH, 0AH DB 0DH,0AH,0dh,0ah,24H BEGIN DB 07H,07H,"按任意键开始检测/清除病毒!!",0dh,0ah,24h DATA ENDS CODE SEGMENT PARA PUBLIC 'CODE' ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK KILLCIH PROC FAR MOV DI,0082H MOV DL,[DI] dec di mov bl,[di] PUSH DS XOR AX,AX PUSH AX PUSH DS MOV AX,DATA MOV DS,AX MOV ES,AX MOV AX,STACK MOV SS,AX ;确定检测盘号 cmp bl,0dh jz disk2 AND DL,05FH CMP DL,41H JNZ DISK1 MOV BYTE PTR[DISKSGN],01H MOV BYTE PTR[DISKCHA],41H JMP DISK2 DISK1: CMP DL,42H JNZ DISK3 MOV BYTE PTR[DISKSGN],02H MOV BYTE PTR[DISKCHA],42H JMP DISK2 DISK3: CMP DL,43H JNZ DISK2 MOV BYTE PTR[DISKSGN],03H MOV BYTE PTR[DISKCHA],43H DISK2: MOV AH,19H INT 21H ;取当前盘号 MOV BYTE PTR[CURRDISK],AL ;保存当前盘号 ; CMP BYTE PTR[DISKSGN],00H JNZ DISK4 ADD AL,41H MOV BYTE PTR[DISKCHA],AL JMP DISK5 ; DISK4: MOV DL,BYTE PTR[DISKSGN] DEC DL MOV AH,0EH INT 21H ;选择磁盘驱动器 ; DISK5: PUSH ES MOV AX,0040H MOV ES,AX MOV DI,0087H MOV AL,ES:[DI] POP ES CMP AL,00H JZ CGA MOV AX,0003H JMP CLS CGA: MOV AX,0006H CLS: INT 10H ;清屏 MOV AH,09H MOV DX,OFFSET TITL INT 21H MOV DX,OFFSET DAT ;磁盘传送首址->DX MOV AH,1AH INT 21H ;CREAT DAT MOV AH,47H MOV DL,BYTE PTR[DISKSGN] MOV SI,OFFSET INITDIR+1 INT 21H ;保存初始目录名 MOV AH,3BH MOV DX,OFFSET CURRDIR INT 21H ;回到根目录 MOV BYTE PTR[FILEBZ],0FFH ;置EXE文件标志 MOV DX,OFFSET EXEFILE ; CALL CLEA_VIRUS ;chesk and clear CIH virus CALL CLE_SDIR ;检测各子目录下文件及消除 ; MOV AH,3BH MOV DX,OFFSET INITDIR INT 21H ;恢复初始目录 MOV DL,BYTE PTR[CURRDISK] MOV AH,0EH INT 21H ;选择磁盘驱动器 DONE: ALTERLINE MOV DX,OFFSET OVERMSG MOV AH,09H INT 21H MOV DX,OFFSET DIRMSG MOV AH,09H INT 21H MOV DI,OFFSET DIRNUM CALL BTOD ;显示目录个数 ALTERLINE MOV DX,OFFSET EXEMSG MOV AH,09H INT 21H MOV DI,OFFSET EXENUM CALL BTOD ;显示EXE文件个数 MOV DX,OFFSET ERRMSG MOV AH,09H INT 21H MOV DI,OFFSET VIREXE CALL BTOD ;显示病毒EXE文件个数 ALTERLINE MOV CX,0200H MOV AH,01H INT 10H ;恢复光标 MOV AH,4CH INT 21H ;结束程序退回DOS ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;Key programm;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CLEA_VIRUS PROC NEAR ;在同一子目下搜寻EXE文件并检测是否存在病毒以及消除 MOV CX,027H MOV AH,4EH INT 21H ;搜寻第一匹配文件 JNC LOOK JMP EXIT ;没找到,->EXIT LOOK: INC BYTE PTR[EXENUM] MOV DX,OFFSET HZSM MOV AH,09H INT 21H MOV DX,OFFSET DISKCHA MOV AH,09H INT 21H MOV DX,OFFSET CURRDIR MOV AH,09H INT 21H ;显示当前目录路径 MOV DI,OFFSET CURRDIR+1 CMP BYTE PTR[DI],00H JZ ZJS1 MOV AH,02H MOV DL,5CH INT 21H ZJS1: MOV DX,OFFSET DAT ADD DX,1EH ;DX:匹配文件名首址 PUSH DX PUSH DX POP DI BZ5: INC DI CMP BYTE PTR[DI],00H JNZ BZ5 INC DI MOV BYTE PTR[DI],24H POP DX MOV AH,09H INT 21H ;显示文件名 MOV DX,OFFSET DAT ADD DX,1EH MOV AX,3D02H INT 21H ;打开匹配文件 JNB CL0 JMP NEXTFILE ;;;;;;;;;;;;; CL0: MOV BX,AX MOV AX,4200H MOV CX,00H MOV DX,3CH INT 21H ;文件指针移到文件头第3CH字节 MOV DX,OFFSET FILESUF ;文件缓冲区首址->DX MOV CX,04H MOV AH,3FH INT 21H ;读入4个字节(File address of new exe header) JNB CL1 JMP NEXTFILE CL1: MOV AX,4200H MOV CX,WORD PTR[FILESUF+2] MOV DX,WORD PTR[FILESUF] MOV WORD PTR[PE_HEAD],DX ;保存PE FILE HEAD 指针 MOV WORD PTR[PE_HEAD+2],CX DEC DX INT 21H ;文件指针移到new exe header-1 MOV DX,OFFSET FILESUF ;文件缓冲区首址->DX MOV CX,0200H MOV AH,3FH INT 21H ;读入512个字节(PE File Signature) JNB CL2 JMP NEXTFILE CL2: CMP WORD PTR[FILESUF+1],04550H ;see if is "PE" format file JZ CL21 JMP NEXTFILE CL21: CMP BYTE PTR[FILESUF],00H JNZ CL3 ;"XPE" May have CIH viurs JMP NEXTFILE ;NOT BEEN INFECTED CIH VIRUS CL3: MOV CX,WORD PTR[FILESUF+07H] ;Get Number of Sections MOV WORD PTR[SECNUM],CX INC CX SHL CX,1 SHL CX,1 SHL CX,1 PUSH CX ;(Section 数+1)*8 =病毒块指针区大小 POP DI ;get PE FILE Entry RVA MOV CX,WORD PTR[FILESUF+2BH] ; MOV DX,WORD PTR[FILESUF+29H] ;[FILESUF+29,2A,2B,2CH]=Entry RVA CMP CX,WORD PTR[FILESUF+57H] ;[FILESUF+55,56,57,58H]=File Header Size JE CL4 JB CL5 ;Maybe has CIH virus JMP NEXTFILE CL4: CMP DX,WORD PTR[FILESUF+55H] JB CL5 ;Maybe has CIH virus JMP NEXTFILE CL5: SUB DX,DI MOV WORD PTR[VIRPOINT],DX MOV WORD PTR[VIRPOINT+2H],CX ;Save CIH first block point MOV AX,4200H INT 21H ;文件指针移到FILE Entry address-病毒块指针区大小(DI) MOV DX,OFFSET VIRSUF ;病毒缓冲区首址->DX MOV CX,100H MOV AH,3FH INT 21H ;读入100H个字节 JNB CL6 JMP NEXTFILE CL6: CMP WORD PTR[VIRSUF+DI+36H],056CCH JZ CL7 ;May CIH virus JMP NEXTFILE CL7: CMP WORD PTR[VIRSUF+DI+4BH],0FBCCH JZ CL8 ;Sure CIH virus JMP NEXTFILE CL8: MOV DX,OFFSET FILEMSG MOV AH,09H INT 21H ;显示有病毒 MOV AX,4301H MOV CX,0020H MOV DX,OFFSET DAT ADD DX,1EH INT 21H ;置文件属性为归档 ; ;Save true Entry RVA MOV AX,WORD PTR[VIRSUF+DI+5EH] MOV WORD PTR[T_ENTRY],AX MOV AX,WORD PTR[VIRSUF+DI+60H] MOV WORD PTR[T_ENTRY+2H],AX ; MOV DX,WORD PTR[VIRPOINT] MOV CX,WORD PTR[VIRPOINT+2H] ;GET CIH first block point MOV AX,4200H INT 21H ;文件指针移到FILE Entry address-病毒块指针区大小 ; MOV CX,WORD PTR[VIRSUF+DI-04H] ;取CIH病毒首块长度 ADD CX,DI ;加上CIH病毒链表指针块区大小 MOV DX,OFFSET CL_ZERO MOV AH,40H INT 21H ;病毒首块及链表指针区清零 ; ;;;;;;;;;;;;;;;;;;;;;; ;Clear other block viurs ; omitted ;;;;;;;;;;;;;;;;;;;;;; ; ;Restore True Entry RVA(Address of Entry Point) MOV AX,4200H MOV CX,WORD PTR[PE_HEAD+2] MOV DX,WORD PTR[PE_HEAD] ADD DX,28H ADC CX,0 INT 21H ;文件指针移到文件头的Entry Point MOV DX,OFFSET FILESUF ;文件缓冲区首址->DX ; MOV CX,4H ; MOV AH,3FH ; INT 21H ;读入Entry Point ; JNB CL11 ; JMP NEXTFILE CL11: MOV CX,WORD PTR[T_ENTRY] MOV WORD PTR[FILESUF],CX MOV CX,WORD PTR[T_ENTRY+2] MOV WORD PTR[FILESUF+2],CX MOV CX,2H MOV AH,40H INT 21H ;将正常的Entry 参数写回 JB NEXTFILE COPYHANDLE MOV SI,[OFFSET DAT+15H] MOV CL,[SI] MOV AX,4301H MOV DX,OFFSET DAT ADD DX,1EH INT 21H ;恢复文件原属性 JB NEXTFILE MOV DX,OFFSET DAT MOV SI,WORD PTR[OFFSET DAT+16H] MOV DI,WORD PTR[OFFSET DAT+18H] MOV CX,[SI] MOV DX,[DI] MOV AX,5701H INT 21H ;恢复文件原建立日期 MOV DX,OFFSET CLEAMSG MOV AH,09H INT 21H INC BYTE PTR[VIREXE] NEXTfile:MOV AH,3EH INT 21H CLD MOV DI,OFFSET DAT ADD DI,1EH MOV CX,0EH MOV AL,24H REPZ STOSB MOV DI,OFFSET FILESUF MOV CX,600H MOV AL,00 REPZ STOSB ;清文件缓冲区 MOV CX,0FFFFH BZ6: LOOP BZ6 MOV CX,0FFFFH BZ7: LOOP BZ7 MOV CX,0FFFFH BZ8: LOOP BZ8 MOV CX,0FFFFH BZ9: LOOP BZ9 MOV DL,0DH MOV AH,02H INT 21H ;只回车 MOV DX,OFFSET HZSM MOV AH,09H INT 21H MOV DX,OFFSET DISKCHA MOV AH,09H INT 21H MOV DX,OFFSET BLANK MOV AH,09H INT 21H MOV DL,0DH MOV AH,02H INT 21H ;回车 MOV AH,4FH INT 21H JC EXIT JMP LOOK EXIT: RET CLEA_VIRUS ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CLE_SDIR PROC NEAR ;搜寻各子目EXE文件并检测是否存在病毒以及消除 CL_SUBD:MOV DX,OFFSET DIRFILE MOV CX,0010H MOV AH,4EH INT 21H ;搜寻第一匹配文件 JNC LOOKS JMP EXITS ;没找到,->EXITS LOOKS: MOV SI,OFFSET DAT ADD SI,15H CMP BYTE PTR[SI],10H JZ NEXT1 JMP NEXTSUB NEXT1: MOV BX,OFFSET DAT ADD BX,1EH ;BX:匹配文件名首址 CMP BYTE PTR[BX],2EH ;是否是“.”或“..”子目录 JNZ SUB1 JMP NEXTSUB SUB1: INC [DIRNUM] ;子目录数量加1 CLD MOV SI,OFFSET DAT MOV DI,OFFSET DIRSUFF ADD DI,WORD PTR[DIRSUFP] MOV CX,0015H REPZ MOVSB ;保存当前目录参数 ADD WORD PTR[DIRSUFP],0015H ;目录参数指针+15H MOV DI,OFFSET CURRDIR+1 CMP BYTE PTR[DI],00H JZ LP2 LP1: INC DI CMP BYTE PTR[DI],00H JNZ LP1 ;找当前子目录名路径尾 MOV BYTE PTR[DI],5CH INC DI LP2: MOV SI,BX MOV CX,0DH REPZ MOVSB MOV DX,OFFSET CURRDIR MOV AH,3BH INT 21H ;进入下一级子目录 CLD MOV DI,OFFSET CURRDIR+1 MOV CX,003FH MOV AL,24H REPZ STOSB MOV AH,47H MOV DL,BYTE PTR[DISKSGN] MOV SI,OFFSET CURRDIR+1 INT 21H ;取当前子目录 MOV BYTE PTR[FILEBZ],0FFH ;置EXE文件标志 MOV DX,OFFSET EXEFILE CALL CLEA_VIRUS ;chesk and clear CIH virus JMP CL_SUBD ;查找当前子目录下一级目录及EXE文件 EXITS: MOV BX,OFFSET CURRDIR+1 CMP BYTE PTR[BX],00 ;判当前目录为根目录否 JNZ SUB2 JMP OVERS ;当前目录为根目录->OVERS SUB2: MOV AH,3BH MOV DX,OFFSET UPDIR INT 21H ;返回上一子目录 MOV AH,47H MOV DL,BYTE PTR[DISKSGN] MOV SI,OFFSET CURRDIR+1 INT 21H ;取当前子目录 STD MOV SI,OFFSET DIRSUFF-1H ADD SI,WORD PTR[DIRSUFP] MOV DI,OFFSET DAT+14H MOV CX,0015H REPZ MOVSB SUB WORD PTR[DIRSUFP],0015H ;恢复当前子目录参数及指针 NEXTSUB:MOV AH,4FH INT 21H JC EXITS JMP LOOKS OVERS: RET CLE_SDIR ENDP ; ; BTOD PROC NEAR ;将[DI]中2进制数转换成十进制数显示 MOV WORD PTR[DECSUF+10H],OFFSET DECSUF MOV DX,0000H MOV AX,[DI] ;DX=数值的高位;AX=数值的低位 PUSH AX POP SI PUSH DX POP DI PUSH BP PUSH BX XOR AX,AX MOV BX,AX MOV BP,AX MOV CX,0020H BTOD1: SHL SI,1 RCL DI,1 XCHG BP,AX ADC AL,AL DAA XCHG AH,AL ADC AL,AL DAA XCHG AH,AL XCHG BP,AX XCHG BX,AX ADC AL,AL DAA XCHG AH,AL ADC AL,AL DAA XCHG AH,AL XCHG BX,AX ADC AL,00 LOOP BTOD1 MOV CX,1810H XCHG DX,AX CALL BTOD2 XCHG BX,AX CALL BTOD3 MOV AX,BP CALL BTOD3 MOV BYTE PTR[DECSUF+0BH],24H MOV AH,09H MOV DX,OFFSET DECSUF INT 21H JMP BTOD6 BTOD3 PROC NEAR PUSH AX MOV DL,AH CALL BTOD7 POP DX BTOD7 PROC NEAR MOV DH,DL SHR DL,1 SHR DL,1 SHR DL,1 SHR DL,1 CALL BTOD2 MOV DL,DH BTOD2 PROC NEAR AND DL,0FH JZ BTOD8 MOV CL,00 BTOD8: DEC CH AND CL,CH OR DL,30H SUB DL,CL PUSH DI MOV DI,WORD PTR[DECSUF+10H] MOV [DI],DL INC DI MOV WORD PTR[DECSUF+10H],DI POP DI RET BTOD2 ENDP BTOD7 ENDP BTOD3 ENDP BTOD6: POP BX POP BP RET BTOD ENDP ; ; KILLCIH ENDP ; CODE ENDS STACK SEGMENT PARA STACK 'STACK' DB 256 DUP(?) STACK ENDS END KILLCIH
|