MineCrack v1.0
Content:
This is a simple crack of the Microsoft XP and lower versions of
Minesweeper. The idea is to use the cheat 'xyzzy' + shift and to
crack the program. This is done by reviewing the pixel at 0,0 of
the screen, which sets to black and white for mine and no mine,
respectively. The program finds the handle for Minesweeperv and
then enters this cheat, reviews the pixel and either left clicks
or right clicks based on what the cheat is telling about the
Minesweeper board. The purpose of this was to learn more skills
in accessing other programs through Win32 API. The concepts
I was trying to learn were:
- Accessing processes through Win32 API
- Intermediate Usage of Win32 API
- Interacting with programs in C
- Intermediate C/C++ Usage
This tutorial should provide a demonstration of these learning objectives and can
prove to be useful in other types of programs, for example to brute force an open
process or finding buffer overflows, without manually entering the data. I hope
that the reader can benefit, and please, provide comments in the comment section
or through e-mail.
Start: Initializing Program
In this, I've included standard headers and initialized my window for Win32 API
as well as including general information about the program.
/*******************************************/
/** @version MineCrack v1.0 **/
/** @author Zachary D. Skelton **/
/** @link http://www.simplyskelton.com **/
/** @date 9/21/2009 **/
/** @email zbert|at|hotmail.com **/
/** **/
/** Description: This minesweeper crack **/
/** uses the 'xyzzy' cheat and then scans **/
/** the field, marking mines as it goes. **/
/*******************************************/
// TODO:
// 1. Fix the mine at 1,1 not being detected.
// 2. Create a stop event in crack loop.
// 3. Fix cheat post errors.
// 4. Make faster.
// 5. Options.
// USE:
// Open Minesweeper and run mineCrack.exe.
// If flags ar marked wrong, manually enter code and hold shift.
// Report errors to the author.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
Return to the Top
Start: Defining Variables
I started this with defining several variables that will be used as globals in
the program. The VK_* variables define a key/mouse button for input. The two
black and white varibles are used to match getPixel()'s data and the crackInfo
struct is used to store data. I plan to clean up my code by creating a better
loop function and will use this struct to pass varibales more efficiently.
/* CONSTANTS FOR KEY INPUT */
#define VK_x 0x58 // x key
#define VK_y 0x59 // y key
#define VK_z 0x5a // z key
#define VK_shft 0x10 // shift key
#define VK_flag 0x01 // left mouse button
#define VK_open 0x02 // right mouse button
/* GLOBAL VARIABLES */
const unsigned int black = 0x00000000;
const unsigned int white = 0x00ffffff;
/* STRUCT FOR CRACK INFO */
struct crackInfo {
int fieldSizeH;
int fieldSizeW;
int blockNumH;
int blockNumW;
int top;
int left;
RECT clnt;
};
typedef struct crackInfo CINFO;
Return to the Top
Start: Error Handling
General error handling and clean up functions to exit on all fatal functions that do
not work correctly.
/* CLEANING FUNCTION */
int clean(HDC s) {
// Release Screen.
if(!ReleaseDC(0,s)) {
printf("\n\n [*] ERRROR - Releasing Screen.\n");
exit(1);
}
// Done.
printf("\nPress ENTER to continue. . .\n");
getchar();
// Close.
return 0;
}
/* FAIL FUNCTION */
int die(char *msg) {
printf("\n\n [*] ERROR - %s\n",msg);
printf("\nPress ENTER to continue. . .\n");
getchar();
exit(1);
}
Return to the Top
Start: Start the Program
The first is the introduction that will be printed just for the start of the program.
/* PRINT INTRO */
void intro() {
if(system("cls"));
printf("|--------------------------------------------------------|\n");
printf("| | Welcome to Minesweeper Crack v1.0 | |\n");
printf("| |-----------------------------------| |\n");
printf("| By: zbert |\n");
printf("| Date: 9-21-2009 |\n");
printf("|--------------------------------------------------------|\n");
printf("\nStarted.\n");
}
Return to the Top
Data: Finding Minesweeper
These are two functions in this section of the program for data. The first fucntion is
the handle of the program "Minesweeper" if it is running. If it is not, the option is
given to open the window. Unfortunately, this does not find the program and is a known
bug that will be worked out in the next version. You'll notice that there is a Sleep()
call; this is just for aesthetics. The left over function for showing the window was
part of the function to bring the window to the front. This also is being currently
worked out in the next version.
The second function is to get the screen data and return the HDC handle. This is used
in collecting data of the pixel at screen location 0,0; which is where the cheat code
displays mine information.
/* CHECK FOR GAME PROCESS AND SHOW */
HWND init(void) {
int ans; // Store MessageBox answer.
// Find the handle.
printf("Finding Minesweeper...");
HWND h = FindWindow("Minesweeper",NULL);
if(!h) {
// Ask if to open and die on 'no'.
ans = MessageBox(0,
"Could not find minesweeper...\nDo you want to open it?",
"ERROR!",
MB_ICONERROR|MB_YESNO|MB_DEFBUTTON1);
if(ans==IDYES) {
ShellExecute(0,"open","C:\\WINDOWS\\system32\\winmine.exe",0,0,SW_SHOW);
HWND h = FindWindow("Minesweeper",NULL);
if(!h)
die("Tried, no luck on minesweeper... check install.");
} else {
die("Could not find minesweeper.");
}
}
Sleep(10);
printf("\t\tFOUND!\n");
// Show the handle.
printf("Showing Minesweeper...");
Sleep(10);
printf("\t\tSHOWN!\n");
// Return the handle.
return h;
}
/* GET SCREEN INFO */
HDC getScreen(void) {
// Define Screen
printf("Getting Screen data...");
HDC h = GetDC(0);
Sleep(10);
printf("\t\tGOT!\n");
// Return the screen.
return h;
}
Return to the Top
Data: Sending the Code
Two functions here, the first is postShift() which uses the win32 API
function PostMessage() to send the keys. This function is currently
has a bug that needs to be worked out, as shift is not sent.
The other function sends keys through the same win32 API function to
send the cheat code, 'xyzzy' as defined in the global varibales.
/* REPOST SHIFT */
void postShift(HWND h) {
// Show Window.
ShowWindow(h,SW_SHOWNORMAL);
// Post Shift, Pause, Release.
PostMessage(h,WM_KEYDOWN,VK_shft,1);
Sleep(500);
PostMessage(h,WM_KEYUP,VK_shft,1);
}
/* SEND CODE TO MINESWEEPER */
void sendCode(HWND h) {
ShowWindow(h, SW_SHOWNORMAL);
SetActiveWindow(h);
printf("Sending code ...");
PostMessage(h,WM_KEYDOWN,VK_x,1);
PostMessage(h,WM_KEYDOWN,VK_y,1);
PostMessage(h,WM_KEYDOWN,VK_z,1);
PostMessage(h,WM_KEYDOWN,VK_z,1);
PostMessage(h,WM_KEYDOWN,VK_y,1);
postShift(h);
printf("\t\tSENT!\n");
}
Return to the Top
Crack: Variables
These variables are what will be used in the main crack. The comments in the code
explain each one.
/* CRACK IT! */
int process(HWND h, HDC s) {
// Variables.
unsigned int clr; // Variable for Color Index.
int start = 1; // To run a setting once only.
int cX, cY; // Control for loop variables.
WINDOWINFO w; // Hold Window Information.
RECT clnt; // Hold Client Window data.
CINFO c; // Struct to hold all.
Return to the Top
Crack: Calculate Window
The next part of the crack starts with a call to GetWindowInfo() which fills the
WINDOWINFO struct. This data is used to calculate where to send the mouse. Next
the CINFO struct is filled with what will be needed in the crack. This struct's
purpose is to be used in a better efficient loop in a seperate function for the
next version of the program. Finally the debugging data is shown to verify field
size and the number of blocks.
// Set Window Info.
GetWindowInfo(h, &w);
clnt = w.rcClient;
// Calculate Distances.
c.fieldSizeW = (clnt.right - 8) - (clnt.left + 12);
c.fieldSizeH = (clnt.bottom - 8) - (clnt.top + 55);
c.blockNumH = c.fieldSizeH/16;
c.blockNumW = c.fieldSizeW/16;
c.top = clnt.top+55+8;
c.left = clnt.left+12+8;
c.clnt = clnt;
// Show Results.
printf("\nHeight: %d\tWidth: %d\n",c.fieldSizeH,c.fieldSizeW);
printf("\nThe Field is: %d x %d\n\n",c.blockNumH,c.blockNumW);
Return to the Top
Crack: Setup
In setting up the crack loop this part is used as a temporary fix for some problems
that I was having in activating the window correctly. It'll set the mouse one row
above and send a click to the window so that it brings the window in front of other
windows. This will be out of the next version when the bug is fixed.
// Set Process Variables.
cY = c.top - 16;
cX = c.clnt.right - 16;
// Activate Window.
SetCursorPos(cY,cX);
mouse_event(MOUSEEVENTF_LEFTDOWN,cX,cY,0,0);
mouse_event(MOUSEEVENTF_LEFTUP,cX,cY,0,0);
// Post Shift.
postShift(h);
Return to the Top
Crack: The Loop - 1
To begin the loop, it'll cycle from left to right, top to bottom. The bounds
were measured in the previous calculation section and loaded into the CINFO
struct.
// Loop Right to Left -- Top to Bottom.
while(cY < c.clnt.bottom-8) {
// Ensure cX is reset.
if(!start)
cX = c.left;
while(cX < c.clnt.right-8) {
Return to the Top
Crack: The Loop - 2
Each time the loop runs, SetCursorPos() will update the mouse to be over the next box
in Minesweeper. It has a short Sleep() function. Without this, the program does not
always collect the right pixel. Finally, GetPixel() is called to load the color into
the variable 'clr'. You'll notice it looks for start, this is to allow the activation
click in the step prior to the start of the loop.
// Get New Info.
SetCursorPos(cX,cY);
Sleep(1);
clr = GetPixel(s,0,0);
// Skip Start.
if(!start) {
Return to the Top
Crack: The Loop - 3
This is the heart of the crack! All variables are loaded and this runs the crack. The
variable clr is an unsigned long, returned by GetPixel(). Defined previously, black is
0x00000000 and white is 0x00ffffff as GetPixel() returns an RGB value in it's integer.
and then this value, loaded in 'clr' is checked. When outside the bounds, it's ignored
but then black will do a right click and white will do a left click. You can see a map
is drawn to the console, as this is great debugging information when it does not work.
if(!start) {
// Process Data.
switch(clr) {
case white: // No mine found.
mouse_event(MOUSEEVENTF_LEFTDOWN,cX,cY,0,0);
printf("[ ]");
mouse_event(MOUSEEVENTF_LEFTUP,cX,cY,0,0);
break;
case black: // Found a mine.
mouse_event(MOUSEEVENTF_RIGHTDOWN,cX,cY,0,0);
printf("[X]");
mouse_event(MOUSEEVENTF_RIGHTUP,cX,cY,0,0);
break;
default: // Out of bounds error.
break;
}
fflush(stdout);
}
Return to the Top
Crack: The Loop - 4
To close the loop, each Minesweeper box is 16 pixels, so the values are incremented
by 16 on each loop. The new line is printed as the program works it's way down for
the debugging map printed to the console.
// Reset x Variables.
cX += 16;
}
// Reset y Variables.
cY += 16;
printf("\n");
start = 0;
}
// Return.
return 0;
}
Return to the Top
Run: main()
Main function, kept clean and runs the program!
/* MAIN CONTROL */
int main() {
// Introduce.
intro();
// Set up Minesweeper.
HWND hWnd = init(); // Window Handler
// Get Screen.
HDC hdcScreen = getScreen(); // Screen Handler
// Send Code.
sendCode(hWnd);
// Process...
process(hWnd,hdcScreen);
// Clean up.
clean(hdcScreen);
// Done.
return 0;
}
Return to the Top
Closing and Summary
The idea for this program is that the cheat code for Minesweeper is well known but
to implement it takes a lot of time, manually. I felt that the use of Win32 API in
this program would allow me to expand my C/C++ skills in hooking and controlling a
program. The use of some of these functions is much more comfortable now and even
though there are several bugs, the programming has allowed me to be more comfortable
in using Win32 API to hook a program.
Where to go from here? The idea is to also use the data stored in memory through the
debugging functions used in Win32 API. The mines are mapped in memory and this can
be accessed to make a map of the mines and to provide hints or answers. I found the
program to be fairly simple to make and if anyone has comments, suggestions or any
questions, I openly invite you to contact me through the comments section on my site
or through e-mail, which is included in the source.
Thank You!
Return to the Top
Links
MSDN is the best resource for information on this API.
theForger's Win32 Guide is a great tutorial site.
FunctionX Win32 Guide GDI tutorials.
Code::Blocks is the IDE used for this program.
MingW32 is the compiler used for this program.
Return to the Top
Download:
Warning: The program has bugs. To use, ensure that Minesweeper is
open and that no other programs, activated or not can cover it. If
it runs and does not click or only left/right clicks, then manually
hold and release shift and restart the program.
README.txt
MineCrack v1.0
Zipped Version - Includes winmine.exe
Return to the Top
Skelton Networks ©2009