Beispiel #1
0
        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);
        }
Beispiel #2
0
 private void CallTlsCallbacks()
 {
     foreach (var tlsCallback in _injectionWrapper.PeParser.GetTlsCallbacks())
     {
         CallEntryPoint(_remoteDllAddress.AddOffset(tlsCallback.Offset));
     }
 }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #5
0
 private void CallTlsCallbacks(InjectionProperties injectionProperties, IntPtr remoteDllAddress)
 {
     foreach (var tlsCallback in injectionProperties.PeParser.GetTlsCallbacks())
     {
         CallEntryPoint(injectionProperties, remoteDllAddress, remoteDllAddress.AddOffset(tlsCallback.Offset));
     }
 }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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;
                    }
                    }
                }
            }
        }
Beispiel #12
0
        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);
            }
        }