24
Apr
09

[C++] :Minesweeper: Toggle Mine Visibility

winmine.StartGame+74

010036EE   |.^\75 D7             JNZ SHORT winmine.010036C7              ;  if its not a mine, jmp back
010036F0   |.  C1E0 05           SHL EAX,5
010036F3   |.  8D8430 40530001   LEA EAX,DWORD PTR DS:[EAX+ESI+rgBlk]
010036FA       8008 80           OR BYTE PTR DS:[EAX],80                 ;  set the square to a mine
010036FD   |.  FF0D 30530001     DEC DWORD PTR DS:[cBombStart]           ;  decrease bomb count
01003703   |.^ 75 C2             JNZ SHORT winmine.010036C7              ;  jmp back if not all bombs set

The above is part of the code that is used in generating the minefield for the game. The game randomly calculates if the square is a bomb, and then at 0x010036FA, it OR’s the value of 0x80 with the default value, 0x0F, giving 0x8F.
From reversing the game further, we know that these are the possible values for the mines:
Mines Revealed

x0 = Blank Square (Pressed)
x1 = #1
x2 = #2
x3 = #3
x4 = #4
x5 = #5
x6 = #6
x7 = #7
x8 = #8
x9 = ? (Pressed)
xA = Mine
xB = Incorrect Mine
xC = Clicked Mine
xD = ? (Unpressed)
xE = Flag
xF = Blank Square (Unpressed)

Where x = 0; the square is not a mine.
Where x = 4; the square was clicked on.
Where x = 8; the square is a mine.
Where x = C; the square was a clicked on mine.

Now, we can modify the assembly at 0x010036FA to set it to one of these values to show that there is a bomb there.

bool MineVisCheat = false;

void ToggleMineVisibleCheat()
{
	int *ori_OR = ((int*) 0x010036FA);
	BYTE MOV[3];
	if(MineVisCheat) {
		MOV[0] = 0x80;
		MOV[1] = 0x08;
		MOV[2] = 0x80;
	}
	else {
		MOV[0] = 0xC6;
		MOV[1] = 0x00;
		MOV[2] = 0x8A;
	}
	DWORD dwProtection;
	VirtualProtect((LPVOID)0x010036FA, 1, PAGE_EXECUTE_READWRITE,&dwProtection);
	memcpy(ori_OR, &MOV, 3);
	VirtualProtect((LPVOID)0x010036FA, 1,dwProtection,&dwProtection);
	MineVisCheat = MineVisCheat^true;
}

Using the values above, this sets the opcode from OR BYTE PTR DS:[EAX],80 to MOV BYTE PTR DS:[EAX],8A. You would modify the image shown by changing the last byte of MOV to one of the values from the list.

010036EE   |.^\75 D7             JNZ SHORT winmine.010036C7
010036F0   |.  C1E0 05           SHL EAX,5
010036F3   |.  8D8430 40530001   LEA EAX,DWORD PTR DS:[EAX+ESI+rgBlk]
010036FA       C600 8E           MOV BYTE PTR DS:[EAX],8A
010036FD   |.  FF0D 30530001     DEC DWORD PTR DS:[cBombStart]
01003703   |.^ 75 C2             JNZ SHORT winmine.010036C7

One thing to take into account however, is that this will require you to start a new game before the effects come into place, as it overwrites the values while the grid is being drawn out.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: