CIH病毒的分析与预防
总参第六十一研究所
樊海宁 刘 勇 柴丽雅
作为首例WIN32病毒,CIH感染32-bit后缀为.EXE的PE格式可执行文件,当染毒文件在Windows
95(或Windows 98)下首次执行时,它将驻留内存、监视之后所有的打开文件操作并传染,由于其用到的技术Windows
NT并不支持,因此染毒文件在NT下无法执行。下面我们以CIH V1.2(最常见的一种)为例进行分析,最后给出一个CIH免疫程序。
首先给出CIH的伪代码:
vir_entry_point:
PUSH 结构化例外处理链
PUSH EAX
SIDT FWORD PTR[ESP-2]
POP EBX;获取中断描述符表(IDT)基址
CLI ;关中断
保存int 3入口地址
设置新int 3入口为new_int3_isr
INT 3;调用int 3使CPU由特权级3转入特权级0
将病毒拷贝至分配的系统内存页中
INT 3 ;在特权级0下常驻内存
vir_exit:
STI ;开中断
POP 结构化例外处理链
PUSH EXE染毒前的程序入口点
RET ;转至程序正常执行处
new_int3_isr:
若已将病毒拷贝至分配的系统内存页中,
JMP to install_hook
MOV ECX,DR0 ;读取系统染毒标志
JECXZ alloc_mem_and_prepare_to_infect
CIH认为系统已染毒,调整栈顶的int 3返回地址为vir_exit
恢复原来int 3入口地址
IRETD ;转至vir_exit处
alloc_mem_and_prepare_to_infect:
调用_PageAllocate分配2页系统内存
IRETD
install_hook:
LEA EAX,file_hook
VXDCall IFSMgr_InstallFileSystemApiHook
MOV DR0,EAX ;
将下一hook的入口点保存在DR0中作为
;系统是否染毒的标志。
恢复原来int 3入口地址
JMP vir_exit
file_hook:
PUSHAD ;保护现场
判断是否打开文件操作(IFSFN_OPEN)、文件后缀是否为.EXE、该文件是否已经染毒(通过PE格式文件的PE标志头的前一字节为0否判别)若条件全部满足则试图感染该EXE文件判断是否为4月26日,若是则试图破坏硬盘及BIOS。
POPAD ;恢复现场
MOV EAX,DR0
JMP [EAX] ;继续下一个hook
CIH两次int 3调用的目的是使CPU由用户态的特权级3转入特权级0,从而能够在核心态进行操作系统级的调用,完成系统内存的分配和文件系统hook的安装。
通过分析,我们知道CIHv1.2没有使用任何反跟踪或变形技术。它通过检查调试寄存器0(DR0)来决定系统是否已被感染;通过检查PE标志头的前一字节决定该文件是否已被感染。基于此,我们可以写一个简单的免疫程序段,它可嵌到C程序中:
#define FLAG 0x12345678
DWORD rDR0;
_asm{
pushad
;保护现场
push ebx
sidt fwordptr[esp-2]
pop ebx
;获取中断描述符表基址
add ebx,0x1c
cli
mov edx,[ebx]
mov dx,[ebx-4]
;保存int 3入口地址
lea ecx,int3_isr
mov [ebx-4],cx
shr ecx,0x10
mov [ebx+2],cx
;设置新int 3入口为int3_isr
int 3
jmp ok
int3_isr:
mov eax,dr0
;在特权级0读取系统染毒标志
mov ecx,FLAG
mov dr0,ecx
iretd
ok:
mov rDR0,eax
mov [ebx-4],dx
shr edx,0x10
mov [ebx+2],dx
;恢复原来int 3入口地址
sti
popad
;恢复现场
}
if(0==rDR0) printf(“疫苗安装成功。”);
else if(FLAG==rDR0) printf(“疫苗已经安装。”);
else printf(“系统可能已被CIH感染!!DR0=%lx”,rDR0);
此方法通过设置调试寄存器DR0为非0使CIH误以为系统已被感染。对于一个干净的Windows
95/98系统,执行上述程序段后系统就不会被CIH感染,并且可以安全执行被CIH感染的EXE文件。