コード例 #1
0
        /// <summary>
        ///     Identifies if the specified executable is a Microsoft Portable Executable
        /// </summary>
        /// <returns><c>true</c> if the specified executable is a Microsoft Portable Executable, <c>false</c> otherwise.</returns>
        /// <param name="stream">Stream containing the executable.</param>
        public static bool Identify(FileStream stream)
        {
            FileStream baseStream     = stream;
            MZ         baseExecutable = new MZ(baseStream);

            if (!baseExecutable.Recognized)
            {
                return(false);
            }

            if (baseExecutable.Header.new_offset >= baseStream.Length)
            {
                return(false);
            }

            baseStream.Seek(baseExecutable.Header.new_offset, SeekOrigin.Begin);
            byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
            baseStream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

            Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
            PEHeader header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));

            Marshal.FreeHGlobal(hdrPtr);
            return(header.signature == SIGNATURE);
        }
コード例 #2
0
        /// <summary>
        ///     Identifies if the specified executable is a Microsoft New Executable
        /// </summary>
        /// <returns><c>true</c> if the specified executable is a Microsoft New Executable, <c>false</c> otherwise.</returns>
        /// <param name="path">Executable path.</param>
        public static bool Identify(string path)
        {
            FileStream BaseStream     = File.Open(path, FileMode.Open, FileAccess.Read);
            MZ         BaseExecutable = new MZ(BaseStream);

            if (!BaseExecutable.Recognized)
            {
                return(false);
            }

            if (BaseExecutable.Header.new_offset >= BaseStream.Length)
            {
                return(false);
            }

            BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
            byte[] buffer = new byte[Marshal.SizeOf(typeof(NEHeader))];
            BaseStream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

            Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
            NEHeader Header = (NEHeader)Marshal.PtrToStructure(hdrPtr, typeof(NEHeader));

            Marshal.FreeHGlobal(hdrPtr);
            return(Header.signature == SIGNATURE);
        }
コード例 #3
0
        void Initialize()
        {
            Recognized = false;
            if (BaseStream == null)
            {
                return;
            }

            baseExecutable = new MZ(BaseStream);
            if (!baseExecutable.Recognized)
            {
                return;
            }

            if (baseExecutable.Header.new_offset >= BaseStream.Length)
            {
                return;
            }

            BaseStream.Seek(baseExecutable.Header.new_offset, SeekOrigin.Begin);
            byte[] buffer = new byte[Marshal.SizeOf(typeof(PEHeader))];
            BaseStream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

            Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
            header = (PEHeader)Marshal.PtrToStructure(hdrPtr, typeof(PEHeader));
            Marshal.FreeHGlobal(hdrPtr);
            Recognized = header.signature == SIGNATURE;

            if (!Recognized)
            {
                return;
            }

            Type = "Portable Executable (PE)";

            if (header.coff.optionalHeader.magic == PE32Plus)
            {
                BaseStream.Position -= 4;
                buffer = new byte[Marshal.SizeOf(typeof(WindowsHeader64))];
                BaseStream.Read(buffer, 0, buffer.Length);
                hdrPtr = Marshal.AllocHGlobal(buffer.Length);
                Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
                winHeader = (WindowsHeader64)Marshal.PtrToStructure(hdrPtr, typeof(WindowsHeader64));
                Marshal.FreeHGlobal(hdrPtr);
            }
            else
            {
                buffer = new byte[Marshal.SizeOf(typeof(WindowsHeader))];
                BaseStream.Read(buffer, 0, buffer.Length);
                hdrPtr = Marshal.AllocHGlobal(buffer.Length);
                Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
                WindowsHeader hdr32 = (WindowsHeader)Marshal.PtrToStructure(hdrPtr, typeof(WindowsHeader));
                Marshal.FreeHGlobal(hdrPtr);
                winHeader = ToPlus(hdr32);
            }

            OperatingSystem reqOs = new OperatingSystem();

            switch (winHeader.subsystem)
            {
            case Subsystems.IMAGE_SUBSYSTEM_UNKNOWN:
                reqOs.Name = "Unknown";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_NATIVE:
                reqOs.Name      = "Windows NT";
                reqOs.Subsystem = "Native";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_GUI:
                reqOs.Name      = winHeader.majorSubsystemVersion <= 3 ? "Windows NT" : "Windows";
                reqOs.Subsystem = "GUI";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_CUI:
                reqOs.Name      = winHeader.majorSubsystemVersion <= 3 ? "Windows NT" : "Windows";
                reqOs.Subsystem = "Console";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_OS2_CUI:
                reqOs.Name      = "Windows NT";
                reqOs.Subsystem = "OS/2";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_POSIX_CUI:
                reqOs.Name      = "Windows NT";
                reqOs.Subsystem = "POSIX";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_NATIVE_WINDOWS:
                reqOs.Name      = "Windows";
                reqOs.Subsystem = "Native";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_CE_GUI:
                reqOs.Name = "Windows CE";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_EFI_APPLICATION:
            case Subsystems.IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
            case Subsystems.IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
            case Subsystems.IMAGE_SUBSYSTEM_EFI_ROM:
                reqOs.Name = "EFI";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_XBOX:
                reqOs.Name = "Xbox OS";
                break;

            case Subsystems.IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION:
                reqOs.Name      = "Windows NT";
                reqOs.Subsystem = "Boot environment";
                break;

            default:
                reqOs.Name = $"Unknown code ${(ushort)winHeader.subsystem}";
                break;
            }

            reqOs.MajorVersion      = winHeader.majorSubsystemVersion;
            reqOs.MinorVersion      = winHeader.minorSubsystemVersion;
            RequiredOperatingSystem = reqOs;

            buffer           = new byte[Marshal.SizeOf(typeof(ImageDataDirectory))];
            directoryEntries = new ImageDataDirectory[winHeader.numberOfRvaAndSizes];
            for (int i = 0; i < directoryEntries.Length; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                directoryEntries[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <ImageDataDirectory>(buffer);
            }

            buffer         = new byte[Marshal.SizeOf(typeof(COFF.SectionHeader))];
            sectionHeaders = new COFF.SectionHeader[header.coff.numberOfSections];
            for (int i = 0; i < sectionHeaders.Length; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                sectionHeaders[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <COFF.SectionHeader>(buffer);
            }

            Dictionary <string, COFF.SectionHeader> newSectionHeaders =
                sectionHeaders.ToDictionary(section => section.name);

            for (int i = 0; i < directoryEntries.Length; i++)
            {
                string tableName;
                switch (i)
                {
                case 0:
                    tableName = ".edata";
                    break;

                case 1:
                    tableName = ".idata";
                    break;

                case 2:
                    tableName = ".rsrc";
                    break;

                case 3:
                    tableName = ".pdata";
                    break;

                case 5:
                    tableName = ".reloc";
                    break;

                case 6:
                    tableName = ".debug";
                    break;

                case 9:
                    tableName = ".tls";
                    break;

                case 14:
                    tableName = ".cormeta";
                    break;

                default: continue;
                }

                if (newSectionHeaders.ContainsKey(tableName))
                {
                    continue;
                }
                if (directoryEntries[i].rva == 0)
                {
                    continue;
                }

                newSectionHeaders.Add(tableName,
                                      new COFF.SectionHeader
                {
                    characteristics =
                        COFF.SectionFlags.IMAGE_SCN_CNT_INITIALIZED_DATA |
                        COFF.SectionFlags.IMAGE_SCN_MEM_READ,
                    name             = tableName,
                    pointerToRawData = RvaToReal(directoryEntries[i].rva, sectionHeaders),
                    virtualAddress   = directoryEntries[i].rva,
                    sizeOfRawData    = directoryEntries[i].size,
                    virtualSize      = directoryEntries[i].size
                });
            }

            List <byte>   chars;
            List <string> strings = new List <string>();

            if (newSectionHeaders.TryGetValue(".edata", out COFF.SectionHeader edata))
            {
                buffer = new byte[Marshal.SizeOf(typeof(ExportDirectoryTable))];
                BaseStream.Position = edata.pointerToRawData;
                BaseStream.Read(buffer, 0, buffer.Length);
                ExportDirectoryTable edataTable =
                    BigEndianMarshal.ByteArrayToStructureLittleEndian <ExportDirectoryTable>(buffer);

                BaseStream.Position = RvaToReal(edataTable.nameRva, sectionHeaders);
                chars = new List <byte>();
                while (true)
                {
                    int ch = BaseStream.ReadByte();
                    if (ch <= 0)
                    {
                        break;
                    }

                    chars.Add((byte)ch);
                }

                moduleName = Encoding.ASCII.GetString(chars.ToArray());

                uint[] namePointers = new uint[edataTable.numberOfNamePointers];
                exportedNames       = new string[edataTable.numberOfNamePointers];
                buffer              = new byte[Marshal.SizeOf(typeof(uint)) * edataTable.numberOfNamePointers];
                BaseStream.Position = RvaToReal(edataTable.namePointerRva, sectionHeaders);
                BaseStream.Read(buffer, 0, buffer.Length);
                for (int i = 0; i < edataTable.numberOfNamePointers; i++)
                {
                    namePointers[i]     = BitConverter.ToUInt32(buffer, i * 4);
                    BaseStream.Position = RvaToReal(namePointers[i], sectionHeaders);

                    chars = new List <byte>();
                    while (true)
                    {
                        int ch = BaseStream.ReadByte();
                        if (ch <= 0)
                        {
                            break;
                        }

                        chars.Add((byte)ch);
                    }

                    exportedNames[i] = Encoding.ASCII.GetString(chars.ToArray());
                }
            }

            if (newSectionHeaders.TryGetValue(".idata", out COFF.SectionHeader idata))
            {
                buffer = new byte[Marshal.SizeOf(typeof(ImportDirectoryTable))];
                BaseStream.Position = idata.pointerToRawData;
                List <ImportDirectoryTable> importDirectoryEntries = new List <ImportDirectoryTable>();

                while (true)
                {
                    BaseStream.Read(buffer, 0, buffer.Length);
                    if (buffer.All(b => b == 0))
                    {
                        break;
                    }

                    importDirectoryEntries.Add(BigEndianMarshal
                                               .ByteArrayToStructureLittleEndian <ImportDirectoryTable>(buffer));
                }

                importedNames = new string[importDirectoryEntries.Count];
                for (int i = 0; i < importDirectoryEntries.Count; i++)
                {
                    BaseStream.Position = RvaToReal(importDirectoryEntries[i].nameRva, sectionHeaders);

                    chars = new List <byte>();
                    while (true)
                    {
                        int ch = BaseStream.ReadByte();
                        if (ch <= 0)
                        {
                            break;
                        }

                        chars.Add((byte)ch);
                    }

                    importedNames[i] = Encoding.ASCII.GetString(chars.ToArray());

                    // BeOS R3 uses PE with no subsystem
                    if (importedNames[i].ToLower() == "libbe.so")
                    {
                        reqOs.MajorVersion      = 3;
                        reqOs.MinorVersion      = 0;
                        reqOs.Subsystem         = null;
                        reqOs.Name              = "BeOS";
                        RequiredOperatingSystem = reqOs;
                    }
                    // Singularity appears as a native NT executable
                    else if (importedNames[i].ToLower() == "singularity.v1.dll")
                    {
                        reqOs.MajorVersion      = 1;
                        reqOs.MinorVersion      = 0;
                        reqOs.Subsystem         = null;
                        reqOs.Name              = "Singularity";
                        RequiredOperatingSystem = reqOs;
                    }
                }
            }

            if (newSectionHeaders.TryGetValue(".debug", out COFF.SectionHeader debug) && debug.virtualAddress > 0)
            {
                buffer = new byte[Marshal.SizeOf(typeof(DebugDirectory))];
                BaseStream.Position = debug.pointerToRawData;
                BaseStream.Read(buffer, 0, buffer.Length);
                debugDirectory = BigEndianMarshal.ByteArrayToStructureLittleEndian <DebugDirectory>(buffer);
            }

            if (newSectionHeaders.TryGetValue(".rsrc", out COFF.SectionHeader rsrc))
            {
                if (reqOs.Name == "BeOS")
                {
                    newSectionHeaders.Remove(".rsrc");
                    rsrc.pointerToRawData = rsrc.virtualAddress;

                    long maxPosition = BaseStream.Length;
                    foreach (KeyValuePair <string, COFF.SectionHeader> kvp in newSectionHeaders)
                    {
                        if (kvp.Value.pointerToRawData <= maxPosition &&
                            kvp.Value.pointerToRawData > rsrc.pointerToRawData)
                        {
                            maxPosition = kvp.Value.pointerToRawData;
                        }
                    }

                    rsrc.sizeOfRawData = (uint)(maxPosition - rsrc.pointerToRawData);
                    rsrc.virtualSize   = rsrc.sizeOfRawData;
                    newSectionHeaders.Add(".rsrc", rsrc);

                    buffer = new byte[rsrc.sizeOfRawData];
                    BaseStream.Position = rsrc.pointerToRawData;
                    BaseStream.Read(buffer, 0, buffer.Length);
                    BeosResources = Resources.Decode(buffer);

                    strings.AddRange(from type in BeosResources
                                     where type.type == Consts.B_VERSION_INFO_TYPE
                                     from resource in type.resources
                                     select BigEndianMarshal
                                     .ByteArrayToStructureLittleEndian <VersionInfo>(resource.data)
                                     into versionInfo
                                     select StringHandlers.CToString(versionInfo.long_info, Encoding.UTF8));
                }
                else
                {
                    WindowsResourcesRoot = GetResourceNode(BaseStream, rsrc.pointerToRawData,
                                                           rsrc.virtualAddress,
                                                           rsrc.pointerToRawData, 0, null, 0);
                    Versions = GetVersions().ToArray();

                    strings.AddRange(from v in Versions from s in v.StringsByLanguage from k in s.Value select k.Value);

                    foreach (ResourceNode rtype in WindowsResourcesRoot.children.Where(r => r.name == "RT_STRING"))
                    {
                        strings.AddRange(GetStrings(rtype));
                    }
                }
            }

            sectionHeaders = newSectionHeaders.Values.OrderBy(s => s.pointerToRawData).ToArray();
            Segment[] segments = new Segment[sectionHeaders.Length];
            for (int i = 0; i < segments.Length; i++)
            {
                segments[i] = new Segment
                {
                    Flags  = $"{sectionHeaders[i].characteristics}",
                    Name   = sectionHeaders[i].name,
                    Offset = sectionHeaders[i].pointerToRawData,
                    Size   = sectionHeaders[i].sizeOfRawData
                }
            }
            ;

            Segments = segments;
            strings.Sort();
            Strings = strings;
        }
コード例 #4
0
ファイル: LX.cs プロジェクト: claunia/libexeinfo
        // TODO: How to know VxD structure offset
        void Initialize()
        {
            Recognized = false;
            if (BaseStream == null)
            {
                return;
            }

            BaseExecutable = new MZ(BaseStream);
            if (!BaseExecutable.Recognized)
            {
                return;
            }

            if (BaseExecutable.Header.new_offset >= BaseStream.Length)
            {
                return;
            }

            BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
            byte[] buffer = new byte[Marshal.SizeOf(typeof(LXHeader))];
            BaseStream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

            Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
            Header = (LXHeader)Marshal.PtrToStructure(hdrPtr, typeof(LXHeader));
            Marshal.FreeHGlobal(hdrPtr);
            Recognized = Header.signature == SIGNATURE || Header.signature == SIGNATURE16;

            if (!Recognized)
            {
                return;
            }

            Type        = Header.signature == SIGNATURE16 ? "Linear Executable (LE)" : "Linear eXecutable (LX)";
            IsBigEndian = Header.byte_order == 1 || Header.word_order == 1;
            List <string> strings = new List <string>();

            OperatingSystem reqOs = new OperatingSystem();

            switch (Header.os_type)
            {
            case TargetOS.OS2:
                reqOs.Name = "OS/2";
                if (Header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
                    !Header.module_flags.HasFlag(ModuleFlags.PMCompatible) ||
                    !Header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
                    Header.module_flags.HasFlag(ModuleFlags.PMCompatible))
                {
                    reqOs.Subsystem = "Console";
                }
                else if (Header.module_flags.HasFlag(ModuleFlags.PMIncompatible) &&
                         Header.module_flags.HasFlag(ModuleFlags.PMCompatible))
                {
                    reqOs.Subsystem = "Presentation Manager";
                }
                break;

            case TargetOS.Windows:
            case TargetOS.Win32:
            case TargetOS.Unknown:
                reqOs.Name = "Windows";
                break;

            case TargetOS.DOS:
                reqOs.Name = "Windows";
                break;

            default:
                reqOs.Name = $"Unknown code {(ushort)Header.os_type}";
                break;
            }

            RequiredOperatingSystem = reqOs;

            if (Header.resident_names_off != 0)
            {
                ResidentNames =
                    GetResidentStrings(BaseStream, BaseExecutable.Header.new_offset, Header.resident_names_off);

                if (ResidentNames.Length >= 1)
                {
                    ModuleName = ResidentNames[0].name;

                    if (ResidentNames.Length > 1)
                    {
                        NE.ResidentName[] newResidentNames = new NE.ResidentName[ResidentNames.Length - 1];
                        Array.Copy(ResidentNames, 1, newResidentNames, 0, ResidentNames.Length - 1);
                        ResidentNames = newResidentNames;
                    }
                    else
                    {
                        ResidentNames = null;
                    }
                }
            }

            if (Header.nonresident_name_table_len > 0)
            {
                NonResidentNames = GetResidentStrings(BaseStream, 0, Header.nonresident_name_table_off);

                if (NonResidentNames.Length >= 1)
                {
                    ModuleDescription = NonResidentNames[0].name;

                    if (NonResidentNames.Length > 1)
                    {
                        NE.ResidentName[] newNonResidentNames = new NE.ResidentName[NonResidentNames.Length - 1];
                        Array.Copy(NonResidentNames, 1, newNonResidentNames, 0, NonResidentNames.Length - 1);
                        NonResidentNames = newNonResidentNames;
                    }
                    else
                    {
                        NonResidentNames = null;
                    }
                }
            }

            if (Header.import_module_table_off != 0 && Header.import_module_entries > 0)
            {
                BaseStream.Position = Header.import_module_table_off + BaseExecutable.Header.new_offset;
                ImportedNames       = new string[Header.import_module_entries];
                for (int i = 0; i < Header.import_module_entries; i++)
                {
                    int len = BaseStream.ReadByte();
                    buffer = new byte[len];
                    BaseStream.Read(buffer, 0, len);
                    ImportedNames[i] = Encoding.ASCII.GetString(buffer);
                }
            }

            if (!string.IsNullOrEmpty(ModuleName))
            {
                strings.Add(ModuleName);
            }
            if (!string.IsNullOrEmpty(ModuleDescription))
            {
                strings.Add(ModuleDescription);
            }

            objectTableEntries     = new ObjectTableEntry[Header.obj_no];
            objectPageTableEntries = new ObjectPageTableEntry[Header.module_pages_no];

            BaseStream.Position = Header.obj_table_off + BaseExecutable.Header.new_offset;
            buffer = new byte[Marshal.SizeOf(typeof(ObjectTableEntry))];
            for (int i = 0; i < Header.obj_no; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                objectTableEntries[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <ObjectTableEntry>(buffer);
            }

            BaseStream.Position = Header.obj_page_table_off + BaseExecutable.Header.new_offset;

            if (Header.signature == SIGNATURE16)
            {
                buffer = new byte[Marshal.SizeOf(typeof(ObjectPageTableEntry16))];
                for (int i = 0; i < Header.module_pages_no; i++)
                {
                    BaseStream.Read(buffer, 0, buffer.Length);
                    ObjectPageTableEntry16 page16 =
                        BigEndianMarshal.ByteArrayToStructureLittleEndian <ObjectPageTableEntry16>(buffer);

                    int pageNo = (page16.High << 8) + page16.Low;

                    objectPageTableEntries[i] = new ObjectPageTableEntry
                    {
                        DataSize       = (ushort)Header.page_size,
                        Flags          = (PageTableAttributes)page16.Flags,
                        PageDataOffset = (uint)((pageNo - 1) * Header.page_size)
                    };
                }
            }
            else
            {
                buffer = new byte[Marshal.SizeOf(typeof(ObjectPageTableEntry))];
                for (int i = 0; i < Header.module_pages_no; i++)
                {
                    BaseStream.Read(buffer, 0, buffer.Length);
                    objectPageTableEntries[i] =
                        BigEndianMarshal.ByteArrayToStructureLittleEndian <ObjectPageTableEntry>(buffer);
                }
            }

            int debugSections   = 0;
            int winrsrcSections = 0;

            if (Header.debug_info_len > 0)
            {
                debugSections = 1;
            }
            if (Header.win_res_len > 0)
            {
                winrsrcSections = 1;
            }

            Segment[] sections = new Segment[objectTableEntries.Length + debugSections + winrsrcSections];
            for (int i = 0; i < objectTableEntries.Length; i++)
            {
                sections[i] = new Segment {
                    Flags = $"{objectTableEntries[i].ObjectFlags}"
                };
                if (objectTableEntries[i].ObjectFlags.HasFlag(ObjectFlags.Resource))
                {
                    sections[i].Name = ".rsrc";
                }
                else if (objectTableEntries[i].ObjectFlags.HasFlag(ObjectFlags.Executable))
                {
                    sections[i].Name = ".text";
                }
                else if (!objectTableEntries[i].ObjectFlags.HasFlag(ObjectFlags.Writable))
                {
                    sections[i].Name = ".rodata";
                }
                else if (StringHandlers.CToString(objectTableEntries[i].Name).ToLower() == "bss")
                {
                    sections[i].Name = ".bss";
                }
                else if (!string.IsNullOrWhiteSpace(StringHandlers.CToString(objectTableEntries[i].Name).Trim()))
                {
                    sections[i].Name = StringHandlers.CToString(objectTableEntries[i].Name).Trim();
                }
                else
                {
                    sections[i].Name = ".data";
                }

                if (objectTableEntries[i].PageTableEntries == 0 ||
                    objectTableEntries[i].PageTableIndex > objectPageTableEntries.Length)
                {
                    sections[i].Size = objectTableEntries[i].VirtualSize;
                    continue;
                }

                int shift = (int)(Header.signature == SIGNATURE16 ? 0 : Header.page_off_shift);

                if (objectPageTableEntries[objectTableEntries[i].PageTableIndex - 1]
                    .Flags.HasFlag(PageTableAttributes.IteratedDataPage))
                {
                    sections[i].Offset =
                        (objectPageTableEntries[objectTableEntries[i].PageTableIndex - 1].PageDataOffset << shift) +
                        Header.obj_iter_pages_off;
                }
                else if (objectPageTableEntries[objectTableEntries[i].PageTableIndex - 1]
                         .Flags.HasFlag(PageTableAttributes.LegalPhysicalPage))
                {
                    sections[i].Offset =
                        (objectPageTableEntries[objectTableEntries[i].PageTableIndex - 1].PageDataOffset << shift) +
                        Header.data_pages_off;
                }
                else
                {
                    sections[i].Offset = 0;
                }

                sections[i].Size = 0;
                for (int j = 0; j < objectTableEntries[i].PageTableEntries; j++)
                {
                    sections[i].Size += objectPageTableEntries[j + objectTableEntries[i].PageTableIndex - 1].DataSize;
                }

                if (sections[i].Offset + sections[i].Size > BaseStream.Length)
                {
                    sections[i].Size = BaseStream.Length - sections[i].Offset;
                }
            }

            if (winrsrcSections > 0)
            {
                sections[sections.Length - debugSections - winrsrcSections] = new Segment
                {
                    Name   = ".rsrc",
                    Size   = Header.win_res_len,
                    Offset = Header.win_res_off
                }
            }
            ;

            if (debugSections > 0)
            {
                sections[sections.Length - debugSections] = new Segment
                {
                    Name   = ".debug",
                    Size   = Header.debug_info_len,
                    Offset = Header.debug_info_off
                }
            }
            ;

            // It only contains a RT_VERSION resource prefixed by some 12-byte header I can't find information about, so let's just skip it.
            if (winrsrcSections > 0)
            {
                buffer = new byte[Header.win_res_len];
                BaseStream.Position = Header.win_res_off + 12;
                BaseStream.Read(buffer, 0, buffer.Length);
                WinVersion = new NE.Version(buffer);
                strings.AddRange(from s in WinVersion.StringsByLanguage from k in s.Value select k.Value);
            }

            resources           = new ResourceTableEntry[Header.resource_entries];
            BaseStream.Position = Header.resource_table_off + BaseExecutable.Header.new_offset;
            buffer = new byte[Marshal.SizeOf(typeof(ResourceTableEntry))];
            for (int i = 0; i < resources.Length; i++)
            {
                BaseStream.Read(buffer, 0, buffer.Length);
                resources[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <ResourceTableEntry>(buffer);
            }

            SortedDictionary <ResourceTypes, List <NE.Resource> > os2Resources =
                new SortedDictionary <ResourceTypes, List <NE.Resource> >();

            for (int i = 0; i < resources.Length; i++)
            {
                os2Resources.TryGetValue(resources[i].type, out List <NE.Resource> thisResourceType);

                if (thisResourceType == null)
                {
                    thisResourceType = new List <NE.Resource>();
                }

                NE.Resource thisResource = new NE.Resource
                {
                    id         = resources[i].id,
                    name       = $"{resources[i].id}",
                    flags      = 0,
                    dataOffset = (uint)(sections[resources[i].obj_no - 1].Offset + resources[i].offset),
                    length     = resources[i].size
                };

                thisResource.data   = new byte[thisResource.length];
                BaseStream.Position = thisResource.dataOffset;
                BaseStream.Read(thisResource.data, 0, thisResource.data.Length);

                thisResourceType.Add(thisResource);
                os2Resources.Remove(resources[i].type);
                os2Resources.Add(resources[i].type, thisResourceType);
            }

            if (os2Resources.Count > 0)
            {
                neFormatResourceTable = new NE.ResourceTable();
                int counter = 0;
                neFormatResourceTable.types = new NE.ResourceType[os2Resources.Count];
                foreach (KeyValuePair <ResourceTypes, List <NE.Resource> > kvp in os2Resources)
                {
                    neFormatResourceTable.types[counter].count     = (ushort)kvp.Value.Count;
                    neFormatResourceTable.types[counter].id        = (ushort)kvp.Key;
                    neFormatResourceTable.types[counter].name      = Resources.IdToName((ushort)kvp.Key);
                    neFormatResourceTable.types[counter].resources = kvp.Value.OrderBy(r => r.id).ToArray();
                    counter++;
                }

                foreach (NE.ResourceType rtype in neFormatResourceTable.types)
                {
                    if (rtype.name != "RT_STRING")
                    {
                        continue;
                    }

                    strings.AddRange(NE.GetOs2Strings(rtype));
                }
            }

            Segments = sections;
            Strings  = strings;
        }
コード例 #5
0
        void Initialize()
        {
            Recognized = false;

            if (BaseStream == null)
            {
                return;
            }

            BaseExecutable = new MZ(BaseStream);
            if (!BaseExecutable.Recognized)
            {
                return;
            }

            if (BaseExecutable.Header.new_offset >= BaseStream.Length)
            {
                return;
            }

            BaseStream.Seek(BaseExecutable.Header.new_offset, SeekOrigin.Begin);
            byte[] buffer = new byte[Marshal.SizeOf(typeof(NEHeader))];
            BaseStream.Read(buffer, 0, buffer.Length);
            IntPtr hdrPtr = Marshal.AllocHGlobal(buffer.Length);

            Marshal.Copy(buffer, 0, hdrPtr, buffer.Length);
            Header = (NEHeader)Marshal.PtrToStructure(hdrPtr, typeof(NEHeader));
            Marshal.FreeHGlobal(hdrPtr);
            if (Header.signature != SIGNATURE)
            {
                return;
            }

            Recognized = true;
            Type       = "New Executable (NE)";
            List <string> strings = new List <string>();

            OperatingSystem reqOs = new OperatingSystem();

            switch (Header.target_os)
            {
            case TargetOS.OS2:
                reqOs.Name = "OS/2";
                if (Header.os_major > 0)
                {
                    reqOs.MajorVersion = Header.os_major;
                    reqOs.MinorVersion = Header.os_minor;
                }
                else
                {
                    reqOs.MajorVersion = 1;
                    reqOs.MinorVersion = 0;
                }

                if (Header.application_flags.HasFlag(ApplicationFlags.FullScreen) &&
                    !Header.application_flags.HasFlag(ApplicationFlags.GUICompatible) ||
                    !Header.application_flags.HasFlag(ApplicationFlags.FullScreen) &&
                    Header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
                {
                    reqOs.Subsystem = "Console";
                }
                else if (Header.application_flags.HasFlag(ApplicationFlags.FullScreen) &&
                         Header.application_flags.HasFlag(ApplicationFlags.GUICompatible))
                {
                    reqOs.Subsystem = "Presentation Manager";
                }
                break;

            case TargetOS.Windows:
            case TargetOS.Win32:
            case TargetOS.Unknown:
                reqOs.Name = "Windows";
                if (Header.os_major > 0)
                {
                    reqOs.MajorVersion = Header.os_major;
                    reqOs.MinorVersion = Header.os_minor;
                }
                else
                {
                    switch (Header.target_os)
                    {
                    case TargetOS.Windows:
                        reqOs.MajorVersion = 2;
                        reqOs.MinorVersion = 0;
                        break;

                    case TargetOS.Unknown:
                        reqOs.MajorVersion = 1;
                        reqOs.MinorVersion = 0;
                        break;
                    }
                }

                break;

            case TargetOS.DOS:
            case TargetOS.Borland:
                reqOs.Name         = "DOS";
                reqOs.MajorVersion = Header.os_major;
                reqOs.MinorVersion = Header.os_minor;
                if (Header.target_os == TargetOS.Borland)
                {
                    reqOs.Subsystem = "Borland Operating System Services";
                }
                break;

            default:
                reqOs.Name         = $"Unknown code {(byte)Header.target_os}";
                reqOs.MajorVersion = Header.os_major;
                reqOs.MinorVersion = Header.os_minor;
                break;
            }

            RequiredOperatingSystem = reqOs;

            if (Header.segment_count > 0 && Header.segment_table_offset > 0 &&
                Header.segment_table_offset + BaseExecutable.Header.new_offset < BaseStream.Length)
            {
                BaseStream.Position = Header.segment_table_offset + BaseExecutable.Header.new_offset;
                segments            = new SegmentEntry[Header.segment_count];
                for (int i = 0; i < segments.Length; i++)
                {
                    buffer = new byte[Marshal.SizeOf(typeof(SegmentEntry))];
                    BaseStream.Read(buffer, 0, buffer.Length);
                    segments[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <SegmentEntry>(buffer);
                }
            }

            // Some executable indicates 0 entries, some indicate a table start and no limit, will need to explore till next item
            ushort resourceUpperLimit = ushort.MaxValue;

            if (Header.entry_table_offset >= Header.resource_table_offset &&
                Header.entry_table_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.entry_table_offset;
            }
            if (Header.segment_table_offset >= Header.resource_table_offset &&
                Header.segment_table_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.segment_table_offset;
            }
            if (Header.module_reference_offset >= Header.resource_table_offset &&
                Header.module_reference_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.module_reference_offset;
            }
            if (Header.nonresident_names_offset >= Header.resource_table_offset &&
                Header.nonresident_names_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = (ushort)Header.nonresident_names_offset;
            }
            if (Header.resident_names_offset >= Header.resource_table_offset &&
                Header.resident_names_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.resident_names_offset;
            }
            if (Header.imported_names_offset >= Header.resource_table_offset &&
                Header.imported_names_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.imported_names_offset;
            }

            if (Header.resource_table_offset < resourceUpperLimit && Header.resource_table_offset != 0)
            {
                if (Header.target_os == TargetOS.Windows || Header.target_os == TargetOS.Win32 ||
                    Header.target_os == TargetOS.Unknown)
                {
                    Resources = GetResources(BaseStream, BaseExecutable.Header.new_offset, Header.resource_table_offset,
                                             resourceUpperLimit);

                    for (int t = 0; t < Resources.types.Length; t++)
                    {
                        Resources.types[t].resources = Resources.types[t].resources.OrderBy(r => r.name).ToArray();
                    }

                    Resources.types = Resources.types.OrderBy(t => t.name).ToArray();

                    Versions = GetVersions().ToArray();

                    strings.AddRange(from v in Versions from s in v.StringsByLanguage from k in s.Value select k.Value);

                    foreach (ResourceType rtype in Resources.types)
                    {
                        if (rtype.name != "RT_STRING")
                        {
                            continue;
                        }

                        strings.AddRange(GetWindowsStrings(rtype));
                    }
                }
                else if (Header.target_os == TargetOS.OS2 && segments != null && Header.resource_entries > 0)
                {
                    BaseStream.Position = BaseExecutable.Header.new_offset + Header.resource_table_offset;
                    buffer = new byte[Header.resource_entries * 4];
                    BaseStream.Read(buffer, 0, buffer.Length);
                    ResourceTableEntry[] entries = new ResourceTableEntry[Header.resource_entries];
                    for (int i = 0; i < entries.Length; i++)
                    {
                        entries[i].etype = BitConverter.ToUInt16(buffer, i * 4 + 0);
                        entries[i].ename = BitConverter.ToUInt16(buffer, i * 4 + 2);
                    }

                    SegmentEntry[] resourceSegments = new SegmentEntry[Header.resource_entries];
                    Array.Copy(segments, Header.segment_count - Header.resource_entries, resourceSegments, 0,
                               Header.resource_entries);
                    SegmentEntry[] realSegments = new SegmentEntry[Header.segment_count - Header.resource_entries];
                    Array.Copy(segments, 0, realSegments, 0, realSegments.Length);
                    segments = realSegments;

                    SortedDictionary <ushort, List <Resource> > os2resources =
                        new SortedDictionary <ushort, List <Resource> >();

                    for (int i = 0; i < entries.Length; i++)
                    {
                        os2resources.TryGetValue(entries[i].etype, out List <Resource> thisResourceType);

                        if (thisResourceType == null)
                        {
                            thisResourceType = new List <Resource>();
                        }

                        Resource thisResource = new Resource
                        {
                            id         = entries[i].ename,
                            name       = $"{entries[i].ename}",
                            flags      = (ResourceFlags)resourceSegments[i].dwFlags,
                            dataOffset = (uint)(resourceSegments[i].dwLogicalSectorOffset << Header.alignment_shift),
                            length     = resourceSegments[i].dwSegmentLength
                        };

                        if (thisResource.length == 0)
                        {
                            thisResource.length = 65536;
                        }
                        if (thisResource.dataOffset == 0)
                        {
                            thisResource.dataOffset = 65536;
                        }
                        if ((resourceSegments[i].dwFlags & (ushort)SegmentFlags.Huge) == (ushort)SegmentFlags.Huge)
                        {
                            thisResource.length <<= Header.alignment_shift;
                        }
                        thisResource.data   = new byte[thisResource.length];
                        BaseStream.Position = thisResource.dataOffset;
                        BaseStream.Read(thisResource.data, 0, thisResource.data.Length);

                        thisResourceType.Add(thisResource);
                        os2resources.Remove(entries[i].etype);
                        os2resources.Add(entries[i].etype, thisResourceType);
                    }

                    if (os2resources.Count > 0)
                    {
                        Resources = new ResourceTable();
                        int counter = 0;
                        Resources.types = new ResourceType[os2resources.Count];
                        foreach (KeyValuePair <ushort, List <Resource> > kvp in os2resources)
                        {
                            Resources.types[counter].count     = (ushort)kvp.Value.Count;
                            Resources.types[counter].id        = kvp.Key;
                            Resources.types[counter].name      = Os2.Resources.IdToName(kvp.Key);
                            Resources.types[counter].resources = kvp.Value.OrderBy(r => r.id).ToArray();
                            counter++;
                        }

                        foreach (ResourceType rtype in Resources.types)
                        {
                            if (rtype.name != "RT_STRING")
                            {
                                continue;
                            }

                            strings.AddRange(GetOs2Strings(rtype));
                        }
                    }
                }
            }

            resourceUpperLimit = ushort.MaxValue;

            if (Header.entry_table_offset >= Header.module_reference_offset &&
                Header.entry_table_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.entry_table_offset;
            }
            if (Header.segment_table_offset >= Header.module_reference_offset &&
                Header.segment_table_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.segment_table_offset;
            }
            if (Header.resource_table_offset >= Header.module_reference_offset &&
                Header.resource_table_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.resource_table_offset;
            }
            if (Header.nonresident_names_offset >= Header.module_reference_offset &&
                Header.nonresident_names_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = (ushort)Header.nonresident_names_offset;
            }
            if (Header.imported_names_offset >= Header.module_reference_offset &&
                Header.imported_names_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.imported_names_offset;
            }

            if (Header.module_reference_offset < resourceUpperLimit && Header.module_reference_offset != 0 &&
                Header.reference_count > 0)
            {
                short[] referenceOffsets = new short[Header.reference_count];
                buffer = new byte[2];
                BaseStream.Position = Header.module_reference_offset + BaseExecutable.Header.new_offset;
                for (int i = 0; i < Header.reference_count; i++)
                {
                    BaseStream.Read(buffer, 0, 2);
                    referenceOffsets[i] = BitConverter.ToInt16(buffer, 0);
                }

                ImportedNames = new string[Header.reference_count];
                for (int i = 0; i < Header.reference_count; i++)
                {
                    BaseStream.Position = Header.imported_names_offset + BaseExecutable.Header.new_offset +
                                          referenceOffsets[i];
                    int len = BaseStream.ReadByte();
                    buffer = new byte[len];
                    BaseStream.Read(buffer, 0, len);
                    ImportedNames[i] = Encoding.ASCII.GetString(buffer);
                }
            }

            resourceUpperLimit = ushort.MaxValue;

            if (Header.entry_table_offset >= Header.resident_names_offset &&
                Header.entry_table_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.entry_table_offset;
            }
            if (Header.segment_table_offset >= Header.resident_names_offset &&
                Header.segment_table_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.segment_table_offset;
            }
            if (Header.module_reference_offset >= Header.resident_names_offset &&
                Header.module_reference_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.module_reference_offset;
            }
            if (Header.nonresident_names_offset >= Header.resident_names_offset &&
                Header.nonresident_names_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = (ushort)Header.nonresident_names_offset;
            }
            if (Header.imported_names_offset >= Header.resident_names_offset &&
                Header.imported_names_offset <= resourceUpperLimit)
            {
                resourceUpperLimit = Header.imported_names_offset;
            }

            if (Header.resident_names_offset < resourceUpperLimit && Header.resident_names_offset != 0)
            {
                ResidentNames = GetResidentStrings(BaseStream, BaseExecutable.Header.new_offset,
                                                   Header.resident_names_offset, resourceUpperLimit);

                if (ResidentNames.Length >= 1)
                {
                    ModuleName = ResidentNames[0].name;

                    if (ResidentNames.Length > 1)
                    {
                        ResidentName[] newResidentNames = new ResidentName[ResidentNames.Length - 1];
                        Array.Copy(ResidentNames, 1, newResidentNames, 0, ResidentNames.Length - 1);
                        ResidentNames = newResidentNames;
                    }
                    else
                    {
                        ResidentNames = null;
                    }
                }
            }

            if (Header.nonresident_table_size > 0)
            {
                NonResidentNames = GetResidentStrings(BaseStream, Header.nonresident_names_offset, 0,
                                                      (ushort)(Header.nonresident_names_offset +
                                                               Header.nonresident_table_size));

                if (NonResidentNames.Length >= 1)
                {
                    ModuleDescription = NonResidentNames[0].name;

                    if (NonResidentNames.Length > 1)
                    {
                        ResidentName[] newNonResidentNames = new ResidentName[NonResidentNames.Length - 1];
                        Array.Copy(NonResidentNames, 1, newNonResidentNames, 0, NonResidentNames.Length - 1);
                        NonResidentNames = newNonResidentNames;
                    }
                    else
                    {
                        NonResidentNames = null;
                    }
                }
            }

            if (!string.IsNullOrEmpty(ModuleName))
            {
                strings.Add(ModuleName);
            }
            if (!string.IsNullOrEmpty(ModuleDescription))
            {
                strings.Add(ModuleDescription);
            }

            if (strings.Count > 0)
            {
                Strings = strings.Distinct().OrderBy(s => s);
            }

            if (segments == null)
            {
                return;
            }

            List <Segment> libsegs = new List <Segment>();

            foreach (SegmentEntry seg in segments)
            {
                Segment libseg = new Segment
                {
                    Flags    = $"{(SegmentFlags)(seg.dwFlags & SEGMENT_FLAGS_MASK)}",
                    Name     = (SegmentType)(seg.dwFlags & SEGMENT_TYPE_MASK) == SegmentType.Code ? ".text" : ".data",
                    Offset   = seg.dwLogicalSectorOffset << Header.alignment_shift,
                        Size = seg.dwSegmentLength
                };

                if (Header.target_os == TargetOS.OS2 && (seg.dwFlags & (int)SegmentFlags.Huge) == (int)SegmentFlags.Huge)
                {
                    libseg.Size <<= Header.alignment_shift;
                }

                libsegs.Add(libseg);
            }

            Segments = libsegs.OrderBy(s => s.Offset).ToArray();
        }