Example #1
0
	/// <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;
	}
Example #2
0
/// <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;
}