惡意代碼清除?惡意代碼的分類包括計算機病毒、蠕蟲、木馬、後門、Rootkit、流氓軟件、間諜軟件、廣告軟件、僵屍(bot) 、Exploit等等,有些技術經常用到,有的也是必然用到,現在小編就來說說關于惡意代碼清除?下面内容希望能幫助到你,我們來一起看看吧!
惡意代碼的分類包括計算機病毒、蠕蟲、木馬、後門、Rootkit、流氓軟件、間諜軟件、廣告軟件、僵屍(bot) 、Exploit等等,有些技術經常用到,有的也是必然用到。
昨天咱們分享了一部分,那麼今天我們就分享其他一些技術,主要包括:後門、文件監控、文件自動删除等。
後門後門常以套件的形式存在,用于将受害者信息發送給攻擊者或者傳輸惡意可執行程序(下載器),最常用的功能是接收攻擊端傳送過來的命令,執行某些操作。
Windows系統中有很多WIN32 API可以執行CMD命令,例如system Winexe CreateProcess等。這裡介紹通過匿名管道實現遠程CMD。
具體過程
1、初始化匿名管道的SECURITY_ATTRIBUTES結構體,調用CreatePipe創建匿名管道,獲取管道數據讀取句柄和寫入句柄。
2、初始化STARTUPINFO結構體,隐藏進程窗口,并把管道數據寫入句柄賦值給新進程控制台窗口的緩存句柄。
3、調用CreateProcess函數創建進程,執行CMD命令并調用WaitForSingleObject等待命令執行完。
4、調用ReadFile根據匿名管道的數據讀取句柄從匿名管道的緩沖區中讀取數據。
5、關閉句柄,釋放資源。
源代碼實現:
#include "stdafx.h"
#include "PipeCmd.h"
void ShowError(char *pszText)
{
char szErr[MAX_PATH] = {0};
::wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
::MessageBox(NULL, szErr, "ERROR", MB_OK);
}
// 執行 cmd 命令, 并獲取執行結果數據
BOOL PipeCmd(char *pszCmd, char *pszResultBuffer, DWORD dwResultBufferSize)
{
HANDLE hReadPipe = NULL;
HANDLE hWritePipe = NULL;
SECURITY_ATTRIBUTES securityAttributes = {0};
BOOL bRet = FALSE;
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
// 設定管道的安全屬性
securityAttributes.bInheritHandle = TRUE;
securityAttributes.nLength = sizeof(securityAttributes);
securityAttributes.lpSecurityDescriptor = NULL;
// 創建匿名管道
bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0);
if (FALSE == bRet)
{
ShowError("CreatePipe");
return FALSE;
}
// 設置新進程參數
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdError = hWritePipe;
si.hStdOutput = hWritePipe;
// 創建新進程執行命令, 将執行結果寫入匿名管道中
bRet = ::CreateProcess(NULL, pszCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
if (FALSE == bRet)
{
ShowError("CreateProcess");
}
// 等待命令執行結束
::WaitForSingleObject(pi.hThread, INFINITE);
::WaitForSingleObject(pi.hProcess, INFINITE);
// 從匿名管道中讀取結果到輸出緩沖區
::RtlZeroMemory(pszResultBuffer, dwResultBufferSize);
::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, NULL, NULL);
// 關閉句柄, 釋放内存
::CloseHandle(pi.hThread);
::CloseHandle(pi.hProcess);
::CloseHandle(hWritePipe);
::CloseHandle(hReadPipe);
return TRUE;
}
全局鈎子可以實現系統監控,Windows提供了一個文件監控接口函數ReadDirectoryChangesW該函數可以對計算機上所有文件操作進行監控。在調用。
ReadDirectoryChangesW設置監控過濾條件之前,需要通過CreateFile函數打開監控目錄,獲取監控目錄的句柄,之後才能調用ReadDirectoryChangesW函數設置監控過濾條件并阻塞,直到有滿足監控過濾條件的操作,ReadDirectoryChangesW才會返回監控數據繼續往下執行。
具體過程
1、打開目錄,獲取文件句柄,調用CreateFile獲取文件句柄,文件句柄必須要有FILE_LIST_DIRECTORY權限。
2、調用ReadDirectoryChangesW設置目錄監控。
3、判斷文件操作類型,隻要有滿足過濾條件的文件操作,ReadDirectoryChangesW函數會立馬返回信息,并将其返回到輸出緩沖區中,而且返回數據是按結構體FILE_NOTIFY_INFORMATION返回的。
調用一次ReadDirectoryChangesW函數隻會監控一次,要想實現持續監控,則需要程序循環調用ReadDirectoryChangesW函數來設置監控并獲取監控數據,由于持續的目錄監控需要不停循環調用ReadDirectoryChangesW函數進行設置監控和獲取監控數據,所以如果把這段代碼放在主線程中則會導緻程序阻塞,為了解決主線程阻塞的問題,可以創建一個文件監控子線程,把文件監控的實現代碼放到子線程中。
源代碼實現:
#include "stdafx.h"
#include "MonitorFile.h"
void ShowError(char *pszText)
{
char szErr[MAX_PATH] = { 0 };
::wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
::MessageBox(NULL, szErr, "ERROR", MB_OK | MB_ICONERROR);
}
// 寬字節字符串轉多字節字符串
void W2C(wchar_t *pwszSrc, int iSrcLen, char *pszDest, int iDestLen)
{
::RtlZeroMemory(pszDest, iDestLen);
// 寬字節字符串轉多字節字符串
::WideCharToMultiByte(CP_ACP,
0,
pwszSrc,
(iSrcLen / 2),
pszDest,
iDestLen,
NULL,
NULL);
}
// 目錄監控多線程
UINT MonitorFileThreadProc(LPVOID lpVoid)
{
char *pszDirectory = (char *)lpVoid;
// 打開目錄, 獲取文件句柄
HANDLE hDirectory = ::CreateFile(pszDirectory, FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE == hDirectory)
{
ShowError("CreateFile");
return 1;
}
char szTemp[MAX_PATH] = { 0 };
BOOL bRet = FALSE;
DWORD dwRet = 0;
DWORD dwBufferSize = 2048;
// 申請一個足夠大的緩沖區
BYTE *pBuf = new BYTE[dwBufferSize];
if (NULL == pBuf)
{
ShowError("new");
return 2;
}
FILE_NOTIFY_INFORMATION *pFileNotifyInfo = (FILE_NOTIFY_INFORMATION *)pBuf;
// 開始循環設置監控
do
{
::RtlZeroMemory(pFileNotifyInfo, dwBufferSize);
// 設置監控目錄
bRet = ::ReadDirectoryChangesW(hDirectory,
pFileNotifyInfo,
dwBufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME | // 修改文件名
FILE_NOTIFY_CHANGE_ATTRIBUTES | // 修改文件屬性
FILE_NOTIFY_CHANGE_LAST_WRITE, // 最後一次寫入
&dwRet,
NULL,
NULL);
if (FALSE == bRet)
{
ShowError("ReadDirectoryChangesW");
break;
}
// 将寬字符轉換成窄字符
W2C((wchar_t *)(&pFileNotifyInfo->FileName), pFileNotifyInfo->FileNameLength, szTemp, MAX_PATH);
// 判斷操作類型并顯示
switch (pFileNotifyInfo->Action)
{
case FILE_ACTION_ADDED:
{
// 新增文件
printf("[File Added Action]%s\n", szTemp);
break;
}
default:
{
break;
}
}
} while (bRet);
// 關閉句柄, 釋放内存
::CloseHandle(hDirectory);
delete[] pBuf;
pBuf = NULL;
return 0;
}
// 創建目錄監控多線程
void MonitorFile(char *pszDirectory)
{
// 創建文件監控多線程
::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MonitorFileThreadProc, pszDirectory, 0, NULL);
}
自删除功能對病毒木馬來說同樣至關重要,它通常在完成目标任務之後删除自身,不留下任何蛛絲馬迹,自删除的方法有很多種,常見的有利用MoveFileEx重啟删除和利用批處理删除兩種方式。
(1)MoveFileEx重啟删除
MOVEFILE_DELAY_UNTIL_REBOOT這個标志隻能由擁有管理員權限的程序或者擁有本地系統權限的程序使用,而且這個标志不能MOVEFILE_COPY_ALLOWED一起使用,并且,删除文件的路徑開頭需要加上“\?\"前綴。
源代碼實現:
#include "stdafx.h"
#include <Windows.h>
BOOL RebootDelete(char *pszFileName)
{
// 重啟删除文件
char szTemp[MAX_PATH] = "\\\\?\\";
::lstrcat(szTemp, pszFileName);
BOOL bRet = ::MoveFileEx(szTemp, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
return bRet;
}
int _tmain(int argc, _TCHAR* argv[])
{
if (FALSE == RebootDelete("C:\\Users\\Test\\Desktop\\520.exe"))
{
printf("Set Reboot Delete Error.\n");
}
else
{
printf("Set Reboot Delete OK.\n");
}
system("pause");
return 0;
}
(2)利用批處理命令删除
del %0
批處理命令會将自身批處理文件删除而且不放進回收站。
具體流程
1 構造自删除批處理文件,該批處理文件的功能就是先利用choice或ping命令延遲一定的時間,之後才開始執行删除文件操作,最後執行自删除命令。
2 在程序中創建一個新進程并調用批處理文件,程序在進程創建成功後,立刻退出整個程序。
源代碼實現:
#include "stdafx.h"
#include <Windows.h>
BOOL CreateChoiceBat(char *pszBatFileName)
{
int iTime = 5;
char szBat[MAX_PATH] = { 0 };
// 構造批處理内容
/*
@echo off
choice /t 5 /d y /n >nul
del *.exe
del %0
*/
::wsprintf(szBat, "@echo off\nchoice /t %d /d y /n >nul\ndel *.exe\ndel %%0\n", iTime);
// 生成批處理文件
FILE *fp = NULL;
fopen_s(&fp, pszBatFileName, "w ");
if (NULL == fp)
{
return FALSE;
}
fwrite(szBat, (1 ::lstrlen(szBat)), 1, fp);
fclose(fp);
return TRUE;
}
BOOL CreatePingBat(char *pszBatFileName)
{
int iTime = 5;
char szBat[MAX_PATH] = {0};
// 構造批處理内容
/*
@echo off
ping 127.0.0.1 -n 5
del *.exe
del %0
*/
::wsprintf(szBat, "@echo off\nping 127.0.0.1 -n %d\ndel *.exe\ndel %%0\n", iTime);
// 生成批處理文件
FILE *fp = NULL;
fopen_s(&fp, pszBatFileName, "w ");
if (NULL == fp)
{
return FALSE;
}
fwrite(szBat, (1 ::lstrlen(szBat)), 1, fp);
fclose(fp);
return TRUE;
}
BOOL DelSelf(int iType)
{
BOOL bRet = FALSE;
char szCurrentDirectory[MAX_PATH] = {0};
char szBatFileName[MAX_PATH] = {0};
char szCmd[MAX_PATH] = {0};
// 獲取當前程序所在目錄
::GetModuleFileName(NULL, szCurrentDirectory, MAX_PATH);
char *p = strrchr(szCurrentDirectory, '\\');
p[0] = '\0';
// 構造批處理文件路徑
::wsprintf(szBatFileName, "%s\\temp.bat", szCurrentDirectory);
// 構造調用執行批處理的 CMD 命令行
::wsprintf(szCmd, "cmd /c call \"%s\"", szBatFileName);
// 創建自删除的批處理文件
if (0 == iType)
{
// choice 方式
bRet = CreateChoiceBat(szBatFileName);
}
else if (1 == iType)
{
// ping 方式
bRet = CreatePingBat(szBatFileName);
}
// 創建新的進程, 以隐藏控制台的方式執行批處理
if (bRet)
{
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
//指定wShowWindow成員有效
si.dwFlags = STARTF_USESHOWWINDOW;
//此成員設為TRUE的話則顯示新建進程的主窗口
si.wShowWindow = FALSE;
BOOL bRet = CreateProcess(
//不在此指定可執行文件的文件名
NULL,
//命令行參數
szCmd,
//默認進程安全性
NULL,
//默認進程安全性
NULL,
//指定當前進程内句柄不可以被子進程繼承
FALSE,
//為新進程創建一個新的控制台窗口
CREATE_NEW_CONSOLE,
//使用本進程的環境變量
NULL,
//使用本進程的驅動器和目錄
NULL,
&si,
&pi);
if (bRet)
{
//不使用的句柄最好關掉
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// 結束進程
exit(0);
::ExitProcess(NULL);
}
}
return bRet;
}
int _tmain(int argc, _TCHAR* argv[])
{
// 程序自删除
BOOL bRet = DelSelf( 0 );
if (FALSE == bRet)
{
printf("Selft Delete Error!\n");
}
else
{
printf("Selft Delete OK!\n");
}
system("pause");
return 0;
}
注:惡意代碼的存在不是由于黑客之類的手段,主要還是我們開發過程中很多情況會用到這樣的技術,所以大家請利用技術做正确的事情!
另外,對于編程學習的小夥伴,如果你想更好的提升你的編程核心能力(内功)不妨從現在開始!
編程學習書籍分享:
編程學習視頻分享:
整理分享(多年學習的源碼、項目實戰視頻、項目筆記,基礎入門教程)
歡迎轉行和學習編程的夥伴,利用更多的資料學習成長比自己琢磨更快哦!
對于C/C 感興趣可以關注小編在後台私信我:【編程交流】一起來學習哦!可以領取一些C/C 的項目學習視頻資料哦!已經設置好了關鍵詞自動回複,自動領取就好了!
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!