Posts Tagged ‘cheat

26
Apr
09

[C++] :Minesweeper: In-game Toggle Mine Visibility 2

A much cleaner solution than what I made here: /c-minesweeper-in-game-toggle-mine-visibility/
It just uses the in game “ShowMines” function rather than having to write your own.

void __stdcall ShowMines(void)
{
	typedef void (__stdcall *ptrFn)(DWORD);
	ptrFn ptrShowMinesFn = (ptrFn)(0x01002F80);
	ptrShowMinesFn(0xE);
}

You call the function ptrShowMinesFn with one of the possible values for mines, the list can be found here:
/c-minesweeper-toggle-mine-visibility/
So, for example 0xE would display flags.

Advertisements
25
Apr
09

[ASM] Minesweeper God Mode Testing III

Fixed the timer now so that it only stops working if you have won the game.
Original
#########################

0100347C w>    8325 64510001 00                AND DWORD PTR DS:[fTimer],0
01003483   |.  56                              PUSH ESI
01003484       8B7424 08                       MOV ESI,DWORD PTR SS:[ESP+8]

#########################
With Jump
#########################

0100347C w>   /E9 0E160000                     JMP winmine.01004A8F
01003481      |90                              NOP
01003482      |90                              NOP
01003483   |. |56                              PUSH ESI
01003484      |8B7424 08                       MOV ESI,DWORD PTR SS:[ESP+8]

#########################
Code Cave
#########################

01004A8F    > \83F8 01                         CMP EAX,1
01004A92    .^ 0F84 EBE9FFFF                   JE winmine.01003483
01004A98    .  8325 64510001 00                AND DWORD PTR DS:[fTimer],0
01004A9F    .^ E9 DFE9FFFF                     JMP winmine.01003483
25
Apr
09

[ASM] Minesweeper God Mode Testing II

Ok after playing around a bit more, i’ve¬† set it up so that after you die, you have the default smiley icon not the dead one:
Original
#########################

0100348C   |.  0F95C0            SETNE AL
0100348F       40                INC EAX
01003490       40                INC EAX
01003491       50                PUSH EAX
01003492       A3 60510001       MOV DWORD PTR DS:[iButtonCur],EAX
01003497       E8 77F4FFFF       CALL winmine.DisplayButton
0100349C       33C0              XOR EAX,EAX

#########################
With Jump
#########################

0100348C   |.  0F95C0            SETNE AL
0100348F       E9 E6150000       JMP winmine.01004A7A
01003494       90                NOP
01003495       90                NOP
01003496       90                NOP
01003497       E8 77F4FFFF       CALL winmine.DisplayButton
0100349C       33C0              XOR EAX,EAX

#########################
Code Cave
#########################

01004A7A       83F8 01           CMP EAX,1
01004A7D       75 05             JNZ SHORT winmine.01004A84
01004A7F       B8 03000000       MOV EAX,3
01004A84       50                PUSH EAX
01004A85       A3 60510001       MOV DWORD PTR DS:[iButtonCur],EAX
01004A8A     ^ E9 08EAFFFF       JMP winmine.01003497
25
Apr
09

[ASM] Minesweeper God Mode Testing

UPDATED [At End]

Got bored and trying to create an effective god mode in Minesweeper that will allow you to keep on playing even after you die.
If I can get it all to work properly, I may make a small hack of the game that allows you to set a number of lives per game, and then you loose after hitting that many mines.

Ill be updating the blog with posts as I research more.
This is what I have so far.
__________________________________
Pretty much everything of use so far has come from the GameOver function called here:

010035AB   |> \E8 CCFEFFFF       CALL winmine.GameOver        ; (CALL winmine.0100347C)

After a bit of playing around, ive created a cave that allows me to continue playing even after hitting a mine:
Original
#########################

010034D4       85F6                       TEST ESI,ESI
010034D6       C705 00500001 10000000     MOV DWORD PTR DS:[fStatus],10
010034E0       5E                         POP ESI

#########################
With Jump
#########################

010034D4   |.  85F6              TEST ESI,ESI
010034D6       E9 B4150000       JMP winmine.01004A8A
010034DB       90                NOP
010034DC       90                NOP
010034DD       90                NOP
010034DE       90                NOP
010034DF       90                NOP
010034E0   |.  5E                POP ESI

#########################
Code Cave
#########################

01004A8A       833D 60510001 03           CMP DWORD PTR DS:[iButtonCur],3
01004A91       5E                         POP ESI
01004A92     ^ 0F85 77EAFFFF              JNZ winmine.0100350F
01004A98       C705 00500001 10000000     MOV DWORD PTR DS:[fStatus],10
01004AA2     ^ E9 3CEAFFFF                JMP winmine.010034E3

This little cave just checks to see if the game has been won or lost. If its been won, then it sets the gamestate to 0x10 (Game Over) else, it keeps the value as 0 and returns to the function.

__________________________________
Update:
I decided that instead of using a cave, just patching the function would work just as nicely:
Original
#########################

010034CF   |.  E8 19040000                CALL winmine.PlayTune
010034D4       85F6                       TEST ESI,ESI
010034D6       C705 00500001 10000000     MOV DWORD PTR DS:[fStatus],10
010034E0       5E                         POP ESI
010034E1       74 2C                      JE SHORT winmine.0100350F
010034E3       66:A1 A0560001             MOV AX,WORD PTR DS:[Preferences]
010034E9       66:3D 0300                 CMP AX,3
010034ED       74 20                      JE SHORT winmine.0100350F
010034EF       8B0D 9C570001              MOV ECX,DWORD PTR DS:[cSec]

#############
PATCHED
#############

010034CF   |.  E8 19040000                CALL winmine.PlayTune
010034D4       66:A1 A0560001             MOV AX,WORD PTR DS:[Preferences]
010034DA       833D 60510001 03           CMP DWORD PTR DS:[iButtonCur],3
010034E1       5E                         POP ESI
010034E2       75 2B                      JNZ SHORT winmine.0100350F
010034E4       C705 00500001 10000000     MOV DWORD PTR DS:[fStatus],10
010034EE       90                         NOP
010034EF       8B0D 9C570001              MOV ECX,DWORD PTR DS:[cSec]
24
Apr
09

[C++] :Minesweeper: In-game Toggle Mine Visibility

Minesweeper stores its minefield in memory, starting at the address  0x1005360, and is set up looking like this:

>>>>>>>>>
>*---*-->
>-*----*>
>-**-*-->
>------->
>---*--->
>>>>>>>>>

With the >’s representing a 1 Byte border, the *’s being mines, and -‘s being empty spaces.
Knowing this, we can effectively create a loop that reads this memory, and checks if a square is a bomb or not.

In order to calculate the size of the loop, we need to read the width and height from the game. These are stored at the two following addresses: 0x1005334 and 0x1005338. The maximum width of the board, is 0x1E, which is 0x20-2, 2 for the border. So, we now know that we can read each column by looping along the rows between 0 and nwidth, and the columns can be calculated by adding 0x20 to the address, each pass between 0 and nheight.

So, now we have the loop sorted, we just need to check if the current address holds a mine, if so, display it to the user.

bool MinesCheat = false;

void ToggleMinesCheat()
{
	int maxX = *((int*) 0x1005334);
	int maxY = *((int*) 0x1005338);
	int address = 0x1005361;

	for(int y = 0;y<maxY;y++) {
		for (int x = 0;x<maxX;x++) {
			BYTE *xmine = (BYTE*) address+x;
			BYTE mine = 0x8F;
			if(MinesCheat)
				mine = 0x8A;
			if(*xmine==mine) {
				if(MinesCheat)
					*xmine = 0x8F;
				else
					*xmine = 0x8A;
			}
		}
		address = address + 0x20;
	}
	InvalidateRect(mhWnd, NULL, 1);
	UpdateWindow(mhWnd);
	MinesCheat = MinesCheat^true;
}

That will either loop through the memory displaying the mines location, by overwriting the memory with 0x8A (Visible Mine), or if the function has already been ran, will hide the mines again by writing the memory with 0x8F (hidden mine)

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.

24
Apr
09

[C++] :Minesweeper: Toggle Timer

Local call from MainWndProc+1A3
winmine.DoTimer

01002FE0 w>/$  833D 64510001 00  CMP DWORD PTR DS:[fTimer],0
01002FE7       74 1E             JE SHORT winmine.01003007
01002FE9   |.  813D 9C570001 E70>CMP DWORD PTR DS:[cSec],3E7
01002FF3   |.  7D 12             JGE SHORT winmine.01003007
01002FF5       FF05 9C570001     INC DWORD PTR DS:[cSec]
01002FFB   |.  E8 B5F8FFFF       CALL winmine.DisplayTime
01003000   |.  6A 01             PUSH 1
01003002   |.  E8 E6080000       CALL winmine.PlayTune
01003007   \>  C3                RETN

At 0x01002FE7 you have an instruction that checks to see if the game is running. If the value is equal, then it jumps over.
There would be many ways to effectively removing the timer, I have done it by changing the opcode of JE, to that of an short unconditional jump, 0xEB.

bool TimerCheat = false;

void ToggleTimerCheat()
{
	int *ori_JE = ((int*) 0x01002FE7);
	int JMP;
	if(TimerCheat)
		JMP = 0x74;
	else
		JMP = 0xEB;
	DWORD dwProtection;
	VirtualProtect((LPVOID)0x01002FE7, 1, PAGE_EXECUTE_READWRITE,&dwProtection);
	memcpy(ori_JE, &JMP, 1);
	VirtualProtect((LPVOID)0x01002FE7, 1,dwProtection,&dwProtection);
	TimerCheat = TimerCheat^true;
}

The above code will either enable or disable the timer based upon the bool TimerCheat.
After calling the function, the timer will not increase, the DoTimer function should look like:

01002FE0 w>/$  833D 64510001 00  CMP DWORD PTR DS:[fTimer],0
01002FE7       EB 1E             JMP SHORT winmine.01003007
01002FE9   |.  813D 9C570001 E70>CMP DWORD PTR DS:[cSec],3E7
01002FF3   |.  7D 12             JGE SHORT winmine.01003007
01002FF5       FF05 9C570001     INC DWORD PTR DS:[cSec]
01002FFB   |.  E8 B5F8FFFF       CALL winmine.DisplayTime
01003000   |.  6A 01             PUSH 1
01003002   |.  E8 E6080000       CALL winmine.PlayTune
01003007   \>  C3                RETN