Exemple #1
0
/// <summary>
/// Return existing or load missing dependency
/// </summary>
/// <param name="pImage">Currently napped image data</param>
/// <param name="path">Dependency path</param>
/// <returns></returns>
const ModuleData* MMap::FindOrMapDependency( ImageContext* pImage, std::wstring& path )
{
    // For win32 one exception handler is enough
    // For amd64 each image must have it's own handler to resolve C++ exceptions properly
#ifdef _M_AMD64
    eLoadFlags newFlags = static_cast<eLoadFlags>(pImage->flags | NoSxS | NoDelayLoad);
#else
    eLoadFlags newFlags = static_cast<eLoadFlags>(pImage->flags | NoSxS | NoDelayLoad | PartialExcept);
#endif

    // Already loaded
    auto hMod = _process.modules().GetModule( path, LdrList, pImage->PEImage.mType(), pImage->FileName.c_str() );
    if (hMod)
        return hMod;

    NameResolve::Instance().ResolvePath( path, pImage->FileName,
                                         Utils::GetParent( pImage->FilePath ),
                                         NameResolve::EnsureFullPath,
                                         _process.pid(),
                                         pImage->FileImage.actx() );
    // Loading method
    if (pImage->flags & ManualImports)
        return FindOrMapModule( path, newFlags );
    else
        return _process.modules().Inject( path );
};
Exemple #2
0
/// <summary>
/// Manually map PE image into underlying target process
/// </summary>
/// <param name="path">Image path</param>
/// <param name="flags">Image mapping flags</param>
/// <returns>Mapped image info</returns>
const ModuleData* MMap::MapImage( const std::wstring& path, int flags /*= NoFlags*/ )
{
    // Already loaded
    if (auto hMod = _process.modules().GetModule( path ))
        return hMod;

    // Prepare target process
    if (_process.remote().CreateRPCEnvironment() != STATUS_SUCCESS)
        return nullptr;    

    // No need to support exceptions if DEP is disabled
    if (_process.core().DEP() == false)
        flags |= NoExceptions;

    // Ignore MapInHighMem for native x64 process
    if (!_process.core().isWow64())
        flags &= ~MapInHighMem;

    // Map module and all dependencies
    auto mod = FindOrMapModule( path, flags );
    if (mod == nullptr)
        return nullptr;

    // Change process base module address if needed
    if (flags & RebaseProcess && !_images.empty() && _images.rbegin()->get()->PEImage.IsExe())
        _process.memory().Write( _process.core().peb() + 2 * WordSize, _images.rbegin()->get()->imgMem.ptr<size_t>() );

    // Run initializers
    for (auto& img : _images)
    {
        // Init once
        if (!img->initialized)
        {
            if (!RunModuleInitializers( img.get(), DLL_PROCESS_ATTACH ))
                return nullptr;

            // Wipe header
            if (img->flags & WipeHeader)
                img->imgMem.Free( img->PEImage.headersSize() );

            img->initialized = true;
        }
    }

    return mod;
}
Exemple #3
0
	const ModuleData* MMap::FindOrMapDependency(ImageContext* pImage, std::wstring& path) {
		// Already loaded
		auto hMod = _process.Modules().GetModule(path, LdrList, pImage->peImage.ImageType(), pImage->FileName.c_str());
		if(hMod)
			return hMod;
		BLACBONE_TRACE(L"ManualMap: Loading new dependency '%ls'", path.c_str());
		auto basedir = pImage->peImage.NoPhysFile() ? Utils::GetExeDirectory() : Utils::GetParent(pImage->FilePath);
		auto status = NameResolve::Instance().ResolvePath(path, pImage->FileName, basedir, NameResolve::EnsureFullPath, _process.Id(), pImage->peImage.ActCtx());
		if(!NT_SUCCESS(status)) {
			BLACBONE_TRACE(L"ManualMap: Failed to resolve dependency path '%ls'", path.c_str());
			return nullptr;
		}
		BLACBONE_TRACE(L"ManualMap: Dependency path resolved to '%ls'", path.c_str());
		LoadData data;
		if(_mapCallback != nullptr) {
			ModuleData tmpData;
			tmpData.baseAddress = 0;
			tmpData.manual = ((pImage->flags & ManualImports) != 0);
			tmpData.fullPath = path;
			tmpData.name = Utils::StripPath(path);
			tmpData.size = 0;
			tmpData.type = mt_unknown;
			data = _mapCallback(PreCallback, _userContext, _process, tmpData);
		}
		// Loading method
		if(data.mtype == MT_Manual || (data.mtype == MT_Default && pImage->flags & ManualImports)) {
			return FindOrMapModule(path, nullptr, 0, false, pImage->flags | NoSxS | NoDelayLoad | PartialExcept);
		} else if(data.mtype != MT_None) {
			return _process.Modules().Inject(path);
		}
		// Aborted by user
		else {
			LastNtStatus(STATUS_REQUEST_CANCELED);
			return nullptr;
		}
	};
Exemple #4
0
	const ModuleData* MMap::MapImageInternal(
		const std::wstring& path,
		void* buffer, size_t size,
		bool asImage /*= false*/,
		eLoadFlags flags /*= NoFlags*/,
		MapCallback mapCallback /*= nullptr*/,
		void* context /*= nullptr*/
		) {
		// Already loaded
		if(auto hMod = _process.Modules().GetModule(path))
			return hMod;
		// Prepare target process
		if(!NT_SUCCESS(_process.Remote().CreateRPCEnvironment())) {
			Cleanup();
			return nullptr;
		}
		// No need to support exceptions if DEP is disabled
		if(_process.Core().DEP() == false)
			flags |= NoExceptions;
		// Ignore MapInHighMem for native x64 process
		if(!_process.Core().IsWOW64())
			flags &= ~MapInHighMem;
		// Set native loader callback
		_mapCallback = mapCallback;
		_userContext = context;
		BLACBONE_TRACE(L"ManualMap: Mapping image '%ls' with flags 0x%x", path.c_str(), flags);
		// Map module and all dependencies
		auto mod = FindOrMapModule(path, buffer, size, asImage, flags);
		if(mod == nullptr) {
			Cleanup();
			return nullptr;
		}
		// Change process base module address if needed
		if(flags & RebaseProcess && !_images.empty() && _images.rbegin()->get()->peImage.IsExecutable()) {
			BLACBONE_TRACE(L"ManualMap: Rebasing process to address 0x%p", static_cast<size_t>(mod->baseAddress));
			// Managed path fix
			if(_images.rbegin()->get()->peImage.PureIL() && !path.empty())
				FixManagedPath(_process.Memory().Read<size_t>(_process.Core().GetPEB() + 2 * WordSize), path);
			_process.Memory().Write(_process.Core().GetPEB() + 2 * WordSize, WordSize, &mod->baseAddress);
		}
		auto wipeMemory = [](Process& proc, ImageContext* img, size_t offset, size_t size)
		{
			size = Align(size, 0x1000);
			std::unique_ptr<uint8_t[]> zeroBuf(new uint8_t[size]());
			if(img->flags & HideVAD) {
				Driver().WriteMem(proc.Id(), img->imgMem.Ptr() + offset, size, zeroBuf.get());
			} else {
				img->imgMem.Write(offset, size, zeroBuf.get());
				if(!NT_SUCCESS(proc.Memory().Free(img->imgMem.Ptr() + offset, size)))
					proc.Memory().Protect(img->imgMem.Ptr() + offset, size, PAGE_NOACCESS);
			}
		};
		// Run initializers
		for(auto& img : _images) {
			// Init once
			if(!img->initialized) {
				// Hack for IL dlls
				if(!img->peImage.IsExecutable() && img->peImage.PureIL()) {
					DWORD flOld = 0;
					auto flg = img->imgMem.Read(img->peImage.ILFlagOffset(), 0);
					img->imgMem.Protect(PAGE_EXECUTE_READWRITE, img->peImage.ILFlagOffset(), sizeof(flg), &flOld);
					img->imgMem.Write(img->peImage.ILFlagOffset(), flg & ~COMIMAGE_FLAGS_ILONLY);
					img->imgMem.Protect(flOld, img->peImage.ILFlagOffset(), sizeof(flg), &flOld);
				}
				if(!RunModuleInitializers(img.get(), DLL_PROCESS_ATTACH))
					return nullptr;
				// Wipe header
				if(img->flags & WipeHeader)
					wipeMemory(_process, img.get(), 0, img->peImage.HeadersSize());
				// Wipe discardable sections for non pure IL images
				for(auto& sec : img->peImage.Sections())
					if(sec.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
						wipeMemory(_process, img.get(), sec.VirtualAddress, sec.Misc.VirtualSize);
				img->initialized = true;
			}
		}
		Cleanup();
		return mod;
	}