internal bool Call(IntPtr dllAddress) { if (_injectionWrapper.InjectionMethod == InjectionMethod.ManualMap) { // Get the entry point of the DLL var dllEntryPointAddress = _injectionWrapper.RemoteProcess.IsWow64 ? dllAddress.AddOffset(_injectionWrapper.PeParser.GetPeHeaders().NtHeaders32.OptionalHeader.AddressOfEntryPoint) : dllAddress.AddOffset(_injectionWrapper.PeParser.GetPeHeaders().NtHeaders64.OptionalHeader.AddressOfEntryPoint); // Call the entry point of the DLL with DllProcessDetach in the remote process _injectionTools.CallRemoteFunction(dllEntryPointAddress, (ulong)dllAddress, Constants.DllProcessDetach, 0); // Free the memory region of the DLL in the remote process _injectionWrapper.MemoryManager.FreeVirtualMemory(dllAddress); return(true); } // Call FreeLibrary in the remote process _injectionTools.CallRemoteFunction("kernel32.dll", "FreeLibrary", (ulong)dllAddress); return(true); }
private void CallTlsCallbacks() { foreach (var tlsCallback in _injectionWrapper.PeParser.GetTlsCallbacks()) { CallEntryPoint(_remoteDllAddress.AddOffset(tlsCallback.Offset)); } }
private void BuildImportTable() { if (_injectionWrapper.PeParser.ImportedFunctions.Count == 0) { // The DLL has no imported functions return; } // Resolve the DLL of any function imported from a virtual DLL foreach (var importedFunction in _injectionWrapper.PeParser.ImportedFunctions) { if (importedFunction.Dll.StartsWith("api-ms")) { importedFunction.Dll = _apiSetMappings.Find(apiSetMapping => apiSetMapping.VirtualDll.Equals(importedFunction.Dll, StringComparison.OrdinalIgnoreCase)).MappedToDll; } } // Group the imported functions by the DLL they reside in var groupedFunctions = _injectionWrapper.PeParser.ImportedFunctions.GroupBy(importedFunction => importedFunction.Dll).ToList(); // Ensure the dependencies of the DLL are loaded in the remote process var systemFolderPath = _injectionWrapper.ProcessManager.IsWow64 ? Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) : Environment.GetFolderPath(Environment.SpecialFolder.System); foreach (var dll in groupedFunctions) { if (_injectionWrapper.ProcessManager.Modules.Any(module => module.Name.Equals(dll.Key, StringComparison.OrdinalIgnoreCase))) { continue; } // Load the DLL into the remote process using (var injector = new Injector(InjectionMethod.CreateThread, _injectionWrapper.ProcessManager.Process.Id, Path.Combine(systemFolderPath, dll.Key))) { injector.InjectDll(); } _injectionWrapper.ProcessManager.Refresh(); } foreach (var importedFunction in groupedFunctions.SelectMany(dll => dll.Select(importedFunction => importedFunction))) { // Write the imported function into the local process var importedFunctionAddress = importedFunction.Name is null ? _injectionWrapper.ProcessManager.GetFunctionAddress(importedFunction.Dll, importedFunction.Ordinal) : _injectionWrapper.ProcessManager.GetFunctionAddress(importedFunction.Dll, importedFunction.Name); Marshal.WriteIntPtr(_localDllAddress.AddOffset(importedFunction.Offset), importedFunctionAddress); } }
private void MapSections(InjectionProperties injectionProperties, IntPtr localDllAddress, IntPtr remoteDllAddress) { foreach (var section in injectionProperties.PeParser.GetHeaders().SectionHeaders) { // Get the data of the section var sectionDataAddress = localDllAddress.AddOffset(section.PointerToRawData); var sectionData = new byte[section.SizeOfRawData]; Marshal.Copy(sectionDataAddress, sectionData, 0, (int)section.SizeOfRawData); // Write the section into the target process var sectionAddress = remoteDllAddress.AddOffset(section.VirtualAddress); injectionProperties.MemoryManager.WriteVirtualMemory(sectionAddress, sectionData); // Adjust the protection of the section var sectionProtection = GetSectionProtection(section.Characteristics); injectionProperties.MemoryManager.ProtectVirtualMemory(sectionAddress, (int)section.SizeOfRawData, sectionProtection); } }
private void CallTlsCallbacks(InjectionProperties injectionProperties, IntPtr remoteDllAddress) { foreach (var tlsCallback in injectionProperties.PeParser.GetTlsCallbacks()) { CallEntryPoint(injectionProperties, remoteDllAddress, remoteDllAddress.AddOffset(tlsCallback.Offset)); } }
public IntPtr Call() { var dllBufferHandle = GCHandle.Alloc(_injectionWrapper.DllBytes.Clone(), GCHandleType.Pinned); _localDllAddress = dllBufferHandle.AddrOfPinnedObject(); _apiSetMappings = GetApiSetMappings(); // Build the import table of the DLL in the local process BuildImportTable(); // Allocate memory for the DLL in the remote process try { _remoteDllAddress = _injectionWrapper.MemoryManager.AllocateVirtualMemory((IntPtr)_injectionWrapper.PeParser.PeHeaders.PEHeader.ImageBase, _injectionWrapper.PeParser.PeHeaders.PEHeader.SizeOfImage); } catch (Win32Exception) { _remoteDllAddress = _injectionWrapper.MemoryManager.AllocateVirtualMemory(_injectionWrapper.PeParser.PeHeaders.PEHeader.SizeOfImage); } // Relocate the DLL in the local process RelocateImage(); // Map the sections of the DLL into the remote process MapSections(); // Map the headers of the DLL into the remote process MapHeaders(); // Enable exception handling within the DLL EnableExceptionHandling(); // Call any TLS callbacks CallTlsCallbacks(); // Call the entry point of the DLL var entryPointAddress = _remoteDllAddress.AddOffset(_injectionWrapper.PeParser.PeHeaders.PEHeader.AddressOfEntryPoint); if (entryPointAddress != _remoteDllAddress) { CallEntryPoint(entryPointAddress); } dllBufferHandle.Free(); return(_remoteDllAddress); }
internal List <ApiSetMapping> GetApiSetMappings() { var apiSetMappings = new List <ApiSetMapping>(); // Look for the .apiset section in the section headers of the DLL var apiSetSectionHeader = _peHeaders.SectionHeaders.Find(section => section.Name.SequenceEqual(Encoding.Default.GetBytes(".apiset\0"))); if (apiSetSectionHeader.Equals(default(Structures.ImageSectionHeader))) { // The DLL has no .apiset section return(apiSetMappings); } // Read the namespace of the API set var setDataAddress = _dllBuffer.AddOffset(apiSetSectionHeader.PointerToRawData); var setNamespace = Marshal.PtrToStructure <Structures.ApiSetNamespace>(setDataAddress); for (var index = 0; index < (int)setNamespace.Count; index += 1) { // Read the set entry of the API set var setEntry = Marshal.PtrToStructure <Structures.ApiSetNamespaceEntry>(setDataAddress.AddOffset(setNamespace.EntryOffset + Marshal.SizeOf <Structures.ApiSetNamespaceEntry>() * index)); // Read the name of the set entry var setEntryName = string.Concat(Marshal.PtrToStringUni(setDataAddress.AddOffset(setEntry.NameOffset)), ".dll"); // Read the value entry that the set entry maps to var valueEntry = Marshal.PtrToStructure <Structures.ApiSetValueEntry>(setDataAddress.AddOffset(setEntry.ValueOffset)); // Read the name of the value entry var valueEntryNameBytes = new byte[valueEntry.ValueCount]; Marshal.Copy(setDataAddress.AddOffset(valueEntry.ValueOffset), valueEntryNameBytes, 0, valueEntryNameBytes.Length); var valueEntryName = Encoding.Unicode.GetString(valueEntryNameBytes); apiSetMappings.Add(new ApiSetMapping(setEntryName, valueEntryName)); } return(apiSetMappings); }
public IntPtr Call() { // Store the DLL bytes in a buffer var dllBufferHandle = GCHandle.Alloc(_injectionWrapper.DllBytes.Clone(), GCHandleType.Pinned); _localDllAddress = dllBufferHandle.AddrOfPinnedObject(); // Build the import table of the DLL in the local process BuildImportTable(); // Allocate memory for the DLL in the remote process var peHeaders = _injectionWrapper.PeParser.GetPeHeaders(); var preferredBaseAddress = _injectionWrapper.RemoteProcess.IsWow64 ? _injectionWrapper.PeParser.GetPeHeaders().NtHeaders32.OptionalHeader.ImageBase : _injectionWrapper.PeParser.GetPeHeaders().NtHeaders64.OptionalHeader.ImageBase; var dllSize = _injectionWrapper.RemoteProcess.IsWow64 ? peHeaders.NtHeaders32.OptionalHeader.SizeOfImage : peHeaders.NtHeaders64.OptionalHeader.SizeOfImage; try { _remoteDllAddress = _injectionWrapper.MemoryManager.AllocateVirtualMemory((IntPtr)preferredBaseAddress, (int)dllSize); } catch (Win32Exception) { _remoteDllAddress = _injectionWrapper.MemoryManager.AllocateVirtualMemory((int)dllSize); } // Relocate the DLL in the local process RelocateImage(); // Map the sections of the DLL into the remote process MapSections(); // Map the headers of the DLL into the remote process MapHeaders(); // Call any TLS callbacks CallTlsCallbacks(); // Call the entry point of the DLL var dllEntryPointAddress = _injectionWrapper.RemoteProcess.IsWow64 ? _remoteDllAddress.AddOffset(peHeaders.NtHeaders32.OptionalHeader.AddressOfEntryPoint) : _remoteDllAddress.AddOffset(peHeaders.NtHeaders64.OptionalHeader.AddressOfEntryPoint); if (dllEntryPointAddress != _remoteDllAddress) { CallEntryPoint(dllEntryPointAddress); } dllBufferHandle.Free(); return(_remoteDllAddress); }
internal List <BaseRelocation> GetBaseRelocations() { var baseRelocations = new List <BaseRelocation>(); // Calculate the offset of the base relocation table var baseRelocationTableRva = _peHeaders.FileHeader.Machine == Enumerations.MachineType.X86 ? _peHeaders.NtHeaders32.OptionalHeader.DataDirectory[5].VirtualAddress : _peHeaders.NtHeaders64.OptionalHeader.DataDirectory[5].VirtualAddress; if (baseRelocationTableRva == 0) { // The DLL has no base relocations return(baseRelocations); } var baseRelocationTableOffset = ConvertRvaToOffset(baseRelocationTableRva); while (true) { // Read the base relocation var baseRelocation = Marshal.PtrToStructure <Structures.ImageBaseRelocation>(_dllBuffer.AddOffset(baseRelocationTableOffset)); if (baseRelocation.SizeOfBlock == 0) { break; } // Calculate the offset of the relocations var relocationsOffset = baseRelocationTableOffset + (uint)Marshal.SizeOf <Structures.ImageBaseRelocation>(); // Calculate the amount of relocations in the base relocation var relocationAmount = (baseRelocation.SizeOfBlock - Marshal.SizeOf <Structures.ImageBaseRelocation>()) / sizeof(ushort); var relocations = new List <Relocation>(); for (var index = 0; index < relocationAmount; index += 1) { // Read the relocation var relocation = Marshal.PtrToStructure <ushort>(_dllBuffer.AddOffset(relocationsOffset + (uint)(sizeof(ushort) * index))); // The relocation offset is located in the upper 4 bits of the ushort var relocationOffset = relocation & 0xFFF; // The relocation type is located in the lower 12 bits of the ushort var relocationType = relocation >> 12; relocations.Add(new Relocation((ushort)relocationOffset, (Enumerations.RelocationType)relocationType)); } baseRelocations.Add(new BaseRelocation(ConvertRvaToOffset(baseRelocation.VirtualAddress), relocations)); // Calculate the offset of the next base relocation baseRelocationTableOffset += baseRelocation.SizeOfBlock; } return(baseRelocations); }
private List <BaseRelocation> GetBaseRelocations() { var baseRelocations = new List <BaseRelocation>(); // Calculate the offset of the base relocation table var baseRelocationTableRva = PeHeaders.PEHeader.BaseRelocationTableDirectory.RelativeVirtualAddress; if (baseRelocationTableRva == 0) { // The PE has no base relocations return(baseRelocations); } var baseRelocationTableOffset = ConvertRvaToOffset((ulong)baseRelocationTableRva); var baseRelocationOffset = 0U; while (true) { // Read the base relocation var baseRelocation = Marshal.PtrToStructure <ImageBaseRelocation>(_peBuffer.AddOffset(baseRelocationTableOffset + baseRelocationOffset)); if (baseRelocation.SizeOfBlock == 0) { break; } // Calculate the amount of relocations in the base relocation var relocationsOffset = baseRelocationTableOffset + (uint)Marshal.SizeOf <ImageBaseRelocation>(); var relocationAmount = (baseRelocation.SizeOfBlock - Marshal.SizeOf <ImageBaseRelocation>()) / sizeof(ushort); var relocations = new List <Relocation>(); // Read the relocations for (var relocationIndex = 0; relocationIndex < relocationAmount; relocationIndex += 1) { var relocation = Marshal.PtrToStructure <ushort>(_peBuffer.AddOffset(relocationsOffset + (uint)(sizeof(ushort) * relocationIndex))); // The relocation offset is located in the upper 4 bits of the ushort var relocationOffset = relocation & 0xFFF; // The relocation type is located in the lower 12 bits of the ushort var relocationType = relocation >> 12; relocations.Add(new Relocation((ushort)relocationOffset, (RelocationType)relocationType)); } baseRelocations.Add(new BaseRelocation(ConvertRvaToOffset(baseRelocation.VirtualAddress), relocations)); // Calculate the offset of the next base relocation baseRelocationOffset += baseRelocation.SizeOfBlock; } return(baseRelocations); }
private void PerformRelocations(InjectionProperties injectionProperties, IntPtr localDllAddress, IntPtr remoteDllAddress) { var baseRelocations = injectionProperties.PeParser.GetBaseRelocations(); if (baseRelocations.Count == 0) { // No relocations need to be applied return; } var peHeaders = injectionProperties.PeParser.GetHeaders(); var baseAddress = injectionProperties.RemoteProcess.IsWow64 ? peHeaders.NtHeaders32.OptionalHeader.ImageBase : peHeaders.NtHeaders64.OptionalHeader.ImageBase; // Calculate the base address delta var delta = (long)remoteDllAddress - (long)baseAddress; if (delta == 0) { // The DLL is loaded at its default base address and no relocations need to be applied return; } foreach (var baseRelocation in baseRelocations) { // Calculate the base address of the relocation block var relocationBlockAddress = localDllAddress.AddOffset(baseRelocation.Offset); foreach (var relocation in baseRelocation.Relocations) { // Calculate the address of the relocation var relocationAddress = relocationBlockAddress.AddOffset(relocation.Offset); switch (relocation.Type) { case Enumerations.RelocationType.HighLow: { // Perform the relocation var relocationValue = Marshal.ReadInt32(relocationAddress) + (int)delta; Marshal.WriteInt32(relocationAddress, relocationValue); break; } case Enumerations.RelocationType.Dir64: { // Perform the relocation var relocationValue = Marshal.ReadInt64(relocationAddress) + delta; Marshal.WriteInt64(relocationAddress, relocationValue); break; } } } } }
private void BuildImportTable(InjectionProperties injectionProperties, IntPtr localDllAddress) { var importedFunctions = injectionProperties.PeParser.GetImportedFunctions(); if (importedFunctions.Count == 0) { // The DLL has no imported functions return; } // Group the imported functions by the DLL they reside in var groupedFunctions = importedFunctions.GroupBy(importedFunction => importedFunction.DllName).ToList(); // Get the API set mappings List <ApiSetMapping> apiSetMappings; using (var peParser = new PeParser(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "apisetschema.dll"))) { apiSetMappings = peParser.GetApiSetMappings(); } var systemFolderPath = injectionProperties.RemoteProcess.IsWow64 ? Environment.GetFolderPath(Environment.SpecialFolder.SystemX86) : Environment.GetFolderPath(Environment.SpecialFolder.System); foreach (var dll in groupedFunctions) { var dllName = dll.Key; if (dllName.StartsWith("api-ms")) { dllName = apiSetMappings.Find(apiSetMapping => apiSetMapping.VirtualDll.Equals(dllName, StringComparison.OrdinalIgnoreCase)).MappedToDll; } // Ensure the DLL is loaded in the target process if (!injectionProperties.RemoteProcess.Modules.Any(module => module.Name.Equals(dllName, StringComparison.OrdinalIgnoreCase))) { // Load the DLL into the target process new Injector().CreateRemoteThread(injectionProperties.RemoteProcess.TargetProcess.Id, Path.Combine(systemFolderPath, dllName)); } } injectionProperties.RemoteProcess.Refresh(); foreach (var importedFunction in groupedFunctions.SelectMany(dll => dll.Select(importedFunction => importedFunction))) { var dllName = importedFunction.DllName; if (dllName.StartsWith("api-ms")) { dllName = apiSetMappings.Find(apiSetMapping => apiSetMapping.VirtualDll.Equals(dllName, StringComparison.OrdinalIgnoreCase)).MappedToDll; } // Get the address of the imported function var importedFunctionAddress = injectionProperties.RemoteProcess.GetFunctionAddress(dllName, importedFunction.Name); // Write the imported function into the local process Marshal.WriteInt64(localDllAddress.AddOffset(importedFunction.Offset), (long)importedFunctionAddress); } }