找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 9407|回复: 2

关于Win7扫雷逆向分析及外挂编写

[复制链接]

307

主题

228

回帖

7337

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5587 个
贡献
253 次
宅之契约
0 份
在线时间
948 小时
注册时间
2014-1-25
发表于 2015-6-6 15:39:22 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
  1. Win7扫雷把玩手记
  2. 我系统Win8.1,直接把Win7 MineSweeper那个文件夹弄过来,,是无法运行扫雷的。
  3. 由于是系统组件,ida载入可以得到符号,先研究为何无法运行!
  4. 从用户入口WinMain开始跟:
  5. int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  6. {
  7.   DWORD v4; // ecx@1
  8.   int result; // eax@2
  9.   HMODULE v6; // eax@3
  10.   void *v7; // eax@6
  11.   void *v8; // esi@7
  12.   WCHAR Buffer; // [sp+4h] [bp-24h]@3
  13.   char v10; // [sp+6h] [bp-22h]@3
  14.   __int16 v11; // [sp+22h] [bp-6h]@3

  15.   HeapSetInformation(0, HeapEnableTerminationOnCorruption, 0, 0);
  16.   if ( IsGamePlayable(v4, L"Shell-InBoxGames-Minesweeper-EnableGame") )
  17.   {
  18.     g_hInstance = hInstance;
  19.     Buffer = 0;
  20.     memset(&v10, 0, 0x1Cu);
  21.     v11 = 0;
  22.     v6 = GetModuleHandleW(0);
  23.     if ( LoadStringW(v6, 0xFBCu, &Buffer, 16) && !lstrcmpW(&Buffer, L"0") )
  24.       g_Flowerbed = 1;
  25.     v7 = operator new(4u);
  26.     if ( v7 )
  27.     {
  28.       *(_DWORD *)v7 = EngineHandler::`vftable';
  29.       v8 = v7;
  30.     }
  31.     else
  32.     {
  33.       v8 = 0;
  34.     }
  35.     RegisterLogNameResolver((const unsigned __int16 *(__stdcall *)(unsigned int))MsLog::MsLogResolver);
  36.     if ( InitializeEngine((struct IEngineInterface *)v8, 0) )
  37.     {
  38.       if ( v8 )
  39.         IEngineInterface::`scalar deleting destructor'(v8, 1);
  40.       result = 0;
  41.     }
  42.     else
  43.     {
  44.       if ( v8 )
  45.         IEngineInterface::`scalar deleting destructor'(v8, 1);
  46.       result = 1;
  47.     }
  48.   }
  49.   else
  50.   {
  51.     result = 1;
  52.   }
  53.   return result;
  54. }

  55. 发现IsGamePlayable处返回失败,在此需要将返回值改为TRUE,接着调试,发现InitializeEngine执行后直接进程结束,因此跟入该函数:
  56. bool __stdcall InitializeEngine(struct IEngineInterface *a1, struct IControllerInterface *a2)
  57. {
  58.   DialogHelper *v2; // eax@1
  59.   DWORD v3; // ST20_4@1
  60.   int v4; // eax@1
  61.   int v5; // ecx@1
  62.   __int16 v6; // dx@2
  63.   rsize_t v7; // ebx@3
  64.   wchar_t *v8; // eax@3
  65.   const wchar_t *v10; // eax@5
  66.   HANDLE v11; // ebx@5
  67.   wchar_t *v12; // eax@8
  68.   const WCHAR *v13; // esi@8
  69.   HWND v14; // ebx@8
  70.   const WCHAR *v15; // eax@12
  71.   LPWSTR *v16; // eax@12
  72.   unsigned int v17; // ecx@12
  73.   const WCHAR *v18; // eax@16
  74.   const unsigned __int16 *v19; // eax@18
  75.   unsigned __int16 *v20; // eax@19
  76.   void *v21; // eax@28
  77.   wchar_t *v22; // eax@31
  78.   DWORD v23; // eax@31
  79.   int i; // ecx@31
  80.   WCHAR v25; // dx@32
  81.   void *v26; // eax@38
  82.   XmlManager *v27; // eax@39
  83.   ResourceBase *v28; // ecx@41
  84.   ResourceWMA *v29; // ecx@41
  85.   DllFileMgr *v30; // eax@45
  86.   wchar_t *v31; // eax@47
  87.   bool v32; // al@47
  88.   wchar_t *v33; // esi@48
  89.   int (**v34)(void); // eax@48
  90.   int v35; // eax@48
  91.   DWORD v36; // eax@54
  92.   void *v37; // eax@57
  93.   ResourceManager *v38; // eax@58
  94.   void *v39; // eax@64
  95.   RenderManager *v40; // eax@65
  96.   void *v41; // eax@69
  97.   Audio *v42; // eax@70
  98.   CommonControllerThread *v43; // eax@75
  99.   void *v44; // eax@77
  100.   ResourceWMA *v45; // eax@78
  101.   XmlNode *v46; // eax@82
  102.   unsigned __int16 *v47; // edi@84
  103.   struct IEngineInterface *v48; // edi@90
  104.   DWORD v49; // ST20_4@96
  105.   HMODULE v50; // eax@96
  106.   bool nSize; // [sp+14h] [bp-6ACh]@0
  107.   const unsigned __int16 *v52; // [sp+18h] [bp-6A8h]@0
  108.   void (__stdcall *v53)(); // [sp+18h] [bp-6A8h]@55
  109.   char v54; // [sp+24h] [bp-69Ch]@48
  110.   struct tagMSG Msg; // [sp+30h] [bp-690h]@98
  111.   int v56; // [sp+4Ch] [bp-674h]@44
  112.   int v57; // [sp+50h] [bp-670h]@44
  113.   int v58; // [sp+54h] [bp-66Ch]@44
  114.   int v59; // [sp+58h] [bp-668h]@44
  115.   void (__stdcall *v60)(unsigned __int32 *); // [sp+5Ch] [bp-664h]@44
  116.   void (__stdcall *v61)(unsigned __int32); // [sp+60h] [bp-660h]@104
  117.   int v62; // [sp+64h] [bp-65Ch]@44
  118.   int v63; // [sp+68h] [bp-658h]@44
  119.   HWND v64; // [sp+6Ch] [bp-654h]@62
  120.   int v65; // [sp+70h] [bp-650h]@62
  121.   int v66; // [sp+74h] [bp-64Ch]@62
  122.   int v67; // [sp+78h] [bp-648h]@62
  123.   int v68; // [sp+7Ch] [bp-644h]@62
  124.   RAWINPUTDEVICE pRawInputDevices; // [sp+80h] [bp-640h]@47
  125.   int pNumArgs; // [sp+8Ch] [bp-634h]@12
  126.   struct IEngineInterface *v71; // [sp+90h] [bp-630h]@1
  127.   XmlNode *v72; // [sp+94h] [bp-62Ch]@1
  128.   unsigned int v73; // [sp+98h] [bp-628h]@12
  129.   void *pv; // [sp+9Ch] [bp-624h]@12
  130.   wchar_t *Dst; // [sp+A0h] [bp-620h]@3
  131.   bool v76; // [sp+A7h] [bp-619h]@16
  132.   OLECHAR psz; // [sp+A8h] [bp-618h]@17
  133.   WCHAR Filename[518]; // [sp+2B0h] [bp-410h]@31
  134.   int v79; // [sp+6BCh] [bp-4h]@16

  135.   v71 = a1;
  136.   v72 = a2;
  137.   v2 = (DialogHelper *)GetModuleHandleW(0);
  138.   DialogHelper::Init(v2, 0, 0, nSize);
  139.   v4 = (*(int (__thiscall **)(struct IEngineInterface *, DWORD))(*(_DWORD *)a1 + 16))(a1, v3);//EngineHandler::GetProjectName
  140.   v5 = v4 + 2;
  141.   do
  142.   {
  143.     v6 = *(_WORD *)v4;
  144.     v4 += 2;
  145.   }
  146.   while ( v6 );
  147.   v7 = ((v4 - v5) >> 1) + 24;
  148.   v8 = (wchar_t *)operator new[](2 * v7);
  149.   Dst = v8;
  150.   if ( v8 )
  151.   {
  152.     wcscpy_s(v8, v7, L"Local\\Oberon_");
  153.     v10 = (const wchar_t *)(*(int (__thiscall **)(struct IEngineInterface *))(*(_DWORD *)a1 + 16))(a1);//EngineHandler::GetProjectName
  154.     wcscat_s(Dst, v7, v10);
  155.     wcscat_s(Dst, v7, L"_Singleton");
  156.     v11 = CreateMutexW(0, 1, Dst);
  157.     operator delete(Dst);
  158.     if ( v11 )
  159.     {
  160.       if ( GetLastError() != 183 )
  161.       {
  162.         v15 = GetCommandLineW();
  163.         pNumArgs = 0;
  164.         v16 = CommandLineToArgvW(v15, &pNumArgs);
  165.         v17 = 1;
  166.         pv = v16;
  167.         v73 = 1;
  168.         if ( pNumArgs > 1 )
  169.         {
  170.           do
  171.           {
  172.             if ( !wcscmp(*((const unsigned __int16 **)pv + v17), L"-mce") )
  173.               g_bMediaCenter = 1;
  174.             v17 = v73++ + 1;
  175.           }
  176.           while ( (signed int)v73 < pNumArgs );
  177.         }
  178.         v18 = GetCommandLineW();
  179.         RegisterApplicationRestart(v18, 0);
  180.         CoInitialize(0);
  181.         v76 = 0;
  182.         Dst = 0;
  183.         v79 = 0;
  184.         if ( CoCreateInstance(
  185.                &_GUID_9a5ea990_3034_4d6f_9128_01f3c61022bc,
  186.                0,
  187.                1u,
  188.                &_GUID_e7b2fb72_d728_49b3_a5f2_18ebf5f1349e,
  189.                (LPVOID *)&Dst) >= 0
  190.           && SHGetFolderPathEx(&FOLDERID_ProgramFiles, 0, 0, &psz, 260) >= 0 )
  191.         {
  192.           v19 = (const unsigned __int16 *)(*(int (__thiscall **)(struct IEngineInterface *))(*(_DWORD *)a1 + 84))(a1);//EngineHandler::GetGdfPath
  193.           if ( StringCchCatW(&psz, 0x104u, v19) >= 0 )
  194.           {
  195.             v20 = SysAllocString(&psz);
  196.             g_bstrGDFPath = v20;
  197.             if ( v20 )
  198.             {
  199.               if ( SysStringLen(v20)
  200.                 && (*(int (__stdcall **)(wchar_t *, unsigned __int16 *, void **))(*(_DWORD *)Dst + 24))(//CGameExplorer::VerifyAccess
  201.                      Dst,
  202.                      g_bstrGDFPath,
  203.                      &pv) >= 0
  204.                 && pv )
  205.                 v76 = 1;
  206.             }
  207.           }
  208.         }
  209.         v79 = -1;
  210.         if ( Dst )
  211.           (*(void (__stdcall **)(wchar_t *))(*(_DWORD *)Dst + 8))(Dst);
  212.         if ( !v76 )
  213.           CleanupEngine(5);
  214.         v21 = operator new(4u);
  215.         if ( v21 )
  216.         {
  217.           *(_DWORD *)v21 = 0;
  218.           g_pSecondTimerCallback = v21;
  219.         }
  220.         else
  221.         {
  222.           g_pSecondTimerCallback = 0;
  223.         }
  224.         _set_new_handler(HandleNewFail);
  225.         _set_new_mode(1);
  226.         g_pInterface = (void *)a1;
  227.         v22 = (wchar_t *)(*(int (__thiscall **)(struct IEngineInterface *))(*(_DWORD *)a1 + 16))(a1);
  228.         g_wszProjectName = LocalizeMessage(v22);
  229.         v23 = GetModuleFileNameW(0, Filename, 0x200u);
  230.         for ( i = v23 - 1; ; --i )
  231.         {
  232.           if ( i > v23 )
  233.             goto LABEL_38;
  234.           v25 = Filename[i];
  235.           if ( v25 == 47 || v25 == 92 )
  236.             break;
  237.         }
  238.         Filename[i] = 0;
  239. LABEL_38:
  240.         SetCurrentDirectoryW(Filename);
  241.         XmlNode::SetNodeName((XmlNode *)&ErrorXml, L"ErrorLog");
  242.         v26 = operator new(0x10u);
  243.         pv = v26;
  244.         v79 = 1;
  245.         if ( v26 )
  246.           v27 = (XmlManager *)XmlManager::XmlManager((XmlManager *)v26);
  247.         else
  248.           v27 = 0;
  249.         v79 = -1;
  250.         g_pXmlManager = v27;
  251.         CheckAllocation((const void *)v27);
  252.         ResourceBase::SetNameForDPI(v28, (bool)g_wszProjectName);
  253.         Log(0x10u, 1129, "Engine.cpp", L"Initializing Virtual FS");
  254.         if ( ResourceWMA::LoadAsNeeded(v29) )
  255.         {
  256.           Log(0x10u, 1138, "Engine.cpp", L"Project name localized to: %s", g_wszProjectName);
  257.           OutputDebugStringW(Filename);
  258.           Log(0x10u, 1142, "Engine.cpp", L"Using working directory: %s", Filename);
  259.           Log(0x10u, 1146, "Engine.cpp", L"Initializing GDI+");
  260.           v56 = 1;
  261.           v58 = 1;
  262.           v57 = 0;
  263.           v59 = 0;
  264.           GdiplusStartup(&g_GdiPlusToken, &v56, &v60);
  265.           v63 = 0;
  266.           v62 = 0;
  267.           LoadWindowPrefs(&v63, &v62);
  268.           pv = operator new(0x1440u);
  269.           v79 = 2;
  270.           if ( pv )
  271.             v30 = (DllFileMgr *)DllFileMgr::DllFileMgr(0);
  272.           else
  273.             v30 = 0;
  274.           v79 = -1;
  275.           ::pv = v30;
  276.           v31 = (wchar_t *)(**(int (***)(void))v71)();
  277.           Str::Str(v31);
  278.           v79 = 3;
  279.           v32 = DllFileMgr::Open(::pv, (const struct Str *)&pRawInputDevices, g_bDebugEnabled, L"input\");
  280.           v79 = -1;
  281.           v76 = v32 == 0;
  282.           Str::~Str((Str *)&pRawInputDevices);
  283.           if ( v76 )
  284.           {
  285.             D3DXTex::TF_Row::TF_Row((D3DXTex::TF_Row *)&pRawInputDevices);
  286.             v79 = 4;
  287.             v33 = *(wchar_t **)(Str::Str(0x37Cu) + 8);
  288.             v34 = *(int (***)(void))v71;
  289.             LOBYTE(v79) = 5;
  290.             v35 = (*v34)();
  291.             Str::Format((Str *)&pRawInputDevices, v33, v35);
  292.             LOBYTE(v79) = 4;
  293.             Str::~Str((Str *)&v54);
  294.             DialogHelper::ShowMessageBox(
  295.               0x385u,
  296.               0,
  297.               1u,
  298.               0xFFFEu,
  299.               0,
  300.               (const unsigned __int16 *)pRawInputDevices.hwndTarget,
  301.               (const unsigned __int16 *)1,
  302.               (bool)v52);
  303.           }
  304.           else if ( CreateGameWindow() )
  305.           {
  306.             if ( g_bMediaCenter )
  307.             {
  308.               Log(0x10u, 1211, "Engine.cpp", L"Initializing MCE Dialog");
  309.               DialogHelper::InitMCE(0, v52);
  310.               if ( g_bMediaCenter )
  311.               {
  312.                 Log(0x10u, 1220, "Engine.cpp", L"Registering for raw input, for remote control");
  313.                 pRawInputDevices.usUsagePage = 12;
  314.                 pRawInputDevices.usUsage = 1;
  315.                 pRawInputDevices.hwndTarget = g_hWnd;
  316.                 pRawInputDevices.dwFlags = 0;
  317.                 if ( !RegisterRawInputDevices(&pRawInputDevices, 1u, 0xCu) )
  318.                 {
  319.                   v36 = GetLastError();
  320.                   Log(0x10u, 1231, "Engine.cpp", L"Register failed, winerror %d", v36);
  321.                 }
  322.               }
  323.             }
  324.             Log(0x10u, 1237, "Engine.cpp", L"Adding system events");
  325.             Event::RegisterEventType(2, Event_MouseEnter::Create);
  326.             Event::RegisterEventType(4, Event_MouseDown::Create);
  327.             Event::RegisterEventType(5, Event_MouseDoubleClick::Create);
  328.             Event::RegisterEventType(3, Event_MouseLeave::Create);
  329.             Event::RegisterEventType(6, Event_MouseRelease::Create);
  330.             Event::RegisterEventType(7, Event_MouseReleaseOut::Create);
  331.             Event::RegisterEventType(8, Event_MouseStatusBarClick::Create);
  332.             Event::RegisterEventType(9, Event_MouseOuterDown::Create);
  333.             Event::RegisterEventType(10, Event_MouseOuterRelease::Create);
  334.             Event::RegisterEventType(11, Event_MouseGlobalRelease::Create);
  335.             Event::RegisterEventType(1, Event_ButtonClick::Create);
  336.             Event::RegisterEventType(13, Event_AnimationComplete::Create);
  337.             Event::RegisterEventType(12, Event_AnimationFrame::Create);
  338.             Event::RegisterEventType(14, Event_AnimationInt::Create);
  339.             Event::RegisterEventType(15, Event_Timer::Create);
  340.             Event::RegisterEventType(16, Event_FocusCheck::Create);
  341.             Event::RegisterEventType(17, Event_FocusGot::Create);
  342.             Event::RegisterEventType(18, Event_FocusLost::Create);
  343.             Event::RegisterEventType(19, Event_FocusSelect::Create);
  344.             Event::RegisterEventType(20, Event_FocusUnSelect::Create);
  345.             Event::RegisterEventType(21, Event_FocusGetNodeAtDir::Create);
  346.             Event::RegisterEventType(22, Event_FocusGetNextTabNode::Create);
  347.             Event::RegisterEventType(23, Event_InitComplete::Create);
  348.             Event::RegisterEventType(24, Event_DoDefaultAction::Create);
  349.             Event::RegisterEventType(25, Event_DragCheck::Create);
  350.             Event::RegisterEventType(26, Event_DragStart::Create);
  351.             Event::RegisterEventType(27, Event_DragMove::Create);
  352.             Event::RegisterEventType(28, Event_DragEnd::Create);
  353.             Event::RegisterEventType(29, Event_KeyDown::Create);
  354.             Event::RegisterEventType(30, Event_KeyUp::Create);
  355.             Event::RegisterEventType(31, Event_AccessGetParent::Create);
  356.             Event::RegisterEventType(32, Event_AccessGetChildCount::Create);
  357.             Event::RegisterEventType(33, Event_AccessGetChild::Create);
  358.             Event::RegisterEventType(34, Event_TipClose::Create);
  359.             Event::RegisterEventType(37, Event_DpiChange::Create);
  360.             Event::RegisterEventType(35, Event_ControllerKey::Create);
  361.             Log(0x10u, 1280, "Engine.cpp", L"Registering Node Types");
  362.             NodeButton::Register();
  363.             NodeLabel::Register();
  364.             NodeBase::Register();
  365.             NodeSprite::Register();
  366.             NodeEmitter::Register();
  367.             NodeShot::Register();
  368.             NodeNumber::Register();
  369.             Log(0x10u, 1291, "Engine.cpp", L"Initializing Timekeeping");
  370.             if ( Timekeeping::InitializeTimekeeping((Timekeeping *)v52) )
  371.             {
  372.               DialogHelper::SetDialogShutdownCallback((DialogHelper *)Engine_ResetTimer, v53);
  373.               Log(0x10u, 1304, "Engine.cpp", L"Initializing ResourceManager");
  374.               v37 = operator new(0x54u);
  375.               pv = v37;
  376.               v79 = 6;
  377.               if ( v37 )
  378.                 v38 = (ResourceManager *)ResourceManager::ResourceManager(v37);
  379.               else
  380.                 v38 = 0;
  381.               v79 = -1;
  382.               g_pResourceManager = v38;
  383.               CheckAllocation((const void *)v38);
  384.               if ( ResourceManager::Initialize(g_pResourceManager) )
  385.               {
  386.                 v65 = 0;
  387.                 v66 = 0;
  388.                 v68 = 0;
  389.                 v64 = g_hRenderWindow;
  390.                 LOWORD(v68) = 0;
  391.                 v67 = 32;
  392.                 (*(void (__stdcall **)(int *, int *))(*(_DWORD *)g_pInterface + 12))(&v65, &v66);
  393.                 if ( g_bDoubleDPI )
  394.                 {
  395.                   v65 *= 2;
  396.                   v66 *= 2;
  397.                 }
  398.                 Log(0x10u, 1331, "Engine.cpp", L"Initializing RenderManager");
  399.                 v39 = operator new(0x90u);
  400.                 pv = v39;
  401.                 v79 = 7;
  402.                 if ( v39 )
  403.                   v40 = (RenderManager *)RenderManager::RenderManager(v39);
  404.                 else
  405.                   v40 = 0;
  406.                 v79 = -1;
  407.                 g_pRenderManager = v40;
  408.                 CheckAllocation((const void *)v40);
  409.                 if ( RenderManager::Initialize(g_pRenderManager, (const struct RenderInitializeOptions *)&v64) )
  410.                 {
  411.                   Log(0x10u, 1342, "Engine.cpp", L"Initializing Audio");
  412.                   v41 = operator new(0x28u);
  413.                   pv = v41;
  414.                   v79 = 8;
  415.                   if ( v41 )
  416.                     v42 = (Audio *)Audio::Audio(v41);
  417.                   else
  418.                     v42 = 0;
  419.                   v79 = -1;
  420.                   g_pAudio = v42;
  421.                   CheckAllocation((const void *)v42);
  422.                   if ( Audio::Initialize(g_pAudio) )
  423.                   {
  424.                     Log(0x10u, 1354, "Engine.cpp", L"Initializing XNA Common Controller");
  425.                     pv = operator new(0x80u);
  426.                     v79 = 9;
  427.                     if ( pv )
  428.                       v43 = (CommonControllerThread *)CommonControllerThread::CommonControllerThread(
  429.                                                         (int)g_hWnd,
  430.                                                         g_bMediaCenter,
  431.                                                         (int)v72);
  432.                     else
  433.                       v43 = 0;
  434.                     v79 = -1;
  435.                     g_pCommonController = v43;
  436.                     Thread::Begin(v43);
  437.                     Log(0x10u, 1361, "Engine.cpp", L"Initializing Timer");
  438.                     v44 = operator new(0x34u);
  439.                     if ( v44 )
  440.                       v45 = (ResourceWMA *)Timer::Timer(v44);
  441.                     else
  442.                       v45 = 0;
  443.                     g_pTimer = v45;
  444.                     CheckAllocation((const void *)v45);
  445.                     if ( ResourceWMA::LoadAsNeeded(g_pTimer) )
  446.                     {
  447.                       Log(0x10u, 1372, "Engine.cpp", L"Loading Fonts");
  448.                       v46 = XmlManager::GetXml(g_pXmlManager, L"xml\\Fonts.xml");
  449.                       if ( v46 )
  450.                       {
  451.                         pv = XmlNode::XPathElementSearch(v46, L"/Font", &v73);
  452.                         Log(0x10u, 1383, "Engine.cpp", L"%d Fonts Found", v73);
  453.                         for ( Dst = 0; (unsigned int)Dst < v73; Dst = (wchar_t *)((char *)Dst + 1) )
  454.                         {
  455.                           v47 = XmlNode::GetNodeValue(*((XmlNode **)pv + (_DWORD)Dst));
  456.                           Log(0x10u, 1388, "Engine.cpp", L"Loading Font: %s", v47);
  457.                           if ( AddFontResourceW(v47) )
  458.                           {
  459.                             Array<NodeBase *>::Add(v47);
  460.                           }
  461.                           else
  462.                           {
  463.                             Log(0x10u, 1412, "Engine.cpp", L"Couldn't add font: %s", v47);
  464.                             operator delete(v47);
  465.                           }
  466.                         }
  467.                         operator delete(pv);
  468.                       }
  469.                       else
  470.                       {
  471.                         Log(0x10u, 1426, "Engine.cpp", L"No Font Xml Found");
  472.                       }
  473.                       Log(0x10u, 1431, "Engine.cpp", L"Registering for session notification");
  474.                       WTSRegisterSessionNotification(g_hWnd, 0);
  475.                       v72 = XmlManager::GetXml(g_pXmlManager, L"engine.xml");
  476.                       g_bInInitializer = 1;
  477.                       Log(0x10u, 1439, "Engine.cpp", L"Engine Initialization Complete: Initializing Game Code.");
  478.                       v48 = v71;
  479.                       if ( !(unsigned __int8)(*(int (__thiscall **)(struct IEngineInterface *))(*(_DWORD *)v71 + 48))(v71) )
  480.                       {
  481.                         Log(0x10u, 1442, "Engine.cpp", L"Game code initialization failed.");
  482.                         CleanupEngine(0);
  483.                       }
  484.                       g_bInInitializer = 0;
  485.                       if ( v72 )
  486.                         g_bFocusPause = XmlNode::GetXmlInt(v72, L"/PauseOnLostFocus", -1) > 0;
  487.                       Engine_LoadingComplete();
  488.                       g_Accelerator = 0;
  489.                       if ( (*(int (__thiscall **)(struct IEngineInterface *))(*(_DWORD *)v48 + 40))(v48) )
  490.                       {
  491.                         v49 = (*(int (__thiscall **)(struct IEngineInterface *))(*(_DWORD *)v48 + 40))(v48);
  492.                         v50 = GetModuleHandleW(0);
  493.                         g_Accelerator = LoadAcceleratorsW(v50, (LPCWSTR)v49);
  494.                       }
  495.                       g_bInitializing = 0;
  496.                       v60(&g_GdiPlusToken);
  497.                       while ( 1 )
  498.                       {
  499.                         while ( !PeekMessageW(&Msg, 0, 0, 0, 0) )
  500.                           RunEngine();
  501.                         if ( !GetMessageW(&Msg, 0, 0, 0) )
  502.                           break;
  503.                         if ( !g_Accelerator || !TranslateAcceleratorW(g_hWnd, g_Accelerator, &Msg) )
  504.                         {
  505.                           TranslateMessage(&Msg);
  506.                           DispatchMessageW(&Msg);
  507.                         }
  508.                       }
  509.                       v61(g_GdiPlusToken);
  510.                       (*(void (__thiscall **)(struct IEngineInterface *))(*(_DWORD *)v48 + 72))(v48);
  511.                       CleanupEngine(0);
  512.                     }
  513.                     Log(0x10u, 1365, "Engine.cpp", L"Failed to initialize Timer");
  514.                   }
  515.                   else
  516.                   {
  517.                     Log(0x10u, 1346, "Engine.cpp", L"Failed to initialize Audio");
  518.                   }
  519.                 }
  520.                 else
  521.                 {
  522.                   Log(0x10u, 1335, "Engine.cpp", L"Failed to initialize RenderManager");
  523.                 }
  524.               }
  525.               else
  526.               {
  527.                 Log(0x10u, 1308, "Engine.cpp", L"Failed to initialize ResourceManager");
  528.               }
  529.             }
  530.             else
  531.             {
  532.               Log(0x10u, 1294, "Engine.cpp", L"Failed to initialize timekeeping");
  533.             }
  534.           }
  535.           else
  536.           {
  537.             Log(0x10u, 1198, "Engine.cpp", L"Window Creation Failed");
  538.           }
  539.         }
  540.         else
  541.         {
  542.           Log(0x10u, 1132, "Engine.cpp", L"InitOberVFS() Failed");
  543.         }
  544.         CleanupEngine(0);
  545.       }
  546.       v12 = (wchar_t *)(*(int (__thiscall **)(struct IEngineInterface *))(*(_DWORD *)a1 + 16))(a1);
  547.       v13 = LocalizeMessage(v12);
  548.       v14 = FindWindowW(v13, 0);
  549.       LocalFree((HLOCAL)v13);
  550.       if ( v14 )
  551.       {
  552.         if ( IsIconic(v14) )
  553.           ShowWindow(v14, 10);
  554.         BringWindowToTop(v14);
  555.         SetForegroundWindow(v14);
  556.       }
  557.     }
  558.     ExitProcess(0);
  559.   }
  560.   return 0;
  561. }

  562. 可以发现,初始化了一个com组件,GUID=e7b2fb72_d728_49b3_a5f2_18ebf5f1349e(感兴趣可以在注册表CLSID中查,是个CGameExplorer类),可以看到最后一个参数获得了一个com对象,调用序列:
  563. EngineHandler::GetProjectName  return "MineSweeper.dll"
  564. CoCreateInstance(CGameExplorer)
  565. EngineHandler::GetGdfPath return "\\Microsoft Games\\Minesweeper\\Minesweeper.exe"
  566. CGameExplorer::VerifyAccess               这里会返回空,也是检测什么东西的,需要改返回值为0

  567. 改了这2处,就可以运行了!改法有很多,不说了
  568. 再来看结构,扫雷用C++写的,用到了XNA,可以找到棋牌类:
  569. void *__thiscall Board::Board(void *this, int a2, int a3, int a4, int a5, int a6, int a7, int a8, char a9)
  570. {
  571.   void *v9; // esi@1
  572.   unsigned int v10; // eax@1
  573.   int v12; // [sp-14h] [bp-30h]@7
  574.   int v13; // [sp-10h] [bp-2Ch]@7
  575.   unsigned int v14; // [sp-Ch] [bp-28h]@3
  576.   signed int v15; // [sp-8h] [bp-24h]@1
  577.   void *v16; // [sp+Ch] [bp-10h]@1
  578.   int v17; // [sp+18h] [bp-4h]@1

  579.   v9 = this;
  580.   v16 = this;
  581.   v15 = 16;
  582.   *(_DWORD *)this = &Board::`vftable';
  583.   Array<UITile *>::Array<UITile *>(v15);
  584.   *((float *)v9 + 7) = 0.0;
  585.   *((_DWORD *)v9 + 8) = a2;
  586.   *((_DWORD *)v9 + 1) = a5;
  587.   *((_DWORD *)v9 + 2) = a4;
  588.   *((_DWORD *)v9 + 3) = a3;
  589.   *((_DWORD *)v9 + 11) = a6;
  590.   *((_DWORD *)v9 + 9) = a7;
  591.   v17 = 0;
  592.   *((_DWORD *)v9 + 4) = 0;
  593.   *((_DWORD *)v9 + 5) = 0;
  594.   *((_DWORD *)v9 + 6) = 0;
  595.   *((_DWORD *)v9 + 16) = 0;
  596.   *((_DWORD *)v9 + 17) = 0;
  597.   *((_DWORD *)v9 + 10) = a8;
  598.   Board::initTiles((Board *)v9);
  599.   v10 = *((_DWORD *)v9 + 9);
  600.   if ( v10 != -1 && *((_DWORD *)v9 + 10) != -1 )
  601.   {
  602.     v15 = *((_DWORD *)v9 + 10);
  603.     v14 = v10;
  604.     if ( a9 )
  605.     {
  606.       Board::placeMines((Board *)v9, v14, v15);
  607.       ++*((_DWORD *)v9 + 6);
  608.     }
  609.     else
  610.     {
  611.       Board::AttemptReveal((Board *)v9, v14, v15);
  612.     }
  613.   }
  614.   if ( *((_DWORD *)v9 + 1) > *((_DWORD *)v9 + 3) * *((_DWORD *)v9 + 2) - 9 )
  615.   {
  616.     v15 = 1;
  617.     Str::Str(L"Too many mines for tile count");
  618.     StrErr(v12, v13, v14, v15);
  619.     *((_DWORD *)v9 + 1) = *((_DWORD *)v9 + 3) * *((_DWORD *)v9 + 2) - 9;
  620.   }
  621.   return v9;
  622. }

  623. 继续向上看,来到Game构造函数:
  624. void *__thiscall Game::Game(void *this)
  625. {
  626.   void *v1; // esi@1
  627.   int v2; // edi@1
  628.   int v3; // eax@1
  629.   int v4; // ST08_4@1
  630.   signed int v5; // eax@1
  631.   int v6; // ST08_4@1

  632.   v1 = this;
  633.   *(_DWORD *)this = &Game::`vftable';
  634.   Array<UITile *>::Array<UITile *>(16);
  635.   Array<UITile *>::Array<UITile *>(16);
  636.   Array<UITile *>::Array<UITile *>(16);
  637.   Array<UITile *>::Array<UITile *>(16);
  638.   Array<UITile *>::Array<UITile *>(16);
  639.   Array<UITile *>::Array<UITile *>(16);
  640.   v2 = (int)((char *)v1 + 152);
  641.   *(_DWORD *)v2 = 0;
  642.   *(_DWORD *)(v2 + 8) = 0;
  643.   *(_DWORD *)(v2 + 12) = 0;
  644.   GameStats::GameStats((char *)v1 + 168);
  645.   Game::G = (Game *)v1;
  646.   *((_DWORD *)v1 + 8) = -1;
  647.   *((_DWORD *)v1 + 9) = -1;
  648.   *((_DWORD *)v1 + 4) = 0;
  649.   *((_DWORD *)v1 + 3) = 0;
  650.   *((_DWORD *)v1 + 2) = 0;
  651.   *((_BYTE *)v1 + 218) = 0;
  652.   *((_DWORD *)v1 + 10) = 2;
  653.   *((_DWORD *)v1 + 12) = 0;
  654.   *((_DWORD *)v1 + 13) = 0;
  655.   *((_BYTE *)v1 + 197) = 0;
  656.   *((_BYTE *)v1 + 195) = 1;
  657.   *((_BYTE *)v1 + 193) = 0;
  658.   *((_BYTE *)v1 + 194) = 0;
  659.   *((_BYTE *)v1 + 196) = 0;
  660.   *((_BYTE *)v1 + 192) = 0;
  661.   *((_DWORD *)v1 + 47) = 0;
  662.   *((_BYTE *)v1 + 24) = 1;
  663.   *((_BYTE *)v1 + 25) = 1;
  664.   *((_BYTE *)v1 + 26) = 1;
  665.   *((_BYTE *)v1 + 27) = 1;
  666.   *((_BYTE *)v1 + 28) = 1;
  667.   *((_BYTE *)v1 + 29) = 1;
  668.   *((_BYTE *)v1 + 30) = 0;
  669.   *((_DWORD *)v1 + 50) = 1;
  670.   v3 = EDifficultyToWidth(1);
  671.   v4 = *((_DWORD *)v1 + 50);
  672.   *((_DWORD *)v1 + 51) = v3;
  673.   v5 = EDifficultyToHeight(v4);
  674.   v6 = *((_DWORD *)v1 + 50);
  675.   *((_DWORD *)v1 + 52) = v5;
  676.   *((_DWORD *)v1 + 53) = EDifficultyToMineCount(v6);
  677.   Game::RandomizeSeedOnTime((Game *)v1);
  678.   CSQMTimeRecorder::SetDataId((CSQMTimeRecorder *)((char *)v1 + 152), 0x17C7u);
  679.   Game::Reset((Game *)v1, 0, 0, 0);
  680.   Game::RequestSetState(v1, 0);
  681.   *((_BYTE *)v1 + 216) = 0;
  682.   *((_BYTE *)v1 + 217) = 0;
  683.   return v1;
  684. }

  685. EDifficultyToWidth和EDifficultyToHeight,分析可知是将默认难度级别转换为雷区阵列的高和宽,同理EDifficultyToMineCount是雷数
  686. 那么Game类结构:
  687. +200        Difficulty        1        2        3
  688. +204        Width                 9        16        16
  689. +208        Height                9        16        30
  690. +212        MineCount        10        40        99
  691. 再往上层看调用者:
  692. struct Game *__stdcall Game::SafeGetSingleton()
  693. {
  694.   void *v0; // ecx@2
  695.   Game *v1; // eax@3
  696.   int v3; // [sp-10h] [bp-2Ch]@6
  697.   int v4; // [sp-Ch] [bp-28h]@6
  698.   int v5; // [sp-8h] [bp-24h]@6
  699.   void *v6; // [sp+Ch] [bp-10h]@2
  700.   int v7; // [sp+18h] [bp-4h]@2

  701.   if ( !Game::G )
  702.   {
  703.     v0 = operator new(0xE0u);
  704.     v6 = v0;
  705.     v7 = 0;
  706.     if ( v0 )
  707.       v1 = (Game *)Game::Game(v0);
  708.     else
  709.       v1 = 0;
  710.     v7 = -1;
  711.     Game::G = v1;
  712.     if ( !v1 || (v6 = &v3, Str::Str(dword_10868FC), !(unsigned __int8)Game::initLogic(Game::G, v3, v4, v5)) )
  713.       Game::PrintFatalErrorAndQuit(103);
  714.   }
  715.   return Game::G;
  716. }
  717. 可见,Game是个单例类,构造的类指针存在了全局变量Game::G中,因此我们只要读取内存PE获取该结构相对.data段偏移,即可获取全部所需数据(或者调用SafeGetSingleton,只不过要定位.text段基址)

  718. 再来看 Game::Reset
  719. void __thiscall Game::Reset(Game *this, bool a2, bool a3, bool a4)
  720. {
  721.   Game *v4; // esi@1
  722.   int v5; // eax@2
  723.   int v6; // edi@5
  724.   double v7; // st7@6
  725.   int v8; // edi@7
  726.   int v9; // eax@8
  727.   int v10; // ecx@9
  728.   int v11; // eax@9
  729.   int v12; // ecx@14
  730.   int v13; // edi@15
  731.   void *v14; // eax@15
  732.   void *v15; // eax@16
  733.   bool v16; // di@18
  734.   void *v17; // ecx@19
  735.   int v18; // eax@22
  736.   void *v19; // eax@22
  737.   int v20; // [sp+18h] [bp-28h]@15
  738.   void *v21; // [sp+18h] [bp-28h]@21
  739.   int v22; // [sp+1Ch] [bp-24h]@15
  740.   int v23; // [sp+20h] [bp-20h]@7
  741.   int v24; // [sp+24h] [bp-1Ch]@9
  742.   int v25; // [sp+28h] [bp-18h]@9
  743.   int v26; // [sp+2Ch] [bp-14h]@13
  744.   char v27; // [sp+33h] [bp-Dh]@1

  745.   v4 = this;
  746.   Game::SetTimerEnabled(this, 0);
  747.   v27 = 0;
  748.   if ( !a3 )
  749.   {
  750.     v5 = *((_DWORD *)v4 + 4);
  751.     if ( v5 )
  752.     {
  753.       if ( *(_DWORD *)(v5 + 24) > 0 && *((_DWORD *)Game::G + 10) == 1 )
  754.       {
  755.         v6 = *(_DWORD *)(v5 + 32);
  756.         if ( v6 != 4 )
  757.         {
  758.           v7 = *(float *)(v5 + 28);
  759.           floorf(*(float *)(v5 + 28));
  760.           GameStats::AddNewScore((char *)v4 + 168, v6, (signed int)v7, 0);
  761.           Game::Save(Game::G, 0, 0);
  762.         }
  763.       }
  764.     }
  765.   }
  766.   v8 = *((_DWORD *)v4 + 50);
  767.   *((float *)v4 + 11) = 1.0;
  768.   v23 = v8;
  769.   if ( a3 && (v9 = *((_DWORD *)v4 + 4)) != 0 )
  770.   {
  771.     v23 = *(_DWORD *)(v9 + 32);
  772.     v24 = *(_DWORD *)(v9 + 12);
  773.     v10 = *(_DWORD *)(v9 + 8);
  774.     v11 = *(_DWORD *)(v9 + 4);
  775.     v25 = v10;
  776.   }
  777.   else if ( v8 == 4 )
  778.   {
  779.     v24 = *((_DWORD *)v4 + 51);
  780.     v25 = *((_DWORD *)v4 + 52);
  781.     v11 = *((_DWORD *)v4 + 53);
  782.   }
  783.   else
  784.   {
  785.     v24 = EDifficultyToWidth(v8);
  786.     v25 = EDifficultyToHeight(v8);
  787.     v11 = EDifficultyToMineCount(v8);
  788.   }
  789.   v26 = v11;
  790.   if ( a3 && (v12 = *((_DWORD *)v4 + 4)) != 0 )
  791.   {
  792.     v13 = *(_DWORD *)(v12 + 36);
  793.     v22 = *(_DWORD *)(v12 + 40);
  794.     v20 = *(_DWORD *)(v12 + 44);
  795.     Board::`scalar deleting destructor'((void *)v12, 1);
  796.     *((_DWORD *)v4 + 4) = 0;
  797.     v14 = operator new(0x48u);
  798.     if ( v14 )
  799.       v15 = Board::Board(v14, v23, v24, v25, v26, v20, v13, v22, 1);
  800.     else
  801.       v15 = 0;
  802.     *((_DWORD *)v4 + 4) = v15;
  803.     *((_DWORD *)v15 + 6) = 0;
  804.     Game::RandomizeSeedOnTime(v4);
  805.     v27 = 1;
  806.     v16 = 1;
  807.   }
  808.   else
  809.   {
  810.     v17 = (void *)*((_DWORD *)v4 + 4);
  811.     v16 = 1;
  812.     if ( v17 )
  813.     {
  814.       Board::`scalar deleting destructor'(v17, 1);
  815.       *((_DWORD *)v4 + 4) = 0;
  816.     }
  817.     v21 = operator new(0x48u);
  818.     if ( v21 )
  819.     {
  820.       v18 = _time(0);
  821.       v19 = Board::Board(v21, v23, v24, v25, v26, v18, -1, -1, 0);
  822.     }
  823.     else
  824.     {
  825.       v19 = 0;
  826.     }
  827.     *((_DWORD *)v4 + 4) = v19;
  828.   }
  829.   Game::SaveGameExplorerStatistics(v4);
  830.   *((_BYTE *)v4 + 217) = 0;
  831.   if ( !*((_BYTE *)v4 + 193) || !Game::RandomizeArt(v4, v16) )
  832.   {
  833.     if ( !a2 )
  834.       goto LABEL_33;
  835.     if ( *((_BYTE *)v4 + 27) )
  836.       UIBoardCanvas::SetAllTilesTopAlpha(*((UIBoardCanvas **)v4 + 3), 0);
  837.     Game::ResetCanvas(v4);
  838.   }
  839.   if ( a2 )
  840.   {
  841.     Game::RequestSetState(v4, 1);
  842.     UIBoardCanvas::Refresh(*((UIBoardCanvas **)v4 + 3), 1);
  843.     Game::DoNewBoardAnimation(v4);
  844.   }
  845. LABEL_33:
  846.   if ( v27 )
  847.     UIBoardCanvas::ShowTipMessage(*((UIBoardCanvas **)v4 + 3), L"Restart");
  848.   if ( a4 )
  849.   {
  850.     UserInterface::ProcessMouseMove(g_pUserInterface, v16);
  851.     Engine_ResetTimer();
  852.   }
  853.   if ( a3 )
  854.     *(_DWORD *)(*((_DWORD *)v4 + 4) + 24) = 1;
  855.   *((_BYTE *)v4 + 197) = 0;
  856. }

  857. 分析可知:
  858. Game:sizeof=224
  859. +8                DWORD
  860. +12                UIBoardCanvas *
  861. +16                Board*
  862. +24                bool
  863. +25                bool
  864. +26                bool
  865. +27                bool
  866. +28                bool
  867. +29                bool
  868. +30                bool
  869. +32                int
  870. +36                int
  871. +40                int state
  872. +48                DWORD
  873. +52                DWORD
  874. +56                Array<UITile *>*
  875. +72                Array<UITile *>*
  876. +88                Array<UITile *>*
  877. +104        Array<UITile *>*
  878. +120        Array<UITile *>*
  879. +136        Array<UITile *>*
  880. +152        CSQMTimeRecorder*
  881. +188        DWORD
  882. +192        bool
  883. +193        bool
  884. +194        bool
  885. +195        bool
  886. +196        bool
  887. +197        bool

  888. +200        Difficulty       
  889. +204        Width                
  890. +208        Height               
  891. +212        MineCount       
  892. +216        bool
  893. +217        bool
  894. +218        bool IsTimerEnabled

  895. Board:sizeof=72
  896. +4                MineCount
  897. +8                Height
  898. +12                Width
  899. +24                是否挖过雷?
  900. +28                float
  901. +32                Difficulty       
  902. +36                HitX
  903. +40                HitY
  904. +44
  905. +68                Array<Array<BYTE>>* MineArray

  906. Array<UITile *>:sizeof=16
  907. +0                MineCount
  908. +4
  909. +8
  910. +12                DWORD[]        MineIndexArray//存储雷位置索引

  911. UITile:
  912. +36                state

  913. void __thiscall Board::placeMines(Board *this, int a2, int a3)
  914. {//布置雷区
  915.   Board *v3; // esi@1
  916.   int v4; // eax@1
  917.   int i; // edi@4
  918.   signed int v6; // ecx@5
  919.   int v7; // eax@9
  920.   int v8; // edi@10
  921.   unsigned int v9; // ebx@13
  922.   unsigned int v10; // ecx@15
  923.   signed int v11; // ebx@16
  924.   int v12; // eax@16
  925.   int v13; // edx@16
  926.   unsigned int Seed; // [sp+Ch] [bp-8h]@1
  927.   int pv; // [sp+10h] [bp-4h]@2

  928.   v3 = this;
  929.   Seed = GetRandomSeed();
  930.   SetRandomSeed(*((_DWORD *)v3 + 11));
  931.   v4 = (int)operator new(0x10u);
  932.   if ( v4 )
  933.     pv = Array<UITile *>::Array<UITile *>(v4, 16);
  934.   else
  935.     pv = 0;
  936.   for ( i = 0; i < *((_DWORD *)v3 + 3) * *((_DWORD *)v3 + 2); ++i )
  937.   {
  938.     v6 = *((_DWORD *)v3 + 3);
  939.     if ( (i % v6 - a2) * (2 * (i % v6 - a2 >= 0) - 1) > 1 || (i / v6 - a3) * (2 * (i / v6 - a3 >= 0) - 1) > 1 )//取第一次点击位置以外的雷区位置,存到数组array1里,这样设计就不会导致第一次就点到雷
  940.       Array<NodeBase *>::Add(pv, i);
  941.   }
  942.   v7 = (int)operator new(0x10u);
  943.   if ( v7 )
  944.     v8 = Array<UITile *>::Array<UITile *>(v7, *((_DWORD *)v3 + 1));
  945.   else
  946.     v8 = 0;
  947.   while ( *(_DWORD *)v8 != *((_DWORD *)v3 + 1) && *(_DWORD *)pv )
  948.   {//若雷数不够且array1没被用完就一直布雷
  949.     v9 = GetRandom(0, *(_DWORD *)pv - 1);//rand(0,array1.size()-1)
  950.     Array<NodeBase *>::Add(v8, *(_DWORD *)(*(_DWORD *)(pv + 12) + 4 * v9));//在array2中增加该位置
  951.     Array<NodeBase *>::Remove(pv, v9);//从array1中去除该位置
  952.   }
  953.   v10 = 0;
  954.   if ( *(_DWORD *)v8 )
  955.   {
  956.     do
  957.     {
  958.       v11 = *((_DWORD *)v3 + 3);
  959.       v12 = *(_DWORD *)(*(_DWORD *)(v8 + 12) + 4 * v10) / v11;
  960.       v13 = *(_DWORD *)(*(_DWORD *)(v8 + 12) + 4 * v10++) % v11;//分别还原横纵坐标
  961.       *(_BYTE *)(v12 + *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*((_DWORD *)v3 + 17) + 12) + 4 * v13) + 12)) = 1;//可以推测出将布雷坐标数组存到Array<Array<BYTE>>二维数组里
  962.     }
  963.     while ( v10 < *(_DWORD *)v8 );
  964.   }
  965.   Array<int>::`scalar deleting destructor'((void *)v8, 1);
  966.   if ( pv )
  967.     Array<int>::`scalar deleting destructor'((void *)pv, 1);
  968.   SetRandomSeed(Seed);
  969. }


  970. 向上层找:
  971. int __thiscall Board::AttemptReveal(Board *this, unsigned int a2, unsigned int a3)
  972. {
  973.   Board *v3; // esi@1
  974.   int v4; // eax@1
  975.   int v5; // eax@6
  976.   unsigned int *v7; // [sp+0h] [bp-10h]@0
  977.   int v8; // [sp+Ch] [bp-4h]@1

  978.   v3 = this;
  979.   v4 = *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*((_DWORD *)this + 16) + 12) + 4 * a2) + 12) + 4 * a3);
  980.   v8 = 0;
  981.   if ( v4 == 9 || v4 == 11 )
  982.   {
  983.     if ( *((_DWORD *)this + 6) )
  984.     {
  985.       if ( *(_BYTE *)(a3 + *(_DWORD *)(*(_DWORD *)(*(_DWORD *)(*((_DWORD *)this + 17) + 12) + 4 * a2) + 12)) )
  986.       {
  987.         v8 = 0;
  988. LABEL_11:
  989.         ++*((_DWORD *)v3 + 6);
  990.         goto LABEL_12;
  991.       }
  992.       v5 = Board::revealAt(this, a2, a3, 0, a2, a3, 0);
  993.     }
  994.     else
  995.     {
  996.       Board::placeMines(this, a2, a3);//如果是首次挖雷,则布雷
  997.       v5 = Board::revealAt(v3, a2, a3, 0, a2, a3, 0);
  998.       *((_DWORD *)v3 + 9) = a2;
  999.       *((_DWORD *)v3 + 10) = a3;//存储点击位置
  1000.     }
  1001.     v8 = v5;
  1002.     goto LABEL_11;
  1003.   }
  1004.   if ( *((_BYTE *)Game::G + 24) )
  1005.     GameAudio::PlaySoundProto(0, 0, 0, v7);
  1006. LABEL_12:
  1007.   if ( *((_DWORD *)v3 + 12) <= 0u )
  1008.     UIBoardCanvas::Refresh(*((UIBoardCanvas **)Game::G + 3), 1);
  1009.   return v8;
  1010. }

  1011. 至此,想得到的结果已经都得到
  1012. 这里只研究了很普通的一些属性,然而代码中却有很多可以挖掘的地方,请自行研究!
复制代码


根据以上分析可以得到代码:
  1. template<typename T>
  2. struct Array
  3. {
  4.         DWORD MineCount;
  5.         DWORD unused1;
  6.         DWORD unused2;
  7.         T* data;
  8. };

  9. #include <TlHelp32.h>
  10. void CWin7MineSweeperHackerDlg::OnBnClickedOk()
  11. {
  12.         // TODO: 在此添加控件通知处理程序代码
  13.         UpdateData(TRUE);
  14.         m_output="";
  15.         PROCESSENTRY32 pe;
  16.         pe.dwSize=sizeof(PROCESSENTRY32);
  17.         HANDLE hProcess=NULL;
  18.         HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  19.         if(hSnapshot == INVALID_HANDLE_VALUE || !Process32First(hSnapshot,&pe))
  20.         {
  21.                 AfxMessageBox("ERROR!");
  22.                 return;
  23.         }
  24.         do
  25.         {
  26.                 if(StrStr(pe.szExeFile,"MineSweeper.exe"))
  27.                 {
  28.                         hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pe.th32ProcessID);
  29.                         break;
  30.                 }
  31.         }
  32.         while(Process32Next(hSnapshot,&pe));
  33.         CloseHandle(hSnapshot);
  34.         if(hProcess == NULL)
  35.         {
  36.                 AfxMessageBox("找不到进程!");
  37.                 return;
  38.         }

  39.         MODULEENTRY32 me;
  40.         me.dwSize=sizeof(MODULEENTRY32);
  41.         LPVOID peBase=NULL;
  42.         DWORD peSize;
  43.         hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pe.th32ProcessID);
  44.         if(hSnapshot == NULL || !Module32First(hSnapshot,&me))
  45.         {
  46.                 AfxMessageBox("ERROR");
  47.                 return;
  48.         }

  49.         do
  50.         {
  51.                 if(StrStrI(me.szModule,"mine"))
  52.                 {
  53.                         peBase=(LPVOID)me.modBaseAddr;
  54.                         peSize=me.modBaseSize;
  55.                         break;
  56.                 }
  57.         } while (Module32Next(hSnapshot,&me));
  58.         CloseHandle(hSnapshot);

  59.         if(peBase == NULL)
  60.         {               
  61.                 AfxMessageBox("ERROR");
  62.                 return;
  63.         }

  64.         BYTE* buffer=new BYTE[peSize];
  65.         DWORD readnum;
  66.         ReadProcessMemory(hProcess,peBase,buffer,peSize,&readnum);
  67.         IMAGE_DOS_HEADER* dosheader=(IMAGE_DOS_HEADER*)buffer;
  68.         IMAGE_NT_HEADERS* ntheader=(IMAGE_NT_HEADERS*)(buffer+dosheader->e_lfanew);
  69.         IMAGE_SECTION_HEADER* cur=(IMAGE_SECTION_HEADER*)(ntheader+1);
  70.         for(int i=0;i<ntheader->FileHeader.NumberOfSections;i++)
  71.         {
  72.                 if(StrStrI((CHAR*)cur->Name,".data"))
  73.                 {
  74.                         break;
  75.                 }
  76.                 cur++;
  77.         }
  78.         struct Board;
  79.         struct Game
  80.         {
  81.                 DWORD unused[4];
  82.                 struct Board* board;
  83.         };
  84.         struct Board
  85.         {
  86.                 DWORD unused1;
  87.                 DWORD MineCount;
  88.                 DWORD Height;
  89.                 DWORD Width;
  90.                 DWORD unused2[4];
  91.                 DWORD Difficulty;
  92.                 DWORD HitX;
  93.                 DWORD HitY;
  94.                 DWORD unused3[6];
  95.                 Array< Array<BYTE> >* MineArray;
  96.         };
  97.        
  98.         BYTE* GameInThatProc = (BYTE*)*(Game**)(buffer + cur->VirtualAddress + 0x88B4);
  99.         //换算成本地地址
  100.         Game G;
  101.         if (GameInThatProc == NULL)
  102.         {
  103.                 AfxMessageBox("数据有误");
  104.                 goto end1;
  105.         }
  106.         ReadProcessMemory(hProcess, GameInThatProc, &G, sizeof(G), &readnum);
  107.         //换算成本地地址
  108.         Board B;
  109.         if (G.board == NULL)
  110.         {
  111.                 AfxMessageBox("数据有误");
  112.                 return;
  113.         }
  114.         ReadProcessMemory(hProcess, G.board, &B, sizeof(B), &readnum);
  115.         Array< Array<BYTE> > MA;
  116.         if (B.MineArray == NULL)
  117.         {
  118.                 AfxMessageBox("数据有误");
  119.                 goto end1;
  120.         }
  121.         ReadProcessMemory(hProcess, B.MineArray, &MA, sizeof(MA), &readnum);
  122.         typedef Array<BYTE>* pMAsub;//先取指针数组
  123.         pMAsub* data1 = new pMAsub[B.Width];
  124.         if (MA.data == NULL)
  125.         {
  126.                 AfxMessageBox("数据有误");
  127.                 goto end1;
  128.         }
  129.         ReadProcessMemory(hProcess, MA.data, data1, sizeof(Array<BYTE>*) * B.Width, &readnum);

  130.         for(int i=0;i<B.Width;i++)
  131.         {
  132.                 Array<BYTE> data2;//对指针数组每个指针找到对象内存
  133.                 ReadProcessMemory(hProcess, data1[i], &data2, sizeof(data2), &readnum);
  134.                 if (data2.data == NULL)
  135.                 {
  136.                         AfxMessageBox("数据有误");
  137.                         goto end1;
  138.                 }
  139.                 BYTE* data3 = new BYTE[B.Height];
  140.                 ReadProcessMemory(hProcess, data2.data, data3, sizeof(BYTE) * B.Height, &readnum);

  141.                 for(int j=0;j<B.Height;j++)
  142.                 {
  143.                         if(data3[j] == 1)//雷
  144.                         {
  145.                                 m_output += "雷";
  146.                         }
  147.                         else
  148.                         {
  149.                                 m_output += "空";
  150.                         }
  151.                 }
  152.                 delete[]data3;
  153.                 m_output += "\r\n";
  154.         }

  155.         delete[]data1;

  156. end1:
  157.         delete []buffer;
  158.         CloseHandle(hProcess);
  159.         UpdateData(FALSE);
  160. }
复制代码


新开一局扫雷,可以发现程序获取结果:
空空空空空空空空空
空空空空空空空空空
空空空空空空空空空
空空空空空空空空空
空空空空空空空空空
空空空空空空空空空
空空空空空空空空空
空空空空空空空空空
空空空空空空空空空

可见,没点击前,是不布雷的,和之前分析的一样
点击以后:
空雷空空空空空空空
空雷空空空空空空空
空空空空空空空空空
空空雷空雷空空空空
空空雷空空空空空空
空空空空空空空空空
雷雷空空空空空空空
空空雷空空空空空空
雷空空空雷空空空空

特别注意,,由于程序中使用的数据结构原因,得到的结果,和扫雷屏幕上显示,关于y=x对称!!!

回复

使用道具 举报

307

主题

228

回帖

7337

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5587 个
贡献
253 次
宅之契约
0 份
在线时间
948 小时
注册时间
2014-1-25
 楼主| 发表于 2015-6-6 15:45:57 | 显示全部楼层
截图:截图




相关文件:
破解的win7扫雷,及工程文件:



http://pan.baidu.com/s/1o6xaPwI
回复 赞! 靠!

使用道具 举报

0

主题

76

回帖

6758

积分

用户组: 真·技术宅

UID
604
精华
0
威望
2 点
宅币
825 个
贡献
5853 次
宅之契约
0 份
在线时间
101 小时
注册时间
2014-12-20
发表于 2015-6-6 16:39:33 | 显示全部楼层
XP下的扫雷用C写的简直太好逆了. C++写的蛋疼多了.. 之前也是纠结为什么不能运行, 没去深入分析. LZ天天坚持练习发帖也是厉害.
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-20 14:46 , Processed in 0.047626 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表