1. 程式人生 > >病毒木馬查殺實戰第017篇:U盤病毒之專殺工具的編寫

病毒木馬查殺實戰第017篇:U盤病毒之專殺工具的編寫

BOOL CUVirusKillerDlg::OnDeviceChange( UINT nEventType, // An event type. 
								       DWORD dwData     // The address of a structure that 
									                    // contains event-specific data. 
								     )
{
    // The system broadcasts the DBT_DEVICEARRIVAL device event when 
	// a device or piece of media has been inserted and becomes available.
	if ( nEventType == DBT_DEVICEARRIVAL )
    {
        // 在未對U盤進行查殺之前,令“安全開啟U盤”不可用
		m_SafeOpen.EnableWindow(FALSE);
		SetDlgItemText(IDC_LIST, csTxt);
		//獲取碟符名稱
		GetDriverName(dwData);
        //顯示可移動磁碟的碟符
		CString TmpFile;
		TmpFile.Format("檢測到可移動磁碟為:%c\r\n", i + 'A');
		csTxt += TmpFile;
		SetDlgItemText(IDC_LIST, csTxt);
        // 如果成功獲取碟符,則繼續執行
        if ( DriverName != "" )
        {
			// 建立CString型別的File,令其儲存autorun.inf的完整路徑
            CString File = DriverName;
            File += "\\autorun.inf";
            // 用於儲存由autorun.inf所啟動的程式名
            char szBuff[MAX_PATH] = { 0 };
            // 判斷可移動磁碟中的autorun.inf檔案是否存在
            if ( GetFileAttributes(File.GetBuffer(0)) == -1 )
            {
                csTxt += "在可移動磁碟中沒有檢測到autorun.inf\r\n";
				SetDlgItemText(IDC_LIST, csTxt);
				// 如果當前U盤中不存在autorun.inf,則令“安全開啟U盤”按鈕可用
				m_SafeOpen.EnableWindow(TRUE);
				return FALSE;
            }
            
			csTxt += "在可移動磁碟中檢測到autorun.inf\r\n";
            csTxt += "正在解析autorun.inf的啟動內容\r\n";
			SetDlgItemText(IDC_LIST, csTxt);
            // 獲取AutoRun.inf檔案中open後面的內容,即所要自動開啟的可疑檔案
            GetPrivateProfileString(
                "AutoRun",        //The name of the section containing the key name.
                "open",           //The name of the key whose associated string is to be retrieved.
                NULL,             //A default string. 
                szBuff,           //A pointer to the buffer that receives the retrieved string.
                MAX_PATH,        //The size of the buffer pointed to by the lpReturnedString 
//parameter, in characters.
                File.GetBuffer(0)       //The name of the initialization file.
            );
            // DelFile儲存由autorun.inf啟動的程式的路徑
			CString DelFile = DriverName;
			DelFile += '\\';
            DelFile += szBuff;

            csTxt += "由autorun.inf啟動的程式為:";
			csTxt += DelFile;
			csTxt += "\r\n正在計算病毒程式的雜湊值...\r\n";
            SetDlgItemText(IDC_LIST, csTxt);
            // 獲取病毒程式的CRC32值
			VirusCRC32 = CalcCRC32(DelFile);           
            // 刪除可移動磁碟中的autorun.inf以及由之啟動的檔案,需要首先將病毒程式的屬性調整為NORMAL
			csTxt += "正在刪除可移動磁碟中的autorun.inf以及由之啟動的程式...\r\n";			
			
			SetFileAttributes(File, FILE_ATTRIBUTE_NORMAL);	
			// 刪除autorun.inf
			BOOL bRet = DeleteFile(File);	
			csTxt += File;
			if (bRet)
			{
                csTxt += _T("病毒程式被刪除!\r\n");
			} 
            else
			{
                csTxt += _T("病毒程式無法刪除!\r\n");
			}				
			        
			SetFileAttributes(DelFile, FILE_ATTRIBUTE_NORMAL);
			// 刪除由autorun.inf啟動的病毒程式
			bRet = DeleteFile(DelFile);	
			csTxt += DelFile;
			if (bRet)
			{
                csTxt += _T("病毒程式被刪除!\r\n");
			} 
            else
			{
                csTxt += _T("病毒程式無法刪除!\r\n");
			}
						
			SearchAndDeleteVirus(DriverName);
			csTxt += _T("U盤修復完畢,您現在可以安全地開啟U盤或修復本地系統!\r\n");
			SetDlgItemText(IDC_LIST, csTxt);
            //令"安全開啟U盤"按鈕可用         
			m_SafeOpen.EnableWindow(TRUE);
        }
    }
    //The system broadcasts the DBT_DEVICEREMOVECOMPLETE device event 
	//when a device or piece of media has been physically removed.
	else if ( nEventType == DBT_DEVICEREMOVECOMPLETE )
    {
        //當U盤被拔出時,令"安全開啟U盤"按鈕不可用
		m_SafeOpen.EnableWindow(FALSE);
    }
    
    return TRUE;
}

編寫“修復本地系統”按鈕事件程式碼

void CUVirusKillerDlg::OnBtnRepair() 
{
	// TODO: Add your control notification handler code here
	csTxt += _T("開始檢測本地系統...\r\n正在檢查登錄檔啟動項...\r\n");
	char RegName[]="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\";
	DWORD dwType = 0;
    DWORD dwBufferSize = MAXBYTE;
    DWORD dwKeySize = MAXBYTE;
	char szValueName[MAXBYTE] = { 0 };
    char szValueKey[MAXBYTE] = { 0 };
	
	//開啟登錄檔啟動項
	HKEY hKey = NULL;
    LONG lRetRun = RegOpenKey(HKEY_LOCAL_MACHINE, RegName, &hKey);
	if ( lRetRun != ERROR_SUCCESS )
    {
        AfxMessageBox("登錄檔啟動項開啟失敗!");
		return ;
    }
	
	int i = 0;	
	
	while ( TRUE )
	{
	    // 列舉鍵項
		lRetRun = RegEnumValue(hKey, i, szValueName, &dwBufferSize, NULL, &dwType, (unsigned char *)szValueKey, &dwKeySize);
        if ( lRetRun == ERROR_NO_MORE_ITEMS )
        {
            break;
        }
        // 如果鍵項為6個字元,並且鍵值指向的程式的CRC32指紋與病毒指紋匹配,則關閉病毒程序以及刪除鍵項與病毒本體
		if ( lstrlen(szValueName) == 6 &&  CalcCRC32(szValueKey) == VirusCRC32 )
		{
		    BOOL bRet = FALSE;
            DWORD dwPid = 0; 
            // 刪除病毒的登錄檔啟動項
			RegDeleteValue(hKey, szValueName);
	        csTxt += _T("登錄檔啟動項清理完畢!\r\n");
			
			strcat(szValueName, ".EXE");
			bRet = FindTargetProcess(szValueName, &dwPid);
			if(TRUE)
			{
			    csTxt += _T("檢查系統記憶體...\r\n");
                csTxt += _T("系統中存在病毒程序:");
				csTxt += szValueName;
                csTxt += _T("準備進行查殺...\r\n");
                SetDlgItemText(IDC_LIST,csTxt);
				
				// 提升許可權
	            bRet = EnableDebugPrivilege(SE_DEBUG_NAME);
				if (bRet == FALSE)
				{
                    csTxt += _T("提升許可權失敗\r\n");
				}
                else
				{
                    csTxt += _T("提升許可權成功!\r\n");
				}
	            SetDlgItemText(IDC_LIST,csTxt);

				// 開啟並嘗試結束病毒程序
		        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPid);
                if (hProcess == INVALID_HANDLE_VALUE)
				{
                    csTxt += _T("無法結束病毒程序\r\n");
                    return ;
				}
		        bRet = TerminateProcess(hProcess,0);
                if (bRet == FALSE)
				{
                    csTxt += _T("無法結束病毒程序\r\n");
                    return ;
				}
                csTxt += _T("病毒程序已經結束\r\n");
                SetDlgItemText(IDC_LIST,csTxt);
                CloseHandle(hProcess);
			}
			break;
		}		
		
		//清空緩衝區
		ZeroMemory(szValueName,MAXBYTE);
        ZeroMemory(szValueKey, MAXBYTE);

		i++;
	}
	RegCloseKey(hKey);

	// 刪除自啟動的病毒程式
	csTxt += szValueKey;
	// 獲取病毒程式所在資料夾的路徑
	szValueKey[lstrlen(szValueKey)-11] = '\0';
	SetFileAttributes(szValueKey, FILE_ATTRIBUTE_NORMAL);	
	BOOL bRet = DeleteDirectory(szValueKey);	
    if (bRet)
	{
        csTxt += _T("病毒程式被刪除!\r\n");
	} 
    else
	{
        csTxt += _T("病毒程式無法刪除!\r\n");
	}
    // 獲取儲存有病毒DLL檔案的資料夾路徑	
	char tempPath[100];
	DWORD dwSize = 100;
	GetTempPath(dwSize, tempPath);
	lstrcat(tempPath, "\E_N4");
    SetFileAttributes(tempPath, FILE_ATTRIBUTE_NORMAL);	
	// 刪除病毒資料夾
	bRet = DeleteDirectory(tempPath);	
	csTxt += tempPath;
    if (bRet)
	{
        csTxt += _T("病毒資料夾被刪除!\r\n");
	} 
    else
	{
        csTxt += _T("病毒資料夾無法刪除!\r\n");
	}
    SetDlgItemText(IDC_LIST,csTxt);
}

至此,所有主要的程式編寫完畢,接下來就可以進行專殺工具的測試了。

專殺工具的測試

這裡我們需要讓本地系統還有U盤保持中毒的狀態,先拔出U盤,然後啟動專殺工具,使其開始進行監控,之後插入U盤,專殺工具就會自動開始查殺:


圖7

此時如果點選“安全開啟U盤”,就會開啟U盤,可以發現此時U盤中已經沒有了病毒程式,並且被隱藏的資料夾也都顯示出來了。如果點選“修復本地系統”,那麼專殺工具會首先結束掉病毒程序,之後再刪除系統中的病毒程式,從而對系統進行徹底的清理。

小結

這次的專殺工具的程式碼稍長,但其實也並不難,都是一些基礎的API函式的呼叫,這其中還使用了很多之前“熊貓燒香專殺工具”的函式程式碼,說明我們應當善於利用之前所編寫過的程式。並且應當善於分析病毒特徵,比如如何判斷病毒名稱以及被隱藏的資料夾等,如果要逆向分析這些演算法,那麼過程無疑是艱辛的。至此,針對於這次的U盤病毒的講解就到這裡,希望大家能夠舉一反三,有所收穫。