Segment information from another process

Segment information from another process

To get information of segments in memory from another process you have three options - read process’ memory, map the process’ memory to the accessible virtual address space or inject dll that can access and read process’ memory. In this post I will use the first approach and read another process’ memory in to a buffer, afterwards I will use content of the buffer to extract header information that contains segment information. For this I’ll be using WINAPI, some of these APIs are describe in detail in another post, you can read it here

#include <Windows.h>
#include <Psapi.h>
#include <vector>
#include <DbgHelp.h>

#pragma comment(lib, "dbghelp.lib")
int main() 
{
	//OPEN HANDLE TO A PROCESS
	int pID = 0x468;
	handle_t hprocess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pID);

	SYSTEM_INFO systemInfo;
	MEMORY_BASIC_INFORMATION regionInfo;
	char * address = 0;

	GetSystemInfo(&systemInfo);

	printf("Address \t\t Size \t\t\t Info\n");

	//GO OVER AVAILABLE MEMORY AND GET REGION INFORMATION
	while (address < systemInfo.lpMaximumApplicationAddress)
	{
		VirtualQueryEx(hprocess, address, &regionInfo, sizeof(regionInfo));

		HMODULE hmodule = reinterpret_cast<HMODULE>(regionInfo.AllocationBase);
		
		MODULEINFO moduleInfo;
		GetModuleInformation(hprocess, hmodule, &moduleInfo, sizeof(moduleInfo));

		//CHECK IF THE MEMORY REGION CONTAINS LOADED MODULE
		if (moduleInfo.lpBaseOfDll != nullptr && regionInfo.BaseAddress == regionInfo.AllocationBase)
		{
			char pathBuffer[MAX_PATH];
			GetModuleFileNameEx(hprocess, hmodule, pathBuffer, MAX_PATH);

			printf("0x%p \t 0x%016x \t %s\n",regionInfo.BaseAddress, regionInfo.RegionSize, pathBuffer);

			std::vector<char> memBuf;
			memBuf.resize(regionInfo.RegionSize);
			ReadProcessMemory(hprocess, address, &memBuf[0], regionInfo.RegionSize, NULL);

			//EXECUTE FUNC TO RETRIEVE NT HEADERS OF LOADED MODULE, IF YOU WANT APPLY STRUCT DIRECTLY ON RETRIEVED MEMORY
			IMAGE_NT_HEADERS *pNtHdr = ImageNtHeader(&memBuf[0]);
			IMAGE_SECTION_HEADER *pSectionHdr = (IMAGE_SECTION_HEADER *)(pNtHdr + 1);
			LPVOID moduleBaseAddress = regionInfo.BaseAddress;

			for (int i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++)
			{
				VirtualQueryEx(hprocess, 
					(char*)moduleBaseAddress + pSectionHdr->VirtualAddress, 
					&regionInfo, 
					sizeof(regionInfo));
				
				char * address = (char *)moduleBaseAddress + pSectionHdr->VirtualAddress;
				int size = pSectionHdr->Misc.VirtualSize + 
					(pNtHdr->OptionalHeader.SectionAlignment - pSectionHdr->Misc.VirtualSize 
					% pNtHdr->OptionalHeader.SectionAlignment);
				
				printf("0x%p\t 0x%016x \t%s \n", address, size, pSectionHdr->Name);

				pSectionHdr++;
			}

			printf("\n");

			address += moduleInfo.SizeOfImage;
		}
		else
		{
			address += regionInfo.RegionSize;
		}
		
	}
}

This is just a spike, if you want to use this for something serious - don’t forget to put error handling. If you are compiling this as 32bit application on a 64bit machine, you could have problems with the first while loop, as it will use 64bit address. In that case don’t use system info struct to find available address range, just go over 32bit address space.

comments powered by Disqus