Пример #1
0
        internal byte[] GetResource(int[] Index)
        {
            UInt32 PEPointer                   = ByteOperations.ReadUInt32(Buffer, 0x3C);
            UInt16 OptionalHeaderSize          = ByteOperations.ReadUInt16(Buffer, PEPointer + 0x14);
            UInt32 SectionTablePointer         = PEPointer + 0x18 + OptionalHeaderSize;
            UInt16 SectionCount                = ByteOperations.ReadUInt16(Buffer, PEPointer + 0x06);
            UInt32?ResourceSectionEntryPointer = null;

            for (int i = 0; i < SectionCount; i++)
            {
                string SectionName = ByteOperations.ReadAsciiString(Buffer, (UInt32)(SectionTablePointer + (i * 0x28)), 8);
                int    e           = SectionName.IndexOf('\0');
                if (e >= 0)
                {
                    SectionName = SectionName.Substring(0, e);
                }
                if (SectionName == ".rsrc")
                {
                    ResourceSectionEntryPointer = (UInt32)(SectionTablePointer + (i * 0x28));
                    break;
                }
            }
            if (ResourceSectionEntryPointer == null)
            {
                throw new Exception("Resource-section not found");
            }
            UInt32 ResourceRawSize        = ByteOperations.ReadUInt32(Buffer, (UInt32)ResourceSectionEntryPointer + 0x10);
            UInt32 ResourceRawPointer     = ByteOperations.ReadUInt32(Buffer, (UInt32)ResourceSectionEntryPointer + 0x14);
            UInt32 ResourceVirtualPointer = ByteOperations.ReadUInt32(Buffer, (UInt32)ResourceSectionEntryPointer + 0x0C);

            UInt32 p = ResourceRawPointer;

            for (int i = 0; i < Index.Length; i++)
            {
                UInt16 ResourceNamedEntryCount = ByteOperations.ReadUInt16(Buffer, p + 0x0c);
                UInt16 ResourceIdEntryCount    = ByteOperations.ReadUInt16(Buffer, p + 0x0e);
                for (int j = ResourceNamedEntryCount; j < ResourceNamedEntryCount + ResourceIdEntryCount; j++)
                {
                    UInt32 ResourceID  = ByteOperations.ReadUInt32(Buffer, (UInt32)(p + 0x10 + (j * 8)));
                    UInt32 NextPointer = ByteOperations.ReadUInt32(Buffer, (UInt32)(p + 0x10 + (j * 8) + 4));
                    if (ResourceID == (UInt32)Index[i])
                    {
                        // Check high bit
                        if (((NextPointer & 0x80000000) == 0) != (i == (Index.Length - 1)))
                        {
                            throw new Exception("Bad resource path");
                        }

                        p = ResourceRawPointer + (NextPointer & 0x7fffffff);
                        break;
                    }
                }
            }

            UInt32 ResourceValuePointer = ByteOperations.ReadUInt32(Buffer, p) - ResourceVirtualPointer + ResourceRawPointer;
            UInt32 ResourceValueSize    = ByteOperations.ReadUInt32(Buffer, p + 4);

            byte[] ResourceValue = new byte[ResourceValueSize];
            Array.Copy(Buffer, ResourceValuePointer, ResourceValue, 0, ResourceValueSize);

            return(ResourceValue);
        }
Пример #2
0
        public PeFile(byte[] Buffer)
        {
            int P = 0;

            this.Buffer = Buffer;

            // Read MS-DOS header section
            DosHeader = MarshalBytesTo <IMAGE_DOS_HEADER>(Buffer, P);

            // MS-DOS magic number should read 'MZ'
            if (DosHeader.e_magic != 0x5a4d)
            {
                throw new InvalidOperationException("File is not a portable executable.");
            }

            // Read NT Headers
            P = (int)DosHeader.e_lfanew;
            NtHeaders.Signature = MarshalBytesTo <UInt32>(Buffer, P);

            // Make sure we have 'PE' in the pe signature
            if (NtHeaders.Signature != 0x4550)
            {
                throw new InvalidOperationException("Invalid portable executable signature in NT header.");
            }

            P += sizeof(UInt32);
            NtHeaders.FileHeader = MarshalBytesTo <IMAGE_FILE_HEADER>(Buffer, P);

            // Read optional headers
            P += Marshal.SizeOf(typeof(IMAGE_FILE_HEADER));
            if (Is32bitAssembly())
            {
                Load32bitOptionalHeaders(Buffer, P);
                ImageBase  = NtHeaders.OptionalHeader32.ImageBase;
                EntryPoint = NtHeaders.OptionalHeader32.AddressOfEntryPoint;
                ExportDirectoryVirtualOffset  = NtHeaders.OptionalHeader32.DataDirectory[0].VirtualAddress;
                ImportDirectoryVirtualOffset  = NtHeaders.OptionalHeader32.DataDirectory[1].VirtualAddress;
                RuntimeDirectoryVirtualOffset = NtHeaders.OptionalHeader32.DataDirectory[3].VirtualAddress;
                RuntimeDirectorySize          = NtHeaders.OptionalHeader32.DataDirectory[3].Size;
            }
            else
            {
                Load64bitOptionalHeaders(Buffer, P);
                ImageBase  = NtHeaders.OptionalHeader64.ImageBase;
                EntryPoint = NtHeaders.OptionalHeader64.AddressOfEntryPoint;
                ExportDirectoryVirtualOffset  = NtHeaders.OptionalHeader64.DataDirectory[0].VirtualAddress;
                ImportDirectoryVirtualOffset  = NtHeaders.OptionalHeader64.DataDirectory[1].VirtualAddress;
                RuntimeDirectoryVirtualOffset = NtHeaders.OptionalHeader64.DataDirectory[3].VirtualAddress;
                RuntimeDirectorySize          = NtHeaders.OptionalHeader64.DataDirectory[3].Size;
            }

            // Read Sections
            _sectionHeaders.ToList().ForEach(s =>
            {
                byte[] RawCode = new byte[s.SizeOfRawData];
                System.Buffer.BlockCopy(Buffer, (int)s.PointerToRawData, RawCode, 0, (int)s.SizeOfRawData);

                Sections.Add(new Section {
                    Header = s, Buffer = RawCode, VirtualAddress = s.VirtualAddress + (UInt32)ImageBase, VirtualSize = s.Misc.VirtualSize, IsCode = ((s.Characteristics & (uint)Constants.SectionFlags.IMAGE_SCN_CNT_CODE) != 0)
                });
            });

            // Read Exports
            // TODO: Proper support for 64-bit files
            if (ExportDirectoryVirtualOffset != 0)
            {
                IMAGE_EXPORT_DIRECTORY ExportDirectory = MarshalBytesTo <IMAGE_EXPORT_DIRECTORY>(Buffer, (int)ConvertVirtualOffsetToRawOffset((uint)(ExportDirectoryVirtualOffset)));
                if (ExportDirectory.AddressOfNames != 0)
                {
                    Section  ExportsSection   = GetSectionForVirtualAddress((uint)(ImageBase + ExportDirectory.AddressOfNames));
                    UInt32   OffsetNames      = (UInt32)(ImageBase + ExportDirectory.AddressOfNames - ExportsSection.VirtualAddress);
                    UInt32   OffsetOrdinals   = (UInt32)(ImageBase + ExportDirectory.AddressOfNameOrdinals - ExportsSection.VirtualAddress);
                    UInt32   OffsetFunctions  = (UInt32)(ImageBase + ExportDirectory.AddressOfFunctions - ExportsSection.VirtualAddress);
                    string[] ExportNames      = new string[ExportDirectory.NumberOfNames];
                    UInt16[] Ordinals         = new UInt16[ExportDirectory.NumberOfNames];
                    UInt32[] VirtualAddresses = new UInt32[ExportDirectory.NumberOfFunctions];
                    for (int i = 0; i < ExportDirectory.NumberOfNames; i++)
                    {
                        UInt32 NamesRVA   = ByteOperations.ReadUInt32(ExportsSection.Buffer, (UInt32)(OffsetNames + (i * sizeof(UInt32))));
                        UInt32 NameOffset = (UInt32)(NamesRVA + ImageBase - ExportsSection.VirtualAddress);
                        ExportNames[i] = ByteOperations.ReadAsciiString(ExportsSection.Buffer, NameOffset);

                        Ordinals[i] = ByteOperations.ReadUInt16(ExportsSection.Buffer, (UInt32)(OffsetOrdinals + (i * sizeof(UInt16))));
                    }
                    for (int i = 0; i < ExportDirectory.NumberOfFunctions; i++)
                    {
                        VirtualAddresses[i]  = ByteOperations.ReadUInt32(ExportsSection.Buffer, (UInt32)(OffsetFunctions + (i * sizeof(UInt32))));
                        VirtualAddresses[i] -= (VirtualAddresses[i] % 2); // Round down for Thumb2
                    }
                    for (int i = 0; i < ExportDirectory.NumberOfNames; i++)
                    {
                        Exports.Add(new FunctionDescriptor()
                        {
                            Name = ExportNames[i], VirtualAddress = (UInt32)(ImageBase + VirtualAddresses[Ordinals[i]])
                        });
                    }
                }
            }

            // Read Imports
            // TODO: Proper support for 64-bit files
            if (ImportDirectoryVirtualOffset != 0)
            {
                Section ImportsSection = GetSectionForVirtualAddress((uint)(ImageBase + ImportDirectoryVirtualOffset));
                IMAGE_IMPORT_DESCRIPTOR ImportDirectory;
                do
                {
                    ImportDirectory = MarshalBytesTo <IMAGE_IMPORT_DESCRIPTOR>(ImportsSection.Buffer, (int)(ImportDirectoryVirtualOffset - (ImportsSection.VirtualAddress - ImageBase)));
                    if (ImportDirectory.OriginalFirstThunk != 0)
                    {
                        // ImportDirectory.OriginalFirstThunk is the VirtualOffset to an array of VirtualOffsets. They point to a struct with a word-value, followed by a zero-terminated ascii-string, which is the name of the import.
                        // ImportDirectory.FirstThunk points to an array pointers which is the actual import table.
                        UInt32 NameArrayOffset = ImportDirectory.OriginalFirstThunk - (ImportsSection.VirtualAddress - (UInt32)ImageBase);
                        UInt32 NameOffset;
                        int    i = 0;
                        do
                        {
                            NameOffset = ByteOperations.ReadUInt32(ImportsSection.Buffer, NameArrayOffset);
                            if ((NameOffset < (ImportsSection.VirtualAddress - ImageBase)) || (NameOffset >= (ImportsSection.VirtualAddress + ImportsSection.VirtualSize - ImageBase)))
                            {
                                NameOffset = 0; // ImportDirectory.OriginalFirstThunk seems to contain Characteristics, not an offset to an array.
                            }
                            NameArrayOffset += sizeof(UInt32);
                            if (NameOffset != 0)
                            {
                                string Name = ByteOperations.ReadAsciiString(ImportsSection.Buffer, NameOffset + 2 - (ImportsSection.VirtualAddress - (UInt32)ImageBase));
                                Imports.Add(new FunctionDescriptor()
                                {
                                    Name = Name, VirtualAddress = ImportDirectory.FirstThunk + (UInt32)ImageBase + (UInt32)(i * sizeof(UInt32))
                                });
                                i++;
                            }
                        }while (NameOffset != 0);

                        ImportDirectoryVirtualOffset += (UInt64)Marshal.SizeOf(typeof(IMAGE_IMPORT_DESCRIPTOR));
                    }
                }while (ImportDirectory.OriginalFirstThunk != 0);
            }

            // Read Runtime functions
            // TODO: Proper support for 64-bit files
            if (RuntimeDirectoryVirtualOffset != 0)
            {
                Section             RuntimeSection = GetSectionForVirtualAddress((uint)(ImageBase + RuntimeDirectoryVirtualOffset));
                RUNTIME_FUNCTION_32 RuntimeFunction;
                for (int i = 0; i < (RuntimeDirectorySize / Marshal.SizeOf(typeof(RUNTIME_FUNCTION_32))); i++)
                {
                    RuntimeFunction = MarshalBytesTo <RUNTIME_FUNCTION_32>(RuntimeSection.Buffer, (int)(RuntimeDirectoryVirtualOffset - (RuntimeSection.VirtualAddress - ImageBase)) + (i * Marshal.SizeOf(typeof(RUNTIME_FUNCTION_32))));
                    RuntimeFunctions.Add(new FunctionDescriptor()
                    {
                        Name = null, VirtualAddress = (UInt32)(RuntimeFunction.RVAofBeginAddress + ImageBase)
                    });
                }
            }
        }