示例#1
0
            private IEnumerable <HarmonyImportLibrary> ResolveImports(Image image)
            {
                IMAGE_DATA_DIRECTORY directory = Environment.Is64BitProcess
                                        ? image.OptionalHeader64->ImportTable
                                        : image.OptionalHeader32->ImportTable;

                if (directory.Size == 0 || (_loadFlags & HarmonyLoadFlags.NoImports) != 0)
                {
                    return(Enumerable.Empty <HarmonyImportLibrary>());
                }

                Dictionary <string, HarmonyLibrary> otherLibraryLookup =
                    _otherLibraries.ToDictionary(l => (Path.GetFileName(l.Name) ?? l.Name).ToLowerInvariant());

                List <HarmonyImportLibrary> imports = new List <HarmonyImportLibrary>();

                IMAGE_IMPORT_DESCRIPTOR *importDescriptor = (IMAGE_IMPORT_DESCRIPTOR *)(image.BasePtr + directory.VirtualAddress);

                for (; !Kernel32.IsBadReadPtr((UIntPtr)importDescriptor, (uint)sizeof(IMAGE_IMPORT_DESCRIPTOR)) &&
                     importDescriptor->Name != 0; importDescriptor++)
                {
                    HarmonyImportLibrary import = LoadImport(image.BasePtr, image.Size, importDescriptor, otherLibraryLookup, _loadFlags);

                    imports.Add(import);
                }

                return(imports);
            }
示例#2
0
        public unsafe int GetMetadata(
            IntPtr self,
            string filename,
            uint imageTimestamp,
            uint imageSize,
            IntPtr mvid,
            uint mdRva,
            uint flags,
            uint bufferSize,
            IntPtr buffer,
            int *pDataSize)
        {
            if (buffer == IntPtr.Zero)
            {
                return(E_INVALIDARG);
            }

            string?filePath = _dataTarget.BinaryLocator.FindBinary(filename, imageTimestamp, imageSize, true);

            if (filePath is null)
            {
                return(E_FAIL);
            }

            // We do not put a using statement here to prevent needing to load/unload the binary over and over.
            PEImage?peimage = _dataTarget.LoadPEImage(filePath);

            if (peimage is null || peimage.OptionalHeader is null)
            {
                return(E_FAIL);
            }

            DebugOnly.Assert(peimage.IsValid);

            uint rva  = mdRva;
            uint size = bufferSize;

            if (rva == 0)
            {
                IMAGE_DATA_DIRECTORY comDescriptor = peimage.OptionalHeader.ComDescriptorDirectory;
                if (comDescriptor.VirtualAddress == 0)
                {
                    return(E_FAIL);
                }

                rva  = comDescriptor.VirtualAddress;
                size = Math.Min(bufferSize, comDescriptor.Size);
            }

            checked
            {
                int read = peimage.Read((int)rva, new Span <byte>(buffer.ToPointer(), (int)size));
                if (pDataSize != null)
                {
                    *pDataSize = read;
                }
            }

            return(S_OK);
        }
示例#3
0
        public Int32 GetModuleCount()
        {
            Int32  count    = 0;
            IntPtr codeBase = this._module.codeBase;
            IMAGE_DATA_DIRECTORY directory = this._module.headers.OptionalHeader.DataDirectory[1];

            if (directory.Size > 0)
            {
                IMAGE_IMPORT_DESCRIPTOR importDesc = PointerHelpers.ToStruct <IMAGE_IMPORT_DESCRIPTOR>(codeBase, directory.VirtualAddress);
                while (importDesc.Name > 0)
                {
                    Int32  str    = codeBase.ToInt32() + (Int32)importDesc.Name;
                    String tmp    = Marshal.PtrToStringAnsi(new IntPtr(str));
                    Int32  handle = Win32Imports.LoadLibrary(tmp);

                    if (handle == -1)
                    {
                        break;
                    }

                    count++;
                    importDesc = PointerHelpers.ToStruct <IMAGE_IMPORT_DESCRIPTOR>(codeBase, (UInt32)(directory.VirtualAddress + (Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR)) * (count))));
                }
            }
            return(count);
        }
示例#4
0
        public uint GetProcAddress(string name)
        {
            unsafe
            {
                IntPtr codeBase = module.codeBase;
                int    idx      = -1;
                uint   i;
                IMAGE_DATA_DIRECTORY directory = module.headers.OptionalHeader.DataDirectory[0];
                if (directory.Size == 0)
                {
                    return(0);
                }
                var exports = PointerHelpers.ToStruct <IMAGE_EXPORT_DIRECTORY>(codeBase, directory.VirtualAddress);
                var nameRef = (uint *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNames);
                var ordinal = (ushort *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNameOrdinals);
                for (i = 0; i < exports.NumberOfNames; i++, nameRef++, ordinal++)
                {
                    var    str = codeBase + (int)(*nameRef);
                    string tmp = Marshal.PtrToStringAnsi(str);
                    if (tmp == name)
                    {
                        idx = *ordinal;
                        break;
                    }
                }

                var tmpaa = (uint *)(codeBase.ToInt32() + (exports.AddressOfFunctions + (idx * 4)));
                var addr  = (uint)((codeBase.ToInt32()) + (*tmpaa));
                return(addr);
            }
        }
        public void ImageDataDirectoryConstructorWorks_Test()
        {
            var dataDirectory = new IMAGE_DATA_DIRECTORY(RawStructures.RawDataDirectory, 2);

            Assert.Equal((uint)0x44332211, dataDirectory.VirtualAddress);
            Assert.Equal(0x88776655, dataDirectory.Size);
        }
示例#6
0
            private ExportDictionaries GetExportDictionaries(Image image)
            {
                Dictionary <string, HarmonyExport> exportsByName    = new Dictionary <string, HarmonyExport>();
                Dictionary <ushort, HarmonyExport> exportsByOrdinal = new Dictionary <ushort, HarmonyExport>();

                IMAGE_DATA_DIRECTORY directory = Environment.Is64BitProcess
                                        ? image.OptionalHeader64->ExportTable : image.OptionalHeader32->ExportTable;

                if (directory.VirtualAddress == 0)
                {
                    return(new ExportDictionaries(exportsByName, exportsByOrdinal));
                }

                IMAGE_EXPORT_DIRECTORY *exportDirectory = (IMAGE_EXPORT_DIRECTORY *)(image.BasePtr + directory.VirtualAddress);
                UIntPtr nameRef     = (UIntPtr)(image.BasePtr + exportDirectory->AddressOfNames);
                UIntPtr ordinalRef  = (UIntPtr)(image.BasePtr + exportDirectory->AddressOfNameOrdinals);
                ushort  ordinalBase = (ushort)exportDirectory->Base;

                for (int i = 0; i < exportDirectory->NumberOfNames; i++, nameRef += sizeof(UInt32), ordinalRef += sizeof(UInt16))
                {
                    byte * namePtr = image.BasePtr + (int)*(UInt32 *)nameRef;
                    string name    = StringOperations.NulTerminatedBytesToString(namePtr, image.BasePtr, image.Size);
                    ushort ordinal = *(UInt16 *)ordinalRef;

                    IntPtr exportAddress = (IntPtr)(image.BasePtr + (int)*(UInt32 *)(image.BasePtr + exportDirectory->AddressOfFunctions + ordinal * sizeof(UInt32)));

                    ushort        displayOrdinal = (ushort)(ordinal + ordinalBase);
                    HarmonyExport export         = new HarmonyExport(name, displayOrdinal, exportAddress);
                    exportsByName[name] = export;
                    exportsByOrdinal[displayOrdinal] = export;
                }

                return(new ExportDictionaries(exportsByName, exportsByOrdinal));
            }
示例#7
0
        public String[] GetProcedures()
        {
            unsafe
            {
                IntPtr codeBase = this._module.codeBase;
                IMAGE_DATA_DIRECTORY directory = this._module.headers.OptionalHeader.DataDirectory[0];
                if (directory.Size == 0)
                {
                    return new String[] { }
                }
                ;

                IMAGE_EXPORT_DIRECTORY exports = PointerHelpers.ToStruct <IMAGE_EXPORT_DIRECTORY>(codeBase, directory.VirtualAddress);
                UInt32 *nameRef = (UInt32 *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNames);
                UInt16 *ordinal = (UInt16 *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNameOrdinals);

                String[] result = new String[exports.NumberOfNames];
                for (UInt32 i = 0; i < exports.NumberOfNames; i++, nameRef++, ordinal++)
                {
                    IntPtr str = new IntPtr(codeBase.ToInt32() + (Int32)(*nameRef));
                    result[i] = Marshal.PtrToStringAnsi(str);
                }
                return(result);
            }
        }
        private static void PatchRelocations(JLibrary.PortableExecutable.PortableExecutable image, IntPtr pAlloc)
        {
            IMAGE_DATA_DIRECTORY image_data_directory = image.NTHeader.OptionalHeader.DataDirectory[5];

            if (image_data_directory.Size > 0)
            {
                IMAGE_BASE_RELOCATION image_base_relocation;
                uint num        = 0;
                uint num2       = ((uint)pAlloc.ToInt32()) - image.NTHeader.OptionalHeader.ImageBase;
                uint ptrFromRVA = image.GetPtrFromRVA(image_data_directory.VirtualAddress);
                uint num4       = (uint)Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
                while ((num < image_data_directory.Size) && image.Read <IMAGE_BASE_RELOCATION>((long)ptrFromRVA, SeekOrigin.Begin, out image_base_relocation))
                {
                    int  num5 = (int)((image_base_relocation.SizeOfBlock - num4) / 2);
                    uint num6 = image.GetPtrFromRVA(image_base_relocation.VirtualAddress);
                    for (int i = 0; i < num5; i++)
                    {
                        ushort num7;
                        if (image.Read <ushort>((ptrFromRVA + num4) + (i << 1), SeekOrigin.Begin, out num7) && (((num7 >> 12) & 3) != 0))
                        {
                            uint num8;
                            uint num10 = num6 + ((uint)(num7 & 0xfff));
                            if (!image.Read <uint>((long)num10, SeekOrigin.Begin, out num8))
                            {
                                throw image.GetLastError();
                            }
                            image.Write <uint>(-4L, SeekOrigin.Current, num8 + num2);
                        }
                    }
                    num        += image_base_relocation.SizeOfBlock;
                    ptrFromRVA += image_base_relocation.SizeOfBlock;
                }
            }
        }
示例#9
0
        public int GetModuleCount()
        {
            int    count    = 0;
            IntPtr codeBase = module.codeBase;
            IMAGE_DATA_DIRECTORY directory = module.headers.OptionalHeader.DataDirectory[1];

            if (directory.Size > 0)
            {
                var importDesc = PointerHelpers.ToStruct <IMAGE_IMPORT_DESCRIPTOR>(codeBase, directory.VirtualAddress);
                while (importDesc.Name > 0)
                {
                    var    str    = codeBase + (int)importDesc.Name;
                    string tmp    = Marshal.PtrToStringAnsi(str);
                    int    handle = Win32Imports.LoadLibrary(tmp);

                    if (handle == -1)
                    {
                        break;
                    }

                    count++;
                    importDesc = PointerHelpers.ToStruct <IMAGE_IMPORT_DESCRIPTOR>(codeBase,
                                                                                   (uint)(directory.VirtualAddress +
                                                                                          (Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR)) * (count))));
                }
            }

            return(count);
        }
示例#10
0
        // Token: 0x06000121 RID: 289 RVA: 0x0000DB90 File Offset: 0x0000BD90
        private static void PatchRelocations(PortableExecutable image, IntPtr pAlloc)
        {
            IMAGE_DATA_DIRECTORY image_DATA_DIRECTORY = image.NTHeader.OptionalHeader.DataDirectory[5];

            if (image_DATA_DIRECTORY.Size > 0u)
            {
                uint num  = 0u;
                uint num2 = (uint)((long)pAlloc.ToInt32() - (long)((ulong)image.NTHeader.OptionalHeader.ImageBase));
                uint num3 = image.GetPtrFromRVA(image_DATA_DIRECTORY.VirtualAddress);
                uint num4 = (uint)Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
                IMAGE_BASE_RELOCATION image_BASE_RELOCATION;
                while (num < image_DATA_DIRECTORY.Size && image.Read <IMAGE_BASE_RELOCATION>((long)((ulong)num3), SeekOrigin.Begin, out image_BASE_RELOCATION))
                {
                    int  num5       = (int)((image_BASE_RELOCATION.SizeOfBlock - num4) / 2u);
                    uint ptrFromRVA = image.GetPtrFromRVA(image_BASE_RELOCATION.VirtualAddress);
                    for (int i = 0; i < num5; i++)
                    {
                        ushort num6;
                        if (image.Read <ushort>((long)((ulong)(num3 + num4) + (ulong)((long)((long)i << 1))), SeekOrigin.Begin, out num6) && (num6 >> 12 & 3) != 0)
                        {
                            uint num7 = (uint)((ulong)ptrFromRVA + (ulong)((long)(num6 & 4095)));
                            uint num8;
                            if (!image.Read <uint>((long)((ulong)num7), SeekOrigin.Begin, out num8))
                            {
                                throw image.GetLastError();
                            }
                            image.Write <uint>(-4L, SeekOrigin.Current, num8 + num2);
                        }
                    }
                    num  += image_BASE_RELOCATION.SizeOfBlock;
                    num3 += image_BASE_RELOCATION.SizeOfBlock;
                }
            }
        }
示例#11
0
 public static PE64DataDirectory FromNativeStruct(IMAGE_DATA_DIRECTORY nativeStruct)
 {
     return(new PE64DataDirectory
     {
         VirtualAddress = nativeStruct.VirtualAddress,
         Size = nativeStruct.Size
     });
 }
示例#12
0
        /// <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);
            }
        }
示例#13
0
        public static IMAGE_DATA_DIRECTORY Deserialize(MultiPartFile file)
        {
            IMAGE_DATA_DIRECTORY idd = new IMAGE_DATA_DIRECTORY();

            idd.VirtualAddress = file.ReadUInt32();
            idd.Size           = file.ReadUInt32();

            return(idd);
        }
    IntPtr GetPtrFromFuncName(string funcName)
    {
        if (Disposed)
        {
            throw new ObjectDisposedException("DLLFromMemory");
        }
        if (string.IsNullOrEmpty(funcName))
        {
            throw new ArgumentException("funcName");
        }
        if (!IsDll)
        {
            throw new InvalidOperationException("Loaded Module is not a DLL");
        }
        if (!_initialized)
        {
            throw new InvalidOperationException("Dll is not initialized");
        }

        IntPtr pDirectory = PtrAdd(pNTHeaders, Of.IMAGE_NT_HEADERS_OptionalHeader + (Is64BitProcess ? Of64.IMAGE_OPTIONAL_HEADER_ExportTable: Of32.IMAGE_OPTIONAL_HEADER_ExportTable));
        IMAGE_DATA_DIRECTORY Directory = PtrRead <IMAGE_DATA_DIRECTORY>(pDirectory);

        if (Directory.Size == 0)
        {
            throw new DllException("Dll has no export table");
        }

        IntPtr pExports = PtrAdd(pCode, Directory.VirtualAddress);
        IMAGE_EXPORT_DIRECTORY Exports = PtrRead <IMAGE_EXPORT_DIRECTORY>(pExports);

        if (Exports.NumberOfFunctions == 0 || Exports.NumberOfNames == 0)
        {
            throw new DllException("Dll exports no functions");
        }

        IntPtr pNameRef = PtrAdd(pCode, Exports.AddressOfNames);
        IntPtr pOrdinal = PtrAdd(pCode, Exports.AddressOfNameOrdinals);

        for (int i = 0; i < Exports.NumberOfNames; i++, pNameRef = PtrAdd(pNameRef, sizeof(uint)), pOrdinal = PtrAdd(pOrdinal, sizeof(ushort)))
        {
            uint   NameRef     = PtrRead <uint>(pNameRef);
            ushort Ordinal     = PtrRead <ushort>(pOrdinal);
            string curFuncName = Marshal.PtrToStringAnsi(PtrAdd(pCode, NameRef));
            if (curFuncName == funcName)
            {
                if (Ordinal > Exports.NumberOfFunctions)
                {
                    throw new DllException("Invalid function ordinal");
                }
                IntPtr pAddressOfFunction = PtrAdd(pCode, (Exports.AddressOfFunctions + (uint)(Ordinal * 4)));
                return(PtrAdd(pCode, PtrRead <uint>(pAddressOfFunction)));
            }
        }

        throw new DllException("Dll exports no function named " + funcName);
    }
示例#15
0
        public static List <string> ExportTable(string dllPath)
        {
            var hModule = LoadLibraryEx(dllPath, IntPtr.Zero, LoadLibraryFlags.DONT_RESOLVE_DLL_REFERENCES);

            if (hModule == IntPtr.Zero)
            {
                throw new Win32Exception(GetLastError());
            }

            try
            {
                var imageDosHeader = Marshal.PtrToStructure <IMAGE_DOS_HEADER>(hModule);
                if (!imageDosHeader.IsValid)
                {
                    throw new Exception($"IMAGE_DOS_HEADER is invalid: {dllPath}");
                }

#if WIN64
                var imageNtHeaders = Marshal.PtrToStructure <IMAGE_NT_HEADERS64>(hModule + imageDosHeader.e_lfanew);
#else
                var imageNtHeaders = Marshal.PtrToStructure <IMAGE_NT_HEADERS32>(hModule + imageDosHeader.e_lfanew);
#endif
                if (!imageNtHeaders.IsValid)
                {
                    throw new Exception($"IMAGE_NT_HEADERS is invalid: {dllPath}");
                }

                IMAGE_DATA_DIRECTORY exportTabledataDirectory = imageNtHeaders.OptionalHeader.ExportTable;
                if (exportTabledataDirectory.Size == 0)
                {
                    return(new List <string>());
                }

                var exportTable =
                    Marshal.PtrToStructure <IMAGE_EXPORT_DIRECTORY>(hModule + exportTabledataDirectory.VirtualAddress);

                var names = new List <string>();
                for (var i = 0; i < exportTable.NumberOfNames; i++)
                {
                    var name = Marshal.PtrToStringAnsi(hModule + Marshal.ReadInt32(hModule + exportTable.AddressOfNames + (i * 4)));
                    if (name == null)
                    {
                        continue;
                    }

                    names.Add(name);
                }

                return(names);
            }
            finally
            {
                FreeLibrary(hModule);
            }
        }
示例#16
0
        internal DataDirectory(PortableExecutableImage image, DataDirectories dataDirs, DataDirectoryType dirType, IMAGE_DATA_DIRECTORY dataDirectory, ulong imageBase)
        {
            _image       = image;
            _type        = dirType;
            _header      = dataDirectory;
            _imageBase   = imageBase;
            _sectionName = new Lazy <string>(DoGetSectionName);
            _section     = new Lazy <Section>(DoGetSection);

            Directories = dataDirs;
        }
示例#17
0
 internal ExportedFunctionsParser(
     byte[] buff,
     IMAGE_EXPORT_DIRECTORY exportDirectory,
     IMAGE_SECTION_HEADER[] sectionHeaders,
     IMAGE_DATA_DIRECTORY exportDataDir
     )
     : base(buff, 0)
 {
     _exportDirectory = exportDirectory;
     _sectionHeaders  = sectionHeaders;
     _exportDataDir   = exportDataDir;
 }
示例#18
0
        /// <inheritdoc />
        public bool TryGetDirectoryHeader(ImageDirectoryEntry type, out IMAGE_DATA_DIRECTORY entry)
        {
            int index = (int)type;

            if (0 <= index && index < _dataDirectories.Length)
            {
                entry = _dataDirectories[index];
                return(true);
            }

            entry = default(IMAGE_DATA_DIRECTORY);
            return(false);
        }
示例#19
0
            public static PDBContainer FromBinaryReader(BinaryReader r, PEHeaderParser parser, bool parsingFile = true)
            {
                IMAGE_DATA_DIRECTORY selectDirectory = parser.NTHeader.OptionalHeader.DebuggingInformation;


                long addr = 0;

                if (parsingFile)
                {
                    for (int i = 0; i < parser.SectionHeaders.Count; ++i)
                    {
                        var section = parser.SectionHeaders[i];
                        if (selectDirectory.VirtualAddress >= section.VirtualAddress && selectDirectory.VirtualAddress <= section.VirtualAddress + section.VirtualSize)
                        {
                            addr = selectDirectory.VirtualAddress - section.VirtualAddress + section.PointerToRawData;
                        }
                    }
                }
                else
                {
                    addr = selectDirectory.VirtualAddress;
                }
                if (selectDirectory.Size > 0 && addr > 0)
                {
                    r.BaseStream.Position = addr;
                    byte[] buf = r.ReadBytes(unchecked ((int)selectDirectory.Size));
                    using (BinaryReader bufFetcher = new BinaryReader(new MemoryStream(buf)))
                    {
                        bufFetcher.BaseStream.Position = 0;
                        DebugDataDirectory debugData = new DebugDataDirectory();
                        debugData.Characteristics = bufFetcher.ReadUInt32();
                        debugData.TimeDateStamp   = bufFetcher.ReadUInt32();
                        debugData.MajorVersion    = bufFetcher.ReadUInt16();
                        debugData.MinorVersion    = bufFetcher.ReadUInt16();

                        debugData.Type             = bufFetcher.ReadUInt32();
                        debugData.SizeOfData       = bufFetcher.ReadUInt32();
                        debugData.AddressOfRawData = bufFetcher.ReadUInt32();
                        debugData.PointerToRawData = bufFetcher.ReadUInt32();
                        if (debugData.SizeOfData > 0 && debugData.PointerToRawData != 0)
                        {
                            PDBContainer pdbContainer = new PDBContainer(debugData.SizeOfData, parser);
                            r.BaseStream.Position = debugData.PointerToRawData;
                            pdbContainer.RawPdb   = r.ReadBytes(unchecked ((int)debugData.SizeOfData));
                            pdbContainer.FillBaseInfo(0, parser.FileSize, selectDirectory.VirtualAddress);
                            return(pdbContainer);
                        }
                    }
                }
                return(null);
            }
示例#20
0
        private static void PatchRelocations(PortableExecutable image, IntPtr pAlloc)
        {
            // Base relocations are essentially Microsofts ingenious way of preserving portability in images.
            // for all absolute address calls/jmps/references...etc, an entry is made into the base relocation
            // table telling the loader exactly where an "absolute" address is being used. This allows the loader
            // to iterate through the relocations and patch these absolute values to ensure they are correct when
            // the image is loaded somewhere that isn't its preferred base address.
            IMAGE_DATA_DIRECTORY relocDir = image.NTHeader.OptionalHeader.DataDirectory[(int)DATA_DIRECTORIES.BaseRelocTable];

            if (relocDir.Size > 0) //check if there are in fact any relocations.
            {
                uint n       = 0;
                uint delta   = (uint)(pAlloc.ToInt32() - image.NTHeader.OptionalHeader.ImageBase); //The difference in loaded/preferred addresses.
                uint pReloc  = image.GetPtrFromRVA(relocDir.VirtualAddress);
                uint szReloc = (uint)Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
                IMAGE_BASE_RELOCATION reloc;

                while (n < relocDir.Size && image.Read(pReloc, SeekOrigin.Begin, out reloc))
                {
                    // A relocation block consists of an IMAGE_BASE_RELOCATION, and an array of WORDs.
                    // To calculate the number of relocations (represented by WORDs), just do some simple math.
                    int    nrelocs = (int)((reloc.SizeOfBlock - szReloc) / sizeof(ushort));
                    uint   pageVa  = image.GetPtrFromRVA(reloc.VirtualAddress); //The Page RVA for this set of relocations (usually a 4K boundary).
                    ushort vreloc;
                    uint   old;

                    for (int i = 0; i < nrelocs; i++)
                    {
                        // There are only 2 types of relocations on Intel machines: ABSOLUTE (padding, nothing needs to be done) and HIGHLOW (0x03)
                        // Highlow means that all 32 bits of the "delta" value need to be added to the relocation value.
                        if (image.Read(pReloc + szReloc + (i << 1), SeekOrigin.Begin, out vreloc) && (vreloc >> 12 & 3) != 0)
                        {
                            uint vp = (uint)(pageVa + (vreloc & 0x0FFF));
                            if (image.Read <uint>(vp, SeekOrigin.Begin, out old))
                            {
                                image.Write <uint>(-4, SeekOrigin.Current, (uint)(old + delta));
                            }
                            else
                            {
                                throw image.GetLastError(); //unlikely, but I hate crashing targets because something in the PE was messed up.
                            }
                        }
                    }
                    n      += reloc.SizeOfBlock;
                    pReloc += reloc.SizeOfBlock;
                }
            }
        }
        private static IReadOnlyDictionary <ImageDataDirectoryEntry, ImageDataDirectory> ReadDirectoryEntries(MemoryMappedViewAccessor view, long location, int count)
        {
            var dictionary      = new Dictionary <ImageDataDirectoryEntry, ImageDataDirectory>();
            var dataDirectories = new IMAGE_DATA_DIRECTORY[count];

            view.ReadArray(location, dataDirectories, 0, dataDirectories.Length);
            for (var i = 0; i < dataDirectories.Length; i++)
            {
                var entry = new ImageDataDirectory
                {
                    Size           = dataDirectories[i].Size,
                    VirtualAddress = dataDirectories[i].VirtualAddress
                };
                dictionary.Add((ImageDataDirectoryEntry)i, entry);
            }
            return(dictionary);
        }
示例#22
0
            private IMAGE_DATA_DIRECTORY[] ReadDataDirectories()
            {
                IMAGE_DATA_DIRECTORY[] directories = new IMAGE_DATA_DIRECTORY[ImageDataDirectoryCount];

                if (!IsValid)
                {
                    return(directories);
                }

                SeekTo(DataDirectoryOffset);
                for (int i = 0; i < directories.Length; i++)
                {
                    directories[i] = Read <IMAGE_DATA_DIRECTORY>() ?? default;
                }

                return(directories);
            }
示例#23
0
        public static IMAGE_OPTIONAL_HEADER Deserialize(MultiPartFile file)
        {
            IMAGE_OPTIONAL_HEADER ioh = new IMAGE_OPTIONAL_HEADER();

            ioh.Magic = file.ReadUInt16();
            ioh.MajorLinkerVersion      = file.ReadByte();
            ioh.MinorLinkerVersion      = file.ReadByte();
            ioh.SizeOfCode              = file.ReadUInt32();
            ioh.SizeOfInitializedData   = file.ReadUInt32();
            ioh.SizeOfUninitializedData = file.ReadUInt32();
            ioh.AddressOfEntryPoint     = file.ReadUInt32();
            ioh.BaseOfCode              = file.ReadUInt32();
            ioh.BaseOfData              = file.ReadUInt32();

            ioh.ImageBase                   = file.ReadUInt32();
            ioh.SectionAlignment            = file.ReadUInt32();
            ioh.FileAlignment               = file.ReadUInt32();
            ioh.MajorOperatingSystemVersion = file.ReadUInt16();
            ioh.MinorOperatingSystemVersion = file.ReadUInt16();
            ioh.MajorImageVersion           = file.ReadUInt16();
            ioh.MinorImageVersion           = file.ReadUInt16();
            ioh.MajorSubsystemVersion       = file.ReadUInt16();
            ioh.MinorSubsystemVersion       = file.ReadUInt16();
            ioh.Reserved1                   = file.ReadUInt32();
            ioh.SizeOfImage                 = file.ReadUInt32();
            ioh.SizeOfHeaders               = file.ReadUInt32();
            ioh.CheckSum            = file.ReadUInt32();
            ioh.Subsystem           = file.ReadUInt16();
            ioh.DllCharacteristics  = file.ReadUInt16();
            ioh.SizeOfStackReserve  = file.ReadUInt32();
            ioh.SizeOfStackCommit   = file.ReadUInt32();
            ioh.SizeOfHeapReserve   = file.ReadUInt32();
            ioh.SizeOfHeapCommit    = file.ReadUInt32();
            ioh.LoaderFlags         = file.ReadUInt32();
            ioh.NumberOfRvaAndSizes = file.ReadUInt32();
            ioh.DataDirectory       = new IMAGE_DATA_DIRECTORY[Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
            for (int i = 0; i < Constants.IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
            {
                ioh.DataDirectory[i] = IMAGE_DATA_DIRECTORY.Deserialize(file);
            }

            return(ioh);
        }
示例#24
0
            private void PerformBaseRelocation(Image image, long delta)
            {
                IMAGE_DATA_DIRECTORY directory = Environment.Is64BitProcess
                                        ? image.OptionalHeader64->BaseRelocationTable
                                        : image.OptionalHeader32->BaseRelocationTable;

                if (directory.Size == 0)
                {
                    return;
                }

                IMAGE_BASE_RELOCATION *relocation = (IMAGE_BASE_RELOCATION *)(image.BasePtr + directory.VirtualAddress);

                while (relocation->VirtualAddress > 0)
                {
                    ApplyRelocationBlock(image, delta, relocation);
                    relocation = (IMAGE_BASE_RELOCATION *)((byte *)relocation + relocation->BlockSizeInclusive);
                }
            }
示例#25
0
        public void PerformBaseRelocation(uint delta)
        {
            IntPtr codeBase   = module.codeBase;
            int    sizeOfBase = Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
            IMAGE_DATA_DIRECTORY directory = module.headers.OptionalHeader.DataDirectory[5];
            int cnt = 0;

            if (directory.Size > 0)
            {
                var relocation = PointerHelpers.ToStruct <IMAGE_BASE_RELOCATION>(codeBase, 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:
                                var patchAddrHl  = (uint *)((dest) + (offset));
                                *   patchAddrHl += delta;
                                break;
                            }
                        }
                    }

                    cnt       += (int)relocation.SizeOfBlock;
                    relocation =
                        PointerHelpers.ToStruct <IMAGE_BASE_RELOCATION>(codeBase,
                                                                        (uint)(directory.VirtualAddress + cnt));
                }
            }
        }
示例#26
0
        /// <summary>
        ///     Create a new IMAGE_OPTIONAL_HEADER object.
        /// </summary>
        /// <param name="buff">A PE file as a byte array.</param>
        /// <param name="offset">Raw offset to the optional header.</param>
        /// <param name="is64Bit">Set to true, if header is for a x64 application.</param>
        public IMAGE_OPTIONAL_HEADER(byte[] buff, uint offset, bool is64Bit)
            : base(buff, offset)
        {
            _is64Bit = is64Bit;

            DataDirectory = new IMAGE_DATA_DIRECTORY[16];

            for (uint i = 0; i < 16; i++)
            {
                if (!_is64Bit)
                {
                    DataDirectory[i] = new IMAGE_DATA_DIRECTORY(buff, offset + 0x60 + i * 0x8);
                }
                else
                {
                    DataDirectory[i] = new IMAGE_DATA_DIRECTORY(buff, offset + 0x70 + i * 0x8);
                }
            }
        }
示例#27
0
        public void PerformBaseRelocation(UInt32 delta)
        {
            IntPtr codeBase   = _module.codeBase;
            Int32  sizeOfBase = Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION));
            IMAGE_DATA_DIRECTORY directory = _module.headers.OptionalHeader.DataDirectory[5];
            Int32 cnt = 0;

            if (directory.Size > 0)
            {
                IMAGE_BASE_RELOCATION relocation = PointerHelpers.ToStruct <IMAGE_BASE_RELOCATION>(codeBase, directory.VirtualAddress);
                while (relocation.VirtualAddress > 0)
                {
                    unsafe
                    {
                        IntPtr  dest    = (IntPtr)(codeBase.ToInt32() + (int)relocation.VirtualAddress);
                        UInt16 *relInfo = (UInt16 *)(codeBase.ToInt32() + (int)directory.VirtualAddress + sizeOfBase);
                        UInt16  i;
                        for (i = 0; i < ((relocation.SizeOfBlock - Marshal.SizeOf(typeof(IMAGE_BASE_RELOCATION))) / 2); i++, relInfo++)
                        {
                            Int32 type   = *relInfo >> 12;
                            Int32 offset = (*relInfo & 0xfff);
                            switch (type)
                            {
                            case 0x00:
                                break;

                            case 0x03:
                                UInt32 *patchAddrHl  = (UInt32 *)((dest.ToInt32()) + (offset));
                                *       patchAddrHl += delta;
                                break;
                            }
                        }
                    }
                    cnt       += (Int32)relocation.SizeOfBlock;
                    relocation = PointerHelpers.ToStruct <IMAGE_BASE_RELOCATION>(codeBase, (UInt32)(directory.VirtualAddress + cnt));
                }
            }
        }
示例#28
0
            public void ExecuteTlsFunctions(Image image, DllCallType callType)
            {
                IMAGE_DATA_DIRECTORY directory = Environment.Is64BitProcess
                                        ? image.OptionalHeader64->TLSTable : image.OptionalHeader32->TLSTable;

                if (directory.VirtualAddress == 0)
                {
                    return;
                }

                if (directory.VirtualAddress > image.Size - sizeof(IntPtr))
                {
                    throw new LoadFailedException("This library's TLS table is damaged or invalid.");
                }

                IMAGE_TLS_DIRECTORY32 *tlsDirectory32 = (IMAGE_TLS_DIRECTORY32 *)(image.BasePtr + directory.VirtualAddress);
                IntPtr callbacks = (IntPtr)tlsDirectory32->AddressOfCallBacks;
                IntPtr endPtr    = (IntPtr)(image.BasePtr + image.Size - sizeof(IntPtr));

                if (callbacks != IntPtr.Zero)
                {
                    IntPtr callback;
                    while ((callback = *(IntPtr *)callbacks) != IntPtr.Zero)
                    {
                        if ((long)callback > (long)endPtr)
                        {
                            throw new LoadFailedException("One of this library's TLS functions is damaged or invalid.");
                        }

                        DllEntryProc dllEntryProc = (DllEntryProc)Marshal.GetDelegateForFunctionPointer(callback, typeof(DllEntryProc));
                        uint         succeeded    = dllEntryProc((IntPtr)image.BasePtr, DllCallType.PROCESS_ATTACH, IntPtr.Zero);
                        if (succeeded == 0)
                        {
                            throw new LoadFailedException("One of this library's TLS functions returned false in response to " + callType + ".");
                        }
                    }
                }
            }
示例#29
0
        public UInt32?GetProcAddress(String name)
        {
            unsafe
            {
                IntPtr codeBase = this._module.codeBase;
                Int32? idx      = null;
                IMAGE_DATA_DIRECTORY directory = this._module.headers.OptionalHeader.DataDirectory[0];
                if (directory.Size == 0)
                {
                    return(null);
                }
                IMAGE_EXPORT_DIRECTORY exports = PointerHelpers.ToStruct <IMAGE_EXPORT_DIRECTORY>(codeBase, directory.VirtualAddress);
                UInt32 *nameRef = (UInt32 *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNames);
                UInt16 *ordinal = (UInt16 *)new IntPtr(codeBase.ToInt32() + exports.AddressOfNameOrdinals);

                for (UInt32 i = 0; i < exports.NumberOfNames; i++, nameRef++, ordinal++)
                {
                    IntPtr str = new IntPtr(codeBase.ToInt32() + (Int32)(*nameRef));
                    String tmp = Marshal.PtrToStringAnsi(str);
                    if (tmp == name)
                    {
                        idx = *ordinal;
                        break;
                    }
                }
                if (idx.HasValue)
                {
                    UInt32 *tmpaa = (UInt32 *)(codeBase.ToInt32() + (exports.AddressOfFunctions + (idx.Value * 4)));
                    UInt32  addr  = (UInt32)((codeBase.ToInt32()) + (*tmpaa));
                    return(addr);
                }
                else
                {
                    return(null);
                }
            }
        }
 public IMAGE_DATA_DIRECTORY_Values()
 {
     Values = new IMAGE_DATA_DIRECTORY[16];
 }
示例#31
0
        private async Task LoadAsync()
        {
            if (!_stream.CanSeek)
            {
                throw new PortableExecutableImageException(this, "Cannot seek in stream.");
            }

            if (!_stream.CanRead)
            {
                throw new PortableExecutableImageException(this, "Cannot read from stream.");
            }

            IMAGE_DOS_HEADER dosHeader;

            try
            {
                dosHeader = await _stream.ReadStructAsync <IMAGE_DOS_HEADER>(DOSHeader.Size).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Cannot read DOS header from stream.", ex);
            }

            if (dosHeader.e_magic != DOSHeader.DOS_MAGIC_MZ)
            {
                throw new PortableExecutableImageException(this, "Incorrect magic number specified in DOS header.");
            }

            if (dosHeader.e_lfanew == 0)
            {
                throw new PortableExecutableImageException(this, "No new header location specified in DOS header, most likely a 16-bit executable.");
            }

            if (dosHeader.e_lfanew >= (256 * (1024 * 1024)))
            {
                throw new PortableExecutableImageException(this, "New header location specified in MS-DOS header is beyond 256mb boundary (see RtlImageNtHeaderEx).");
            }

            if (dosHeader.e_lfanew % 4 != 0)
            {
                throw new PortableExecutableImageException(this, "New header location specified in MS-DOS header is not properly aligned.");
            }

            if (dosHeader.e_lfanew < DOSHeader.Size)
            {
                throw new PortableExecutableImageException(this, "New header location specified is invalid.");
            }

            var stubOffset = DOSHeader.Size;
            var stubSize   = dosHeader.e_lfanew - DOSHeader.Size;
            var stubRead   = await _stream.SkipBytesAsync(stubSize).ConfigureAwait(false);

            if (stubRead < stubSize)
            {
                throw new PortableExecutableImageException(this, "Could not read DOS stub from stream.");
            }

            _stream.Seek(dosHeader.e_lfanew, SeekOrigin.Begin);

            var  ntOffset = _stream.Position;
            uint peSig;

            try
            {
                peSig = await _stream.ReadUInt32Async().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Could not read PE signature from stream.", ex);
            }

            if (peSig != NTHeaders.PE_MAGIC_MZ)
            {
                throw new PortableExecutableImageException(this, "Incorrect PE signature found in NT Header.");
            }

            IMAGE_FILE_HEADER fileHdr;

            try
            {
                fileHdr = await _stream.ReadStructAsync <IMAGE_FILE_HEADER>(FileHeader.Size).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Could not read NT Header from stream.", ex);
            }

            ushort magic = 0;

            try
            {
                magic = await _stream.ReadUInt16Async().ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Could not read Optional Header magic number from stream.", ex);
            }

            Is32Bit = (magic == (ushort)MagicType.PE32);
            Is64Bit = (magic == (ushort)MagicType.PE32plus);

            if (!Is32Bit && !Is64Bit)
            {
                throw new PortableExecutableImageException(this, "Unknown PE type.");
            }

            byte[] optionalHeaderBytes;

            try
            {
                var optionalHeaderSize = (Is32Bit ? Utils.SizeOf <IMAGE_OPTIONAL_HEADER32>() : Utils.SizeOf <IMAGE_OPTIONAL_HEADER64>());

                optionalHeaderBytes = await _stream.ReadBytesAsync(optionalHeaderSize).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                throw new PortableExecutableImageException(this, "Could not read Optional Header from stream.", ex);
            }

            IMAGE_OPTIONAL_HEADER32 optionalHeader32 = new IMAGE_OPTIONAL_HEADER32();
            IMAGE_OPTIONAL_HEADER64 optionalHeader64 = new IMAGE_OPTIONAL_HEADER64();
            var dirCount = 0;

            if (Is32Bit)
            {
                optionalHeader32 = Utils.Read <IMAGE_OPTIONAL_HEADER32>(optionalHeaderBytes);

                dirCount = optionalHeader32.NumberOfRvaAndSizes.ToInt32();
            }
            else
            {
                optionalHeader64 = Utils.Read <IMAGE_OPTIONAL_HEADER64>(optionalHeaderBytes);

                dirCount = optionalHeader64.NumberOfRvaAndSizes.ToInt32();
            }

            var dataDirs    = new IMAGE_DATA_DIRECTORY[dirCount];
            var dataDirSize = Utils.SizeOf <IMAGE_DATA_DIRECTORY>();

            for (var i = 0; i < dirCount; i++)
            {
                try
                {
                    dataDirs[i] = await _stream.ReadStructAsync <IMAGE_DATA_DIRECTORY>(dataDirSize).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    throw new PortableExecutableImageException(this, "Could not read data directory from stream.", ex);
                }
            }

            var sectionTableEntrySize = Utils.SizeOf <IMAGE_SECTION_HEADER>();
            var sectionTable          = new IMAGE_SECTION_HEADER[fileHdr.NumberOfSections];

            for (var i = 0; i < fileHdr.NumberOfSections; i++)
            {
                try
                {
                    sectionTable[i] = await _stream.ReadStructAsync <IMAGE_SECTION_HEADER>(sectionTableEntrySize).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    throw new PortableExecutableImageException(this, "Could not read section table entry from stream.", ex);
                }
            }

            IsCLR = false;

            var clrIndex = (int)DataDirectoryType.CLRRuntimeHeader;

            if (clrIndex >= 0 && clrIndex <= (dataDirs.Length - 1))
            {
                var clrDirectory = dataDirs[clrIndex];

                if (clrDirectory.VirtualAddress > 0 && clrDirectory.Size > 0)
                {
                    IsCLR = true;
                }
            }

            IsSigned = false;

            var certIndex = (int)DataDirectoryType.CertificateTable;

            if (certIndex >= 0 && certIndex <= (dataDirs.Length - 1))
            {
                var certDirectory = dataDirs[certIndex];

                if (certDirectory.VirtualAddress > 0 && certDirectory.Size > 0)
                {
                    IsSigned = true;
                }
            }

            var imageBase = (Is32Bit ? optionalHeader32.ImageBase : optionalHeader64.ImageBase);

            DOSHeader = new DOSHeader(this, dosHeader, imageBase);
            DOSStub   = new DOSStub(this, stubOffset.ToUInt64(), stubSize.ToUInt32(), imageBase);

            var            fileHeader = new FileHeader(this, fileHdr, DOSStub.Location.FileOffset + DOSStub.Location.FileSize + 4, imageBase);
            OptionalHeader optionalHeader;

            if (Is32Bit)
            {
                optionalHeader = new OptionalHeader32(this, optionalHeader32, fileHeader.Location.FileOffset + fileHeader.Location.FileSize, imageBase, magic);
            }
            else
            {
                optionalHeader = new OptionalHeader64(this, optionalHeader64, fileHeader.Location.FileOffset + fileHeader.Location.FileSize, imageBase, magic);
            }

            var dataDirectories = new DataDirectories(this, optionalHeader, dataDirs);

            NTHeaders    = new NTHeaders(this, ntOffset.ToUInt64(), imageBase, fileHeader, optionalHeader, dataDirectories);
            SectionTable = new SectionTable(this, sectionTable, NTHeaders.Location.FileOffset + NTHeaders.Location.FileSize, imageBase);
            Sections     = new Sections(this, SectionTable);
        }