/// <summary> /// Get existing module or map it if absent /// </summary> /// <param name="path">Image path</param> /// <param name="buffer">Image data buffer</param> /// <param name="size">Buffer size.</param> /// <param name="asImage">If set to true - buffer has image memory layout</param> /// <param name="flags">Mapping flags</param> /// <returns>Module info</returns> const ModuleData* MMap::FindOrMapModule( const std::wstring& path, void* buffer, size_t size, bool asImage, eLoadFlags flags /*= NoFlags*/ ) { NTSTATUS status = STATUS_SUCCESS; std::unique_ptr<ImageContext> pImage(new ImageContext()); pImage->FilePath = path; pImage->FileName = Utils::StripPath(pImage->FilePath); pImage->flags = flags; // Load and parse image status = buffer ? pImage->peImage.Load(buffer, size, !asImage) : pImage->peImage.Load(path, flags & NoSxS ? true : false); if(!NT_SUCCESS(status)) { BLACBONE_TRACE(L"ManualMap: Failed to load image '%ls'/0x%p. Status 0x%X", path.c_str(), buffer, status); pImage->peImage.Release(); return nullptr; } // Check if already loaded if(auto hMod = _process.Modules().GetModule(path, LdrList, pImage->peImage.ImageType())) { pImage->peImage.Release(); return hMod; } BLACBONE_TRACE(L"ManualMap: Loading new image '%ls'", path.c_str()); // Try to map image in high (>4GB) memory range if(flags & MapInHighMem) { AllocateInHighMem(pImage->imgMem, pImage->peImage.ImageSize()); } // Try to map image at it's original ASRL-aware base else if(flags & HideVAD) { ptr_t base = pImage->peImage.ImageBase(); ptr_t isize = pImage->peImage.ImageSize(); if(!NT_SUCCESS(Driver().EnsureLoaded())) { pImage->peImage.Release(); return nullptr; } // Allocate as physical at desired base status = Driver().AllocateMem(_process.Id(), base, isize, MEM_COMMIT, PAGE_EXECUTE_READWRITE, true); // Allocate at any base if(!NT_SUCCESS(status)) { base = 0; size = pImage->peImage.ImageSize(); status = Driver().AllocateMem(_process.Id(), base, isize, MEM_COMMIT, PAGE_EXECUTE_READWRITE, true); } // Store allocated region if(NT_SUCCESS(status)) { pImage->imgMem = MemBlock(&_process.Memory(), base, static_cast<size_t>(isize), PAGE_EXECUTE_READWRITE, true, true); } // Stop mapping else { //flags &= ~HideVAD; BLACBONE_TRACE(L"ManualMap: Failed to allocate physical memory for image, status 0x%d", status); pImage->peImage.Release(); return nullptr; } } // Allocate normally if something went wrong if(pImage->imgMem == 0) pImage->imgMem = _process.Memory().Allocate(pImage->peImage.ImageSize(), PAGE_EXECUTE_READWRITE, pImage->peImage.ImageBase()); BLACBONE_TRACE(L"ManualMap: Image base allocated at 0x%p", pImage->imgMem.Ptr<size_t>()); if(!pImage->imgMem.Valid()) return nullptr; // Create Activation context for SxS if(pImage->peImage.ManifestID() == 0) flags |= NoSxS; if(!(flags & NoSxS)) CreateActx(pImage->peImage.ManifestFile(), pImage->peImage.ManifestID(), !pImage->peImage.NoPhysFile()); // Core image mapping operations if(!CopyImage(pImage.get()) || !RelocateImage(pImage.get())) { pImage->peImage.Release(); return nullptr; } auto mt = pImage->peImage.ImageType(); auto pMod = _process.Modules().AddManualModule(pImage->FilePath, pImage->imgMem.Ptr<module_t>(), pImage->imgMem.Size(), mt); // Import tables if(!ResolveImport(pImage.get()) || (!(flags & NoDelayLoad) && !ResolveImport(pImage.get(), true))) { pImage->peImage.Release(); _process.Modules().RemoveManualModule(pImage->FileName, mt); return nullptr; } // Apply proper memory protection for sections if(!(flags & HideVAD)) ProtectImageMemory(pImage.get()); // Make exception handling possible (C and C++) if(!(flags & NoExceptions)) { status = EnableExceptions(pImage.get()); if(!NT_SUCCESS(status) && status != STATUS_NOT_FOUND) { BLACBONE_TRACE(L"ManualMap: Failed to enable exception handling for image %ls", pImage->FileName.c_str()); pImage->peImage.Release(); _process.Modules().RemoveManualModule(pImage->FileName, mt); return nullptr; } } // Unlink image from VAD list if(flags & HideVAD && !NT_SUCCESS(ConcealVad(pImage->imgMem))) { pImage->peImage.Release(); _process.Modules().RemoveManualModule(pImage->FileName, mt); return nullptr; } // Initialize security cookie if(!InitializeCookie(pImage.get())) { pImage->peImage.Release(); _process.Modules().RemoveManualModule(pImage->FileName, mt); return nullptr; } // Get entry point pImage->EntryPoint = pImage->peImage.EntryPoint(pImage->imgMem.Ptr<ptr_t>()); // Create reference for native loader functions LdrRefFlags ldrFlags = flags & CreateLdrRef ? Ldr_All : Ldr_None; if(_mapCallback != nullptr) { auto mapData = _mapCallback(PostCallback, _userContext, _process, *pMod); ldrFlags = mapData.ldrFlags; } if(ldrFlags != Ldr_None) { _process.NativeLdr().CreateNTReference( pImage->imgMem.Ptr<HMODULE>(), pImage->peImage.ImageSize(), pImage->FilePath, static_cast<size_t>(pImage->EntryPoint), ldrFlags ); } // Static TLS data if(!(flags & NoTLS) && !InitStaticTLS(pImage.get())) { pImage->peImage.Release(); _process.Modules().RemoveManualModule(pImage->FileName, mt); return nullptr; } // Fill TLS callbacks pImage->peImage.GetTLSCallbacks(pImage->imgMem.Ptr<ptr_t>(), pImage->tlsCallbacks); // Unload local copy pImage->peImage.Release(); // Release ownership of image memory block pImage->imgMem.Release(); // Store image _images.emplace_back(std::move(pImage)); return pMod; }
/// <summary> /// Get existing module or map it if absent /// </summary> /// <param name="path">Image path</param> /// <param name="flags">Mapping flags</param> /// <returns>Module info</returns> const ModuleData* MMap::FindOrMapModule( const std::wstring& path, int flags /*= NoFlags*/ ) { std::unique_ptr<ImageContext> pImage( new ImageContext() ); pImage->FilePath = path; pImage->FileName = Utils::StripPath( pImage->FilePath ); pImage->flags = static_cast<eLoadFlags>(flags); // Load and parse image if (!pImage->FileImage.Project( path ) || !pImage->PEImage.Parse( pImage->FileImage, pImage->FileImage.isPlainData() )) return nullptr; // Check if already loaded if (auto hMod = _process.modules().GetModule( path, LdrList, pImage->PEImage.mType() )) return hMod; // Try to map image in high memory range if (flags & MapInHighMem) { if (AllocateInHighMem( pImage->imgMem, pImage->PEImage.imageSize() ) == false) pImage->imgMem = _process.memory().Allocate( pImage->PEImage.imageSize( ), PAGE_EXECUTE_READWRITE, pImage->PEImage.imageBase() ); } // Try to map image at it's original ASRL-aware base else { pImage->imgMem = _process.memory().Allocate( pImage->PEImage.imageSize(), PAGE_EXECUTE_READWRITE, pImage->PEImage.imageBase() ); } if (!pImage->imgMem.valid()) return nullptr; // Create Activation context for SxS // .exe files usually contain manifest under id of 1 // .dll files have manifest under id of 2 if (!(flags & NoSxS)) CreateActx( path, pImage->FileImage.manifestID() ); // Manual Debug tests only /*if (!(flags & NoExceptions)) { MExcept::pImageBase = pImage->image.ptr<void*>( ); MExcept::imageSize = pImage->PEImage.imageSize( ); }*/ // Core image mapping operations if (!CopyImage( pImage.get() ) || !RelocateImage( pImage.get() )) return nullptr; auto mt = pImage->PEImage.mType(); auto pMod = _process.modules().AddManualModule( pImage->FilePath, pImage->imgMem.ptr<module_t>(), pImage->imgMem.size(), mt ); // Import tables if (!ResolveImport( pImage.get() ) || (!(flags & NoDelayLoad) && !ResolveImport( pImage.get(), true ))) { _process.modules().RemoveManualModule( pImage->FileName, mt ); return nullptr; } // Apply proper memory protection for sections ProtectImageMemory( pImage.get() ); // Make exception handling possible (C and C++) if (!(flags & NoExceptions) && !EnableExceptions( pImage.get() )) { _process.modules().RemoveManualModule( pImage->FileName, mt ); return nullptr; } // Unlink image from VAD list if (flags & UnlinkVAD) UnlinkVad( pImage->imgMem ); // Initialize security cookie if (!InitializeCookie( pImage.get() )) { _process.modules().RemoveManualModule( pImage->FileName, mt ); return nullptr; } // Create reference for native loader functions if (flags & CreateLdrRef) _process.nativeLdr().CreateNTReference( pImage->imgMem.ptr<HMODULE>(), pImage->PEImage.imageSize(), pImage->FilePath ); // Static TLS data if (!(flags & NoTLS) &&! InitStaticTLS( pImage.get( ) )) { _process.modules().RemoveManualModule( pImage->FileName, mt ); return nullptr; } // Fill TLS callbacks pImage->PEImage.GetTLSCallbacks( pImage->imgMem.ptr<ptr_t>(), pImage->tlsCallbacks ); // Get entry point pImage->EntryPoint = pImage->PEImage.entryPoint( pImage->imgMem.ptr<ptr_t>() ); // Unload local copy pImage->FileImage.Release(); // Release image pImage->imgMem.Release(); // Store image _images.emplace_back( std::move( pImage ) ); return pMod; }