[返回]
计算机世界1999年第11期

CIH病毒

木子石

  作为首例WIN32病毒,CIH 感染32位后缀为.EXE的PE格式可执行文件,当染毒文件在Windows 9x下首次执行时,它将驻留内存、监视之后所有的打开文件操作并传染,由于WindowsNT并不支持其用到的技术,因此染毒文件在NT下无法执行。下面我们以CIH V1.2为例进行分析,最后给出一个CIH免疫程序。

  首先给出CIH的伪代码:

vir_entry_point:

push 结构化例外处理链

push EAX

sidt FWORDPTR[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的安装。

  通过分析,我们知道CIH v1.2没有使用任何反跟踪或变形技术。它通过检查调试寄存器0(DR0)来决定系统是否已被感染;通过检查PE标志头的前一字节决定该文件是否已被感染。基于此,我们可以写一个简单的免疫程序段,它可嵌到C程序中:


#define FLAG 0x12345678

DWORD rDR0;

_asm{

pushad ;保护现场

push ebx

sidt fword ptr [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文件。