在早期互聯(lián)網(wǎng)還不發(fā)達(dá)的時(shí)候,病毒都是通過軟盤,、光盤等媒介進(jìn)行傳播的,。到后來互聯(lián)網(wǎng)被普及以后,通過互聯(lián)網(wǎng)進(jìn)行傳播的病毒大面積地相繼出現(xiàn),。雖然軟盤已經(jīng)被淘汰,但是并沒有使移動(dòng)磁盤的病毒減少,。相反,,U盤的普及使得移動(dòng)磁盤對病毒的傳播更加方便。U盤的數(shù)據(jù)傳輸速度和數(shù)據(jù)存儲(chǔ)容量等多方面都比軟盤要先進(jìn)很多,,因此,,軟盤可以傳播病毒,U盤當(dāng)然也可以傳播病毒,。
通過U盤來傳播病毒通常是使用操作系統(tǒng)的自動(dòng)運(yùn)行功能,,并配合U盤下的Autorun.inf文件來實(shí)現(xiàn)的。著名的“擺渡攻擊”就是依靠此Autorun.inf來進(jìn)行實(shí)施的,。如果讓操作系統(tǒng)不自動(dòng)運(yùn)行移動(dòng)磁盤,,或者保證移動(dòng)磁盤下不存在Autorun.inf文件,那么通過U盤感染病毒的幾率就小很多了,。
1. 通過系統(tǒng)配置禁止自動(dòng)運(yùn)行
先來介紹如何通過系統(tǒng)配置禁止U盤中Autorun.inf的自動(dòng)運(yùn)行,。通常情況下需要進(jìn)行兩方面的設(shè)置,一方面是通過“管理工具”中的“服務(wù)”來進(jìn)行設(shè)置,,另一方面是通過“組策略”來進(jìn)行設(shè)置,。一般這兩處都需要進(jìn)行修改。下面分別介紹如何對這兩處進(jìn)行設(shè)置,。
先來看如何在“服務(wù)”中進(jìn)行設(shè)置,。首先打開控制面板中的“管理工具”,然后找到“服務(wù)”,,將其雙擊打開,。在服務(wù)列表中找到名稱為“Shell Hardware Detection”的服務(wù),雙擊該服務(wù),,打開“Shell Hardware Detection的屬性”對話框,。單擊“停止”按鈕將該服務(wù)停止,,再把“啟動(dòng)類型”修改為“已禁用”狀態(tài),如圖1所示,。
圖1 禁用“Shell Hardware Detection”服務(wù)
將服務(wù)中的“Shell Hardware Detection”禁用后,,再對“組策略”進(jìn)行設(shè)置。首先在“運(yùn)行”中輸入“gpedit.msc”,,然后依次單擊左邊的樹形控件“計(jì)算機(jī)配置”→“管理模板”→“系統(tǒng)”,,再在右邊雙擊“關(guān)閉自動(dòng)播放”選項(xiàng),彈出“關(guān)閉自動(dòng)播放屬性”對話框,。在“設(shè)置”選項(xiàng)卡中選擇“已啟用”單選項(xiàng),,在“關(guān)閉自動(dòng)播放”處選擇“所有驅(qū)動(dòng)器”選項(xiàng),設(shè)置完成后單擊“確定”按鈕,。再到左邊的樹形控件中選擇“用戶配置”→“管理模板”→“系統(tǒng)”,,到右邊找到“自動(dòng)關(guān)閉播放”選項(xiàng),設(shè)置方法同上,,如圖2所示,。
圖2 組策略中的“關(guān)閉自動(dòng)播放”
通過以上設(shè)置,的確可以相對有效地保護(hù)計(jì)算機(jī)不中U盤相關(guān)的病毒,。不過,,不能因此而滿足,因?yàn)槟康氖谴蛟煲粋€(gè)U盤防御的軟件,。
2. 打造一個(gè)簡易的U盤防御軟件
這里打造一個(gè)U盤防火墻,,當(dāng)插入U(xiǎn)盤時(shí)會(huì)有提示,并且自動(dòng)檢查U盤下是否有Autorun.inf文件,,并解析Autorun.inf文件,。除此之外,通過U盤防火墻可以打開U盤,,從而安全地使用U盤,。
如何才能知道有U盤被插入電腦呢,?可以使用定時(shí)器不斷地檢查,,也可以開啟一個(gè)線程不斷地檢查,還可以通過Windows的消息得到通知,。前兩種方法笨了些,,這里主動(dòng)不斷地檢查是否有U盤插入,不如被動(dòng)地等待Windows的消息來通知,。
在Windows下有一個(gè)消息可以通知應(yīng)用程序計(jì)算機(jī)配置發(fā)生了變化,,這個(gè)消息是WM_ DEVICECHANGE。消息過程定義如下:
LRESULT CALLBACK WindowProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
?。?;
該消息通過兩個(gè)附加參數(shù)來進(jìn)行使用,,其中wParam表示設(shè)備改變的事件,lParam表示事件對應(yīng)的數(shù)據(jù),。要得到設(shè)備被插入的消息類型,,因此wParam的取值為DBT_DEVIC EARRIVAL,而該消息對應(yīng)的數(shù)據(jù)類型為DEV_BROADCAST_HDR,,該結(jié)構(gòu)體的定義如下:
typedef struct _DEV_BROADCAST_HDR {
DWORD dbch_size;
DWORD dbch_devicetype;
DWORD dbch_reserved;
} DEV_BROADCAST_HDR;
typedef DEV_BROADCAST_HDR *PDEV_BROADCAST_HDR;
在該結(jié)構(gòu)體中,,主要看的是dbch_devicetype,也就是設(shè)備的類型,。如果設(shè)備類型為DBT_DEVTYP_VOLUME,,則把當(dāng)前結(jié)構(gòu)體轉(zhuǎn)換為DEV_BROADCAST_VOLUME結(jié)構(gòu)體,該結(jié)構(gòu)體定義如下:
typedef struct _DEV_BROADCAST_VOLUME {
DWORD dbcv_size;
DWORD dbcv_devicetype;
DWORD dbcv_reserved;
DWORD dbcv_unitmask;
WORD dbcv_flags;
} DEV_BROADCAST_VOLUME;
typedef DEV_BROADCAST_VOLUME *PDEV_BROADCAST_VOLUME;
在該結(jié)構(gòu)體中,,主要看的是dbcv_unitmask和dbcv_flags,。dbcv_unitmask通過位表示邏輯盤符,第0位表示A盤,,第1位表示B盤,。dbcv_flags表示受影響的盤符或媒介,其值為0時(shí)表示U盤或移動(dòng)硬盤,。
上面介紹了WM_DEVICECHANGE消息,,由于是在MFC下進(jìn)行開發(fā)的,因此可以使用OnDeviceChange()消息響應(yīng)函數(shù)來代替WM_DEVICECHANGE消息,。雖然使用了OnDeviceChange()消息響應(yīng)函數(shù)而沒有使用WM_DEVICECHANGE,,但是響應(yīng)函數(shù)的附加參數(shù)與WM_DEVICECHANGE相同。OnDeviceChange()函數(shù)定義如下:
afx_msg BOOL OnDeviceChange( UINT nEventType, DWORD dwData ),;
3. 通過OnDeviceChange()消息獲得被插入U(xiǎn)盤的盤符
下面使用MFC下的OnDeviceChange()消息響應(yīng)函數(shù)來編寫一個(gè)獲取被插入U(xiǎn)盤的盤符的小程序,,為編寫U盤防火墻做簡單的準(zhǔn)備工作。首先來添加消息映射,,具體代碼如下:
BEGIN_MESSAGE_MAP(CUFirewallDlg, CDialog)
//{{AFX_MSG_MAP(CUFirewallDlg)
ON_MESSAGE(WM_DEVICECHANGE, OnDeviceChange)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
在頭文件中添加消息響應(yīng)函數(shù)的定義,,具體如下:
// Generated message map functions
//{{AFX_MSG(CUFirewallDlg)
afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData); // 消息響應(yīng)函數(shù)
virtual BOOL OnInitDialog(),;
afx_msg void OnSysCommand(UINT nID, LPARAM lParam),;
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon(),;
//}}AFX_MSG
最后添加消息響應(yīng)函數(shù)的實(shí)現(xiàn),,具體代碼如下:
BOOL CUFirewallDlg::OnDeviceChange(UINT nEventType, DWORD dwData)
{
if ( nEventType == DBT_DEVICEARRIVAL )
{
PDEV_BROADCAST_HDR pDevHdr = (PDEV_BROADCAST_HDR)dwData;
if ( pDevHdr->dbch_devicetype == DBT_DEVTYP_VOLUME )
{
PDEV_BROADCAST_VOLUME pDevVolume = (PDEV_BROADCAST_VOLUME)pDevHdr;
// pDevVolume->dbcv_flags 為 0 表示為 U 盤
if ( pDevVolume->dbcv_flags == 0 )
{
CString DriverName;
char i;
// 通過將 pDevVolume->dbcv_unitmask 移位來判斷盤符
DWORD dwUnitmask = pDevVolume->dbcv_unitmask;
for (i = 0; i < 26; ++i)
{
if ( dwUnitmask & 0x1)
{
break;
}
dwUnitmask = dwUnitmask 》 1;
}
if ( i >= 26 )
{
return ;
}
DriverName.Format(“檢測到的 U 盤盤符為: %c \r\n”, i + 'A‘);
// 顯示盤符
MessageBox(DriverName),;
}
}
}
}
將其編譯連接并運(yùn)行,,插入一個(gè)U盤,得到如圖3所示的提示,。
圖3 檢測到的U盤盤符
上面的這段代碼可以將其封裝為一個(gè)函數(shù),,封裝后的函數(shù)定義如下:
VOID GetDriverName(DWORD dwData),;
在使用類似DBT_DEVICEARRIVAL的以DBT_開頭的宏時(shí),應(yīng)包含頭文件“dbt.h”文件,。
4. U盤防火墻的完善
前面已經(jīng)獲得了被插入U(xiǎn)盤的盤符,,接下來就可以對U盤上的Autorun.inf文件進(jìn)行分析,并刪除要運(yùn)行的程序,,還可以安全地打開U盤,。改寫OnDeviceChange()函數(shù),以實(shí)現(xiàn)要完成的功能,,具體代碼如下:
BOOL CUFirewallDlg::OnDeviceChange(UINT nEventType, DWORD dwData)
{
if ( nEventType == DBT_DEVICEARRIVAL )
{
GetDriverName(dwData),;
MessageBox(DriverName);
if ( DriverName != “” )
{
m_SafeOpen.EnableWindow(TRUE),;
CString File = DriverName;
File += “\\autorun.inf”;
char szBuff[MAX_PATH] = { 0 };
if ( GetFileAttributes(File.GetBuffer(0)) == -1 )
{
m_SafeOpen.EnableWindow(FALSE),;
return FALSE;
}
// 獲取 open 后面的內(nèi)容
GetPrivateProfileString(“AutoRun”,“open”,
NULL,szBuff,MAX_PATH,File.GetBuffer(0));
CString str;
str = “是否刪除:”;
str += szBuff;
if ( MessageBox(str, NULL, MB_YESNO) == IDYES )
{
// 刪除要執(zhí)行的文件
DeleteFile(str.GetBuffer(0)),;
}
}
}
else if ( nEventType == DBT_DEVICEREMOVECOMPLETE )
{
m_SafeOpen.EnableWindow(FALSE),;
}
return TRUE;
}
安全打開U盤的實(shí)現(xiàn)代碼如下:
void CUFirewallDlg::OnBtnSafeopen()
{
// TODO: Add your control notification handler code here
ShellExecute(NULL, “open”, DriverName.GetBuffer(0), NULL, NULL, SW_SHOW),;
}
用DeleteFile()函數(shù)刪除U盤中要運(yùn)行的程序可能會(huì)失敗,,因?yàn)橛袝r(shí)U盤并沒有完全準(zhǔn)備好??梢酝ㄟ^判斷來完成,,但這里就不給出代碼了,大家可自行修改完成,。代碼中涉及兩個(gè)新的API函數(shù),,分別是GetPrivateProfileString()和ShellExecute()。這兩個(gè)函數(shù)的功能分別是獲取配置文件中指定鍵的鍵值,、運(yùn)行指定的文件或文件夾,。
在上面的程序中,通過提示讓用戶選擇是否要?jiǎng)h除U盤中要被執(zhí)行的文件,。如果用戶對此并沒有太多的了解和認(rèn)識(shí)的話,,很有可能不刪除。如果刪了本不該刪的文件,,那么用戶對該軟件的友好感便會(huì)降低,。應(yīng)該如何做呢,?應(yīng)該建立一個(gè)白名單和黑名單,,無論是通過散列進(jìn)行比較,還是通過文件名進(jìn)行比較,,都可以,。當(dāng)然,,越精確的匹配方法越好。這樣,,就可以提早為用戶進(jìn)行判斷了,,然后給出一個(gè)安全建議,這樣不但提高了軟件的友好度,,而且會(huì)顯得相對較為專業(yè),。