應用場景:
病毒木馬會廣泛常用資源文件釋放技術。程序會將一些DLL文件、文本文件、圖片文件或其它的音/視頻文件作為資源插入到程序里,等到程序運行后,使用資源文件釋放技術將它們釋放到本地上,這樣編譯出來的程序只有一個exe文件,而不需要附帶其它文件,因而程序變得簡潔,降低了被發現的風險。
資源插入的步驟:
介紹資源文件釋放技術之前,先要了解如何向程序中插入資源。畢竟沒有資源,你釋放光和熱嗎?資源插入不需要編碼操作,只需要手動設置VS開發環境即可完成。操作如下:
(1).解決方案中,選擇 “添加”,選中 “資源”
(2).在彈出對話框中選擇 “自定義(C)...”按鈕,如下圖所示:
(3).在 “新建自定義資源” 對話框中,輸入 “資源類型” ,建議輸入有意思的類型名,如 “MYRES"(我的資源),然后點擊確定。
(4).通過上面步驟設置好自定義資源的類型后,接着回到 ”添加資源“對話框,選中剛新建的自定義資源類型 ”MYRES",然后單擊右側的 ”導入(M)...”按鈕來選中導入文件
資源文件釋放實現原理:
(1).通過FindResource定位程序里的資源,獲取資源信息塊的句柄。主要是根據 “資源類型” 和 “資源名稱” 進行定位。
(2).根據上面獲取的資源信息塊的句柄,使用SizeOfResource獲取資源的大小
(3).根據 (1) 步獲得的資源信息塊的句柄,使用LoadResource把資源加載到程序內存中
(4).根據上一步返回的數據資源句柄,使用LockResource鎖定加載到內存中的資源,防止程序中的其它操作影響這塊內存,返回值就是資源在進程內存中的起始地址
(5).最后根據第二步獲得的資源大小以及第四步獲得的資源在進程內存中的起始地址,使用文件寫函數fwrite將資源讀取出來並保存為本地文件
注意:在資源釋放過程中,必須明確資源所在的模塊,要指明資源所在模塊句柄並且統一。因為文件可以以資源的形式插入到dll中,所以當dll加載到其它進程時,資源所在的模塊仍是該dll模塊。要想成功釋放資源,需要先通過GetModuleHandle函數獲取該DLL模塊的句柄。否則,資源釋放會因為指定了錯誤模塊而失敗。
代碼實現:
//************************************ // 函數名: CBasicsDlg::FreeMyResource // 返回類型: BOOL // 功能:釋放資源將資源保存為文件 // 參數1: 資源名 // 參數2: 資源類型 // 參數3: 文件名 //************************************ BOOL CBasicsDlg::FreeMyResource(UINT uiResourceName, char* lpszResourceType, char* lpszSaveFileName) { //獲取指定模塊里的資源 HRSRC hRsrc = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(uiResourceName), (LPCWSTR)lpszResourceType); if (NULL == hRsrc) { m_FreeResTipMsg += _T("獲取資源")+ CString(lpszSaveFileName)+_T("失敗\r\n"); return FALSE; } else { m_FreeResTipMsg += _T("獲取資源") + CString(lpszSaveFileName) + _T("成功\r\n"); } //獲取資源大小 DWORD dwSize = SizeofResource(NULL, hRsrc); if (dwSize <= 0) { m_FreeResTipMsg += _T("獲取") + CString(lpszSaveFileName) + _T("資源大小失敗\r\n"); return FALSE; } else { m_FreeResTipMsg += _T("獲取") + CString(lpszSaveFileName) + _T("資源大小成功\r\n"); } //將資源加載到內存里 HGLOBAL hGlobal = LoadResource(NULL, hRsrc); if (NULL == hGlobal) { m_FreeResTipMsg += _T("資源") + CString(lpszSaveFileName) + _T("加載到內存失敗\r\n"); return FALSE; } else { m_FreeResTipMsg += _T("資源") + CString(lpszSaveFileName) + _T("加載到內存成功\r\n"); } //鎖定資源 LPVOID lpVoid = LockResource(hGlobal); if (NULL == lpVoid) { m_FreeResTipMsg += _T("資源") + CString(lpszSaveFileName) + _T("鎖定失敗\r\n"); return FALSE; } else { m_FreeResTipMsg += _T("資源") + CString(lpszSaveFileName) + _T("鎖定成功\r\n"); } //保存資源為文件 FILE* fp = NULL; fopen_s(&fp, lpszSaveFileName,"wb+"); if (NULL == fp) { m_FreeResTipMsg += _T("創建文件") + CString(lpszSaveFileName) + _T("失敗\r\n"); return FALSE; } DWORD res = fwrite(lpVoid, sizeof(char), dwSize, fp); if (res != dwSize) { m_FreeResTipMsg += _T("資源") + CString(lpszSaveFileName) + _T("保存為文件時有數據丟失\r\n"); fclose(fp); return FALSE; } else { m_FreeResTipMsg += _T("資源") + CString(lpszSaveFileName) + _T("成功保存為文件\r\n"); fclose(fp); return TRUE; } }