首页
社区
课程
招聘
[原创][十三]第三阶段第一题解决方案
发表于: 2007-9-19 18:42 11100

[原创][十三]第三阶段第一题解决方案

2007-9-19 18:42
11100

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期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (19)
雪    币: 116
活跃值: (220)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
2
很好,很强大。。。
2007-9-19 18:54
0
雪    币: 1946
活跃值: (263)
能力值: (RANK:330 )
在线值:
发帖
回帖
粉丝
3
现真身了。
2007-9-19 18:55
0
雪    币: 105
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
现真身了。
2007-9-19 19:13
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
高兴  高兴
2007-9-19 19:52
0
雪    币: 8209
活跃值: (4528)
能力值: ( LV15,RANK:2473 )
在线值:
发帖
回帖
粉丝
6
你贴那个哪是测试样本
2007-9-19 19:53
0
雪    币: 116
活跃值: (220)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
7
ResetCode不对吧,如果专杀被注入了,岂不是等于没恢复?
2007-9-19 19:57
0
雪    币: 226
活跃值: (15)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
8
你贴那个哪是测试样本


不好意思,把你的代码贴上来了,罪过罪过,佛祖饶恕。

ResetCode不对吧,如果专杀被注入了,岂不是等于没恢复?


自己内存也扫啊。
2007-9-19 20:25
0
雪    币: 209
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
哦。。。很强大。。。
2007-9-19 20:28
0
雪    币: 116
活跃值: (220)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
10
good, ok and ok
刚才没看清,呵呵
2007-9-19 20:32
0
雪    币: 709
活跃值: (2420)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
11
严重学习~
2007-9-19 22:36
0
雪    币: 1634
活跃值: (1387)
能力值: (RANK:50 )
在线值:
发帖
回帖
粉丝
12
很好,很好,很好
2007-9-20 02:29
0
雪    币: 211
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
太强了,学习!!
2007-9-20 09:27
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
还要到多久才能到达你哪一种水平啊,
2007-9-20 11:05
0
雪    币: 0
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
15
俺是新手, 看不懂
2007-9-20 11:20
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
好文就要细细读
2007-9-20 12:02
0
雪    币: 334
活跃值: (22)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
very good!!!!
2007-9-20 12:27
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
18
向牛人学习,,,,,
2007-9-20 14:33
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
19
真身,,,,,
2007-9-20 14:35
0
雪    币: 206
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
好文章呀,楼主好厉害
2007-9-20 21:02
0
游客
登录 | 注册 方可回帖
返回
//