1.病毒分析

被感染的文件可能是通过修改OEP感染,也可能通过是修改附近的代码为CALL来感染,
有的可能会是多重感染。

执行到病毒头时,病毒头先解密后面代码的内容。
然后有个时间检测,大于C00则跳回原文件处继续执行。
得到一些要使用的API的输出地址
创建"Vx_4"事件
如果已经创建则跳回执行原文件代码.
保存
ZwCreateFile
ZwOpenFile
ZwCreateProcess
ZwCreateProcessEx
的服务号到代码中.

调用
ZwCreateSection,ZwMapViewOfSection
将病毒代码复制到新空间去并调用到偏移449处执行.

提升进程权限

查找进程
饶过前面3个系统进程.
在进程中Section.并HOOK上面的Zw系列4个函数
第4个winlogon进程创建远程线程
跳回原文件执行.
**************************************************************************************
winlogon远程线程中执行的代码

先调用sfc.dll或sfc_os.dll的2号函数,然后HOOK sfc中一个内部函数改为ExitThread.
用来关闭系统文件保护的.

检查
"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\TargetHost

然后Sleep(-1)躺下了,这里应该被和蔼可亲的评委同志改过了。

所有被注入代码的进程都被HOOK了4个文件相关的函数.
所以只要进程一用到哪个文件,它就会将其感染.


2.解决思路
先将内存中的 HOOK 恢复.
扫全盘文件,检测PE文件是否有love标志,有则进行查杀.
查杀使用反汇编引擎扫描代码,解密代码,并计算出OEP和恢复被修改代码.

下面是源代码

CVx_AntiVirusDlg* m_dlg;
//提权
void AdjustProcess()
{
  HANDLE hToken;              // 令牌句柄
  TOKEN_PRIVILEGES tkp;       // 令牌结构指针
  OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken);

  LookupPrivilegeValue(NULL, SE_DEBUG_NAME,&tkp.Privileges[0].Luid);
  tkp.PrivilegeCount = 1;  // one privilege to set   
  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL,0);
}

#define APICOUT 4
char ResetApiName[APICOUT][255] = 
{
  "ZwCreateFile",
  "ZwOpenFile",
  "ZwCreateProcess",
  "ZwCreateProcessEx"
};
#define NONEHOOK 0
#define ANTIHOOKFAILD 1
#define ANTIHOOKTRUE  2
//恢复原来的代码
int ResetCode(HANDLE theHandle)
{
  BYTE code[5] = {0};
  BYTE Newcode[5] = {0};
  DWORD dwReadnum;
  DWORD oldpro;
  BOOL ret = NONEHOOK;
  for(int i = 0; i < APICOUT; i++)
  {
    DWORD ApiAddr = (DWORD)GetProcAddress(GetModuleHandle("NTDLL.DLL"),ResetApiName[i]);
    if( ApiAddr )
    {
      VirtualProtectEx(theHandle,(LPVOID)ApiAddr,5,PAGE_EXECUTE_READWRITE,&oldpro);
      ReadProcessMemory(theHandle,(LPVOID)ApiAddr,code,5,&dwReadnum);
      if( dwReadnum != 0)
      {
        if( 0xE8 == code[0] )//if Hook
        {
          DWORD NewAddr = ApiAddr + *(DWORD*)&code[1] + 5;
          VirtualProtectEx(theHandle,(LPVOID)NewAddr,5,PAGE_EXECUTE_READWRITE,&oldpro);
          ReadProcessMemory(theHandle,(LPVOID)NewAddr,Newcode,5,&dwReadnum);
          if( dwReadnum != 0)
          {
            //restore hook
            if( !WriteProcessMemory(theHandle,(LPVOID)ApiAddr,Newcode,5,&dwReadnum) )
            {
              ret = ANTIHOOKFAILD;
            }
            else
            {
              ret = ANTIHOOKTRUE;
            }
          }
        }
      }
    }
  }
  return ret;
}



void CloseFileProtect(HANDLE ProcessHandle)
{
  HMODULE hSfc;
  DWORD dwVersion = GetVersion();
  if ((DWORD)(LOBYTE(LOWORD(dwVersion))) == 5)// Windows 2000/XP
  {
    if((DWORD)(HIBYTE(LOWORD(dwVersion))) == 0)//Windows 2000
    {
      hSfc = LoadLibrary("sfc.dll");
    }
    else 
    {//if((DWORD)(HIBYTE(LOWORD(dwVersion))) = 1) //Windows XP
      hSfc = LoadLibrary("sfc_os.dll");
    }
  }
  DWORD func = (DWORD)GetProcAddress(hSfc,MAKEINTRESOURCE(2));
  DWORD dwThreadPid;
  HANDLE hThread = CreateRemoteThread(ProcessHandle,NULL,0,(DWORD (__stdcall *) (void *))func,NULL,0,&dwThreadPid); 
  DWORD dw = WaitForSingleObject(hThread, 4000); // attends 4 secondes
  CloseHandle(hThread); 
}

//修复HOOK
BOOL AntiHook()
{
  char path[MAX_PATH] = "";
  HANDLE hProcessSnap = NULL;
  PROCESSENTRY32 pe32 = {0};
  hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if(hProcessSnap == (HANDLE)-1)
  {
    m_dlg->MessageBox("创建进程快照失败!");
    return FALSE;
  }
  pe32.dwSize = sizeof(PROCESSENTRY32);
  int idx = 0;
  if (Process32First(hProcessSnap, &pe32))
  {
    do
    {
      idx++;
      if( idx > 4 )
      {
        m_dlg->SetCurText(path);
        HANDLE theHandle = OpenProcess(PROCESS_ALL_ACCESS,TRUE,pe32.th32ProcessID);
        GetModuleFileNameEx(theHandle,NULL,path,MAX_PATH);

        if( theHandle )
        {
          if( idx == 5)//winlogon.exe
          {
            CloseFileProtect(theHandle);//关闭文件保护
          }
          int retcode = ResetCode(theHandle);
          if( retcode == ANTIHOOKTRUE )
          {
            m_dlg->InsertText(path,"内存","是","已清除",0);
          }
          else if( retcode == ANTIHOOKFAILD )
          {
            m_dlg->InsertText(path,"内存","是","清除失败",0);
          }

        }
      }
    }
    while (Process32Next(hProcessSnap, &pe32));
  }
  else
  {
    m_dlg->MessageBox("枚举进程失败!");
    CloseHandle (hProcessSnap);
    return FALSE;
  }
  CloseHandle (hProcessSnap);
  return TRUE;
}

//文件感染病毒信息
struct VirusInfo 
{
  char strpath[MAX_PATH];
  HANDLE hFileMap;
  HANDLE hFile;
  BYTE* pvFile;
  int  idx;
};

//修复文件
void RepairFile(VirusInfo* info);
BOOL bOnlyCheck;//只查毒

HANDLE dwFindThread = 0;
HANDLE dwVirusThread = 0;
deque<CString> strdeque;
BOOL bStopFind = FALSE;
CRITICAL_SECTION cs;

BOOL IsExeExtendName(char* strname)
{
  if( !strname ) return FALSE;
  char* p = strchr(strname,'.');
  if( !p ) return FALSE;
  if( _stricmp(p,".EXE") == 0 )
  {
    return TRUE;
  }
  return FALSE;
}

void FindFileInDirectory(char* strpath)
{
  WIN32_FIND_DATA fileinfo = {0};
  HANDLE handle = FindFirstFile( strpath, &fileinfo );
  if (NULL != handle && INVALID_HANDLE_VALUE != handle)
  {
    do
    {
      if( fileinfo.cFileName[0] != '.' )
      {
        if ((FILE_ATTRIBUTE_DIRECTORY & fileinfo.dwFileAttributes) == FILE_ATTRIBUTE_DIRECTORY)
        {
          char strdirpath[MAX_PATH];
          strcpy_s(strdirpath,MAX_PATH,strpath);
          strdirpath[strlen(strdirpath)-1] = 0;
          strcat_s(strdirpath,MAX_PATH,fileinfo.cFileName);
          strcat_s(strdirpath,MAX_PATH,"\\*");
          FindFileInDirectory(strdirpath);
        }
        else if( m_dlg->bScanAllFile || IsExeExtendName(fileinfo.cFileName) )
        {
          char strfilepath[MAX_PATH] = "";
          strcpy_s(strfilepath,MAX_PATH,strpath);
          strfilepath[strlen(strfilepath)-1] = 0;
          strcat_s(strfilepath,MAX_PATH,fileinfo.cFileName);

          m_dlg->SetCurText(strfilepath);
          EnterCriticalSection(&cs);
          strdeque.push_back(strfilepath);
          LeaveCriticalSection(&cs);
        }
      }
    }while (FindNextFile( handle, &fileinfo ));
    FindClose(handle);
  }
}
DWORD WINAPI FindFileThread(LPVOID lp)
{
  char strpath[30] = "";
  for(int i=1;i<=25;i++)
  {
    //sprintf_s(strpath,10,"%c:\\",'A'+i);
    sprintf_s(strpath,30,"%c:\\",'A'+i);
    if(GetDriveType(strpath) != DRIVE_NO_ROOT_DIR)
    {
      strcat_s(strpath,10,"*");

      FindFileInDirectory(strpath);
    }
  }
  bStopFind = TRUE;
  return 0;
}
//检验是否染毒
void VaildVirus(CString strPath)
{
  if(strPath == "") return;

  HANDLE hFile = CreateFile(strPath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hFile == INVALID_HANDLE_VALUE) 
  {
    DWORD dw = GetLastError();
    return;
  }
  DWORD dwFileSize = GetFileSize(hFile, NULL);
  if( dwFileSize < 2048 )
  {
    CloseHandle(hFile);
    return;
  }

  HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE,0,dwFileSize,NULL);
  if (hFileMap == NULL) 
  {
    CloseHandle(hFile);
    return;
  }
  DWORD pvFile = (DWORD)MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
  if (pvFile == NULL) 
  {
    CloseHandle(hFileMap);
    CloseHandle(hFile);
    return;
  }
  IMAGE_DOS_HEADER *dos_header = (IMAGE_DOS_HEADER *)pvFile;
  IMAGE_NT_HEADERS *Nt_Header = (IMAGE_NT_HEADERS *)(pvFile+dos_header->e_lfanew);
  if( *(WORD*)pvFile != IMAGE_DOS_SIGNATURE ||                                  //检测MZ头
    (DWORD)dos_header->e_lfanew > dwFileSize ||                                  //检测偏移是否有问题
    Nt_Header->Signature != IMAGE_NT_SIGNATURE ||                                //检测PE头
    (Nt_Header->FileHeader.Characteristics & IMAGE_FILE_DLL) == IMAGE_FILE_DLL ||                //检测是否是DLL
    (Nt_Header->FileHeader.TimeDateStamp != 'evol' &&                              //检测是否已经感染过
    Nt_Header->FileHeader.TimeDateStamp != 'love') || 
    Nt_Header->FileHeader.TimeDateStamp == '\0bug'                                //已修复PE文件
    )
  {
    UnmapViewOfFile((LPVOID)pvFile);
    CloseHandle(hFileMap);
    CloseHandle(hFile);
    return;
  }
  if( !bOnlyCheck )
  {
    VirusInfo* virusinfo = new VirusInfo;
    memset(virusinfo,0,sizeof(VirusInfo));
    strcpy_s( virusinfo->strpath, MAX_PATH, strPath );
    virusinfo->pvFile = (BYTE*)pvFile;
    virusinfo->hFile = hFile;
    virusinfo->hFileMap = hFileMap;
    virusinfo->idx = m_dlg->InsertText(strPath.GetBuffer(0),"文件","是","未清除",(DWORD)virusinfo);
    RepairFile(virusinfo);
  }
  else
  {
    m_dlg->InsertText(strPath.GetBuffer(0),"文件","是","未清除",0);
  }
}

DWORD WINAPI FindVirusThread(LPVOID lp)
{
  while(!bStopFind)
  {
    while(strdeque.size())
    {
      EnterCriticalSection(&cs);
      CString strPath = strdeque.front();
      VaildVirus(strPath);
      strdeque.pop_front();
      LeaveCriticalSection(&cs);
    }
  }
  m_dlg->SetCurText("");
  m_dlg->m_ProgressCtrl.End();
  m_dlg->m_ProgressCtrl.Reset();
  m_dlg->SetStatusText("杀毒完毕");
  return 0;
}

IMAGE_DOS_HEADER* image_dos_header;
IMAGE_NT_HEADERS* image_nt_header;
IMAGE_SECTION_HEADER *image_section_header;
BYTE* EpAddr = NULL;

DWORD PEAlign(DWORD dwTarNum,DWORD dwAlignTo)
{  
  DWORD dwtemp;
  dwtemp=dwTarNum/dwAlignTo;
  if((dwTarNum%dwAlignTo)!=0)
  {
    dwtemp++;
  }
  dwtemp=dwtemp*dwAlignTo;
  return(dwtemp);
}

int FindSectionIndex(DWORD addr)
{
  int i = 0;
  for ( i = 0; i < image_nt_header->FileHeader.NumberOfSections; i++ )
  {
    if (addr >= image_section_header[i].VirtualAddress && 
      addr < image_section_header[i].VirtualAddress + image_section_header[i].Misc.VirtualSize)
    {
      break;
    }
  }
  if ( i < image_nt_header->FileHeader.NumberOfSections )
    return (i);
  else
    return (-1);
}
DWORD RvaToOffset(DWORD addr)
{
  int i = FindSectionIndex(addr);
  if (i >= 0)
    return (addr - image_section_header[i].VirtualAddress + image_section_header[i].PointerToRawData);

  return (NULL);
}

BYTE pushcode = 0x50;
DWORD jmpaddr;
BYTE OldByteCode[5] = {0};
DWORD ModifyAddr;
VirusInfo* m_info;
BYTE xorkey;

BYTE* pMem;//对齐后的内存
void InitpMem()
{
  int Cout = 0;
  for ( int i = 0; i < image_nt_header->FileHeader.NumberOfSections; i++ )
  {
    Cout += PEAlign(image_section_header[i].Misc.VirtualSize,image_nt_header->OptionalHeader.SectionAlignment);
  }
  pMem = (BYTE*)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,Cout+0x1000);
  BYTE* paddr = pMem + image_nt_header->OptionalHeader.SectionAlignment;
  Cout = 0;
  for ( int i = 0; i < image_nt_header->FileHeader.NumberOfSections; i++ )
  {
    memcpy(paddr,m_info->pvFile+image_section_header[i].PointerToRawData,image_section_header[i].SizeOfRawData);
    paddr += PEAlign(image_section_header[i].Misc.VirtualSize,image_nt_header->OptionalHeader.SectionAlignment);
  }
}
void decode(BYTE* addr,int len);

BYTE* VirusStartAddr;
BYTE* VirusEndAddr;

//解密数据
BYTE  decodekey;//解密KEY
int    method;//方法,0减法,1是异或
BOOL  UseAdd;//是否使用加法
BOOL  AddNum;
DWORD decodereg;//变形用的寄存器
int   nAddrReg;//解码起始地址寄存器
int  postion = 0;//0 之前 1 之中 2 之后 3 循环之后 4 jmp reg 结束

int CaclOEP(BYTE* addr,DWORD VirtualAddress,DWORD HookAddr,BOOL bLevel);
//搜索病毒头
void FindVirusEP(BYTE* addr,DWORD VirtualAddress,BOOL bLevel);

int FindBaseInfo_Proc(BYTE* BaseAddr,BYTE* code,DWORD VirtualAddress)
{
  t_disasm da;
  int ret = Disasm((char*)code,16,VirtualAddress,&da,DISASM_CODE);

  if( !_stricmp(da.vm_name,"VXCHG_MEM08_REG08") ||
    !_stricmp(da.vm_name,"VMOV_REG08_MEM08") ||
    !_stricmp(da.vm_name,"VMOV_MEM08_REG08")
    )
  {
    if( postion == 0 )
    {
      postion = 1;//decode之中
    }
    else if( postion == 1 )
    {
      postion = 2;//decode之后
    }
    else if( postion == 2 )//又出现了,出错
      return -1;
    nAddrReg = da.addrreg1;//保存使用的寄存器
  }

  if( postion == 3 )
  {
    if( !_stricmp(da.vm_name,"VJMP_REG32") && da.reg[0] == nAddrReg )//如果是跳到解密代码的语句,则结束
    {
      postion = 4;//结束
    }
  }
  if( postion == 1 )//在解密code中
  {
    if( !_stricmp(da.vm_name,"VSUB_REG16_REG16") )
    {
      method = 0;//减法
      decodereg = da.reg[1];
    }
    else if( !_stricmp(da.vm_name,"VXOR_REG16_REG16") )
    {
      method = 1;//异或
      decodereg = da.reg[1];
    }
  }
  if( postion == 2 )//解密code之后,循环之前
  {
    if( decodereg != -1 && da.reg[0] == decodereg )//又使用了解码寄存器
    {
      if( strstr(da.vm_name,"VINC") )
      {
        UseAdd = TRUE;
        AddNum = 1;//加1
      }
      else if( strstr(da.vm_name,"VADD") )
      {
        UseAdd = TRUE;
        AddNum = da.immconst;//加常数
      }
    }
    if( !_stricmp(da.vm_name,"VJNZ_IMM32") || !_stricmp(da.vm_name,"VJA_IMM32") )
    {
      postion = 3;//循环之后
    }
  }

  if( nAddrReg != -1 && decodereg != -1 && method != -1 && postion == 4 )//全都已经得到
  {
    return 0;
  }
  return ret;
}
//范围数据
DWORD LastFuncAddr;//最后一个FUNC地址
int   dwOffset;//解密的偏移地址
DWORD CodeCout;//代码长度

//寻找常数过程
int FindConstInfo_Proc(BYTE* BaseAddr,BYTE* code,DWORD VirtualAddress,DWORD HookAddr,BOOL bLevel)
{
  t_disasm da;
  int ret = Disasm((char*)code,16,VirtualAddress,&da,DISASM_CODE);
  if( !_stricmp(da.vm_name,"VCALL_IMM32" ) )//寻找最后一个CALL
  {
    LastFuncAddr = (DWORD)code;
  }
  //定位位置
  if( !_stricmp(da.vm_name,"VXCHG_MEM08_REG08") ||
    !_stricmp(da.vm_name,"VMOV_REG08_MEM08") ||
    !_stricmp(da.vm_name,"VMOV_MEM08_REG08")
    )
  {
    if( postion == 0 )
    {
      postion = 1;//decode之中
    }
    else if( postion == 1 )
    {
      postion = 2;//decode之后
    }
    else if( postion == 2 )//又出现了,出错
      return -1;
    nAddrReg = da.addrreg1;//保存使用的寄存器
  }
  if( postion == 2 )//解密code之后,循环之前
  {
    if( !_stricmp(da.vm_name,"VJNZ_IMM32") || !_stricmp(da.vm_name,"VJA_IMM32") )
    {
      postion = 3;//循环之后
    }
  }
  if( postion == 3 )
  {
    if( !_stricmp(da.vm_name,"VJMP_REG32") && da.reg[0] == nAddrReg )//如果是跳到解密代码的语句,则结束
    {
      postion = 4;//结束
      VirusEndAddr = (code+2);//设置结束地址
    }
  }

  if( postion == 0 )
  {
    if( !_stricmp(da.vm_name,"VSUB_REG32_IMM32") || !_stricmp(da.vm_name,"VADD_REG32_IMM32") )
    {
      if( da.reg[0] == nAddrReg )//如果是解码地址寄存器
      {
        dwOffset = abs(da.immconst);
      }
    }
  }
  if( !_stricmp(da.vm_name,"VXOR_REG32_IMM32") || 
    !_stricmp(da.vm_name,"VMOV_REG32_IMM32") ||
    !_stricmp(da.vm_name,"VOR_REG32_IMM32") )
  {
    if( da.immconst > 0x2000 && da.immconst < 0x4000 && da.reg[0] != nAddrReg )//常数大于0xFF并且没有使用解码地址寄存器
      CodeCout = da.immconst;
    else if( abs(da.immconst) > 0 && abs(da.immconst) <= 0xFF && postion == 0)//如果小于FF
    {
      if( *(code+ret) == 0x8D && *(code+ret+3) == 0xE2 )//8D == lea xxx,[xxx+1] && E2 == loop
      {//则是解码寄存器
        decodekey = (BYTE)abs(da.immconst);
      }
    }
  }
  if( !_stricmp(da.vm_name,"VMOV_REG08_IMM32" ) ||
    !_stricmp(da.vm_name,"VMOV_REG32_IMM32" ) ||
    !_stricmp(da.vm_name,"VADD_REG08_IMM32" ) ||
    !_stricmp(da.vm_name,"VADD_REG32_IMM32" ) ||
    !_stricmp(da.vm_name,"VSUB_REG08_IMM32" ) ||
    !_stricmp(da.vm_name,"VSUB_REG32_IMM32" ) ||
    !_stricmp(da.vm_name,"VOR_REG32_IMM32" ) 
    )
  {
    //常数大于0且小于FF且位置在解码之前
    if( abs(da.immconst) > 0 && abs(da.immconst) <= 0xFF && postion == 0 )
    {
      if(da.reg[0] == decodereg )//是解码寄存器
      {
        decodekey = (BYTE)abs(da.immconst);
      }
      else if( *(code+ret) == 0x8D )//8D == lea xxx,[xxx+1]
      {//则是解码寄存器
        decodekey = (BYTE)abs(da.immconst);
      }
    }
  }
  if( postion == 4 && LastFuncAddr && dwOffset && CodeCout && decodekey )//全部得到了
  {
    ret = 0;
    DWORD nextaddr = 0;
    DWORD oepoffset = 0;
    DWORD dwSubConst = 0;//减去的阀值
    DWORD IsRestore  = 0;//是否要恢复8字节CODE
    DWORD RestoreHookCodeAddr = 0;//恢复5字节地址

    //得到下一次地址
    nextaddr = LastFuncAddr + dwOffset + 5;
    decode((BYTE*)nextaddr,CodeCout);//解码OEP偏移

    DWORD Count = *(DWORD*)(nextaddr + 0x6A);//恢复OEP时ESI的长度
    dwSubConst = *(DWORD*)(nextaddr + 0x5B);
    IsRestore = *(DWORD*)(nextaddr + 5 - dwSubConst + *(DWORD*)(nextaddr + 0xFB));
    RestoreHookCodeAddr = nextaddr + 5 - dwSubConst + *(DWORD*)(nextaddr + 0x10C);//8字节的Esi地址

    DWORD NextGoEsiAddr = nextaddr + 5 - dwSubConst + *(DWORD*)(nextaddr + 0x65);//Esi地址
    DWORD NextEP;
    if( !HookAddr )
      NextEP = nextaddr + 5 - *(DWORD*)(nextaddr+0x55);//OEP地址(需要恢复的地址)
    else
      NextEP = HookAddr + 5 - *(DWORD*)(nextaddr+0x55);//OEP地址(需要恢复的地址)

    if( Count )//需要复制
    {
      memcpy((BYTE*)NextEP,(BYTE*)NextGoEsiAddr,Count);
    }
    if( (IsRestore & 0x80000000) == 0x80000000 )//需要恢复5字节代码(内存)
    {
      memcpy((BYTE*)NextEP,(BYTE*)RestoreHookCodeAddr,5);
    }
    DWORD virtualaddress = image_nt_header->OptionalHeader.ImageBase + (DWORD)NextEP - (DWORD)pMem;
    memset(VirusStartAddr,0,VirusEndAddr-VirusStartAddr);//清除内存中病毒代码
    if( !CaclOEP((BYTE*)NextEP,virtualaddress,0,bLevel) )//是OEP头
    {
      DWORD OepOffset = NextEP - (DWORD)pMem;

      if( Count )
      {
        BYTE* fileaddr = m_info->pvFile + RvaToOffset(OepOffset);
        memcpy( fileaddr,(BYTE*)NextGoEsiAddr,Count );
      }
      if( (IsRestore & 0x80000000) == 0x80000000 )//需要恢复5字节代码(文件)
      {
        BYTE* fileaddr = m_info->pvFile + RvaToOffset(OepOffset);
        memcpy((BYTE*)fileaddr,(BYTE*)RestoreHookCodeAddr,5);
      }
      BYTE* fileaddr = m_info->pvFile + RvaToOffset(VirusStartAddr-pMem);
      memset((BYTE*)fileaddr,0,VirusEndAddr-VirusStartAddr);//在文件中的代码

      if( !HookAddr )//没有搜索过
      {
        FindVirusEP((BYTE*)NextEP,virtualaddress,1);//搜索OEP附近是否还有病毒头
      }
      if( !bLevel )//顶级嵌套
      {
        image_nt_header->OptionalHeader.AddressOfEntryPoint = OepOffset;
        image_nt_header->FileHeader.TimeDateStamp = '\0bug';
        m_dlg->SetText(m_info->idx,"已清除");
      }
    }
  }
  return ret;
}

int CaclOEP(BYTE* addr,DWORD VirtualAddress,DWORD HookAddr,BOOL bLevel)
{
  LastFuncAddr = 0;
  dwOffset = 0;
  CodeCout = 0;

  decodekey = 0;
  postion = 0;
  method = -1;
  UseAdd = FALSE;
  AddNum = 0;
  decodereg = -1;
  nAddrReg  = -1;

  int codelen = 0;
  int i = 0;

  //first find reg
  DWORD stepVirtualAddress = VirtualAddress;
  while( i < 0x120 )
  {
    if( addr+i >= VirusStartAddr && addr+i <= VirusEndAddr )//如果在上一个病毒头中
    {
      i += (DWORD)(VirusEndAddr-VirusStartAddr);
      stepVirtualAddress += (DWORD)(VirusEndAddr-VirusStartAddr);
    }
    else
    {
      codelen = FindBaseInfo_Proc(pMem,addr+i,stepVirtualAddress);
      if( !codelen )
        break;
      if( codelen == -1 )//出错
        codelen = 0x120;//结束
      i += codelen;
      stepVirtualAddress += codelen;
    }
  }
  if( i < 0x120 )//是病毒头
  {
    //解码并计算EP
    postion = 0;
    int codelen = 0;
    int i = 0;
    stepVirtualAddress = VirtualAddress;
    
    VirusStartAddr = (addr+i);//设置起始地址
    while( i < 0x120 )
    {
      codelen = FindConstInfo_Proc(pMem,addr+i,stepVirtualAddress,HookAddr,bLevel);
      if( !codelen )
        break;
      if( codelen == -1 )//出错
        codelen = 0x120;//结束
      i += codelen;
      stepVirtualAddress += codelen;
    }
    return 1;//病毒头
  }
  else
  {
    return 0;//OEP头
  }
  return 0;
}
//搜索病毒头
void FindVirusEP(BYTE* addr,DWORD VirtualAddress,BOOL bLevel)
{
  int i = 0;
  DWORD stepVirtualAddress = VirtualAddress;
  t_disasm da;
  while( i < 0x200 )
  {
    if( *(addr+i) == 0xCC )//int3
    {
      return;
    }
    if( *(addr+i) == 0xE8 )//call
    {
      BYTE* calladdr = (BYTE*)(addr+i + *(DWORD*)(addr+i+1) + 5);
      if( !IsBadReadPtr(calladdr,5) )//地址有效
      {
        DWORD NextVirtualAddress = stepVirtualAddress + *(DWORD*)(addr+i+1) + 5;
        CaclOEP(calladdr,NextVirtualAddress,(DWORD)addr+i,bLevel);//是病毒头则清除
      }
    }

    int codelen = Disasm((char*)addr+i,16,stepVirtualAddress,&da,DISASM_CODE);
    i += codelen;
    stepVirtualAddress += codelen;
  }
}

//修复文件
void RepairFile(VirusInfo* info)
{
  if( !info ) return;

  m_info = info;
  image_dos_header = (IMAGE_DOS_HEADER*)info->pvFile;
  image_nt_header = (IMAGE_NT_HEADERS*)(info->pvFile + image_dos_header->e_lfanew);
  image_section_header = (IMAGE_SECTION_HEADER *)(info->pvFile + image_dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS));

  InitpMem();
  EpAddr = pMem + image_nt_header->OptionalHeader.AddressOfEntryPoint;
  DWORD VirtualAddress = image_nt_header->OptionalHeader.ImageBase + image_nt_header->OptionalHeader.AddressOfEntryPoint;

  VirusStartAddr = NULL;
  VirusEndAddr = NULL;
  if( !CaclOEP(EpAddr,VirtualAddress,0,0) )//不是病毒头,则检测附近是否有stolen code
  {
    FindVirusEP(EpAddr,VirtualAddress,0);//搜索病毒头
  }

  UnmapViewOfFile((LPVOID)m_info->pvFile);m_info->pvFile = NULL;
  CloseHandle(m_info->hFileMap);m_info->hFileMap = NULL;
  CloseHandle(m_info->hFile);m_info->hFile = NULL;

  GlobalFree(pMem);
}

void ClearList()
{
  if( !m_dlg ) return;
  int cout = m_dlg->m_List.GetItemCount();
  for(int i = 0; i < cout; i++)
  {
    VirusInfo* tmpinfo = (VirusInfo*)m_dlg->m_List.GetItemData(i);
    if( tmpinfo )
    {
      if( tmpinfo->pvFile )
      {
        UnmapViewOfFile((LPVOID)tmpinfo->pvFile);tmpinfo->pvFile = NULL;
      }
      if( tmpinfo->hFileMap )
      {
        CloseHandle(tmpinfo->hFileMap);tmpinfo->hFileMap = NULL;
      }
      if( tmpinfo->hFile )
      {
        CloseHandle(tmpinfo->hFile);tmpinfo->hFile = NULL;
      }
      delete tmpinfo; tmpinfo = NULL;
    }
    m_dlg->m_List.SetItemData(i,0);
  }
}

//开始杀毒
BOOL StartKill(CVx_AntiVirusDlg* dlg,BOOL OnlyCheck)
{
  bOnlyCheck = OnlyCheck;

  InitializeCriticalSection(&cs);
  m_dlg = dlg;
  bStopFind = FALSE;

  strdeque.clear();
  m_dlg->m_List.DeleteAllItems();

  if( dlg->bScanMemory )
  {
    if( !AntiHook() )
    {
      return FALSE;
    }
  }

  DWORD dwId;
  dwFindThread = CreateThread(NULL,0,FindFileThread,NULL,0,&dwId);
  dwVirusThread = CreateThread(NULL,0,FindVirusThread,NULL,0,&dwId);
  return TRUE;
}

//停止杀毒
void StopKill()
{
  DWORD dw = 0;
  bStopFind = TRUE;

  dw = WaitForSingleObject(dwVirusThread,1500);
  if(dw == WAIT_TIMEOUT)
  {
    TerminateThread(dwVirusThread,0);
  }

  TerminateThread(dwFindThread,0);

  ClearList();

  DeleteCriticalSection(&cs);
}
//解码函数
void decode(BYTE* addr,int len)
{
  for(int i = 0; i < len; i++)
  {
    if( method == 0 )
      addr[i] -= decodekey;
    else
      addr[i] ^= decodekey;
    if( UseAdd )
      decodekey += AddNum;
  }
}

这是源代码
Vx_AntiVirus.rar

再放个ccfer拿来测试的样本
附件 8818

密码是vir

谢谢观看