CIH 病毒(又稱 Chernobyl、Spacefiller)是 1998 年極具破壞力的 Windows 9x PE 檔案感染型病毒,感染後不增加檔案大小(利用 PE 區段間隙),並能在特定日期觸發破壞 BIOS 與硬碟資料。本文解析一個純組合語言(TASM/MASM)編寫的 CIH 掃描清除工具,展示如何解析 PE 結構、定位病毒殘留區塊、恢復原始入口點(Entry Point)並修復檔案。
*.EXE 檔案。e_lfanew 獲取 PE Header 位置。PE\0\0 簽名(偏移 0x00)。AddressOfEntryPoint(偏移 0x28)是否指向區段間隙(病毒常駐區)。NumberOfSections 計算區段表大小,定位病毒可能藏匿的「區段表之後、區段資料之前」的空隙。0xCC56?偏移 0x4B 處為 0xCCFB?(對應 CIH v1.2/v1.3 關鍵指令序列)。AddressOfEntryPoint(儲存在病毒代碼固定偏移處)。DATA SEGMENT EXEFILE DB '*.EXE',00 DIRFILE DB '*.*',00 FILEBZ DB 00 ; 檔案類型標誌 PE_HEAD DB 4 DUP(0) ; PE Header 指標 VIRSUF DB 1024 DUP(0) ; 病毒代碼緩衝區 VIRPOINT DB 4 DUP(0) ; 病毒首塊指標 SECNUM DB 00,00 ; 區段數 T_ENTRY DB 4 DUP(0) ; 真實 Entry RVA FILEMSG DB ' ( CIH virus) ',24H CLEAMSG DB ' killed !!',0DH,0AH,24H CL_ZERO DB 1024 DUP(0) ; 清零資料 ... DATA ENDS
CLEA_VIRUS PROC NEAR MOV CX,027H; MOV AH,4EH; INT 21H ; FindFirst *.EXE JNC LOOK; JMP EXIT LOOK: INC [EXENUM] ; 顯示掃描路徑... MOV DX,OFFSET DAT+1EH; MOV AX,3D02H; INT 21H ; 開啟檔案 (R/W) JNB CL0; JMP NEXTFILE CL0: MOV BX,AX MOV AX,4200H; MOV CX,0; MOV DX,3CH; INT 21H ; Seek to e_lfanew MOV DX,OFFSET FILESUF; MOV CX,4; MOV AH,3FH; INT 21H ; Read 4 bytes MOV AX,4200H; MOV CX,WORD PTR[FILESUF+2]; MOV DX,WORD PTR[FILESUF] MOV WORD PTR[PE_HEAD],DX; MOV WORD PTR[PE_HEAD+2],CX DEC DX; INT 21H ; Seek to PE Header - 1 MOV DX,OFFSET FILESUF; MOV CX,0200H; MOV AH,3FH; INT 21H ; Read 512 bytes CMP WORD PTR[FILESUF+1],04550H ; 'PE' signature JZ CL21; JMP NEXTFILE CL21: CMP BYTE PTR[FILESUF],00H ; Infected mark (first byte of PE sig = 00) JNZ CL3; JMP NEXTFILE CL3: MOV CX,WORD PTR[FILESUF+07H] ; NumberOfSections MOV WORD PTR[SECNUM],CX INC CX; SHL CX,1; SHL CX,1; SHL CX,1 ; (Sections+1)*8 = virus ptr area size PUSH CX; POP DI ; Get Entry RVA MOV CX,WORD PTR[FILESUF+2BH] MOV DX,WORD PTR[FILESUF+29H] CMP CX,WORD PTR[FILESUF+57H] ; FileAlignment? JE CL4 JB CL5 ; Maybe infected JMP NEXTFILE CL4: CMP DX,WORD PTR[FILESUF+55H]; JB CL5; JMP NEXTFILE CL5: SUB DX,DI; MOV WORD PTR[VIRPOINT],DX; MOV WORD PTR[VIRPOINT+2H],CX MOV AX,4200H; INT 21H ; Seek to virus block MOV DX,OFFSET VIRSUF; MOV CX,100H; MOV AH,3FH; INT 21H ; Read virus code CMP WORD PTR[VIRSUF+DI+36H],056CCH; JZ CL7; JMP NEXTFILE CL7: CMP WORD PTR[VIRSUF+DI+4BH],0FBCCH; JZ CL8; JMP NEXTFILE CL8: ; Found virus! MOV DX,OFFSET FILEMSG; MOV AH,09H; INT 21H MOV AX,4301H; MOV CX,0020H; MOV DX,OFFSET DAT+1EH; INT 21H ; Set Archive attr ; Save true Entry RVA from virus body 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 ; Seek to virus block again MOV DX,WORD PTR[VIRPOINT]; MOV CX,WORD PTR[VIRPOINT+2H]; MOV AX,4200H; INT 21H MOV CX,WORD PTR[VIRSUF+DI-04H]; ADD CX,DI ; Virus first block size + ptr area MOV DX,OFFSET CL_ZERO; MOV AH,40H; INT 21H ; Zero out virus code ; Clear other blocks (omitted)... ; Restore true Entry RVA MOV AX,4200H; MOV CX,WORD PTR[PE_HEAD+2]; MOV DX,WORD PTR[PE_HEAD] ADD DX,28H; ADC CX,0; INT 21H ; Seek to AddressOfEntryPoint in PE Header MOV DX,OFFSET FILESUF; 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 COPYHANDLE ; 復制 handle 關閉 ; Restore file attributes, time... MOV DX,OFFSET CLEAMSG; MOV AH,09H; INT 21H INC [VIREXE] NEXTFILE: ... EXIT: RET CLEA_VIRUS ENDP
使用 INT 21h AH=4Eh/4Fh 搜尋 *.*,檢測屬性位 10h(子目錄),排除 . 與 ..,保存當前目錄上下文(DIRSUFF 緩衝區),CHDIR 進入子目錄遞歸呼叫 CLEA_VIRUS,返回時恢復上下文繼續搜尋。
使用 BCD 運算(DAA 指令)將 16 位元二進制數轉換為 5 位元十進制 ASCII 字串顯示統計數字(目錄數、EXE 數、感染數)。
這個工具展示了純 DOS 組合語言實現完整 PE 解析器、遞歸目錄遍歷、檔案修復的驚人能力。它不依賴任何外部庫、無需作業系統支援,直接操作磁碟扇區與檔案系統(透過 INT 21h),是病毒分析與底層系統程式設計的經典教材。雖然現代殺毒引擎已大不相同,但 PE 結構解析、區段間隙掃描、入口點修復等核心思想依然是靜態查殺的基石。