查看: 395|回复: 1

[转载图文] 小白也能逆向分析扫雷游戏

[复制链接]
发表于 2020-10-10 18:40:12 | 显示全部楼层 |阅读模式
1.样本概况具体分析过程
1.1 应用程序信息
      
             应用程序名称:winmine.exe(扫雷)
             说明:一款基础的扫雷游戏

1.2 分析环境及工具
      
             系统环境:Win7 32位
             工具:
                      OllyDbg(动态调试代码)
                      Cheat Engine(搜索数据)
                      Spy++(寻找窗口回调函数)
                      PEID/exeinfo(查壳,查编译环境)
                      Visual Studio2019(开发程序)
                      MFCInject(注入工具)

1.3 分析目标

            1)标注某处是否有雷
            2)一键通关

2.具体分析过程2.1 已知与推测
2.1.1判断开发游戏的语言

               首先将游戏拖拽到PEID上会发现是由C++编写的程序

               

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

              当我们打开游戏时是一个窗口,而不是一个黑框框,猜测是SDK或MFC编写的

              

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

             猜测是SDK编写的,这是由于
                   1)点击子系统箭头,点击导入表箭头,会发现列表中有msvrt.dll,这是微软的运行时库,故多半是SDK编写

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

                  2)列表中没有MFC特有的库
                  3)查看该游戏大小只有100kb,若是MFC静态编译则会有1M左右

           若游戏是由SDK编写的,这意味着会有一些相关的函数可供我们查找与调用
              如   
                   CreateWindowExW/CreateWindowExA(创建窗口)
                   GetWindowTextA/GetWindowTextW(将指定窗口的标题拷贝到一个缓冲区内)
                   SetWindowTextA/SetWindowTextW(改变控件的文本内容,窗口也是一个控件)
                   rand(产生随机数函数)

2.1.2可探究路线
              1)动态调试,即从API函数入手
                 由于是由SDK编写的代码,那么必定含有windows的api函数,那么就可以用OllyDbg进行调试,来探究这款游戏内部的逻辑,得到更多的信息
              2)数据分析,即从变化的数据入手
                 由于扫雷是一款游戏,必定有一些数据来代表着游戏的内容,诸如雷的数量,时间等信息。像雷的分布,可能会有一个数组来标注,那么我们可以通过获取数组的地址,来得到雷的分布数据。对于以上这些信息,通过Cheat Engine不仅可以获得,还可以进行修改,通过修改,可以验证我们的一些猜想。

2.2数据分析
2.2.1寻找重要数值
             通过观察,左上角有自定义游戏选项,可自定义高度,宽度,雷的数量,右上角的时间计时与左上角的已判断雷数计数
             其中游戏通关与否与时间和待判定雷数无关,高度,宽度可用于表示坐标,雷数是用于判断的重要指标并与多项游戏机制相关,所以主要寻找高度,宽度,雷的数量这三项数据即可

              

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏
2.2.2寻找数值地址

               Cheat Engine添加扫雷进程
               

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

                 通过自定义选项改变游戏的高,宽,雷数,不断搜索这些数值,筛选到最后,剩下绿色标记的就是基地址(不会因为重新打开游戏而变化的地址),最终得到6条地址信息

                  

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏
                  通过更改地址,得到访问数据的地址信息

                  

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏
  
                  

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

                 用OllyDbg查找响应地址,数据窗口跟随,发现初始化雷数组的汇编代码区域
                 宽的地址是0x1005334;
                 高的地址是0x1005338;
                 雷数的地址是0x1005330;
                 雷数组的地址是1005340,边界的值是10,雷的值是8F

                 

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏
  

3.游戏反汇编代码调试与注入软件编写
          用Visual Studio2019 创建项目

         

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏
  

          用spy++获取窗口类名,知道窗口的地址为1001BC9

         

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏
  
         许多代码已被编写,直接写在instance函数中编写即可,SetWindowLong将游戏的回调函数替换为自己的回调函数,判断若返回值为NULL,说明没找到      窗口,用于提示报错
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
BOOL CMFCGamePlugApp::InitInstance()
{
    CWinApp::InitInstance();

    //1.通过查找窗口,获取窗口句柄
    g_Wnd=::FindWindow(L"扫雷", L"扫雷");
    if (g_Wnd==NULL)
    {
        OutputDebugString(L"无法找到 扫雷窗口");
        return FALSE;
    }

    //2.设置窗口回调函数
    g_OldProc = (WNDPROC)SetWindowLong(g_Wnd,GWL_WNDPROC, (LONG)WindowProc);
    if (g_OldProc == NULL)
    {
        OutputDebugString(L"设置窗口回调函数 失败");
        return FALSE;
    }

    return TRUE;
}


        回调函数编写,如果按下F5,则进行接下来的行为(启动注入)

1
2
3
4
5
6
7
8
9
10
11
12
13
LRESULT CALLBACK WindowProc(
    _In_ HWND hWnd,
    _In_ UINT Msg,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam)
{
    if (Msg == WM_KEYDOWN && wParam == VK_F5)
    {
        
    }

    return CallWindowProc(g_OldProc, hWnd, Msg, wParam, lParam);
}


        编写代码,用MFCInject注入,按下F5后用DebugView查看是否得到想要的内容

1
2
3
4
5
6
int nWidth = *g_pWidth;
int nHeight = *g_pHeight;
int nMineCount = *g_pMineCount;
CString strString;
strString.Format(L"宽度: %d,高度: %d,雷数:%d ", nWidth, nHeight,nMineCount);
OutputDebugString(strString.GetBuffer());


        

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

        

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

        输入窗口的地址,在OllyDbg中找到窗口回调汇编代码,分析参数坐标和我们需要输出内容的数学计算关系
        

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

        编写代码,根据鼠标移动获取坐标,用Spy++查看窗口输出的消息中是否有想要的坐标,最后在窗口标题处显示是否有雷

        

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
else if (Msg == WM_MOUSEMOVE)
    {
        //鼠标移动
        int x, y;
        x = LOWORD(lParam);
        y = HIWORD(lParam);
        x = (x + 4) >> 4;
        y = (y-0x27)>>4;
        BYTE byCode = *(PBYTE)((DWORD)g_pBase + x + y * 32);
        if (byCode == MINE)
        {
            SetWindowText(hWnd,L"此处有雷");
        }
        else
        {
            SetWindowText(hWnd, L"无事");
        }
    }


        在回调函数处设置条件断点,当点击时断下,分析反汇编代码,得到x,y坐标
         

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

         

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏
        

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

        通过模拟点击事件把所有非雷区域点击,实现一键通关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
if (Msg == WM_KEYDOWN && wParam == VK_F5)
    {
        //一键通关
        OutputDebugString(L"F5");
        int nWidth = *g_pWidth;
        int nHeight = *g_pHeight;
        int nMineCount = *g_pMineCount;
        CString strString;
        strString.Format(L"宽度: %d,高度: %d,雷数:%d ", nWidth, nHeight,nMineCount);
        OutputDebugString(strString.GetBuffer());
        int nFindCount = 0;
        for (size_t y = 1;y<nHeight+1;y++)
        {
            CString strLine;
            for (size_t x = 1; x < nWidth + 1; x++)
            {
                //数组基地址+(y+1)*32+x+1(y=0到高度)
                BYTE byCode = *(PBYTE)((DWORD)g_pBase + x + y * 32);
                if (byCode == MINE)
                {
                    nFindCount++;
                }
                else
                {
                    int xPos, yPos;
                    xPos = (x << 4) - 4;
                    yPos = (y << 4) + 0x27;               
                    SendMessage(hWnd,WM_LBUTTONDOWN,0,MAKELPARAM(xPos,yPos));
                    SendMessage(hWnd,WM_LBUTTONUP,0,MAKELPARAM(xPos,yPos));
                }
                CString strCode;
                strCode.Format(L"%02x ", byCode);
                strLine += strCode;
            }
            OutputDebugString(strLine.GetBuffer());
        }
        CString strCode;
        strCode.Format(L"找到的雷数 %d ", nFindCount);
        OutputDebugString(strCode.GetBuffer());
    }


4.最终效果与附件下载
            

小白也能逆向分析扫雷游戏

小白也能逆向分析扫雷游戏

           附件中包含:
                  注入的dll
                  注入工具MFCInject
                  游戏本体
                  dll源码(用 Visual Studio2019编写)
游客,如果您要查看本帖隐藏内容请回复
温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的最好奖励,还可以获得学币奖励,请尊重作者的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046

0

主题

15

帖子

0

精华

中级会员

Rank: 8Rank: 8

学币
81
荣耀
0
rank
0
违规
0

    发表于 2020-10-17 14:11:25 | 显示全部楼层
    66666666跟着楼主一起学习扫雷
    学逆向论坛-免费的逆向学习论坛
    微信公众号
    快速回复 返回顶部 返回列表