#include <windows.h>
// Microsoft Minesweeper Version 5.1
// Build 2600.xpsp_sp3_gdr.120411-1615 : Service Pack 3
// Other versions may need to change the respective memory addresses
#define ADR_WIDTH_X 0x1005334 // Memory address where map width X is stored
#define ADR_HEIGHT_Y 0x1005338 // Memory address where map height Y is stored
#define ADR_GAME_MAP 0x1005340 // Memory address of game map
#define MAX_HEIGHT_Y (24+2) // Max. Y height for Custom game
#define MAX_WIDTH_X (30+2) // Max. X width for Custom game
// Add 2 to include boundary data (0x10 value) of game map
#define MINE_VALUE 0x8F // value of a mine in game map
#define NO_MINE_VALUE 0x0F // value of a mine in game ap
#define FIRST_MINE_X 20 // First Mine X Location
#define FIRST_MINE_Y 62 // First Mine Y Location
#define STEP_X 16 // X step size between adjacent mines
#define STEP_Y 16 // Y step size between adjacent mines
// Function declaration
BOOL Process_Game(HWND hMineAppWnd,DWORD ProcessID);
// Global variables
char ProgramName[]="winmine.exe";
BYTE Game_Map[MAX_HEIGHT_Y*MAX_WIDTH_X];
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hAppWnd;
DWORD ProcID;
// Check whether Minesweeper is launched
hAppWnd = FindWindow("Minesweeper", NULL);
if (hAppWnd == NULL)
{
MessageBox(NULL,"Minesweeper Not Found ...","Minesweeper AutoBot",MB_OK);
return FALSE;
}
GetWindowThreadProcessId(hAppWnd, &ProcID);
if (Process_Game(hAppWnd,ProcID))
{
MessageBox(NULL,"Complete ...","Minesweeper AutoBot",MB_OK);
} else
{
MessageBox(NULL,"Error ...","Minesweeper AutoBot",MB_OK);
}
return 0;
}
Use IDA Pro to locate the respective memory addresses of Map Width X, Map Height Y and Map Data.
Use Winspy to obtain the PostMessage details for WM_LBUTTONDOWN, WM_LBUTTONUP.
// Minesweeper Hack II - DLL Inject Method
#include <windows.h>
// Microsoft Minesweeper Version 5.1
// Build 2600.xpsp_sp3_gdr.120411-1615 : Service Pack 3
#define ADR_WIDTH_X 0x1005334 // Memory address where map width X is stored
#define ADR_HEIGHT_Y 0x1005338 // Memory address where map height Y is stored
#define ADR_GAME_MAP 0x1005340 // Memory address of game map
#define MAX_HEIGHT_Y (24+2) // Max. Y height for Custom game
#define MAX_WIDTH_X (30+2) // Max. X width for Custom game
// Add 2 to include boundary data (0x10 value) of game map
#define MINE_VALUE 0x8F // value of a mine in game map
#define NO_MINE_VALUE 0x0F // value of a mine in game ap
#define FIRST_MINE_X 20 // First Mine X Location
#define FIRST_MINE_Y 62 // First Mine Y Location
#define STEP_X 16 // X step size between adjacent mines
#define STEP_Y 16 // Y step size between adjacent mines
// Function declaration
DWORD WINAPI GetKeyThread(LPVOID);
void __stdcall Process_Game(void);
// Global variables
BYTE Game_Map[MAX_HEIGHT_Y*MAX_WIDTH_X];
HMODULE g_hModule;
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hDLL);
g_hModule = hDLL;
CreateThread(NULL, NULL, &GetKeyThread, NULL, NULL, NULL);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
DWORD WINAPI GetKeyThread(LPVOID)
{
while(1)
{
// Set F3 as our hotkey to play game
// Set F4 as our hotkey to end hook
if(GetAsyncKeyState(VK_F3) & 1)
{
Process_Game();
}
else if(GetAsyncKeyState(VK_F4) & 1)
{
break;
}
Sleep(100);
}
FreeLibraryAndExitThread(g_hModule, 0);
return 0;
}
void __stdcall Process_Game(void)
{
DWORD Map_Width_X, Map_Height_Y;
DWORD x,y;
HWND hMineAppWnd;
POINT pt;
hMineAppWnd=FindWindow("Minesweeper", NULL);
// Read Width & Height of current game map
memcpy(&Map_Width_X,LPCVOID(ADR_WIDTH_X),4);
memcpy(&Map_Height_Y,LPCVOID(ADR_HEIGHT_Y),4);
// Read map data
memcpy(&Game_Map,LPCVOID(ADR_GAME_MAP),(MAX_HEIGHT_Y*MAX_WIDTH_X));
// x & y starts from 1 to skip the boundary data
for (x = 1; x <= Map_Width_X; x++)
{
for (y = 1; y <= Map_Height_Y; y++)
{
// No mine is found in this cell
if (Game_Map[x + y * 32] == NO_MINE_VALUE)
{
pt.x = FIRST_MINE_X + ((x-1)*STEP_X);
pt.y = FIRST_MINE_Y + ((y-1)*STEP_Y);
// Click cell
PostMessage(hMineAppWnd,WM_LBUTTONDOWN,0x1,MAKELPARAM(pt.x,pt.y));
PostMessage(hMineAppWnd,WM_LBUTTONUP,0,MAKELPARAM(pt.x,pt.y));
}
}
}
}