Posts Tagged ‘read

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