Posts Tagged ‘memory

09
May
09

[C++] Read External Treeview

After quite some time and a lot of research, I finally got it to work. The method is summarised below:

xProcess = eXternal Process
Find xProc Window
Find Treeview in window
Get xProcess ID
Set Debug Privelages
Open xProcess
Allocate Memory in xProc
Get Root Node
Loop:
	Create and fill TVITEM structure
	Write TVITEM to xprocess
	Send GET_ITEM to get Node name
	Read string from xprocess memory
	print
	Get Next Node
Free Memory
Close Handle

I also had some trouble in some processes with trying to open them, so the code includes a setDebug function that changes your privileges and is used in the printTreeviewNodes function before attempting to open the process. Below is the code, including an example of how to use it (Using Teamspeak 2 as a target program):

// Read External Treeview.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "commctrl.h"
#include <iostream>

using namespace std;

bool setDebug() {
	HANDLE hToken;
	if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		TOKEN_PRIVILEGES tp;
		LUID luid;
		TOKEN_PRIVILEGES tpPrevious;
		DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
		if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
			tp.PrivilegeCount = 1;
			tp.Privileges[0].Luid = luid;
			tp.Privileges[0].Attributes = 0;
			if(AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)) {
				tpPrevious.PrivilegeCount = 1;
				tpPrevious.Privileges[0].Luid = luid;
				tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
				if(AdjustTokenPrivileges( hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL )) {
					CloseHandle(hToken);
					return true;
				}
			}
		}
	}
	CloseHandle(hToken);
	return false;
}

void printTreeviewNodes(HWND treeview) {
	DWORD pID;
	GetWindowThreadProcessId(treeview, &pID);
	if(pID) {
		if(setDebug()) {
			HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pID);
			if(hProcess) {
			/*
				Memory allocation:
			   0---------|---------|----------------14F
				 TVITEM    rBuffer       pszText
				  (28)      (28)          (FF)
			*/
				DWORD remoteBuffer = (DWORD)::VirtualAllocEx(hProcess, NULL, 335, MEM_COMMIT, PAGE_READWRITE);
				if(remoteBuffer) {
					HTREEITEM Root = (HTREEITEM)::SendMessage(treeview, TVM_GETNEXTITEM, TVGN_ROOT, 0);
					while(Root) {
						TVITEM tvItem;
						tvItem.mask = TVIF_TEXT;
						tvItem.hItem = Root;
						tvItem.pszText = (LPWSTR)remoteBuffer + sizeof(TVITEM);
						tvItem.cchTextMax = 255;
						if(WriteProcessMemory(hProcess, (LPVOID)remoteBuffer, (LPCVOID)&tvItem, sizeof(TVITEM), 0)) {
							SendMessage(treeview, TVM_GETITEM, 0, remoteBuffer);
							wchar_t bytRtn[255];
							int rAdd = remoteBuffer + sizeof(TVITEM)*2;
							if(ReadProcessMemory(hProcess, (LPCVOID)rAdd, (LPVOID)&bytRtn, 255, 0)) {
								wcout << bytRtn << endl;
							}
							Root = (HTREEITEM)::SendMessage(treeview, TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)Root);
						}
					}
					VirtualFreeEx(hProcess, (LPVOID)remoteBuffer, 335, MEM_RELEASE);
				}
			}
			CloseHandle(hProcess);
		}
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	HWND tsmhWnd = FindWindow(L"TMainForm", L"TeamSpeak 2");
	tsmhWnd = FindWindowEx(tsmhWnd, NULL, L"TPanel", NULL);
	HWND tsTVhWnd = FindWindowEx(tsmhWnd, NULL, L"TTreeView", NULL);
	printTreeviewNodes(tsTVhWnd);
	return 0;
}

If anybody has a better method than this or any comments, I’d be more than happy for input ^^

Advertisements
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)