C Board  

Go Back   C Board > Platform Specific Boards > Windows Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 02-09-2010, 06:08 AM   #1
Registered User
 
Join Date: May 2008
Location: Australia
Posts: 198
Reading Process Memory

Hi guys, so I'm trying to write a program that will read a user chosen process' memory starting at address 0x400000 and ending at 0x7FFFFFFF. The problem is it will only read a processes memory every 5 or so times I run the program. Some times I have to restart the program like 15 times before it reads the processes memory. The times it doesn't work GetLastError() will return 299, which is the following:

ERROR_PARTIAL_COPY: Only part of a ReadProcessMemory or WriteProcessMemory request was completed.

Can anyone tell me why it can work sometimes and not others?

This is all a learning experience for me so it wouldn't surprise me if I'm doing something quite strange. You probably only need to see the ReadProcessMemory() loop but I'll post the whole program just in case.

Thanks a lot guys!

Code:
#include <iostream>
#include <windows.h>
#include <Tlhelp32.h>
#include <vector>

using namespace std;

typedef struct ProcessInfo {
	int procId;
	char * procName;
} ProcessInfo;

ProcessInfo EnumerateProcesses();

int main(int argc, char * argv[]) {
	if (argc != 2 && argc != 1) {
		printf("Usage: <memHack.exe> <executable.exe>\n");
		return 1;
	}
	
	LUID privLuid;
	HANDLE hTokenHandle = 0;
	
	/* Change the process security token to debug mode */
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hTokenHandle))
		printf("[!] Error opening process token: %d\n", GetLastError());

	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privLuid))
		printf("[!] Error looking up the privilege value: %d\n", GetLastError());

	TOKEN_PRIVILEGES sTokenPrivs;
	sTokenPrivs.PrivilegeCount = 1;
	sTokenPrivs.Privileges[0].Luid = privLuid;
	sTokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	if (!AdjustTokenPrivileges(hTokenHandle, FALSE, &sTokenPrivs, NULL, NULL, NULL))
		printf("[!] Error adjusting process token privileges: %d\n", GetLastError());

	CloseHandle(hTokenHandle);

	bool userInput = false;
	ProcessInfo sProcInfo;
	memset(&sProcInfo, 0, sizeof(ProcessInfo));

	/* Check if file exists */
	if (argc == 2) {
		OFSTRUCT fileInfo;
		HFILE fileHandle = 0;
		if ((fileHandle = OpenFile(argv[1], &fileInfo, OF_EXIST)) == HFILE_ERROR) {
			if (GetLastError() == ERROR_FILE_NOT_FOUND) {
				printf("[!] File \"%s\" does not exist.\n", argv[1]);
				CloseHandle((HANDLE)fileHandle);
				return 1;
			}
		}
		CloseHandle((HANDLE)fileHandle);
	}
	
	/* If not parsed a file to load, enumerate processes for user decision */
	else {
		userInput = true;
		sProcInfo = EnumerateProcesses();
	}
	
	HANDLE targetProcess = 0;

	/* Opening a running process or loading a process */
	if (userInput) {
		if ((targetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, sProcInfo.procId)) == NULL) {
			printf("[!] Error acquiring %s process handle with PID %d: %d\n", 
				sProcInfo.procName, 
				sProcInfo.procId, 
				GetLastError());
			return 1;
		}
	}

	else {
		STARTUPINFO startupInfo;
		PROCESS_INFORMATION processInformation;

		memset(&startupInfo, 0, sizeof STARTUPINFO);
		memset(&processInformation, 0, sizeof PROCESS_INFORMATION);

		startupInfo.cb = sizeof STARTUPINFO;
		
		if (!CreateProcess(argv[1], NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation)) {
			printf("[!] Error loading program and creating process: %d\n", GetLastError());
			return 1;
		}
		
		if (processInformation.hProcess)
			targetProcess = processInformation.hProcess;

		if (processInformation.hThread)
			CloseHandle(processInformation.hThread);
	}

	unsigned char memoryDump[65535];
	int byteCount = 0;
	SIZE_T readAmount = 0;
	
	// Read memory into buffer in 65k byte chunks
	for (SIZE_T y = 0x00400000; y < 0x7FFFFFFF; y += 65535) {
		if (ReadProcessMemory(targetProcess, &y, memoryDump, 65535, &readAmount)) {
			for (SIZE_T n = 0; n < 65535; n++) {
				// 16 bytes have been printed
				if (byteCount % 16 == 0)
					printf("\n0x%x: ", y+n);
				printf("%02x ", memoryDump[n]);
				byteCount++;
			}
		}
		else {
			printf("\n[!] Error reading process memory: %d, read %d bytes before error.\n", GetLastError(), readAmount);
			break;
		}
	}

	if (targetProcess)
		CloseHandle(targetProcess);
}


// Returns the name of the user chosen process
ProcessInfo EnumerateProcesses() {
		HANDLE hSnapshot = 0;
		hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		
		if (hSnapshot == INVALID_HANDLE_VALUE) {
			printf("[!] Failed to obtain process snapshot handle: %d\n", GetLastError());
			CloseHandle(hSnapshot);
			exit(0);
		}

		PROCESSENTRY32 sProc;
		sProc.dwSize = sizeof(PROCESSENTRY32);
		if (!Process32First(hSnapshot, &sProc)) {
			printf("Failed to enumerate first process from snapshot: %d\n", GetLastError());
			CloseHandle(hSnapshot);
			exit(0);
		}
		
		vector<char *> processes;
		vector<int> processIds;

		do {
			char * tmp = new char[MAX_PATH];
			strcpy(tmp, sProc.szExeFile);
			processes.push_back(tmp);
			processIds.push_back(sProc.th32ProcessID);
		} while (Process32Next(hSnapshot, &sProc));

		for (int i = 2; i < processes.size(); i++) {
			printf("[%d] %s - %d\n", i - 1, processes[i], processIds[i]);
		}
		
		int process = 0;
		printf("\nProcess #: ");
		cin >> process;
		process += 1;
		
		ProcessInfo sProcInfo;
		sProcInfo.procName = new char[MAX_PATH];
		strcpy(sProcInfo.procName, processes[process]);
		sProcInfo.procId = processIds[process];

		for (int i = 0; i < processes.size(); i++)
			delete [] processes[i];

		return sProcInfo;
}
__________________
Quote:
Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

Last edited by pobri19; 02-09-2010 at 07:22 AM. Reason: Fixed output
pobri19 is offline   Reply With Quote
Old 02-09-2010, 07:35 AM   #2
Registered User
 
Join Date: May 2008
Location: Australia
Posts: 198
Okay so I just tested this on Windows XP and it runs fine every single time, which leads me to believe it's a new security feature on Windows 7 (my test environment) and possibly Windows Vista too. Does anyone have any ideas on what this security feature is and how I'm supposed to the problem it's causing?

Edit: Well actually it also depends on the program I test it on. If I run it against the firefox process or msn messenger process it works fine on Windows XP every time, but if I test it on some other processes (non-windows) such as a C# app I developed it 299 errors every time... What the?

And here's another problem I'm encountering, the program works fine when the user runs it without any paramaters and chooses a process from the enumerated process list, but if I attempt to run the program with an executable as a paramater it will run the program but it will also error with 299, on Windows XP as well, and it errors EVERY TIME. I'm assuming the process isn't inheriting the security access token therefore it's not allowing me to read its memory because it is not in Debug mode? Or is this wrong? Here's that section of code so you don't need to find it:

Code:
else {
		STARTUPINFO startupInfo;
		PROCESS_INFORMATION processInformation;

		memset(&startupInfo, 0, sizeof STARTUPINFO);
		memset(&processInformation, 0, sizeof PROCESS_INFORMATION);

		startupInfo.cb = sizeof STARTUPINFO;
		
		if (!CreateProcess(argv[1], NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation)) {
			printf("[!] Error loading program and creating process: %d\n", GetLastError());
			return 1;
		}
		
		if (processInformation.hProcess)
			targetProcess = processInformation.hProcess;

		if (processInformation.hThread)
			CloseHandle(processInformation.hThread);
	}
__________________
Quote:
Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.

Last edited by pobri19; 02-09-2010 at 10:03 AM.
pobri19 is offline   Reply With Quote
Old 02-09-2010, 10:32 AM   #3
Registered User
 
Join Date: May 2008
Location: Australia
Posts: 198
I did a bit more research and it turns out you get that error if you try and reference protected memory addresses. It's beyond me why it would work some times and not others... There's something new that changes the position of the code in memory I'm assuming, which is causing that?

Anyways so how am I supposed to find what is protected and what is not... Suggestions? That is if you think I am indeed on the right track. Thanks.
__________________
Quote:
Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
pobri19 is offline   Reply With Quote
Old 02-12-2010, 06:33 PM   #4
Registered User
 
Join Date: May 2008
Location: Australia
Posts: 198
I take it no one knows? Anyway I figured it out, posting the solution in case anyone else finds this thread has the same problem. Needed VirtualQueryEx() to check the protection type of each segment of memory. Now I'm saving all memory to disk that isn't protected.

Code:
#include <iostream>
#include <windows.h>
#include <Tlhelp32.h>
#include <vector>
#include <fstream>
#include <Shlwapi.h>

using namespace std;

typedef struct ProcessInfo {
	int procId;
	char * procName;
} ProcessInfo;

ProcessInfo EnumerateProcesses();
void PrintMemoryProtection(DWORD constant);
int CheckProtection(DWORD constant);

int main(int argc, char * argv[]) {
	if (argc != 2 && argc != 1) {
		printf("Usage: <memHack.exe> <executable.exe>\n");
		return 1;
	}

	char path[MAX_PATH];

	GetModuleFileName(0, path, MAX_PATH);
	PathRemoveFileSpec(path);
	SetCurrentDirectory(path);
	
	LUID privLuid;
	HANDLE hTokenHandle = 0;

	// Change the process security token to debug mode
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hTokenHandle))
		printf("[!] Error opening process token: %d\n", GetLastError());

	if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privLuid))
		printf("[!] Error looking up the privilege value: %d\n", GetLastError());

	TOKEN_PRIVILEGES sTokenPrivs;
	sTokenPrivs.PrivilegeCount = 1;
	sTokenPrivs.Privileges[0].Luid = privLuid;
	sTokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

	if (!AdjustTokenPrivileges(hTokenHandle, FALSE, &sTokenPrivs, NULL, NULL, NULL))
		printf("[!] Error adjusting process token privileges: %d\n", GetLastError());

	CloseHandle(hTokenHandle);

	bool userInput = false;
	ProcessInfo sProcInfo;
	memset(&sProcInfo, 0, sizeof(ProcessInfo));

	/* Check if file exists */
	if (argc == 2) {
		OFSTRUCT fileInfo;
		HFILE fileHandle = 0;
		if ((fileHandle = OpenFile(argv[1], &fileInfo, OF_EXIST)) == HFILE_ERROR) {
			if (GetLastError() == ERROR_FILE_NOT_FOUND) {
				printf("[!] File \"%s\" does not exist.\n", argv[1]);
				CloseHandle((HANDLE)fileHandle);
				return 1;
			}
		}
		CloseHandle((HANDLE)fileHandle);
	}
	
	/* If not parsed a file to load, enumerate processes for user decision */
	else {
		userInput = true;
		sProcInfo = EnumerateProcesses();
	}
	
	HANDLE targetProcess = 0;

	/* Opening a running process or loading a process */
	if (userInput) {
		if ((targetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, sProcInfo.procId)) == NULL) {
			printf("[!] Error acquiring %s process handle with PID %d: %d\n", sProcInfo.procName, sProcInfo.procId, GetLastError());
			return 1;
		}
	}

	else {
		STARTUPINFO startupInfo;
		PROCESS_INFORMATION processInformation;

		memset(&startupInfo, 0, sizeof STARTUPINFO);
		memset(&processInformation, 0, sizeof PROCESS_INFORMATION);

		startupInfo.cb = sizeof STARTUPINFO;
		
		if (!CreateProcess(argv[1], NULL, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation)) {
			printf("[!] Error loading program and creating process: %d\n", GetLastError());
			return 1;
		}
		
		if (processInformation.hProcess)
			targetProcess = processInformation.hProcess;

		if (processInformation.hThread)
			CloseHandle(processInformation.hThread);
	}

	MEMORY_BASIC_INFORMATION mbi;
	SYSTEM_INFO si;

	GetSystemInfo(&si);

	void * memCount = 0;
	unsigned char * memoryDump = 0;
	ofstream file("dump.txt");

	while (memCount < si.lpMaximumApplicationAddress) {
		VirtualQueryEx(targetProcess, memCount, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
		memoryDump = new unsigned char[mbi.RegionSize];
		if (CheckProtection(mbi.Protect)) {
			if (ReadProcessMemory(targetProcess, mbi.BaseAddress, memoryDump, mbi.RegionSize, NULL)) {
				for (SIZE_T n = 0; n < mbi.RegionSize; n++) {
					if (byteCount % 16 == 0)
						sprintf((char *)file, "\n0x%x: ", (unsigned long)mbi.BaseAddress + n);
				file.write((const char *)memoryDump, mbi.RegionSize);
				delete [] memoryDump;
			}
		}
		memCount = (LPVOID)((unsigned long)mbi.BaseAddress + (unsigned long)mbi.RegionSize);
	}

	file.close();

	if (targetProcess)
		CloseHandle(targetProcess);
}

// Returns the name of the user chosen process
ProcessInfo EnumerateProcesses() {
		HANDLE hSnapshot = 0;
		hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		
		if (hSnapshot == INVALID_HANDLE_VALUE) {
			printf("[!] Failed to obtain process snapshot handle: %d\n", GetLastError());
			CloseHandle(hSnapshot);
			exit(0);
		}

		PROCESSENTRY32 sProc;
		sProc.dwSize = sizeof(PROCESSENTRY32);
		if (!Process32First(hSnapshot, &sProc)) {
			printf("Failed to enumerate first process from snapshot: %d\n", GetLastError());
			CloseHandle(hSnapshot);
			exit(0);
		}
		
		vector<char *> processes;
		vector<int> processIds;

		do {
			char * tmp = new char[MAX_PATH];
			strcpy(tmp, sProc.szExeFile);
			processes.push_back(tmp);
			processIds.push_back(sProc.th32ProcessID);
		} while (Process32Next(hSnapshot, &sProc));

		for (unsigned int i = 2; i < processes.size(); i++)
			printf("[%02d] %s - %d\n", i - 1, processes[i], processIds[i]);
		
		int process = 0;
		printf("\nProcess #: ");
		cin >> process;
		process += 1;
		
		ProcessInfo sProcInfo;
		sProcInfo.procName = new char[MAX_PATH];
		strcpy(sProcInfo.procName, processes[process]);
		sProcInfo.procId = processIds[process];

		for (unsigned int i = 0; i < processes.size(); i++)
			delete [] processes[i];

		return sProcInfo;
}

int CheckProtection(DWORD constant) {
	switch (constant) {
	case PAGE_EXECUTE:
		return 1;
		break;
	case PAGE_EXECUTE_READ:
		return 1;
		break;
	case PAGE_EXECUTE_READWRITE:
		return 1;
		break;
	case PAGE_EXECUTE_WRITECOPY:
		return 1;
		break;
	case PAGE_NOACCESS:
		return 0;
		break;
	case PAGE_READONLY:
		return 1;
		break;
	case PAGE_READWRITE:
		return 1;
		break;
	case PAGE_WRITECOPY:
		return 1;
		break;
	default:
		return 0;
	}
}
__________________
Quote:
Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
pobri19 is offline   Reply With Quote
Old 02-12-2010, 08:20 PM   #5
Registered User
 
Join Date: Jan 2010
Posts: 202
You should also test for PAGE_GUARD
A page where the PAGE_GUARD flag is set cannot be read even if you have read access to it.
_Mike is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Bug in Best-Fit Memory Allocation program (Simulation) RommelTJ C Programming 6 12-13-2009 04:43 PM
sequenceing or queueing multiple process sv_joshi_pune Windows Programming 1 08-14-2009 09:43 AM
Question regarding Memory Leak clegs C++ Programming 29 12-07-2007 01:57 AM
patching memory in another process 44ffcc Windows Programming 2 02-06-2006 09:32 AM
Reading from file into memory GaPe C Programming 15 12-17-2001 04:19 PM


All times are GMT -6. The time now is 04:53 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22