惡意代碼的分類包括計算機病毒、蠕蟲、木馬、后門、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]
", 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 curityAttributes = {0}; BOOL bRet = FALSE; STARTUPINFO si = {0}; PROCESS_INFORMATION pi = {0}; // 設定管道的安全屬性 curityAttributes.bInheritHandle = TRUE; curityAttributes.nLength = sizeof(curityAttributes); curityAttributes.lpSecurityDescriptor = NULL; // 創建匿名管道 bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &curityAttributes, 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); // 關閉句柄, 釋放內存 ::CloHandle(pi.hThread); ::CloHandle(pi.hProcess); ::CloHandle(hWritePipe); ::CloHandle(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]
", 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) { ca FILE_ACTION_ADDED: { // 新增文件 printf("[File Added Action]%s
", szTemp); break; } default: { break; } } } while (bRet); // 關閉句柄, 釋放內存 ::CloHandle(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:\Urs\Test\Desktop\520.exe")) { printf("Set Reboot Delete Error.
"); } el { printf("Set Reboot Delete OK.
"); } system("pau"); 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
choice /t %d /d y /n >nul
del *.exe
del %%0
", iTime); // 生成批處理文件 FILE *fp = NULL; fopen_s(&fp, pszBatFileName, "w+"); if (NULL == fp) { return FALSE; } fwrite(szBat, (1 + ::lstrlen(szBat)), 1, fp); fclo(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
ping 127.0.0.1 -n %d
del *.exe
del %%0
", iTime); // 生成批處理文件 FILE *fp = NULL; fopen_s(&fp, pszBatFileName, "w+"); if (NULL == fp) { return FALSE; } fwrite(szBat, (1 + ::lstrlen(szBat)), 1, fp); fclo(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] = ''; // 構造批處理文件路徑 ::wsprintf(szBatFileName, "%s\temp.bat", szCurrentDirectory); // 構造調用執行批處理的 CMD 命令行 ::wsprintf(szCmd, "cmd /c call "%s"", szBatFileName); // 創建自刪除的批處理文件 if (0 == iType) { // choice 方式 bRet = CreateChoiceBat(szBatFileName); } el 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) { //不使用的句柄最好關掉 CloHandle(pi.hThread); CloHandle(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!
"); } el { printf("Selft Delete OK!
"); } system("pau"); return 0;}
注:惡意代碼的存在不是由于黑客之類的手段,主要還是我們開發過程中很多情況會用到這樣的技術,所以大家請利用技術做正確的事情!
另外,對于編程學習的小伙伴,如果你想更好的提升你的編程核心能力(內功)不妨從現在開始!
編程學習書籍分享:
編程學習視頻分享:
整理分享(多年學習的源碼、項目實戰視頻、項目筆記,基礎入門教程)
歡迎轉行和學習編程的伙伴,利用更多的資料學習成長比自己琢磨更快哦!
對于C/C++感興趣可以關注小編在后臺私信我:【編程交流】一起來學習哦!可以領取一些C/C++的項目學習視頻資料哦!已經設置好了關鍵詞自動回復,自動領取就好了!
本文發布于:2023-02-28 20:14:00,感謝您對本站的認可!
本文鏈接:http://www.newhan.cn/zhishi/a/167766477182388.html
版權聲明:本站內容均來自互聯網,僅供演示用,請勿用于商業和其他非法用途。如果侵犯了您的權益請與我們聯系,我們將在24小時內刪除。
本文word下載地址:stdafx.h.doc
本文 PDF 下載地址:stdafx.h.pdf
| 留言與評論(共有 0 條評論) |