//bug fix: had endless loop if process exited after OpenProcess succeeded 7-23-16 dz int memMap(int pid, char* pth) { HANDLE hProcess; DWORD cbNeeded; int rv=0; hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | SYNCHRONIZE, FALSE, pid ); if (NULL == hProcess){ printf("Error: failed to open process.."); return 1; } MEMORY_BASIC_INFORMATION mbi; long long va = 0; SIZE_T wErr; FILE* f = fopen(pth, "w"); char mod[500]; DWORD modLen=0; int i=0; if(f==NULL){ printf("Error: failed to open file %s", pth); return 1; } fprintf(f, "va, AllocationBase, Size, AllocationProtect, Type, Protect, State, ModuleFileName\r\n"); while(va < 0x000007FFFFFFFFFF)// x64 User Space Limit { wErr = VirtualQueryEx(hProcess, (LPCVOID)va, &mbi, sizeof(mbi)); if(mbi.State != MEM_FREE){ mod[0]=0; modLen=0; if(va > 0){ modLen = GetModuleFileNameExA(hProcess, (HMODULE)va, mod, 500); if(modLen==0) mod[0]=0; } fprintf(f, /*"%.16llX,%.16llX,%.16llX,%.8lX,%.8lX,%.8lX,%.8lX,%s\r\n",*/ "%llX,%llX,%llX,%lX,%lX,%lX,%lX,%s\r\n", va, mbi.AllocationBase, mbi.RegionSize, mbi.AllocationProtect, mbi.Type, mbi.Protect, mbi.State, mod); } if(!IsProcHandleValid(hProcess)) break; if(mbi.RegionSize < 1) break; va += mbi.RegionSize; //printf("%d) %.16llX\r\n", i++, va); /*if(va >= 0x000007FFFFFFFFFF) { break; }*/ } fclose(f); return 0; }
void UpdateMemoryMap(void) { MemMap.clear(); MemMapCode.clear(); MemMapData.clear(); MemMapModule.clear(); Exports.clear(); CustomNames.clear(); if (hProcess == NULL) return; if (!IsProcHandleValid(hProcess)) { hProcess = NULL; return; } SYSTEM_INFO SysInfo; GetSystemInfo(&SysInfo); MEMORY_BASIC_INFORMATION MBI; ULONG_PTR pMemory = (ULONG_PTR)SysInfo.lpMinimumApplicationAddress; while(pMemory < (ULONG_PTR)SysInfo.lpMaximumApplicationAddress) { if ( VirtualQueryEx(hProcess,(LPCVOID)pMemory,&MBI,sizeof(MBI)) != 0) { if (MBI.State == MEM_COMMIT /*&& MBI.Type == MEM_PRIVATE*/) { MemMapInfo Mem; Mem.Start = (DWORD_PTR)pMemory; Mem.End = (DWORD_PTR)pMemory + MBI.RegionSize - 1; MemMap.push_back(Mem); } pMemory = (ULONG_PTR)MBI.BaseAddress + MBI.RegionSize; } else { pMemory += 1024; } } MODULEENTRY32 ModInfo; ModInfo.dwSize = sizeof(MODULEENTRY32); HANDLE ModuleList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetProcessId(hProcess)); if ((int)ModuleList != -1) { BOOL rm = Module32First(ModuleList,&ModInfo); while(rm) { MemMapInfo Mem; Mem.Start = (DWORD_PTR)ModInfo.modBaseAddr; Mem.End = Mem.Start + ModInfo.modBaseSize; Mem.Name = ModInfo.szModule; MemMapModule.push_back(Mem); rm = Module32Next(ModuleList,&ModInfo); } CloseHandle(ModuleList); } AddressName Entry; ModuleList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetProcessId(hProcess)); if ((int)ModuleList != -1) { BOOL rm = Module32First(ModuleList,&ModInfo); while(rm) { IMAGE_DOS_HEADER DH; IMAGE_NT_HEADERS pe; ReadProcessMemory(hProcess,ModInfo.modBaseAddr,&DH,sizeof(DH),NULL); ReadProcessMemory(hProcess,ModInfo.modBaseAddr + DH.e_lfanew,&pe,sizeof(pe),NULL); DWORD ssize = (DWORD)pe.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); PIMAGE_SECTION_HEADER sh = (PIMAGE_SECTION_HEADER)(new char[ssize]); ReadProcessMemory(hProcess,ModInfo.modBaseAddr + DH.e_lfanew + sizeof(IMAGE_NT_HEADERS),sh,ssize,NULL); for (int i=0; i < pe.FileHeader.NumberOfSections; i++) { CString txt; MemMapInfo Mem; txt.Format("%.8s",sh[i].Name); txt.MakeLower(); if (txt == ".text" || txt == "code") { Mem.Start = (DWORD_PTR)ModInfo.modBaseAddr + sh[i].VirtualAddress; Mem.End = Mem.Start + sh[i].Misc.VirtualSize; Mem.Name = ModInfo.szModule; MemMapCode.push_back(Mem); } if (txt == ".data" || txt == "data" || txt == ".rdata" || txt == ".idata") { Mem.Start = (DWORD_PTR)ModInfo.modBaseAddr + sh[i].VirtualAddress; Mem.End = Mem.Start + sh[i].Misc.VirtualSize; Mem.Name = ModInfo.szModule; MemMapData.push_back(Mem); } } delete sh; rm = Module32Next(ModuleList,&ModInfo); } CloseHandle(ModuleList); } for (UINT i=0; i<MemMap.size();i++) { if (IsModule(MemMap[i].Start)) MemMap[i].Name = GetModuleName(MemMap[i].Start); } }
bool UpdateMemoryMap(void) { MemMap.clear(); MemMapCode.clear(); MemMapData.clear(); MemMapModule.clear(); Exports.clear(); CustomNames.clear(); if (g_hProcess == NULL) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Process handle NULL!")); #endif return 0; } if (!IsProcHandleValid(g_hProcess)) { g_hProcess = NULL; #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Process handle invalid!")); #endif return 0; } SYSTEM_INFO SysInfo; GetSystemInfo(&SysInfo); MEMORY_BASIC_INFORMATION MemInfo; size_t pMemory = (size_t)SysInfo.lpMinimumApplicationAddress; while (pMemory < (size_t)SysInfo.lpMaximumApplicationAddress) { if (VirtualQueryEx(g_hProcess, (LPCVOID)pMemory, &MemInfo, sizeof(MEMORY_BASIC_INFORMATION)) != 0) { if (MemInfo.State == MEM_COMMIT /*&& MemInfo.Type == MEM_PRIVATE*/) { MemMapInfo Mem; Mem.Start = (size_t)pMemory; Mem.End = (size_t)pMemory + MemInfo.RegionSize - 1; MemMap.push_back(Mem); } pMemory = (ULONG_PTR)MemInfo.BaseAddress + MemInfo.RegionSize; } else { pMemory += 1024; } } static HMODULE hNtDll = (HMODULE)Utils::GetLocalModuleHandle("ntdll.dll"); static tNtQueryInformationProcess NtQueryInformationProcess = (tNtQueryInformationProcess)Utils::GetProcAddress(hNtDll, "NtQueryInformationProcess"); PPROCESS_BASIC_INFORMATION ProcessInfo = NULL; PEB Peb; PEB_LDR_DATA LdrData; // Try to allocate buffer HANDLE hHeap = GetProcessHeap(); DWORD dwSize = sizeof(PROCESS_BASIC_INFORMATION); ProcessInfo = (PPROCESS_BASIC_INFORMATION)HeapAlloc(hHeap, HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, dwSize); ULONG dwSizeNeeded = 0; NTSTATUS status = NtQueryInformationProcess(g_hProcess, ProcessBasicInformation, ProcessInfo, dwSize, &dwSizeNeeded); if (status >= 0 && dwSize < dwSizeNeeded) { if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); ProcessInfo = (PPROCESS_BASIC_INFORMATION)HeapAlloc(hHeap, HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, dwSizeNeeded); if (!ProcessInfo) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Couldn't allocate heap buffer!")); #endif return 0; } status = NtQueryInformationProcess(g_hProcess, ProcessBasicInformation, ProcessInfo, dwSizeNeeded, &dwSizeNeeded); } // Did we successfully get basic info on process if (NT_SUCCESS(status)) { // Check for PEB if (!ProcessInfo->PebBaseAddress) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: PEB is null! Aborting UpdateExports!")); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } // Read Process Environment Block (PEB) SIZE_T dwBytesRead = 0; if ( ReadMemory( ProcessInfo->PebBaseAddress, &Peb, sizeof(PEB), &dwBytesRead) == 0) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Failed to read PEB! Aborting UpdateExports!")); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } // Get Ldr dwBytesRead = 0; if ( ReadMemory( Peb.Ldr, &LdrData, sizeof(LdrData), &dwBytesRead) == 0) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Failed to read PEB Ldr Data! Aborting UpdateExports!")); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } LIST_ENTRY *pLdrListHead = (LIST_ENTRY *)LdrData.InLoadOrderModuleList.Flink; LIST_ENTRY *pLdrCurrentNode = LdrData.InLoadOrderModuleList.Flink; do { LDR_DATA_TABLE_ENTRY lstEntry = { 0 }; dwBytesRead = 0; if (! ReadMemory( (void*)pLdrCurrentNode, &lstEntry, sizeof(LDR_DATA_TABLE_ENTRY), &dwBytesRead)) { #ifdef _DEBUG PrintOut(_T("[UpdateMemoryMap]: Could not read list entry from LDR list. Error = %s"), Utils::GetLastErrorString().GetString()); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } pLdrCurrentNode = lstEntry.InLoadOrderLinks.Flink; if (lstEntry.DllBase != NULL /*&& lstEntry.SizeOfImage != 0*/) { unsigned char* ModuleBase = (unsigned char*)lstEntry.DllBase; DWORD ModuleSize = lstEntry.SizeOfImage; wchar_t wcsFullDllName[MAX_PATH] = { 0 }; wchar_t* wcsModule = 0; if (lstEntry.FullDllName.Length > 0) { dwBytesRead = 0; if ( ReadMemory( (LPVOID)lstEntry.FullDllName.Buffer, &wcsFullDllName, lstEntry.FullDllName.Length, &dwBytesRead)) { wcsModule = wcsrchr(wcsFullDllName, L'\\'); if (!wcsModule) wcsModule = wcsrchr(wcsFullDllName, L'/'); wcsModule++; if (g_AttachedProcessAddress == NULL) { wchar_t filename[MAX_PATH]; GetModuleFileNameExW(g_hProcess, NULL, filename, MAX_PATH); if (_wcsicmp(filename, wcsFullDllName) == 0) { g_AttachedProcessAddress = (size_t)ModuleBase; g_AttachedProcessSize = ModuleSize; } } } } // module info MemMapInfo Mem; Mem.Start = (size_t)ModuleBase; Mem.End = Mem.Start + ModuleSize; Mem.Size = ModuleSize; Mem.Name = wcsModule; Mem.Path = wcsFullDllName; //PrintOut(_T("%s: %IX"), Mem.Name.GetBuffer(), Mem.Start); MemMapModule.push_back(Mem); // module code IMAGE_DOS_HEADER DosHdr; IMAGE_NT_HEADERS NtHdr; ReadMemory( ModuleBase, &DosHdr, sizeof(IMAGE_DOS_HEADER), NULL); ReadMemory( ModuleBase + DosHdr.e_lfanew, &NtHdr, sizeof(IMAGE_NT_HEADERS), NULL); DWORD sectionsSize = (DWORD)NtHdr.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)malloc(sectionsSize); ReadMemory( ModuleBase + DosHdr.e_lfanew + sizeof(IMAGE_NT_HEADERS), sections, sectionsSize, NULL); for (int i = 0; i < NtHdr.FileHeader.NumberOfSections; i++) { CString txt; MemMapInfo Mem; txt.Format(_T("%.8s"), sections[i].Name); txt.MakeLower(); if (txt == ".text" || txt == "code") { Mem.Start = (size_t)ModuleBase + sections[i].VirtualAddress; Mem.End = Mem.Start + sections[i].Misc.VirtualSize; Mem.Name = wcsModule; MemMapCode.push_back(Mem); } if (txt == ".data" || txt == "data" || txt == ".rdata" || txt == ".idata") { Mem.Start = (size_t)ModuleBase + sections[i].VirtualAddress; Mem.End = Mem.Start + sections[i].Misc.VirtualSize; Mem.Name = wcsModule; MemMapData.push_back(Mem); } } delete sections; } } while (pLdrListHead != pLdrCurrentNode); } else { #ifdef _DEBUG PrintOut(_T("[UpdateExports]: NtQueryInformationProcess failed! Aborting...")); #endif if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); return 0; } if (ProcessInfo) HeapFree(hHeap, 0, ProcessInfo); for (UINT i = 0; i < MemMap.size(); i++) { if (IsModule(MemMap[i].Start)) MemMap[i].Name = GetModuleName(MemMap[i].Start); } return 1; }