Exemplo n.º 1
0
	bool MMap::RunModuleInitializers(ImageContext* pImage, DWORD dwReason) {
		AsmJitHelper a;
		uint64_t result = 0;
		auto hNtdll = _process.Modules().GetModule(L"ntdll.dll", LdrList, pImage->peImage.ImageType());
		auto pActivateActx = _process.Modules().GetExport(hNtdll, "RtlActivateActivationContext");
		auto pDeactivateeActx = _process.Modules().GetExport(hNtdll, "RtlDeactivateActivationContext");
		a.GenPrologue();
		// ActivateActCtx
		if(_pAContext.Valid() && pActivateActx.procAddress) {
			a->mov(a->zax, _pAContext.Ptr<size_t>());
			a->mov(a->zax, asmjit::host::dword_ptr(a->zax));
			a.GenCall(static_cast<size_t>(pActivateActx.procAddress), {0, a->zax, _pAContext.Ptr<size_t>() + sizeof(HANDLE)});
		}
		// Function order
		// TLS first, entry point last
		if(dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH) {
			// PTLS_CALLBACK_FUNCTION(pImage->ImageBase, dwReason, NULL);
			if(!(pImage->flags & NoTLS))
				for(auto& pCallback : pImage->tlsCallbacks) {
					BLACBONE_TRACE(L"ManualMap: Calling TLS callback at 0x%p for '%ls', Reason: %d",
						static_cast<size_t>(pCallback), pImage->FileName.c_str(), dwReason);
					a.GenCall(static_cast<size_t>(pCallback), {pImage->imgMem.Ptr<size_t>(), dwReason, NULL});
				}
			// DllMain
			if(pImage->EntryPoint != 0) {
				BLACBONE_TRACE(L"ManualMap: Calling entry point for '%ls', Reason: %d", pImage->FileName.c_str(), dwReason);
				a.GenCall(static_cast<size_t>(pImage->EntryPoint), {pImage->imgMem.Ptr<size_t>(), dwReason, NULL});
			}
		}
		// Entry point first, TLS last
		else {
			// DllMain
			if(pImage->EntryPoint != 0) {
				BLACBONE_TRACE(L"ManualMap: Calling entry point for '%ls', Reason: %d", pImage->FileName.c_str(), dwReason);
				a.GenCall(static_cast<size_t>(pImage->EntryPoint), {pImage->imgMem.Ptr<size_t>(), dwReason, NULL});
			}
			// PTLS_CALLBACK_FUNCTION(pImage->ImageBase, dwReason, NULL);
			if(!(pImage->flags & NoTLS))
				for(auto& pCallback : pImage->tlsCallbacks) {
					BLACBONE_TRACE(L"ManualMap: Calling TLS callback at 0x%p for '%ls', Reason: %d",
						static_cast<size_t>(pCallback), pImage->FileName.c_str(), dwReason);
					a.GenCall(static_cast<size_t>(pCallback), {pImage->imgMem.Ptr<size_t>(), dwReason, NULL});
				}
		}
		// DeactivateActCtx
		if(_pAContext.Valid() && pDeactivateeActx.procAddress) {
			a->mov(a->zax, _pAContext.Ptr<size_t>() + sizeof(HANDLE));
			a->mov(a->zax, asmjit::host::dword_ptr(a->zax));
			a.GenCall(static_cast<size_t>(pDeactivateeActx.procAddress), {0, a->zax});
		}
		_process.Remote().AddReturnWithEvent(a, pImage->peImage.ImageType());
		a.GenEpilogue();
		_process.Remote().ExecInWorkerThread(a->make(), a->getCodeSize(), result);
		return true;
	}
Exemplo n.º 2
0
	bool MMap::RelocateImage(ImageContext* pImage) {
		BLACBONE_TRACE(L"ManualMap: Relocating image '%ls'", pImage->FilePath.c_str());
		// Reloc delta
		size_t Delta = pImage->imgMem.Ptr<size_t>() - static_cast<size_t>(pImage->peImage.ImageBase());
		// No need to relocate
		if(Delta == 0) {
			BLACBONE_TRACE(L"ManualMap: No need for relocation");
			LastNtStatus(STATUS_SUCCESS);
			return true;
		}
		auto start = pImage->peImage.DirectoryAddress(IMAGE_DIRECTORY_ENTRY_BASERELOC);
		auto end = start + pImage->peImage.DirectorySize(IMAGE_DIRECTORY_ENTRY_BASERELOC);
		RelocData* fixrec = reinterpret_cast<RelocData*>(start);
		if(fixrec == nullptr) {
			// TODO: return proper error code
			BLACBONE_TRACE(L"ManualMap: Can't relocate image, no relocation data");
			LastNtStatus(STATUS_IMAGE_NOT_AT_BASE);
			return false;
		}
		while((size_t)fixrec < end && fixrec->BlockSize) {
			DWORD count = (fixrec->BlockSize - 8) >> 1;             // records count
			for(DWORD i = 0; i < count; ++i) {
				WORD fixtype = (fixrec->Item[i].Type);              // fixup type
				WORD fixoffset = (fixrec->Item[i].Offset) % 4096;   // offset in 4K block
																	// no fixup required
				if(fixtype == IMAGE_REL_BASED_ABSOLUTE)
					continue;
				// add delta 
				if(fixtype == IMAGE_REL_BASED_HIGHLOW || fixtype == IMAGE_REL_BASED_DIR64) {
					size_t fixRVA = fixoffset + fixrec->PageRVA;
					size_t val = *reinterpret_cast<size_t*>(pImage->peImage.ResolveRVAToVA(fixoffset + fixrec->PageRVA)) + Delta;
					auto status = STATUS_SUCCESS;
					if(pImage->flags & HideVAD)
						status = Driver().WriteMem(_process.Id(), pImage->imgMem.Ptr() + fixRVA, sizeof(val), &val);
					else
						status = pImage->imgMem.Write(fixRVA, val);
					// Apply relocation
					if(!NT_SUCCESS(status)) {
						BLACBONE_TRACE(L"ManualMap: Failed to apply relocation at offset 0x%x. Status = 0x%x", fixRVA, status);
						return false;
					}
				} else {
					// TODO: support for all remaining relocations
					BLACBONE_TRACE(L"ManualMap: Abnormal relocation type %d. Aborting", fixtype);
					LastNtStatus(STATUS_INVALID_IMAGE_FORMAT);
					return false;
				}
			}
			// next reloc entry
			fixrec = reinterpret_cast<RelocData*>(reinterpret_cast<size_t>(fixrec) + fixrec->BlockSize);
		}
		return true;
	}
Exemplo n.º 3
0
/// <summary>
/// Reload driver
/// </summary>
/// <param name="path">Path to the driver file</param>
/// <returns>Status code</returns>
NTSTATUS DriverControl::Reload( std::wstring path /*= L"" */ )
{
    NTSTATUS status = STATUS_SUCCESS;

    Unload();

    // Use default path
    if (path.empty())
    {
        const wchar_t* filename = nullptr;

        if (IsWindows10OrGreater())
            filename = L"BlackBoneDrv10.sys";
        else if (IsWindows8Point1OrGreater())
            filename = L"BlackBoneDrv81.sys";
        else if (IsWindows8OrGreater())
            filename = L"BlackBoneDrv8.sys";
        else if (IsWindows7OrGreater())
            filename = L"BlackBoneDrv7.sys";
        else
            filename = L"BlackBoneDrv.sys";

        path = Utils::GetExeDirectory() + L"\\" + filename;
    }

    status = _loadStatus = LoadDriver( DRIVER_SVC_NAME, path );
    if (!NT_SUCCESS( status ))
    {
        BLACBONE_TRACE( L"Failed to load driver %ls. Status 0x%X", path.c_str(), status );
        return LastNtStatus( status );
    }

    _hDriver = CreateFileW(
                   BLACKBONE_DEVICE_FILE,
                   GENERIC_READ | GENERIC_WRITE,
                   FILE_SHARE_READ | FILE_SHARE_WRITE,
                   NULL, OPEN_EXISTING, 0, NULL
               );

    if (_hDriver == INVALID_HANDLE_VALUE)
    {
        status = LastNtStatus();
        BLACBONE_TRACE( L"Failed to open driver handle. Status 0x%X", status );
        return status;
    }

    return status;
}
Exemplo n.º 4
0
	bool MMap::InitializeCookie(ImageContext* pImage) {
		auto pLC = reinterpret_cast<PIMAGE_LOAD_CONFIG_DIRECTORY>(pImage->peImage.DirectoryAddress(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG));
		//
		// Cookie generation based on MSVC++ compiler
		//
		if(pLC && pLC->SecurityCookie) {
			BLACBONE_TRACE(L"ManualMap: Performing security cookie initializtion for image '%ls'", pImage->FileName.c_str());
			FILETIME systime = {0};
			LARGE_INTEGER PerformanceCount = {{0}};
			uintptr_t cookie = 0;
			GetSystemTimeAsFileTime(&systime);
			QueryPerformanceCounter(&PerformanceCount);
			cookie = _process.Id() ^ _process.Remote().GetWorkerThread()->Id() ^ reinterpret_cast<uintptr_t>(&cookie);
			#ifdef USE64
			cookie ^= *reinterpret_cast<uint64_t*>(&systime);
			cookie ^= (PerformanceCount.QuadPart << 32) ^ PerformanceCount.QuadPart;
			cookie &= 0xFFFFFFFFFFFF;
			if(cookie == 0x2B992DDFA232)
				cookie++;
			#else
			cookie ^= systime.dwHighDateTime ^ systime.dwLowDateTime;
			cookie ^= PerformanceCount.LowPart;
			cookie ^= PerformanceCount.HighPart;
			if(cookie == 0xBB40E64E)
				cookie++;
			else if(!(cookie & 0xFFFF0000))
				cookie |= (cookie | 0x4711) << 16;
			#endif
			_process.Memory().Write(REBASE(pLC->SecurityCookie, pImage->peImage.ImageBase(), pImage->imgMem.Ptr<ptr_t>()), cookie);
		}
		return true;
	}
Exemplo n.º 5
0
	NTSTATUS MMap::DisableExceptions(ImageContext* pImage) {
		BLACBONE_TRACE(L"ManualMap: Disabling exception support for image '%ls'", pImage->FileName.c_str());
		#ifdef USE64
		if(pImage->pExpTableAddr) {
			AsmJitHelper a;
			size_t result = 0;
			auto pRemoveTable = _process.Modules().GetExport(
				_process.Modules().GetModule(L"ntdll.dll", LdrList, pImage->peImage.ImageType()),
				"RtlDeleteFunctionTable"
				);
			a.GenPrologue();
			// RtlDeleteFunctionTable(pExpTable);
			a.GenCall(static_cast<size_t>(pRemoveTable.procAddress), {pImage->pExpTableAddr});
			_process.Remote().AddReturnWithEvent(a);
			a.GenEpilogue();
			auto status = _process.Remote().ExecInWorkerThread(a->make(), a->getCodeSize(), result);
			if(!NT_SUCCESS(status))
				return status;
			return MExcept::RemoveVEH((pImage->flags & CreateLdrRef) != 0);
		} else
			return STATUS_NOT_FOUND;
		#else
		return MExcept::RemoveVEH((pImage->flags & PartialExcept) != 0);
		#endif
	}
Exemplo n.º 6
0
	/// <summary>
	/// Copies image into target process
	/// </summary>
	/// <param name="pImage">Image data</param>
	/// <returns>true on success</returns>
	bool MMap::CopyImage(ImageContext* pImage) {
		NTSTATUS status = STATUS_SUCCESS;
		BLACBONE_TRACE(L"ManualMap: Performing image copy");
		// offset to first section equals to header size
		size_t dwHeaderSize = pImage->peImage.HeadersSize();
		// Copy header
		if(pImage->flags & HideVAD)
			status = Driver().WriteMem(_process.Id(), pImage->imgMem.Ptr(), dwHeaderSize, pImage->peImage.FileBase());
		else
			status = pImage->imgMem.Write(0, dwHeaderSize, pImage->peImage.FileBase());
		if(!NT_SUCCESS(status)) {
			BLACBONE_TRACE(L"ManualMap: Failed to copy image headers. Status = 0x%x", status);
			return false;
		}
		// Set header protection
		if(!(pImage->flags & HideVAD) && pImage->imgMem.Protect(PAGE_READONLY, 0, dwHeaderSize) != STATUS_SUCCESS) {
			BLACBONE_TRACE(L"ManualMap: Failed to set header memory protection. Status = 0x%x", LastNtStatus());
			return false;
		}
		auto& sections = pImage->peImage.Sections();
		// Copy sections
		for(auto& section : sections) {
			// Skip discardable sections
			if(section.Characteristics & (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_EXECUTE)) {
				if(section.SizeOfRawData == 0)
					continue;
				uint8_t* pSource = reinterpret_cast<uint8_t*>(pImage->peImage.ResolveRVAToVA(section.VirtualAddress));
				// Copy section data
				if(pImage->flags & HideVAD) {
					status = Driver().WriteMem(
						_process.Id(), pImage->imgMem.Ptr() + section.VirtualAddress,
						section.SizeOfRawData, pSource
						);
				} else {
					status = pImage->imgMem.Write(section.VirtualAddress, section.SizeOfRawData, pSource);
				}
				if(!NT_SUCCESS(status)) {
					BLACBONE_TRACE(
						L"ManualMap: Failed to copy image section at offset 0x%x. Status = 0x%x",
						section.VirtualAddress, status
						);
					return false;
				}
			}
		}
		return true;
	}
Exemplo n.º 7
0
	bool MMap::InitStaticTLS(ImageContext* pImage) {
		IMAGE_TLS_DIRECTORY *pTls = reinterpret_cast<decltype(pTls)>(pImage->peImage.DirectoryAddress(IMAGE_DIRECTORY_ENTRY_TLS));
		auto pRebasedTls = reinterpret_cast<IMAGE_TLS_DIRECTORY*>(REBASE(pTls, pImage->peImage.FileBase(), pImage->imgMem.Ptr<ptr_t>()));
		// Use native TLS initialization
		if(pTls && pTls->AddressOfIndex) {
			BLACBONE_TRACE(L"ManualMap: Performing static TLS initialization for image '%ls'", pImage->FileName.c_str());
			_process.NativeLdr().AddStaticTLSEntry(pImage->imgMem.Ptr<void*>(), pRebasedTls);
		}
		return true;
	}
Exemplo n.º 8
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;
		}
	};
Exemplo n.º 9
0
	bool MMap::ProtectImageMemory(ImageContext* pImage) {
		// Set section memory protection
		for(auto& section : pImage->peImage.Sections()) {
			auto prot = GetSectionProt(section.Characteristics);
			if(prot != PAGE_NOACCESS) {
				if(pImage->imgMem.Protect(prot, section.VirtualAddress, section.Misc.VirtualSize) != STATUS_SUCCESS) {
					BLACBONE_TRACE(
						L"ManualMap: Failed to set section memory protection at offset 0x%x. Status = 0x%x",
						section.VirtualAddress, LastNtStatus()
						);
					return false;
				}
			}
			// Decommit pages with NO_ACCESS protection
			else {
				_process.Memory().Free(pImage->imgMem.Ptr() + section.VirtualAddress, section.Misc.VirtualSize, MEM_DECOMMIT);
			}
		}
		return true;
	}
Exemplo n.º 10
0
	NTSTATUS MMap::EnableExceptions(ImageContext* pImage) {
		BLACBONE_TRACE(L"ManualMap: Enabling exception support for image '%ls'", pImage->FileName.c_str());
		bool partial = (pImage->flags & PartialExcept) != 0;
		#ifdef USE64
		size_t size = pImage->peImage.DirectorySize(IMAGE_DIRECTORY_ENTRY_EXCEPTION);
		auto pExpTable = reinterpret_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(pImage->peImage.DirectoryAddress(IMAGE_DIRECTORY_ENTRY_EXCEPTION));
		// Invoke RtlAddFunctionTable
		if(pExpTable) {
			AsmJitHelper a;
			uint64_t result = 0;
			pImage->pExpTableAddr = REBASE(pExpTable, pImage->peImage.FileBase(), pImage->imgMem.Ptr<ptr_t>());
			auto pAddTable = _process.Modules().GetExport(
				_process.Modules().GetModule(L"ntdll.dll", LdrList, pImage->peImage.ImageType()),
				"RtlAddFunctionTable"
				);
			a.GenPrologue();
			a.GenCall(
				static_cast<size_t>(pAddTable.procAddress), {
					pImage->pExpTableAddr,
					size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY),
				pImage->imgMem.Ptr<size_t>()}
			);
			_process.Remote().AddReturnWithEvent(a, pImage->peImage.ImageType());
			a.GenEpilogue();
			auto status = _process.Remote().ExecInWorkerThread(a->make(), a->getCodeSize(), result);
			if(!NT_SUCCESS(status))
				return status;
			return (pImage->flags & CreateLdrRef) ? STATUS_SUCCESS :
				MExcept::CreateVEH(pImage->imgMem.Ptr<size_t>(), pImage->peImage.ImageSize(), pImage->peImage.ImageType(), partial);
		}
		// No exception table
		else
			return STATUS_NOT_FOUND;
		#else
		bool safeseh = false;
		if(!_process.NativeLdr().InsertInvertedFunctionTable(pImage->imgMem.Ptr<void*>(), pImage->peImage.ImageSize(), safeseh))
			return STATUS_UNSUCCESSFUL;
		return safeseh ? STATUS_SUCCESS :
			MExcept::CreateVEH(pImage->imgMem.Ptr<size_t>(), pImage->peImage.ImageSize(), pImage->peImage.ImageType(), partial);
		#endif
	}
Exemplo n.º 11
0
	/// <summary>
	/// Unmap all manually mapped modules
	/// </summary>
	/// <returns>true on success</returns>
	bool MMap::UnmapAllModules() {
		for(auto img = _images.rbegin(); img != _images.rend(); ++img) {
			auto pImage = img->get();
			BLACBONE_TRACE(L"ManualMap: Unmapping image '%ls'", pImage->FileName.c_str());
			// Call main
			RunModuleInitializers(pImage, DLL_PROCESS_DETACH);
			// Remove VEH
			if(!(pImage->flags & NoExceptions))
				DisableExceptions(pImage);
			// Remove from loader
			auto mod = _process.Modules().GetModule(pImage->FileName);
			_process.Modules().Unlink(mod);
			// Free memory
			pImage->imgMem.Free();
			// Remove reference from local modules list
			_process.Modules().RemoveManualModule(pImage->FilePath, pImage->peImage.ImageType());
		}
		Cleanup();
		Reset();
		return true;
	}
Exemplo n.º 12
0
	bool MMap::CreateActx(const std::wstring& path, int id /*= 2 */, bool asImage /*= true*/) {
		AsmJitHelper a;
		uint64_t result = 0;
		ACTCTXW act = {0};
		_pAContext = _process.Memory().Allocate(512, PAGE_READWRITE);
		act.cbSize = sizeof(act);
		act.lpSource = reinterpret_cast<LPCWSTR>(_pAContext.Ptr<size_t>() + sizeof(HANDLE) + sizeof(act));
		// Ignore some fields for pure manifest file
		if(asImage) {
			act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
			act.lpResourceName = MAKEINTRESOURCEW(id);
		}
		bool switchMode = (_process.Core().GetNative()->GetWow64Barrier().type == wow_64_32);
		auto pCreateActx = _process.Modules().GetExport(_process.Modules().GetModule(L"kernel32.dll"), "CreateActCtxW");
		if(pCreateActx.procAddress == 0) {
			BLACBONE_TRACE(L"ManualMap: Failed to create activation context for image '%ls'. 'CreateActCtxW' is absent", path.c_str());
			return false;
		}
		// CreateActCtx(&act)
		// Emulate Wow64
		if(switchMode) {
			_ACTCTXW_T<DWORD> act32 = {0};
			act32.cbSize = sizeof(act32);
			act32.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
			act32.lpSource = _pAContext.Ptr<uint32_t>() + sizeof(HANDLE) + sizeof(act32);
			act32.lpResourceName = id;
			a->push(_pAContext.Ptr<uint32_t>() + static_cast<uint32_t>(sizeof(HANDLE)));
			a->mov(asmjit::host::eax, static_cast<uint32_t>(pCreateActx.procAddress));
			a->call(a->zax);
			a->mov(asmjit::host::edx, _pAContext.Ptr<uint32_t>());
			//a->mov( asmjit::host::dword_ptr( asmjit::host::edx ), asmjit::host::eax );
			a->dw('\x01\x02');
			auto pTermThd = _process.Modules().GetExport(_process.Modules().GetModule(L"ntdll.dll"), "NtTerminateThread");
			a->push(a->zax);
			a->push(uint32_t(0));
			a->mov(asmjit::host::eax, static_cast<uint32_t>(pTermThd.procAddress));
			a->call(a->zax);
			a->ret(4);
			// Write path to file
			_pAContext.Write(sizeof(HANDLE), act32);
			_pAContext.Write(sizeof(HANDLE) + sizeof(act32), (path.length() + 1) * sizeof(wchar_t), path.c_str());
			auto pCode = _process.Memory().Allocate(0x1000);
			pCode.Write(0, a->getCodeSize(), a->make());
			result = _process.Remote().ExecDirect(pCode.Ptr<ptr_t>(), _pAContext.Ptr<size_t>() + sizeof(HANDLE));
		}
		// Native way
		else {
			a.GenPrologue();
			a.GenCall(static_cast<size_t>(pCreateActx.procAddress), {_pAContext.Ptr<size_t>() + sizeof(HANDLE)});
			a->mov(a->zdx, _pAContext.Ptr<size_t>());
			a->mov(a->intptr_ptr(a->zdx), a->zax);
			_process.Remote().AddReturnWithEvent(a);
			a.GenEpilogue();
			// Write path to file
			_pAContext.Write(sizeof(HANDLE), act);
			_pAContext.Write(sizeof(HANDLE) + sizeof(act), (path.length() + 1) * sizeof(wchar_t), path.c_str());
			_process.Remote().ExecInWorkerThread(a->make(), a->getCodeSize(), result);
		}
		if(reinterpret_cast<HANDLE>(result) == INVALID_HANDLE_VALUE) {
			_pAContext.Free();
			// SetLastError( err::mapping::CantCreateActx );
			BLACBONE_TRACE(L"ManualMap: Failed to create activation context for image '%ls'. Status: 0x%x",
				path.c_str(), _process.Remote().GetLastStatus());
			return false;
		}
		return true;
	}
Exemplo n.º 13
0
	bool MMap::ResolveImport(ImageContext* pImage, bool useDelayed /*= false */) {
		auto imports = pImage->peImage.GetImports(useDelayed);
		if(imports.empty())
			return true;
		// Traverse entries
		for(auto& importMod : imports) {
			std::wstring wstrDll = importMod.first;
			// Load dependency if needed
			auto hMod = FindOrMapDependency(pImage, wstrDll);
			if(!hMod) {
				// TODO: Add error code
				BLACBONE_TRACE(L"ManualMap: Failed to load dependency '%ls'. Status = 0x%x", wstrDll.c_str(), LastNtStatus());
				return false;
			}
			for(auto& importFn : importMod.second) {
				exportData expData;
				if(importFn.importByOrd)
					expData = _process.Modules().GetExport(hMod, reinterpret_cast<const char*>(importFn.importOrdinal));
				else
					expData = _process.Modules().GetExport(hMod, importFn.importName.c_str());
				// Still forwarded, load missing modules
				while(expData.procAddress && expData.isForwarded) {
					std::wstring wdllpath = expData.forwardModule;
					// Ensure module is loaded
					auto hFwdMod = FindOrMapDependency(pImage, wdllpath);
					if(!hFwdMod) {
						// TODO: Add error code
						BLACBONE_TRACE(L"ManualMap: Failed to load forwarded dependency '%ls'. Status = 0x%x", wstrDll.c_str(), LastNtStatus());
						return false;
					}
					if(expData.forwardByOrd)
						expData = _process.Modules().GetExport(hFwdMod, reinterpret_cast<const char*>(expData.forwardOrdinal), wdllpath.c_str());
					else
						expData = _process.Modules().GetExport(hFwdMod, expData.forwardName.c_str(), wdllpath.c_str());
				}
				// Failed to resolve import
				if(expData.procAddress == 0) {
					LastNtStatus(STATUS_ORDINAL_NOT_FOUND);
					if(importFn.importByOrd)
						BLACBONE_TRACE(L"ManualMap: Failed to get import #%d from image '%ls'",
							importFn.importOrdinal, wstrDll.c_str());
					else
						BLACBONE_TRACE(L"ManualMap: Failed to get import '%ls' from image '%ls'",
							Utils::AnsiToWstring(importFn.importName).c_str(), wstrDll.c_str());
					return false;
				}
				auto status = STATUS_SUCCESS;
				if(pImage->flags & HideVAD) {
					size_t address = static_cast<size_t>(expData.procAddress);
					status = Driver().WriteMem(_process.Id(), pImage->imgMem.Ptr() + importFn.ptrRVA, sizeof(address), &address);
				} else
					status = pImage->imgMem.Write(importFn.ptrRVA, static_cast<size_t>(expData.procAddress));
				// Write function address
				if(!NT_SUCCESS(status)) {
					BLACBONE_TRACE(L"ManualMap: Failed to write import function address at offset 0x%x. Status = 0x%x",
						importFn.ptrRVA, status);
					return false;
				}
			}
		}
		return true;
	}
Exemplo n.º 14
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;
	}
Exemplo n.º 15
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;
	}
Exemplo n.º 16
0
	NTSTATUS MExcept::CreateVEH(size_t pTargetBase, size_t imageSize, eModType mt, bool partial) {
		AsmJitHelper a;
		uint64_t result = 0;
		auto& mods = _proc.Modules();
		#ifdef USE64 
		// Add module to module table
		if(!_pModTable.Valid()) {
			_pModTable = _proc.Memory().Allocate(0x1000);
			_pModTable.Release();
			if(!_pModTable.Valid())
				return LastNtStatus();
		}
		ModuleTable table;
		_pModTable.Read(0, table);
		// Add new entry to the table
		table.entry[table.count].base = pTargetBase;
		table.entry[table.count].size = imageSize;
		table.count++;
		_pModTable.Write(0, table);
		// No handler required
		if(partial)
			return STATUS_SUCCESS;
		// VEH codecave
		_pVEHCode = _proc.Memory().Allocate(0x2000);
		_pVEHCode.Release();
		if(!_pVEHCode.Valid())
			return LastNtStatus();
		BLACBONE_TRACE("ManualMap: Vectored hander: 0x%p\n", _pVEHCode.Ptr());
		asmjit::Label lExit = a->newLabel();
		asmjit::Label lLoop1 = a->newLabel();
		asmjit::Label skip1 = a->newLabel();
		asmjit::Label found1 = a->newLabel();
		//
		// Assembly code for VectoredHandler64
		// 0x10 - EXCEPTION_RECORD.ExceptionAddress
		// 0x20 - EXCEPTION_RECORD.ExceptionInformation[0]
		// 0x30 - EXCEPTION_RECORD.ExceptionInformation[2]
		// 0x38 - EXCEPTION_RECORD.ExceptionInformation[3]
		//
		a->mov(asmjit::host::rax, asmjit::host::qword_ptr(asmjit::host::rcx));
		a->cmp(asmjit::host::dword_ptr(asmjit::host::rax), EH_EXCEPTION_NUMBER);            // Exception code
		a->jne(lExit);
		a->cmp(asmjit::host::qword_ptr(asmjit::host::rax, 0x20), EH_PURE_MAGIC_NUMBER1);    // Sub code
		a->jne(lExit);
		a->cmp(asmjit::host::qword_ptr(asmjit::host::rax, 0x38), 0);                        // Image base
		a->jne(lExit);
		a->mov(asmjit::host::r9, _pModTable.Ptr());
		a->mov(asmjit::host::rdx, asmjit::host::qword_ptr(asmjit::host::r9));               // Record count
		a->add(asmjit::host::r9, sizeof(table.count));
		a->xor_(asmjit::host::r10, asmjit::host::r10);
		a->bind(lLoop1);
		a->mov(asmjit::host::r8, asmjit::host::qword_ptr(asmjit::host::rax, 0x30));
		a->mov(asmjit::host::r11, asmjit::host::qword_ptr(asmjit::host::r9));
		a->cmp(asmjit::host::r8, asmjit::host::r11);
		a->jl(skip1);
		a->add(asmjit::host::r11, asmjit::host::qword_ptr(asmjit::host::r9, sizeof(table.entry[0].base)));    // Size
		a->cmp(asmjit::host::r8, asmjit::host::r11);
		a->jg(skip1);
		a->jmp(found1);
		a->bind(skip1);
		a->add(asmjit::host::r9, sizeof(ExceptionModule));
		a->add(asmjit::host::r10, 1);
		a->cmp(asmjit::host::r10, asmjit::host::rdx);
		a->jne(lLoop1);
		a->jmp(lExit);
		a->bind(found1);
		a->mov(asmjit::host::qword_ptr(asmjit::host::rax, 0x20), EH_MAGIC_NUMBER1);
		a->mov(asmjit::host::rcx, asmjit::host::qword_ptr(asmjit::host::rcx));
		a->mov(asmjit::host::rdx, asmjit::host::qword_ptr(asmjit::host::r9));
		a->mov(asmjit::host::qword_ptr(asmjit::host::rax, 0x38), asmjit::host::rdx);
		a->bind(lExit);
		a->xor_(asmjit::host::rax, asmjit::host::rax);
		a->ret();
		a->db(0xCC);
		a->db(0xCC);
		a->db(0xCC);
		if(_pVEHCode.Write(0, a->getCodeSize(), a->make()) != STATUS_SUCCESS) {
			_pVEHCode.Free();
			return LastNtStatus();
		}
		#else
		UNREFERENCED_PARAMETER(pTargetBase);
		UNREFERENCED_PARAMETER(imageSize);
		// No handler required
		if(partial)
			return STATUS_SUCCESS;
		// VEH codecave
		_pVEHCode = _proc.Memory().Allocate(0x2000);
		_pVEHCode.Release();
		if(!_pVEHCode.Valid())
			return LastNtStatus();
		// Resolve compiler incremental table address, if any
		void *pFunc = ResolveJmp(&VectoredHandler);
		size_t fnSize = static_cast<size_t>(SizeOfProc(pFunc));
		size_t dataOfs = 0, code_ofs = 0, code_ofs2 = 0;;
		// Find and replace magic values
		for(uint8_t *pData = reinterpret_cast<uint8_t*>(pFunc);
		pData < reinterpret_cast<uint8_t*>(pFunc) + fnSize - 4;
			pData++) {
			// LdrpInvertedFunctionTable
			if(*(size_t*)pData == 0xDEADDA7A) {
				dataOfs = pData - reinterpret_cast<uint8_t*>(pFunc);
				continue;
			}
			// DecodeSystemPointer address
			if(*(size_t*)pData == 0xDEADC0DE) {
				code_ofs = pData - reinterpret_cast<uint8_t*>(pFunc);
				break;
			}
			// LdrProtectMrdata address
			if(*(size_t*)pData == 0xDEADC0D2) {
				code_ofs2 = pData - reinterpret_cast<uint8_t*>(pFunc);
				continue;
			}
		}
		auto pDecode = mods.GetExport(mods.GetModule(L"ntdll.dll", Sections, mt), "RtlDecodeSystemPointer").procAddress;
		// Write handler data into target process
		if(!NT_SUCCESS(_pVEHCode.Write(0, fnSize, pFunc)) ||
			!NT_SUCCESS(_pVEHCode.Write(dataOfs, _proc.NativeLdr().LdrpInvertedFunctionTable())) ||
			!NT_SUCCESS(_pVEHCode.Write(code_ofs, static_cast<size_t>(pDecode))) ||
			!NT_SUCCESS(_pVEHCode.Write(code_ofs2, _proc.NativeLdr().LdrProtectMrdata()))) {
			_pVEHCode.Free();
			return LastNtStatus();
		}
		#endif
		// AddVectoredExceptionHandler(0, pHandler);
		auto pAddHandler = mods.GetExport(mods.GetModule(L"ntdll.dll", Sections, mt), "RtlAddVectoredExceptionHandler").procAddress;
		if(pAddHandler == 0)
			return STATUS_NOT_FOUND;
		a->reset();
		a.GenPrologue();
		a.GenCall(static_cast<size_t>(pAddHandler), {0, _pVEHCode.Ptr<size_t>()});
		_proc.Remote().AddReturnWithEvent(a, mt);
		a.GenEpilogue();
		_proc.Remote().ExecInWorkerThread(a->make(), a->getCodeSize(), result);
		_hVEH = static_cast<size_t>(result);
		return (_hVEH == 0 ? STATUS_NOT_FOUND : STATUS_SUCCESS);
	}