天天看點

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

1.樣本概況

1.1 應用程式資訊

  ----------------------

應用程式名稱:掃雷(基于Windows xp系統)

MD5值:16A4FD569A3EB5CEBEB3DA99EF1D17E1

SHA1值:31A1A89BA067EA95F117754818429D6D8E8E59CF

簡單功能介紹:

1. 遊戲模式:分為初級,中級,進階,自定義模式

2. 自定義:可以設定遊戲界面的高度(max=24),寬度(max=30),雷數(max=667)

3. 遊戲視窗:顯示有雷數,計時,和需要探測點選的雷區

4. 遊戲規則:滑鼠點選不為雷的區域會顯示數字,提示周圍的雷數,右鍵點選可以下标記,當所有不為雷的區域被點選即成功,點選到雷則遊戲失敗,點選笑臉可以重置目前雷區

1.2 分析環境及工具

系統環境:win7 Professional 32位(15pb實驗環境)

工具:

1. DIE(PE檔案分析)

2. Cheat Engine(搜尋資料)

3. VS2019(編寫DLL程式)

4. MFCInject(dll注入工具)

5. DebugView(輸出調試資訊)

6. OllyDbg(動态調試分析)

7. Spy++(擷取視窗資訊)

8. Hash(計算MD5,SHA1)

1.3 分析目标

實作掃雷外挂:

    1. 滑鼠移動懸停在雷區時,在視窗右上角顯示雷區坐标及目前區域是否有雷

    2. 實作F5一鍵掃雷功能,模拟點選所有不為雷的區域完成遊戲

2.具體分析過程

2.1 DIE查殼

2.1.1 樣本基礎資訊

連結器版本:Microsoft Linker7.0

編寫工具:從連結器版本判斷為VS2003

類型:32位

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.1.2 樣本詳細資訊

分析樣本導入庫,為使用SDK編寫的程式

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.2 CE搜尋資料

2.2.1 擷取關鍵資料

擷取資料基本步驟

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

多次修改擷取到三個的高,寬,雷數的資料,且在CE中位址為綠色(靜态位址,全局),有多份可能為(代碼備援,實際顯示需要)

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.2.2 驗證資料有效性

在VS2019中編寫MFC DLL(靜态編譯,不依賴環境),關鍵調試代碼

  1. //調式擷取到的高度,寬度,雷數變量位址  
  2. PDWORD pHeigth = (PDWORD)0x01005338;  
  3. PDWORD pWidth = (PDWORD)0x01005334;  
  4. PDWORD pMineCount = (PDWORD)0x01005330;  
  5. //顯示錯誤  
  6. BOOL CheckResult(BOOL result, WCHAR* str)  
  7. {  
  8.     if (!result)  
  9.     {  
  10.         OutputDebugString(str);  
  11.         return FALSE;  
  12.     }  
  13.     return TRUE;  
  14. }  
  15. //儲存視窗句柄  
  16. HWND g_hWnd = 0;  
  17. //原來的回調函數  
  18. WNDPROC OldWinProc = 0;  
  19. //新的視窗回調函數  
  20. LRESULT CALLBACK NewWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  
  21. {  
  22.     switch (uMsg)  
  23.     {  
  24.         //如果是鍵盤消息  
  25.         //一鍵掃雷思路:周遊掃雷數組中的元素,判斷不為雷的區域,模拟滑鼠點選  
  26.         case WM_KEYDOWN:  
  27.         {  
  28.             //f5  
  29.             if (wParam == VK_F5)  
  30.             {                  
  31.                 CString str;  
  32.                 str.Format(L"高:%d,寬:%d,雷數:%d\n", *pHeigth, *pWidth, *pMineCount);  
  33.                 OutputDebugString(str);  
  34.              }  
  35.         }  
  36.     }  
  37.     //CallWindowProc 不處理的消息讓原來的回調函數處理  
  38.     return OldWinProc(hWnd, uMsg, wParam, lParam);  
  39. // CMFCmineApp 初始化  
  40. BOOL CMFCmineApp::InitInstance()  
  41. {  
  42.     CWinApp::InitInstance();  
  43.     //1. 通過查找視窗擷取視窗句柄 spy++  
  44.     //通過視窗名,視窗類名擷取視窗句柄  
  45.     g_hWnd = ::FindWindow(L"掃雷", L"掃雷");  
  46.     //判斷是否找到  
  47.     if (CheckResult(g_hWnd != 0, L"未找到掃雷視窗\n") == 0)  
  48.         return 0;  
  49.     //2. 設定視窗回調函數  
  50.     OldWinProc = WNDPROC(SetWindowLong(g_hWnd, GWL_WNDPROC, LONG(NewWndProc)));  
  51.     //判斷是否修改成功  
  52.     if (CheckResult(OldWinProc != 0, L"修改回調函數失敗\n") == 0)  
  53.         return 0;  
  54.     return TRUE;  

使用注入工具MFCInject注入編寫的dll,并打開ViewDebug檢視調試資訊,判斷資料有效

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.3 OD分析代碼邏輯

2.3.1 CE中找到通路資料位置

這時可以跟蹤資料,右鍵選擇是誰通路了這個資料(原理:下斷點)

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

這時笑臉重置按鈕就發揮作用了,點選,在CE彈出的視窗中檢視

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.3.2 OD中分析

在OD中跳轉到通路關鍵資料的位址進行分析

一共三處,其他兩處檢視與界面相關,不做具體分析,分析位址為0x01002EE4

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

對代碼邏輯進行分析,判斷為擷取高寬對雷區進行重置的操作,這裡可以得到雷區數組的初始位址,雷區總大小

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.3.3 擷取雷區資訊

根據記憶體視窗對照掃雷視窗區分雷區屬性(最好寬度對應)

雷區基位址:0x01005430

空白:0x0F

雷:0x8F

邊界:0x10

點選後的周圍雷數:0x40+周圍雷數

爆炸的雷:0x8A

掃雷逆向分析1.樣本概況2.具體分析過程3.總結
掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.3.4 調式輸出雷區數組

在DLL中編寫周遊雷區數組的代碼進行調試,關鍵代碼

  1. //如果是鍵盤消息  
  2.        //一鍵掃雷思路:周遊掃雷數組中的元素,判斷不為雷的區域,模拟滑鼠點選  
  3.        case WM_KEYDOWN:  
  4.        {  
  5.            //f5  
  6.            if (wParam == VK_F5)  
  7.            {               
  8.                int count = 0;  
  9.                //循環周遊整個雷區數組  
  10.                for (int y = 1; y < *pHeigth + 1; y++)  
  11.                {  
  12.                    //儲存每一行雷區資訊  
  13.                    CString S = 0;  
  14.                    //周遊行  
  15.                    for (int x = 1; x < *pWidth + 1; x++)  
  16.                    {  
  17.                        //擷取資訊  
  18.                        PBYTE pCode = PBYTE(dwBaseAddr + y * 32 + x);  
  19.                        //雷計數  
  20.                        if (*pCode == MINE)  
  21.                            count++;  
  22.                        //存放每個位置資訊  
  23.                        CString s;  
  24.                        s.Format(L"%02x ", *pCode);  
  25.                        S += s;  
  26.                    }  
  27.                    //調試輸出  
  28.                    OutputDebugString(S);  
  29.                }  
  30.                //輸出雷數  
  31.                str.Format(L"雷數:%d", count);  
  32.                OutputDebugString(str);  
  33.            }  
  34.            break;  
  35.        }  

ViewDebug調試資訊如下

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.3.5 查找消息回調

SPY++查找

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

也可以使用OD中W視窗右鍵點選視窗檢視ClassProc

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

或者在關鍵API下斷點回溯找到

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.3.6 分析回調函數

在OD中找到回調函數的位置,可以初步判斷消息的點選消息為WM_LBUTTONDOWN

技巧:Ctrl+A - 右鍵分析 - 假定參數選擇WndProc

設定消息斷點,選擇需要設定斷點的消息(WM_LBUTTONDWON)

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

回調函數原型為

LRUSULT CALLBACK WinProc(HWND hWnd, UINT uMes, Wparam wPAram, LPARAM lParam){}

參數2為消息類型,參數4為WM_LBUTTONDWON的滑鼠坐标

高位y坐标HIWORD(lParam),低位x坐标LOWORD(lParam)

消息回調中初步檢視操作了儲存滑鼠坐标lParam的代碼

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

該處經檢視分析為判斷點選的代碼,不做具體分析

掃雷逆向分析1.樣本概況2.具體分析過程3.總結
掃雷逆向分析1.樣本概況2.具體分析過程3.總結

再次找到操作WM_LBUTTONDOWN消息操作坐标的代碼,對擷取到的滑鼠坐标處理

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

根據處理完的值與點選的雷區界面對比,猜測為此處操作将客戶區坐标轉換為數組坐标

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

與掃雷視窗點選的區域對應

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

2.4 完成功能的實作

2.4.1 滑鼠懸停提示

在注入DLL中的消息回調響應滑鼠移動,根據分析的轉換算法将滑鼠坐标轉換成數組坐标,判斷目前雷區數組沒區域是否為雷,在标題欄提示

主要代碼如下

  1. //滑鼠移動顯示資訊  
  2.         case WM_MOUSEMOVE:  
  3.         {  
  4.             CString sCaption;  
  5.             //x,y坐标  
  6.             DWORD x = LOWORD(lParam);  
  7.             DWORD y = HIWORD(lParam);  
  8.             //轉換為數組坐标  
  9.             x = (x + 4) >> 4;  
  10.             y = (y - 0x27) >> 4;  
  11.             //在雷區範圍内  
  12.             if (0 < x && x <= *pWidth && 0 < y && y <= *pHeigth)  
  13.             {  
  14.                 //如果判斷為雷  
  15.                 if (*(PBYTE(dwBaseAddr + y * 32 + x)) == MINE)  
  16.                     sCaption.Format(L"掃雷 (x:%d,y:%d) 有雷", x, y);  
  17.                 else  
  18.                     sCaption.Format(L"掃雷 (x:%d,y:%d) 無雷", x, y);  
  19.                 SetWindowText(g_hWnd, sCaption);  
  20.             }   
  21.         }  

2.4.2 F5一鍵掃雷

在注入DLL中的消息回調響應F5按鍵消息,根據分析的轉換算法将雷區數組坐标轉換成客戶區坐标,判斷目前區域是否為雷,如果不是則發送消息模拟點選完成遊戲

主要代碼如下,這裡需要注意要同時發送滑鼠左鍵按下與擡起的消息,視窗才能完成響應整個模拟點選的操作

  1.                    //如果不是雷 F5一鍵掃雷功能  
  2.                  if (*pCode != MINE)  
  3.                  {  
  4.                      //首先将x,y數組坐标轉換為客戶區坐标  
  5.                      int xPos, yPos;  
  6.                      yPos = (y << 4) + 0x27;  
  7.                      xPos = (x << 4) - 4;  
  8.                      //前面為低位元組  
  9.                      DWORD lparam = MAKELPARAM(xPos, yPos);  
  10.                      //給掃雷發送消息 模拟點選  
  11.                      SendMessage(g_hWnd, WM_LBUTTONDOWN, 0, lparam);  
  12.                      SendMessage(g_hWnd, WM_LBUTTONUP, 0, lparam);  
  13.                  } 

2.5 實作效果

2.5.1 效果截圖

掃雷逆向分析1.樣本概況2.具體分析過程3.總結

3.總結

很久之前玩掃雷,就想過一鍵掃雷的情景,作為第一個逆向的程式,還是從中擷取到了很多的。首先第一次系統性的分析一個檔案,從連結器資訊,編寫語言到使用的庫,關鍵的邏輯判斷及調式到實作,整個流程下來算是比較完整的,感覺逆向測試的過程還是比較需要技術的。

對逆向分析中使用的工具的了解和掌握也是比較重要的,不同的工具可以完成特定的分析功能,熟練的使用可以節約大量的時間,要讓他們成為分析時的左膀右臂,還是就是對回調函數的了解及分析,基于消息驅動使得消息處理尤為重要,是使用者與程式互動的重要樞紐,很多邏輯判斷也是在其中實作的。

作為第一次分析是沒有什麼思路的,經過視訊的講解還是在腦子裡有了個大概的過程,這次的掃雷是通過使用CE從資料入手,找到使用資料的地方,進而在OD動态分析邏輯,找到關鍵位置,再基于消息的響應處理找到是實作坐标的轉換算法,期間使用了注入和Debugview的功能完成了動态調試,進而實作了整個功能(實際還是利用原程式完成自己功能的實作,總結下就是用最小的開銷騙過程式來實作自己想要的效果)。

整體感覺還是需要多練習,基礎要紮實,這樣才可以更快的分析(基于知識和經驗的猜測)到關鍵點做判斷。