/// <summary>
        /// Relocates a module in memory.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author>
        /// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
        /// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
        /// <returns>void</returns>
        private static void RelocateModule(PE_META_DATA PEINFO, IntPtr ModuleMemoryBase)
        {
            IMAGE_DATA_DIRECTORY idd = PEINFO.Is32Bit ? PEINFO.OptHeader32.BaseRelocationTable : PEINFO.OptHeader64.BaseRelocationTable;
            Int64 ImageDelta         = PEINFO.Is32Bit ? (Int64)((UInt64)ModuleMemoryBase - PEINFO.OptHeader32.ImageBase) :
                                       (Int64)((UInt64)ModuleMemoryBase - PEINFO.OptHeader64.ImageBase);

            // Ptr for the base reloc table
            IntPtr pRelocTable         = (IntPtr)((UInt64)ModuleMemoryBase + idd.VirtualAddress);
            Int32  nextRelocTableBlock = -1;

            // Loop reloc blocks
            while (nextRelocTableBlock != 0)
            {
                IMAGE_BASE_RELOCATION ibr;
                ibr = (IMAGE_BASE_RELOCATION)Marshal.PtrToStructure(pRelocTable, typeof(IMAGE_BASE_RELOCATION));

                Int64 RelocCount = ((ibr.SizeOfBlock - Marshal.SizeOf(ibr)) / 2);
                for (int i = 0; i < RelocCount; i++)
                {
                    // Calculate reloc entry ptr
                    IntPtr pRelocEntry = (IntPtr)((UInt64)pRelocTable + (UInt64)Marshal.SizeOf(ibr) + (UInt64)(i * 2));
                    UInt16 RelocValue  = (UInt16)Marshal.ReadInt16(pRelocEntry);

                    // Parse reloc value
                    // The type should only ever be 0x0, 0x3, 0xA
                    // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#base-relocation-types
                    UInt16 RelocType  = (UInt16)(RelocValue >> 12);
                    UInt16 RelocPatch = (UInt16)(RelocValue & 0xfff);

                    // Perform relocation
                    if (RelocType != 0) // IMAGE_REL_BASED_ABSOLUTE (0 -> skip reloc)
                    {
                        try
                        {
                            IntPtr pPatch = (IntPtr)((UInt64)ModuleMemoryBase + ibr.VirtualAdress + RelocPatch);
                            if (RelocType == 0x3) // IMAGE_REL_BASED_HIGHLOW (x86)
                            {
                                Int32 OriginalPtr = Marshal.ReadInt32(pPatch);
                                Marshal.WriteInt32(pPatch, (OriginalPtr + (Int32)ImageDelta));
                            }
                            else // IMAGE_REL_BASED_DIR64 (x64)
                            {
                                Int64 OriginalPtr = Marshal.ReadInt64(pPatch);
                                Marshal.WriteInt64(pPatch, (OriginalPtr + ImageDelta));
                            }
                        }
                        catch
                        {
                            throw new Exception(DSTR(DSTR_MEM_ACCESS_VIOLATION));
                        }
                    }
                }

                // Check for next block
                pRelocTable         = (IntPtr)((UInt64)pRelocTable + ibr.SizeOfBlock);
                nextRelocTableBlock = Marshal.ReadInt32(pRelocTable);
            }
        }
Exemple #2
0
        /// <summary>
        /// Call a manually mapped DLL by DllMain -> DLL_PROCESS_ATTACH.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author>
        /// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
        /// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
        /// <returns>void</returns>
        private static void CallMappedDLLModule(PE_META_DATA PEINFO, IntPtr ModuleMemoryBase)
        {
            IntPtr lpEntryPoint = PEINFO.Is32Bit ? (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader32.AddressOfEntryPoint) :
                                  (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader64.AddressOfEntryPoint);

            DllMain fDllMain = (DllMain)Marshal.GetDelegateForFunctionPointer(lpEntryPoint, typeof(DllMain));
            bool    CallRes  = fDllMain(ModuleMemoryBase, DLL_PROCESS_ATTACH, IntPtr.Zero);

            if (!CallRes)
            {
                throw new Exception(DSTR(DSTR_DINVOKE_MAIN_FAILED));
            }
        }
Exemple #3
0
        /// <summary>
        /// Call a manually mapped DLL by Export.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author>
        /// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
        /// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
        /// <param name="ExportName">The name of the export to search for (e.g. "NtAlertResumeThread").</param>
        /// <param name="FunctionDelegateType">Prototype for the function, represented as a Delegate object.</param>
        /// <param name="Parameters">Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference.</param>
        /// <param name="CallEntry">Specify whether to invoke the module's entry point.</param>
        /// <returns>void</returns>
        public static object CallMappedDLLModuleExport(PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, string ExportName, Type FunctionDelegateType, ref object[] Parameters, bool CallEntry = true)
        {
            // Call entry point if user has specified
            if (CallEntry)
            {
                CallMappedDLLModule(PEINFO, ModuleMemoryBase);
            }

            // Get export pointer
            IntPtr pFunc = ModuleMapper.GetExportAddress(ModuleMemoryBase, ExportName);

            // Call export
            return(DynamicFunctionInvoke(pFunc, FunctionDelegateType, ref Parameters));
        }
        /// <summary>
        /// Set correct module section permissions.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author>
        /// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
        /// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
        /// <returns>void</returns>
        public static void SetModuleSectionPermissions(PE_META_DATA PEINFO, IntPtr ModuleMemoryBase)
        {
            // Apply RO to the module header
            IntPtr BaseOfCode = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.BaseOfCode : (IntPtr)PEINFO.OptHeader64.BaseOfCode;

            Native.NtProtectVirtualMemoryD((IntPtr)(-1), ref ModuleMemoryBase, ref BaseOfCode, Native.PAGE_READONLY);

            // Apply section permissions
            foreach (IMAGE_SECTION_HEADER ish in PEINFO.Sections)
            {
                bool isRead       = (ish.Characteristics & DataSectionFlags.MEM_READ) != 0;
                bool isWrite      = (ish.Characteristics & DataSectionFlags.MEM_WRITE) != 0;
                bool isExecute    = (ish.Characteristics & DataSectionFlags.MEM_EXECUTE) != 0;
                uint flNewProtect = 0;
                if (isRead & !isWrite & !isExecute)
                {
                    flNewProtect = Native.PAGE_READONLY;
                }
                else if (isRead & isWrite & !isExecute)
                {
                    flNewProtect = Native.PAGE_READWRITE;
                }
                else if (isRead & isWrite & isExecute)
                {
                    flNewProtect = Native.PAGE_EXECUTE_READWRITE;
                }
                else if (isRead & !isWrite & isExecute)
                {
                    flNewProtect = Native.PAGE_EXECUTE_READ;
                }
                else if (!isRead & !isWrite & isExecute)
                {
                    flNewProtect = Native.PAGE_EXECUTE;
                }
                else
                {
                    throw new Exception(DSTR(DSTR_UNK_SEC_FLAG, ish.Characteristics));
                }

                // Calculate base
                IntPtr pVirtualSectionBase = (IntPtr)((UInt64)ModuleMemoryBase + ish.VirtualAddress);
                IntPtr ProtectSize         = (IntPtr)ish.VirtualSize;

                // Set protection
                Native.NtProtectVirtualMemoryD((IntPtr)(-1), ref pVirtualSectionBase, ref ProtectSize, flNewProtect);
            }
        }
Exemple #5
0
        /// <summary>
        /// Set correct module section permissions.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author> (modified for external ProcessEx)
        /// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
        /// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
        /// <returns>void</returns>
        public void MMSetModuleSectionPermissions(PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, byte[] rawData)
        {
            // Apply RO to the module header
            IntPtr BaseOfCode = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.BaseOfCode : (IntPtr)PEINFO.OptHeader64.BaseOfCode;

            NativeStealth.VirtualProtectEx(Handle, ModuleMemoryBase, BaseOfCode.ToInt32(), (int)Native.PAGE_READONLY, out _);

            // Apply section permissions
            foreach (IMAGE_SECTION_HEADER ish in PEINFO.Sections)
            {
                bool isRead       = (ish.Characteristics & DataSectionFlags.MEM_READ) != 0;
                bool isWrite      = (ish.Characteristics & DataSectionFlags.MEM_WRITE) != 0;
                bool isExecute    = (ish.Characteristics & DataSectionFlags.MEM_EXECUTE) != 0;
                uint flNewProtect = 0;
                if (isRead & !isWrite & !isExecute)
                {
                    flNewProtect = Native.PAGE_READONLY;
                }
                else if (isRead & isWrite & !isExecute)
                {
                    flNewProtect = Native.PAGE_READWRITE;
                }
                else if (isRead & isWrite & isExecute)
                {
                    flNewProtect = Native.PAGE_EXECUTE_READWRITE;
                }
                else if (isRead & !isWrite & isExecute)
                {
                    flNewProtect = Native.PAGE_EXECUTE_READ;
                }
                else if (!isRead & !isWrite & isExecute)
                {
                    flNewProtect = Native.PAGE_EXECUTE;
                }
                else
                {
                    throw new InvalidOperationException(DSTR(DSTR_UNK_SEC_FLAG, ish.Characteristics));
                }

                // Calculate base
                IntPtr pVirtualSectionBase = (IntPtr)((UInt64)ModuleMemoryBase + ish.VirtualAddress);
                IntPtr ProtectSize         = (IntPtr)ish.VirtualSize;

                // Set protection
                NativeStealth.VirtualProtectEx(Handle, pVirtualSectionBase, ProtectSize.ToInt32(), (int)flNewProtect, out _);
            }
        }
Exemple #6
0
        /// <summary>
        /// Retrieve PE header information from the module base pointer.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author>
        /// <param name="pModule">Pointer to the module base.</param>
        /// <returns>PE.PE_META_DATA</returns>
        public static PE_META_DATA GetPeMetaData(IntPtr pModule)
        {
            PE_META_DATA PeMetaData = new PE_META_DATA();

            try
            {
                UInt32 e_lfanew = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + 0x3c));
                PeMetaData.Pe = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + e_lfanew));
                // Validate PE signature
                if (PeMetaData.Pe != 0x4550)
                {
                    throw new InvalidOperationException("Invalid PE signature.");
                }
                PeMetaData.ImageFileHeader = (IMAGE_FILE_HEADER)Marshal.PtrToStructure((IntPtr)((UInt64)pModule + e_lfanew + 0x4), typeof(IMAGE_FILE_HEADER));
                IntPtr OptHeader = (IntPtr)((UInt64)pModule + e_lfanew + 0x18);
                UInt16 PEArch    = (UInt16)Marshal.ReadInt16(OptHeader);
                // Validate PE arch
                if (PEArch == 0x010b) // Image is x32
                {
                    PeMetaData.Is32Bit     = true;
                    PeMetaData.OptHeader32 = (IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure(OptHeader, typeof(IMAGE_OPTIONAL_HEADER32));
                }
                else if (PEArch == 0x020b) // Image is x64
                {
                    PeMetaData.Is32Bit     = false;
                    PeMetaData.OptHeader64 = (IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure(OptHeader, typeof(IMAGE_OPTIONAL_HEADER64));
                }
                else
                {
                    throw new InvalidOperationException("Invalid magic value (PE32/PE32+).");
                }
                // Read sections
                IMAGE_SECTION_HEADER[] SectionArray = new IMAGE_SECTION_HEADER[PeMetaData.ImageFileHeader.NumberOfSections];
                for (int i = 0; i < PeMetaData.ImageFileHeader.NumberOfSections; i++)
                {
                    IntPtr SectionPtr = (IntPtr)((UInt64)OptHeader + PeMetaData.ImageFileHeader.SizeOfOptionalHeader + (UInt32)(i * 0x28));
                    SectionArray[i] = (IMAGE_SECTION_HEADER)Marshal.PtrToStructure(SectionPtr, typeof(IMAGE_SECTION_HEADER));
                }
                PeMetaData.Sections = SectionArray;
            }
            catch
            {
                throw new InvalidOperationException("Invalid module base specified.");
            }
            return(PeMetaData);
        }
        /// <summary>
        /// Manually map module into current process.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author> (modified for external)
        /// <param name="pModule">Pointer to the module base.</param>
        /// <returns>PE_MANUAL_MAP object</returns>
        private static PE_MANUAL_MAP MapModuleToMemory(PointerEx pModule)
        {
            // Fetch PE meta data
            PE_META_DATA PEINFO = GetPeMetaData(pModule);

            // Check module matches the process architecture
            if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4))
            {
                Marshal.FreeHGlobal(pModule);
                throw new Exception(DSTR(DSTR_MOD_ARCHITECTURE_WRONG));
            }

            // Alloc PE image memory -> RW
            IntPtr BaseAddress = IntPtr.Zero;
            IntPtr RegionSize  = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage;
            IntPtr pImage      = Native.NtAllocateVirtualMemoryD(
                (IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize,
                Native.AllocationType.Commit | Native.AllocationType.Reserve,
                Native.PAGE_READWRITE
                );

            return(MapModuleToMemory(pModule, pImage, PEINFO));
        }
Exemple #8
0
        /// <summary>
        /// Manually map module into remote process.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author> (modified for external ProcessEx)
        /// <param name="localModuleHandle">Pointer to the module base.</param>
        /// <returns>PE_MANUAL_MAP object</returns>
        private PE_MANUAL_MAP MapModuleToMemory(PointerEx localModuleHandle, byte[] moduleRaw)
        {
#if DEBUG
            DLog($"Attempting to map module of size {moduleRaw.Length}");
#endif
            // Fetch PE meta data
            PE_META_DATA PEINFO = GetPeMetaData(localModuleHandle);

            // Check module matches the process architecture
            if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4))
            {
                Marshal.FreeHGlobal(localModuleHandle);
                throw new InvalidOperationException(DSTR(DSTR_MOD_ARCHITECTURE_WRONG));
            }

            // Alloc PE image memory -> RW
            IntPtr RegionSize         = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage;
            IntPtr remoteModuleHandle = QuickAlloc(RegionSize);

#if DEBUG
            DLog($"Module memory allocated at 0x{remoteModuleHandle.ToInt64():X16}");
#endif
            return(__MapModuleToMemory(localModuleHandle, remoteModuleHandle, moduleRaw, PEINFO));
        }
        /// <summary>
        /// Rewrite IAT for manually mapped module.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author> (modified for external)
        /// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
        /// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
        /// <returns>void</returns>
        private static void RewriteModuleIAT(PE_META_DATA PEINFO, IntPtr ModuleMemoryBase)
        {
            IMAGE_DATA_DIRECTORY idd = PEINFO.Is32Bit ? PEINFO.OptHeader32.ImportTable : PEINFO.OptHeader64.ImportTable;

            // Check if there is no import table
            if (idd.VirtualAddress == 0)
            {
                // Return so that the rest of the module mapping process may continue.
                return;
            }

            // Ptr for the base import directory
            IntPtr pImportTable = (IntPtr)((UInt64)ModuleMemoryBase + idd.VirtualAddress);

            // Get API Set mapping dictionary if on Win10+
            Native.OSVERSIONINFOEX OSVersion = new Native.OSVERSIONINFOEX();
            Native.RtlGetVersionD(ref OSVersion);
            if (OSVersion.MajorVersion < 10)
            {
                throw new Exception(DSTR(DSTR_OS_VERSION_TOO_OLD));
            }

            // Loop IID's
            int counter = 0;

            Native.IMAGE_IMPORT_DESCRIPTOR iid = new Native.IMAGE_IMPORT_DESCRIPTOR();
            iid = (Native.IMAGE_IMPORT_DESCRIPTOR)Marshal.PtrToStructure(
                (IntPtr)((UInt64)pImportTable + (uint)(Marshal.SizeOf(iid) * counter)),
                typeof(Native.IMAGE_IMPORT_DESCRIPTOR)
                );
            while (iid.Name != 0)
            {
                // Get DLL
                string DllName = string.Empty;
                try
                {
                    DllName = Marshal.PtrToStringAnsi((IntPtr)((UInt64)ModuleMemoryBase + iid.Name));
                }
                catch { }

                // Loop imports
                if (DllName == string.Empty)
                {
                    throw new Exception(DSTR(DSTR_MODULE_NAME_INVALID));
                }
                else
                {
                    // API Set DLL?
                    string dll_resolved;
                    if ((DllName.StartsWith("api-") || DllName.StartsWith("ext-")))
                    {
                        // for some reason, Lunar's resolve apiset is 1000x better than the dictionary setup done in dinvoke, so we will just use that.
                        // lmfao: https://github.com/cobbr/SharpSploit/issues/58
                        if ((dll_resolved = EnvironmentEx.ResolveAPISet(DllName)) == null)
                        {
                            throw new Exception(DSTR(DSTR_API_DLL_UNRESOLVED, DllName));
                        }
                        // Not all API set DLL's have a registered host mapping
                        DllName = dll_resolved;
                    }

                    // Check and / or load DLL
                    IntPtr hModule = GetLoadedModuleAddress(DllName);
                    if (hModule == IntPtr.Zero)
                    {
                        hModule = LoadModuleFromDisk(DllName);
                        if (hModule == IntPtr.Zero)
                        {
                            throw new Exception(DSTR(DSTR_MODULE_FILE_NOT_FOUND, DllName));
                        }
                    }

                    // Loop thunks
                    if (PEINFO.Is32Bit)
                    {
                        IMAGE_THUNK_DATA32 oft_itd;
                        for (int i = 0; true; i++)
                        {
                            oft_itd = (IMAGE_THUNK_DATA32)Marshal.PtrToStructure((IntPtr)((UInt64)ModuleMemoryBase + iid.OriginalFirstThunk + (UInt32)(i * (sizeof(UInt32)))), typeof(IMAGE_THUNK_DATA32));
                            IntPtr ft_itd = (IntPtr)((UInt64)ModuleMemoryBase + iid.FirstThunk + (UInt64)(i * (sizeof(UInt32))));
                            if (oft_itd.AddressOfData == 0)
                            {
                                break;
                            }

                            if (oft_itd.AddressOfData < 0x80000000) // !IMAGE_ORDINAL_FLAG32
                            {
                                IntPtr pImpByName = (IntPtr)((UInt64)ModuleMemoryBase + oft_itd.AddressOfData + sizeof(UInt16));
                                IntPtr pFunc;
                                pFunc = GetNativeExportAddress(hModule, Marshal.PtrToStringAnsi(pImpByName));

                                // Write ProcAddress
                                Marshal.WriteInt32(ft_itd, pFunc.ToInt32());
                            }
                            else
                            {
                                ulong  fOrdinal = oft_itd.AddressOfData & 0xFFFF;
                                IntPtr pFunc;
                                pFunc = GetNativeExportAddress(hModule, (short)fOrdinal);

                                // Write ProcAddress
                                Marshal.WriteInt32(ft_itd, pFunc.ToInt32());
                            }
                        }
                    }
                    else
                    {
                        IMAGE_THUNK_DATA64 oft_itd;
                        for (int i = 0; true; i++)
                        {
                            oft_itd = (IMAGE_THUNK_DATA64)Marshal.PtrToStructure((IntPtr)((UInt64)ModuleMemoryBase + iid.OriginalFirstThunk + (UInt64)(i * (sizeof(UInt64)))), typeof(IMAGE_THUNK_DATA64));
                            IntPtr ft_itd = (IntPtr)((UInt64)ModuleMemoryBase + iid.FirstThunk + (UInt64)(i * (sizeof(UInt64))));
                            if (oft_itd.AddressOfData == 0)
                            {
                                break;
                            }

                            if (oft_itd.AddressOfData < 0x8000000000000000) // !IMAGE_ORDINAL_FLAG64
                            {
                                IntPtr pImpByName = (IntPtr)((UInt64)ModuleMemoryBase + oft_itd.AddressOfData + sizeof(UInt16));
                                IntPtr pFunc;
                                pFunc = GetNativeExportAddress(hModule, Marshal.PtrToStringAnsi(pImpByName));

                                // Write pointer
                                Marshal.WriteInt64(ft_itd, pFunc.ToInt64());
                            }
                            else
                            {
                                ulong  fOrdinal = oft_itd.AddressOfData & 0xFFFF;
                                IntPtr pFunc;
                                pFunc = GetNativeExportAddress(hModule, (short)fOrdinal);

                                // Write pointer
                                Marshal.WriteInt64(ft_itd, pFunc.ToInt64());
                            }
                        }
                    }
                    counter++;
                    iid = (Native.IMAGE_IMPORT_DESCRIPTOR)Marshal.PtrToStructure(
                        (IntPtr)((UInt64)pImportTable + (uint)(Marshal.SizeOf(iid) * counter)),
                        typeof(Native.IMAGE_IMPORT_DESCRIPTOR)
                        );
                }
            }
        }
        /// <summary>
        /// Manually map module into current process.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author>
        /// <param name="rawModule">Pointer to the module base.</param>
        /// <param name="allocatedModule">Pointer to the PEINFO image.</param>
        /// <param name="PEINFO">PE_META_DATA of the module being mapped.</param>
        /// <returns>PE_MANUAL_MAP object</returns>
        private static PE_MANUAL_MAP MapModuleToMemory(IntPtr rawModule, IntPtr allocatedModule, PE_META_DATA PEINFO)
        {
            // Check module matches the process architecture
            if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4))
            {
                Marshal.FreeHGlobal(rawModule);
                throw new Exception(DSTR(DSTR_MOD_ARCHITECTURE_WRONG));
            }

            // Write PE header to memory
            UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders;
            UInt32 BytesWritten;

            Native.NtWriteVirtualMemoryD((IntPtr)(-1), allocatedModule, rawModule, SizeOfHeaders);

            // Write sections to memory
            foreach (IMAGE_SECTION_HEADER ish in PEINFO.Sections)
            {
                // Calculate offsets
                IntPtr pVirtualSectionBase = (IntPtr)((UInt64)allocatedModule + ish.VirtualAddress);
                IntPtr pRawSectionBase     = (IntPtr)((UInt64)rawModule + ish.PointerToRawData);

                // Write data
                BytesWritten = Native.NtWriteVirtualMemoryD((IntPtr)(-1), pVirtualSectionBase, pRawSectionBase, ish.SizeOfRawData);
                if (BytesWritten != ish.SizeOfRawData)
                {
                    throw new Exception(DSTR(DSTR_FAILED_MEMORY_WRITE));
                }
            }

            // Perform relocations
            RelocateModule(PEINFO, allocatedModule);

            // Rewrite IAT
            RewriteModuleIAT(PEINFO, allocatedModule);

            // Set memory protections
            SetModuleSectionPermissions(PEINFO, allocatedModule);

            // Free temp HGlobal
            Marshal.FreeHGlobal(rawModule);

            // Prepare return object
            PE_MANUAL_MAP ManMapObject = new PE_MANUAL_MAP
            {
                ModuleBase = allocatedModule,
                PEINFO     = PEINFO
            };

            return(ManMapObject);
        }
Exemple #11
0
        /// <summary>
        /// Manually map module into remote process.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author> (modified for external ProcessEx)
        /// <param name="localModuleHandle">Pointer to the module base.</param>
        /// <param name="remoteModuleHandle">Pointer to the PEINFO image.</param>
        /// <param name="PEINFO">PE_META_DATA of the module being mapped.</param>
        /// <returns>PE_MANUAL_MAP object</returns>
        private PE_MANUAL_MAP __MapModuleToMemory(IntPtr localModuleHandle, IntPtr remoteModuleHandle, byte[] moduleRaw, PE_META_DATA PEINFO)
        {
            // Check module matches the process architecture
            if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4))
            {
                Marshal.FreeHGlobal(localModuleHandle);
                throw new InvalidOperationException(DSTR(DSTR_MOD_ARCHITECTURE_WRONG));
            }

            // Write PE header to memory
            UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders;
            IntPtr RegionSize    = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage;

            byte[] moduleRemote = new byte[RegionSize.ToInt32()];
            moduleRaw.Take((int)SizeOfHeaders).ToArray().CopyTo(moduleRemote, 0);

#if DEBUG
            DLog($"PE Header written at 0x{remoteModuleHandle.ToInt64():X16}");
#endif

            // Write sections to memory
            foreach (IMAGE_SECTION_HEADER ish in PEINFO.Sections)
            {
                // Calculate offsets
                IntPtr pVirtualSectionBase = (IntPtr)(ish.VirtualAddress);

                moduleRaw.Skip((int)ish.PointerToRawData).Take((int)ish.SizeOfRawData).ToArray().CopyTo(moduleRemote, pVirtualSectionBase.ToInt32());
#if DEBUG
                DLog($"{new string(ish.Name).Trim().Replace('\x00'.ToString(), "")} written at 0x{pVirtualSectionBase.ToInt64():X16}, Size: 0x{ish.SizeOfRawData:X8}");
#endif
            }

            // Perform relocations
            __MMRelocateModule(PEINFO, remoteModuleHandle, moduleRaw, moduleRemote);

            // Rewrite IAT
            __MMRewriteModuleIAT(PEINFO, remoteModuleHandle, moduleRaw, moduleRemote);

            // Write the module to memory
            SetBytes(remoteModuleHandle, moduleRemote);

            // Set memory protections
            MMSetModuleSectionPermissions(PEINFO, remoteModuleHandle, moduleRaw);

            // Free temp HGlobal
            Marshal.FreeHGlobal(localModuleHandle);

            // Prepare return object
            PE_MANUAL_MAP ManMapObject = new PE_MANUAL_MAP
            {
                ModuleBase = remoteModuleHandle,
                PEINFO     = PEINFO
            };
            return(ManMapObject);
        }
Exemple #12
0
        /// <summary>
        /// Rewrite IAT for manually mapped remote module.
        /// </summary>
        /// <author>Ruben Boonen (@FuzzySec)</author> (modified for external ProcessEx)
        /// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
        /// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
        /// <returns>void</returns>
        private void __MMRewriteModuleIAT(PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, byte[] moduleRaw, byte[] moduleRemote)
        {
            IMAGE_DATA_DIRECTORY idd = PEINFO.Is32Bit ? PEINFO.OptHeader32.ImportTable : PEINFO.OptHeader64.ImportTable;

            // Check if there is no import table
            if (idd.VirtualAddress == 0)
            {
                // Return so that the rest of the module mapping process may continue.
                return;
            }

            // Ptr for the base import directory
            IntPtr pImportTable = (IntPtr)(idd.VirtualAddress);

            // Get API Set mapping dictionary if on Win10+
            Native.OSVERSIONINFOEX OSVersion = new Native.OSVERSIONINFOEX();
            Native.RtlGetVersionD(ref OSVersion);
            if (OSVersion.MajorVersion < 10)
            {
                throw new Exception(DSTR(DSTR_OS_VERSION_TOO_OLD));
            }

#if DEBUG
            DLog($"Starting IAT rewrite...");
#endif

            // Loop IID's
            int counter = 0;
            Native.IMAGE_IMPORT_DESCRIPTOR iid = new Native.IMAGE_IMPORT_DESCRIPTOR();
            iid = moduleRemote.Skip(pImportTable.ToInt32() + (int)(Marshal.SizeOf(typeof(Native.IMAGE_IMPORT_DESCRIPTOR)) * counter)).Take(Marshal.SizeOf(typeof(Native.IMAGE_IMPORT_DESCRIPTOR))).ToArray().ToStruct <Native.IMAGE_IMPORT_DESCRIPTOR>();
            while (iid.Name != 0)
            {
                // Get DLL
                string DllName = string.Empty;
                try
                {
                    DllName = moduleRemote.String((int)iid.Name);
                }
                catch { }

                // Loop imports
                if (DllName == string.Empty)
                {
                    throw new Exception(DSTR(DSTR_MODULE_NAME_INVALID));
                }
                else
                {
                    // API Set DLL?
                    string dll_resolved;
                    if ((DllName.StartsWith("api-") || DllName.StartsWith("ext-")))
                    {
                        // for some reason, Lunar's resolve apiset is 1000x better than the dictionary setup done in dinvoke, so we will just use that.
                        // lmfao: https://github.com/cobbr/SharpSploit/issues/58
                        if ((dll_resolved = ResolveAPISet(DllName)) == null)
                        {
                            throw new Exception(DSTR(DSTR_API_DLL_UNRESOLVED, DllName));
                        }
                        // Not all API set DLL's have a registered host mapping
                        DllName = dll_resolved;
                    }

#if DEBUG
                    DLog($"Resolving {DllName}...");
#endif

                    // Check and / or load DLL
                    IntPtr hModule = GetLoadedModuleAddress(DllName);
                    if (hModule == IntPtr.Zero)
                    {
#if DEBUG
                        DLog($"Unresolved: {DllName}, Loading into memory...");
#endif
                        hModule = LoadAndRegisterDllRemote(DllName).BaseAddress;
                        if (hModule == IntPtr.Zero)
                        {
                            throw new Exception(DSTR(DSTR_MODULE_FILE_NOT_FOUND, DllName));
                        }
                    }

                    // Locate the module by its base address
                    ProcessModuleEx sModule = FindModuleByAddress(hModule);

#if DEBUG
                    DLog($"Resolved Module: {sModule.ModuleName}:{sModule.BaseAddress:X}, {sModule.ModulePath}");
#endif

                    // Loop thunks
                    if (PEINFO.Is32Bit)
                    {
                        IMAGE_THUNK_DATA32 oft_itd = new IMAGE_THUNK_DATA32();
                        for (int i = 0; true; i++)
                        {
                            oft_itd = moduleRemote.Skip((int)(iid.OriginalFirstThunk + (UInt32)(i * (sizeof(UInt32))))).Take(4).ToArray().ToStruct <IMAGE_THUNK_DATA32>();
                            IntPtr ft_itd = (IntPtr)((UInt64)iid.FirstThunk + (UInt64)(i * (sizeof(UInt32))));
                            if (oft_itd.AddressOfData == 0)
                            {
                                break;
                            }

                            if (oft_itd.AddressOfData < 0x80000000) // !IMAGE_ORDINAL_FLAG32
                            {
                                uint pImpByName = (uint)((uint)oft_itd.AddressOfData + sizeof(UInt16));

                                var pFunc = GetProcAddress(sModule.ModuleName, moduleRemote.String((int)pImpByName));

                                // Write ProcAddress
                                BitConverter.GetBytes((int)pFunc).CopyTo(moduleRemote, ft_itd.ToInt32());
                            }
                            else
                            {
                                ulong fOrdinal = oft_itd.AddressOfData & 0xFFFF;
                                var   pFunc    = GetModuleExportAddress(sModule.ModuleName, (short)fOrdinal);

                                // Write ProcAddress
                                BitConverter.GetBytes((int)pFunc).CopyTo(moduleRemote, ft_itd.ToInt32());
                            }
                        }
                    }
                    else
                    {
                        IMAGE_THUNK_DATA64 oft_itd = new IMAGE_THUNK_DATA64();
                        for (int i = 0; true; i++)
                        {
                            oft_itd = moduleRemote.Skip((int)(iid.OriginalFirstThunk + (uint)(i * sizeof(ulong)))).Take(8).ToArray().ToStruct <IMAGE_THUNK_DATA64>();
                            IntPtr ft_itd = (IntPtr)((UInt64)iid.FirstThunk + (UInt64)(i * (sizeof(UInt64))));
                            if (oft_itd.AddressOfData == 0)
                            {
                                break;
                            }

                            if (oft_itd.AddressOfData < 0x8000000000000000) // !IMAGE_ORDINAL_FLAG64
                            {
                                uint pImpByName = (uint)((uint)oft_itd.AddressOfData + sizeof(UInt16));
                                var  pFunc      = GetProcAddress(sModule.ModuleName, moduleRemote.String((int)pImpByName));

                                // Write pointer
                                BitConverter.GetBytes((long)pFunc).CopyTo(moduleRemote, ft_itd.ToInt32());
                            }
                            else
                            {
                                ulong fOrdinal = oft_itd.AddressOfData & 0xFFFF;
                                var   pFunc    = GetModuleExportAddress(sModule.ModuleName, (short)fOrdinal);

                                // Write pointer
                                BitConverter.GetBytes((long)pFunc).CopyTo(moduleRemote, ft_itd.ToInt32());
                            }
                        }
                    }
                    counter++;
                    iid = moduleRemote.Skip(pImportTable.ToInt32() + (int)(Marshal.SizeOf(typeof(Native.IMAGE_IMPORT_DESCRIPTOR)) * counter)).Take(Marshal.SizeOf(typeof(Native.IMAGE_IMPORT_DESCRIPTOR))).ToArray().ToStruct <Native.IMAGE_IMPORT_DESCRIPTOR>();
                }
            }
        }