Example #1
0
        /// <summary>
        /// Relocates a module in remote memory.
        /// </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 __MMRelocateModule(PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, byte[] moduleRaw, byte[] moduleRemote)
        {
            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)(idd.VirtualAddress);
            Int32  nextRelocTableBlock = -1;

            // Loop reloc blocks
            while (nextRelocTableBlock != 0)
            {
                IMAGE_BASE_RELOCATION ibr = new IMAGE_BASE_RELOCATION();
                ibr = moduleRemote.Skip(pRelocTable.ToInt32()).Take(Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION))).ToArray().ToStruct <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)BitConverter.ToUInt16(moduleRemote, pRelocEntry.ToInt32());

                    // 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)(ibr.VirtualAdress + RelocPatch);
                            if (RelocType == 0x3) // IMAGE_REL_BASED_HIGHLOW (x86)
                            {
                                Int32 OriginalPtr = BitConverter.ToInt32(moduleRemote, pPatch.ToInt32());
                                BitConverter.GetBytes((OriginalPtr + (Int32)ImageDelta)).CopyTo(moduleRemote, pPatch.ToInt32());
                            }
                            else // IMAGE_REL_BASED_DIR64 (x64)
                            {
                                Int64 OriginalPtr = BitConverter.ToInt64(moduleRemote, pPatch.ToInt32());
                                BitConverter.GetBytes((OriginalPtr + ImageDelta)).CopyTo(moduleRemote, pPatch.ToInt32());
                            }
                        }
                        catch
                        {
                            throw new Exception(DSTR(DSTR_MEM_ACCESS_VIOLATION));
                        }
                    }
                }

                // Check for next block
                pRelocTable         = (IntPtr)((UInt64)pRelocTable + ibr.SizeOfBlock);
                nextRelocTableBlock = BitConverter.ToInt32(moduleRemote, pRelocTable.ToInt32());
            }
        }
Example #2
0
        private int GetModuleCount(IntPtr codeBase, IMAGE_DATA_DIRECTORY directory)
        {
            int result = 0;            
            if (directory.Size > 0)
            {
                IMAGE_IMPORT_DESCRIPTOR importDesc = codeBase.ToStruct<IMAGE_IMPORT_DESCRIPTOR>(directory.VirtualAddress);

                while (importDesc.Name > 0)
                {
                    string moduleName = Marshal.PtrToStringAnsi(codeBase.Add(importDesc.Name));
                    if (Native.LoadLibrary(moduleName) == IntPtr.Zero) break;

                    result++;
                    importDesc = codeBase.ToStruct<IMAGE_IMPORT_DESCRIPTOR>((uint)(directory.VirtualAddress + (Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR)) * result)));
                }
            }
            return result;
        }
Example #3
0
        private void PerformBaseRelocation64(ulong delta)
        {
            //ConsoleWindow.WriteLine("PerformBaseRelocation: Delta="+delta);
            IntPtr codeBase = module64.codeBase;
            int sizeOfBase = Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
            IMAGE_DATA_DIRECTORY directory = module64.headers.OptionalHeader.BaseRelocationTable;

            int cnt = 0;
            if (directory.Size > 0)
            {
                var relocation = codeBase.ToStruct<IMAGE_BASE_RELOCATION>(directory.VirtualAddress);
                while (relocation.VirtualAddress > 0)
                {
                    unsafe
                    {
                        var dest = (IntPtr)(codeBase.ToInt32() + (int)relocation.VirtualAddress);
                        var relInfo = (ushort*)(codeBase.ToInt32() + (int)directory.VirtualAddress + sizeOfBase);
                        uint i;
                        for (i = 0; i < ((relocation.SizeOfBlock - Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION))) / 2); i++, relInfo++)
                        {
                            int type = *relInfo >> 12;
                            int offset = (*relInfo & 0xfff);
                            switch (type)
                            {
                                case 0x00:
                                break;
                                case 0x03:
                                    uint* patchAddrHl = (uint*)((int)dest + offset);
                                    *patchAddrHl += (uint)delta;
                                break;
                                case 0x0A:
                                    ulong* patchAddrDIR64 = (ulong*)((long)dest + offset);
                                    *patchAddrDIR64 += delta;
                                break;
                            }
                        }
                    }
                    cnt += (int)relocation.SizeOfBlock;
                    relocation = codeBase.ToStruct<IMAGE_BASE_RELOCATION>((uint)(directory.VirtualAddress + cnt));
                }
            }
        }
Example #4
0
        private void BuildImportTable64(MEMORYMODULE64 module64)
        {
            int moduleCount = 0;
            IntPtr codeBase = module64.codeBase;
            IMAGE_DATA_DIRECTORY directory = module64.headers.OptionalHeader.ImportTable;

            if (directory.Size > 0)
            {
                //Log.Console("ImportTable.Size: "+ directory.Size);

                ulong* nameRef, funcRef;
                IMAGE_IMPORT_DESCRIPTOR importDesc = codeBase.ToStruct<IMAGE_IMPORT_DESCRIPTOR>(directory.VirtualAddress);                

                while (importDesc.Name > 0)
                {
                    string moduleName = Marshal.PtrToStringAnsi(codeBase.Add(importDesc.Name));
                    //Log.Console("Import Module: " + moduleName);

                    IntPtr handle = Native.LoadLibrary(moduleName);
                    if (handle == IntPtr.Zero) break;

                    if (importDesc.CharacteristicsOrOriginalFirstThunk > 0)
                    {                        
                        nameRef = (ulong*)codeBase.Add(importDesc.CharacteristicsOrOriginalFirstThunk);
                        funcRef = (ulong*)codeBase.Add(importDesc.FirstThunk);
                    }
                    else
                    {
                        nameRef = (ulong*)codeBase.Add(importDesc.FirstThunk);
                        funcRef = (ulong*)codeBase.Add(importDesc.FirstThunk);
                    }

                    for (; *nameRef > 0; nameRef++, funcRef++)
                    {
                        //Log.Console("Import: " + nameRef->ToString("X16") + ", 0x" + funcRef->ToString("x16"));

                        if ((*nameRef & 0x8000000000000000) != 0)
                        {
                            *funcRef = (ulong)Native.GetProcAddress(handle, new IntPtr((long)*nameRef & 0xffff));
                        }
                        else
                        {
                            string functionName = Marshal.PtrToStringAnsi(codeBase.Add((long)(*nameRef) + 2));                        
                            *funcRef = (ulong)Native.GetProcAddress(handle, functionName);
                            //Log.Console("Import Function: " + functionName + " -> 0x" + funcRef->ToString("x16"));
                        }

                        //Log.Console("Import nameRef: 0x" + nameRef->ToString("X16"));
                        //Log.Console("Import funcRef: 0x" + funcRef->ToString("X16"));                                                

                        if (*funcRef == 0)
                        {
                            break;
                        }
                    }

                    moduleCount++;
                    importDesc = codeBase.ToStruct<IMAGE_IMPORT_DESCRIPTOR>(directory.VirtualAddress + (uint)(Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR)) * moduleCount));
                }            
            }
        }
Example #5
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>();
                }
            }
        }