Uninformed: Informative Information for the Uninformed

Vol 1» 2005.May


Virtual Mine Sweeper

In this section, the reader will be introduced to portions of the Windows API that will allow one to develop an application that will perform the following:

  1. Locate and attach to the WinMine process
  2. Read the WinMine playing grid
  3. Manipulate the grid to either reveal or remove hidden bombs
  4. Write the newly modified grid back into WinMine application space
To accomplish the first task, one can enlist the services of the Tool Help Library, which is exposed via Tlhelp32.h. A snapshot of running processes can be obtained by calling CreateToolhelp32Snapshot, which has the following prototype7.1:
HANDLE WINAPI CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);
This function, when called with dwFlags set to TH32CS_SNAPPROCESS will provide the reader with a handle to the current process list. To enumerate this list, the reader must first invoke the Process32First function, which has the following prototype:
BOOL WINAPI Process32First(
  HANDLE hSnapshot,
  LPPROCESSENTRY32 lppe
);
Subsequent iterations through the process list are accessible via the Process32Next function, which has the following prototype:
BOOL WINAPI Process32Next(
  HANDLE hSnapshot,
  LPPROCESSENTRY32 lppe
);
As the reader surely noticed, both of these functions return a LPPROCESSENTRY32, which includes a variety of helpful information:
typedef struct tagPROCESSENTRY32 {
  DWORD dwSize;
  DWORD cntUsage;
  DWORD th32ProcessID;
  ULONG_PTR th32DefaultHeapID;
  DWORD th32ModuleID;
  DWORD cntThreads;
  DWORD th32ParentProcessID;
  LONG pcPriClassBase;
  DWORD dwFlags;
  TCHAR szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32;
Most notably of which is szExeFile, which will allow the reader to locate the WinMine process, and th32ProcessID, which provides the process ID to attach to once the WinMine process is found. Once the WinMine process is located, it can be attached to via the OpenProcess function, which has the following prototype:
HANDLE OpenProcess(
  DWORD dwDesiredAccess,
  BOOL bInheritHandle,
  DWORD dwProcessId
);
Once the WinMine process has been opened, the reader may read the current playing grid from its virtual memory via the ReadProcessMemory function, which has the following prototype:
BOOL ReadProcessMemory(
  HANDLE hProcess,
  LPCVOID lpBaseAddress,
  LPVOID lpBuffer,
  SIZE_T nSize,
  SIZE_T* lpNumberOfBytesRead
);
After the grid is read into the buffer, the reader may loop through it replacing all instances of 0x8f with either 0x8a to reveal bombs, or 0x0f to remove them. This modified buffer can then be written back into the WinMine process with the WriteProcessMemory function, which has the following prototype:
BOOL WriteProcessMemory(
  HANDLE hProcess,
  LPVOID lpBaseAddress,
  LPCVOID lpBuffer,
  SIZE_T nSize,
  SIZE_T* lpNumberOfBytesWritten
);
With this information, the reader has the tools necessary to develop an application that to reach the ultimate goal of this paper, to reveal and/or remove bombs from the WinMine playing grid. The source code for a functioning demonstration of this can be found in the reference section.[13]