bool SHMProcess::Private::validate(vector <VersionInfo *> & known_versions) { // try to identify the DF version IMAGE_NT_HEADERS32 pe_header; IMAGE_SECTION_HEADER sections[16]; HMODULE hmod = NULL; DWORD junk; HANDLE hProcess; bool found = false; identified = false; // open process, we only need the process open hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, process_ID ); if (NULL == hProcess) return false; // try getting the first module of the process if(EnumProcessModules(hProcess, &hmod, 1 * sizeof(HMODULE), &junk) == 0) { CloseHandle(hProcess); // cout << "EnumProcessModules fail'd" << endl; return false; } // got base ;) uint32_t base = (uint32_t)hmod; // read from this process uint32_t pe_offset = self->readDWord(base+0x3C); self->read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header); self->read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)§ions ); // iterate over the list of memory locations vector<VersionInfo *>::iterator it; for ( it=known_versions.begin() ; it < known_versions.end(); it++ ) { uint32_t pe_timestamp; try { pe_timestamp = (*it)->getPE(); } catch(Error::MissingMemoryDefinition&) { continue; } if (pe_timestamp == pe_header.FileHeader.TimeDateStamp) { VersionInfo *m = new VersionInfo(**it); m->RebaseAll(base); memdescriptor = m; m->setParentProcess(self); identified = true; cerr << "identified " << m->getVersion() << endl; CloseHandle(hProcess); return true; } } return false; }
NormalProcess::NormalProcess(uint32_t pid, vector <VersionInfo *> & known_versions) : d(new Private()) { HMODULE hmod = NULL; DWORD junk; HANDLE hProcess; bool found = false; IMAGE_NT_HEADERS32 pe_header; IMAGE_SECTION_HEADER sections[16]; d->identified = false; // open process hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pid ); if (NULL == hProcess) return; // try getting the first module of the process if(EnumProcessModules(hProcess, &hmod, 1 * sizeof(HMODULE), &junk) == 0) { CloseHandle(hProcess); // cout << "EnumProcessModules fail'd" << endl; return; //if enumprocessModules fails, give up } // got base ;) uint32_t base = (uint32_t)hmod; // temporarily assign this to allow some checks d->my_handle = hProcess; d->my_main_thread = 0; // read from this process try { uint32_t pe_offset = readDWord(base+0x3C); read(base + pe_offset , sizeof(pe_header), (uint8_t *)&pe_header); read(base + pe_offset+ sizeof(pe_header), sizeof(sections) , (uint8_t *)§ions ); d->my_handle = 0; } catch (exception &) { CloseHandle(hProcess); d->my_handle = 0; return; } // see if there's a version entry that matches this process vector<VersionInfo*>::iterator it; for ( it=known_versions.begin() ; it < known_versions.end(); it++ ) { // filter by OS if(VersionInfo::OS_WINDOWS != (*it)->getOS()) continue; uint32_t pe_timestamp; // filter by timestamp, skip entries without a timestamp try { pe_timestamp = (*it)->getPE(); } catch(Error::MissingMemoryDefinition&) { continue; } if (pe_timestamp != pe_header.FileHeader.TimeDateStamp) continue; // all went well { printf("Match found! Using version %s.\n", (*it)->getVersion().c_str()); d->identified = true; // give the process a data model and memory layout fixed for the base of first module VersionInfo *m = new VersionInfo(**it); m->RebaseAll(base); // keep track of created memory_info object so we can destroy it later d->my_descriptor = m; m->setParentProcess(this); // process is responsible for destroying its data model d->my_pid = pid; d->my_handle = hProcess; d->identified = true; // TODO: detect errors in thread enumeration vector<uint32_t> threads; getThreadIDs( threads ); d->my_main_thread = OpenThread(THREAD_ALL_ACCESS, FALSE, (DWORD) threads[0]); OffsetGroup * strGrp = m->getGroup("string")->getGroup("MSVC"); d->STLSTR_buf_off = strGrp->getOffset("buffer"); d->STLSTR_size_off = strGrp->getOffset("size"); d->STLSTR_cap_off = strGrp->getOffset("capacity"); found = true; break; // break the iterator loop } } // close handle of processes that aren't DF if(!found) { CloseHandle(hProcess); } }