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拿来测试的样本 virus.rar
密码是vir
谢谢观看
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: