Example #1
0
        public override Program Load(Address?addrLoad)
        {
            BeImageReader rdr = new BeImageReader(this.RawImage, 0);
            FileHeader    str = rdr.ReadStruct <FileHeader>();

            if (str.f_opthdr != 0)
            {
                aux = rdr.ReadStruct <AuxFileHeader>();
            }
            if (str.f_nscns == 0)
            {
                throw new BadImageFormatException("Expected at least one XCoff32 section.");
            }
            var segments = new ImageSegment[str.f_nscns + 1];

            for (int i = 1; i <= str.f_nscns; ++i)
            {
                segments[i] = LoadSegment(rdr);
            }
            var mem      = new ByteMemoryArea(addrLoad ?? PreferredBaseAddress, RawImage);
            var seg      = new ImageSegment("foo", mem, AccessMode.ReadWriteExecute);
            var map      = new SegmentMap(segments.Skip(1).ToArray());
            var cfgSvc   = Services.RequireService <IConfigurationService>();
            var arch     = cfgSvc.GetArchitecture("ppc-be-32") !;
            var platform = new DefaultPlatform(Services, arch);

            return(new Program(map, arch, platform));
        }
Example #2
0
        public override Program Load(Address?addrLoad)
        {
            var rdr    = new BeImageReader(RawImage);
            var header = rdr.ReadStruct <filehdr>();

            if (header.f_opthdr != 0)
            {
                var sectionOffset = rdr.Offset + header.f_opthdr;
                opthdr     = rdr.ReadStruct <aouthdr>();
                rdr.Offset = sectionOffset;
            }
            var sections = new scnhdr[header.f_nscns];

            for (int i = 0; i < sections.Length; ++i)
            {
                sections[i] = rdr.ReadStruct <scnhdr>();
            }
            var imgSegments = new ImageSegment[header.f_nscns];

            for (int i = 0; i < sections.Length; ++i)
            {
                imgSegments[i] = LoadImageSegment(sections[i]);
            }

            var arch     = LoadArchitecture(header.f_magic);
            var platform = new DefaultPlatform(Services, arch);
            var segmap   = new SegmentMap(imgSegments);

            return(new Program(segmap, arch, platform));
        }
Example #3
0
        private List <Symbol> ReadSymbols(BeImageReader rdr, uint nsyms)
        {
            var syms = new List <Symbol>((int)nsyms);

            for (uint i = 0; i < nsyms; ++i)
            {
                var xcoffSym = rdr.ReadStruct <Symbol>();
                syms.Add(xcoffSym);
            }
            return(syms);
        }
Example #4
0
        private bool TryLoadHeader(BeImageReader rdr, out PrgHeader hdr)
        {
            var h = rdr.ReadStruct <PrgHeader>();

            if (h.Magic != 0x601A)
            {
                hdr = default(PrgHeader);
                return(false);
            }
            hdr = h;
            return(true);
        }
Example #5
0
        public override Program LoadProgram(Address?addrLoad)
        {
            var rdr    = new BeImageReader(RawImage);
            var header = rdr.ReadStruct <filehdr>();

            if (header.f_opthdr != 0)
            {
                var sectionOffset = rdr.Offset + header.f_opthdr;
                opthdr     = rdr.ReadStruct <aouthdr>();
                rdr.Offset = sectionOffset;
            }
            var sections = new scnhdr[header.f_nscns];

            for (int i = 0; i < sections.Length; ++i)
            {
                sections[i] = rdr.ReadStruct <scnhdr>();
            }
            var imgSegments = new ImageSegment[header.f_nscns];

            for (int i = 0; i < sections.Length; ++i)
            {
                imgSegments[i] = LoadImageSegment(sections[i]);
            }

            var arch     = LoadArchitecture(header.f_magic);
            var platform = new DefaultPlatform(Services, arch);
            var segmap   = new SegmentMap(imgSegments);
            var program  = new Program(segmap, arch, platform);

            if (this.opthdr.HasValue)
            {
                var addrEntry = Address.Ptr32(opthdr.Value.entry);   //$64
                var ep        = ImageSymbol.Procedure(program.Architecture, addrEntry, "_start");
                program.EntryPoints.Add(ep.Address, ep);
            }
            return(program);
        }
Example #6
0
        public override Program Load(Address?addrLoad)
        {
            BeImageReader rdr = new BeImageReader(this.RawImage, 0);
            FileHeader64? str = rdr.ReadStruct <FileHeader64>();

            if (!str.HasValue)
            {
                throw new BadImageFormatException("Invalid XCoff64 header.");
            }
            var mem      = new ByteMemoryArea(addrLoad ?? PreferredBaseAddress, RawImage);
            var seg      = new ImageSegment("foo", mem, AccessMode.ReadWriteExecute);
            var map      = new SegmentMap(seg);
            var cfgSvc   = Services.RequireService <IConfigurationService>();
            var arch     = cfgSvc.GetArchitecture("ppc-64-be") !;
            var platform = new DefaultPlatform(Services, arch);

            return(new Program(map, arch, platform));
        }
Example #7
0
        private Program LoadExecSegments(BeImageReader rdr)
        {
            var segments = new List <ImageSegment>();
            var execAux  = rdr.ReadStruct <SOM_Exec_aux_hdr>();

            var cfgSvc = Services.RequireService <IConfigurationService>();
            var arch   = cfgSvc.GetArchitecture("paRisc");

            var dlHeaderRdr = ReadDynamicLibraryInfo(execAux, arch);

            var textBytes = new byte[execAux.exec_tsize];
            var textAddr  = Address.Ptr32(execAux.exec_tmem);

            Array.Copy(RawImage, (int)execAux.exec_tfile, textBytes, 0, textBytes.Length);
            var textSeg = new ImageSegment(
                ".text",
                new ByteMemoryArea(textAddr, textBytes),
                AccessMode.ReadExecute);

            segments.Add(textSeg);

            var dataBytes = new byte[execAux.exec_dsize];
            var dataAddr  = Address.Ptr32(execAux.exec_tmem);

            Array.Copy(RawImage, (int)execAux.exec_dfile, dataBytes, 0, dataBytes.Length);
            var dataSeg = new ImageSegment(
                ".data",
                new ByteMemoryArea(dataAddr, dataBytes),
                AccessMode.ReadWrite);

            segments.Add(dataSeg);

            var segmap = new SegmentMap(
                segments.Min(s => s.Address),
                segments.ToArray());
            var platform = cfgSvc.GetEnvironment("hpux").Load(Services, arch);

            return(new Program(segmap, arch, platform));
        }
Example #8
0
        private ImageSegment LoadSegment(BeImageReader rdr)
        {
            var section = rdr.ReadStruct <Section>();
            var name    = Utf8StringFromFixedArray(section.s_name);
            var addr    = Address.Ptr32(section.v_paddr);
            var bytes   = new byte[section.s_size];

            if (section.s_scnptr != 0)
            {
                Array.Copy(RawImage, section.s_scnptr, bytes, 0, bytes.Length);
            }
            var mem    = new ByteMemoryArea(addr, bytes);
            var access = SectionAccessMode(section.s_flags);
            var seg    = new ImageSegment(name, mem, access);

            Debug.Print("   {0} {1,-10} {2}", seg.Address, section.s_flags, seg.Name);
            SetWellKnownSection(section, SectionFlags.STYP_TEXT, seg, ref textSection);
            SetWellKnownSection(section, SectionFlags.STYP_DATA, seg, ref dataSection);
            SetWellKnownSection(section, SectionFlags.STYP_BSS, seg, ref bssSection);
            SetWellKnownSection(section, SectionFlags.STYP_LOADER, seg, ref loaderSection);
            return(seg);
        }
Example #9
0
        public override Program Load(Address addrLoad, IProcessorArchitecture arch, IPlatform platform)
        {
            BeImageReader rdr = new BeImageReader(this.RawImage, 0);
            DolStructure? str = rdr.ReadStruct <DolStructure>();

            if (!str.HasValue)
            {
                throw new BadImageFormatException("Invalid DOL header.");
            }
            this.hdr = new DolHeader(str.Value);
            var segments = new List <ImageSegment>();

            // Create code segments
            for (uint i = 0, snum = 1; i < 7; i++, snum++)
            {
                if (hdr.addressText[i] == Address32.NULL)
                {
                    continue;
                }
                var bytes = new byte[hdr.sizeText[i]];
                Array.Copy(RawImage, hdr.offsetText[i], bytes, 0, bytes.Length);
                var mem = new ByteMemoryArea(hdr.addressText[i], bytes);
                segments.Add(new ImageSegment(
                                 string.Format("Text{0}", snum),
                                 mem,
                                 AccessMode.ReadExecute));
            }

            // Create all data segments
            for (uint i = 0, snum = 1; i < 11; i++, snum++)
            {
                if (hdr.addressData[i] == Address32.NULL ||
                    hdr.sizeData[i] == 0)
                {
                    continue;
                }
                var bytes = new byte[hdr.sizeData[i]];
                Array.Copy(RawImage, hdr.offsetData[i], bytes, 0, bytes.Length);
                var mem = new ByteMemoryArea(hdr.addressText[i], bytes);

                segments.Add(new ImageSegment(
                                 string.Format("Data{0}", snum),
                                 mem,
                                 AccessMode.ReadWrite));
            }

            if (hdr.addressBSS != Address32.NULL)
            {
                segments.Add(new ImageSegment(
                                 ".bss",
                                 new ByteMemoryArea(hdr.addressBSS, new byte[hdr.sizeBSS]),
                                 AccessMode.ReadWrite));
            }

            var segmentMap = new SegmentMap(addrLoad, segments.ToArray());

            var entryPoint = ImageSymbol.Procedure(arch, this.hdr.entrypoint);
            var program    = new Program(
                segmentMap,
                arch,
                platform)
            {
                ImageSymbols = { { this.hdr.entrypoint, entryPoint } },
                EntryPoints  = { { this.hdr.entrypoint, entryPoint } }
            };

            return(program);
        }
Example #10
0
        private void LoadHeaders()
        {
            ImageData imageData = xexData;

            xexData.header = rdr.ReadStruct <XexHeader>();

            XexHeader header = xexData.header;

            switch (header.magic)
            {
            case XEX2_MAGIC:
            case XEX1_MAGIC:
                break;

            default:
                throw new BadImageFormatException("Invalid XEX Magic");
            }

            for (uint i = 0; i < header.header_count; i++)
            {
                bool add = true;
                XexOptionalHeader st_optionalHeader = rdr.ReadStruct <XexOptionalHeader>();
                OptionalHeader    optionalHeader    = new OptionalHeader(st_optionalHeader);

                switch ((byte)optionalHeader.key)
                {
                // just the data
                case 0x00:
                case 0x01:
                    optionalHeader.value  = optionalHeader.offset;
                    optionalHeader.offset = 0;
                    break;

                case 0xFF:
                    optionalHeader.length = rdr.ReadAt <UInt32>(optionalHeader.offset, (r) =>
                    {
                        return(r.ReadUInt32());
                    });
                    optionalHeader.offset += 4;

                    if (optionalHeader.length + optionalHeader.offset > rdr.Bytes.Length)
                    {
                        decompilerEventListener.Warn(
                            new NullCodeLocation(""),
                            $"Optional header {i} (0x{optionalHeader.key:X}) crosses file boundary. Will not be read"
                            );
                        add = false;
                    }
                    break;

                default:
                    optionalHeader.length = ((uint)(byte)optionalHeader.key) * 4;

                    if (optionalHeader.length + optionalHeader.offset > rdr.Bytes.Length)
                    {
                        decompilerEventListener.Warn(
                            new NullCodeLocation(""),
                            $"Optional header {i} (0x{optionalHeader.key:X}) crosses file boundary. Will not be read"
                            );
                        add = false;
                    }
                    break;
                }

                if (add)
                {
                    optional_headers.Add(optionalHeader);
                }
            }

            for (int i = 0; i < optional_headers.Count; i++)
            {
                OptionalHeader opt = optional_headers[i];

                // go to the header offset
                if (opt.length > 0 && opt.offset != 0)
                {
                    rdr.Offset = opt.offset;
                }

                // process the optional headers
                switch (opt.key)
                {
                case XEXHeaderKeys.XEX_HEADER_SYSTEM_FLAGS:
                    imageData.system_flags = (XEXSystemFlags)opt.value;
                    break;

                case XEXHeaderKeys.XEX_HEADER_RESOURCE_INFO:
                    uint count = (opt.length - 4) / 16;
                    xexData.resources = new List <XexResourceInfo>((int)count);

                    for (uint n = 0; n < count; n++)
                    {
                        xexData.resources.Insert(i, rdr.ReadStruct <XexResourceInfo>());
                    }
                    break;

                case XEXHeaderKeys.XEX_HEADER_EXECUTION_INFO:
                    imageData.execution_info = rdr.ReadStruct <XexExecutionInfo>();
                    break;

                case XEXHeaderKeys.XEX_HEADER_GAME_RATINGS:
                    break;

                case XEXHeaderKeys.XEX_HEADER_TLS_INFO:
                    imageData.tls_info = rdr.ReadStruct <XexTlsInfo>();
                    break;

                case XEXHeaderKeys.XEX_HEADER_IMAGE_BASE_ADDRESS:
                    imageData.exe_address = opt.value;
                    break;

                case XEXHeaderKeys.XEX_HEADER_ENTRY_POINT:
                    imageData.exe_entry_point = opt.value;
                    break;

                case XEXHeaderKeys.XEX_HEADER_DEFAULT_STACK_SIZE:
                    imageData.exe_stack_size = opt.value;
                    break;

                case XEXHeaderKeys.XEX_HEADER_DEFAULT_HEAP_SIZE:
                    imageData.exe_heap_size = opt.value;
                    break;

                case XEXHeaderKeys.XEX_HEADER_FILE_FORMAT_INFO:
                    XexEncryptionHeader encHeader = rdr.ReadStruct <XexEncryptionHeader>();

                    imageData.file_format_info.encryption_type  = encHeader.encryption_type;
                    imageData.file_format_info.compression_type = encHeader.compression_type;

                    switch (encHeader.compression_type)
                    {
                    case XEXCompressionType.XEX_COMPRESSION_NONE:
                        break;

                    case XEXCompressionType.XEX_COMPRESSION_DELTA:
                        throw new NotImplementedException("XEX: image::Binary is using unsupported delta compression");

                    case XEXCompressionType.XEX_COMPRESSION_BASIC:
                        uint block_count = (opt.length - 8) / 8;
                        imageData.file_format_info.basic_blocks = new List <XexFileBasicCompressionBlock>((int)block_count);

                        for (int ib = 0; ib < block_count; ib++)
                        {
                            imageData.file_format_info.basic_blocks.Insert(ib, rdr.ReadStruct <XexFileBasicCompressionBlock>());
                        }
                        break;

                    case XEXCompressionType.XEX_COMPRESSION_NORMAL:
                        imageData.file_format_info.normal = rdr.ReadStruct <XexFileNormalCompressionInfo>();
                        break;
                    }

                    if (encHeader.encryption_type != XEXEncryptionType.XEX_ENCRYPTION_NONE)
                    {
                        //
                    }
                    break;

                case XEXHeaderKeys.XEX_HEADER_IMPORT_LIBRARIES:
                    XexImportLibraryBlockHeader blockHeader = rdr.ReadStruct <XexImportLibraryBlockHeader>();

                    long string_table = rdr.Offset;
                    for (int j = 0; j < blockHeader.count; j++)
                    {
                        string name = rdr.ReadCString(PrimitiveType.Char, Encoding.ASCII).ToString();
                        imageData.libNames.Add(name);
                    }
                    rdr.Offset = string_table + blockHeader.string_table_size;

                    for (int m = 0; m < blockHeader.count; m++)
                    {
                        XexImportLibaryHeader imp_header = rdr.ReadStruct <XexImportLibaryHeader>();

                        string name       = null;
                        int    name_index = (byte)imp_header.name_index;
                        if (name_index < blockHeader.count)
                        {
                            name = imageData.libNames[name_index];
                        }

                        for (uint ri = 0; ri < imp_header.record_count; ++ri)
                        {
                            UInt32 recordEntry = rdr.ReadUInt32();
                            xexData.import_records.Add(recordEntry);
                        }
                    }
                    break;
                }
            }

            // load the loader info
            {
                rdr.Offset = header.security_offset;

                switch (header.magic)
                {
                case XEX1_MAGIC:
                    Xex1LoaderInfo info1 = rdr.ReadStruct <Xex1LoaderInfo>();
                    xexData.loader_info.aes_key = info1.aes_key;
                    break;

                case XEX2_MAGIC:
                    Xex2LoaderInfo info2 = rdr.ReadStruct <Xex2LoaderInfo>();
                    xexData.loader_info.aes_key = info2.aes_key;
                    break;
                }
            }

            // load the sections
            {
                rdr.Offset = header.security_offset + 0x180;

                UInt32 sectionCount = rdr.ReadUInt32();
                xexData.sections = new List <XexSection>((int)sectionCount);

                for (int si = 0; si < sectionCount; si++)
                {
                    xexData.sections.Insert(0, rdr.ReadStruct <XexSection>());
                }
            }

            // decrypt the XEX key
            {
                byte[] keyToUse = xe_xex2_devkit_key;
                if (header.magic != XEX1_MAGIC && xexData.execution_info.title_id != 0)
                {
                    keyToUse = xe_xex2_retail_key;
                }

                Rijndael aes = new RijndaelManaged()
                {
                    BlockSize = 128,
                    KeySize   = 128,
                    Mode      = CipherMode.ECB,
                    Key       = keyToUse,
                    Padding   = PaddingMode.None
                };

                xexData.session_key = aes
                                      .CreateDecryptor()
                                      .TransformFinalBlock(xexData.loader_info.aes_key, 0, 16);
                decompilerEventListener.Info(
                    new NullCodeLocation(""),
                    "XEX Session key: " + BitConverter.ToString(xexData.session_key).Replace("-", "")
                    );
            }
        }
Example #11
0
        private void LoadPEImage()
        {
            long fileDataSize = rdr.Bytes.Length - xexData.header.header_size;

            BeImageReader memRdr    = new BeImageReader(xexData.memoryData);
            DOSHeader     dosHeader = memRdr.ReadStruct <DOSHeader>();

            dosHeader.Validate();

            memRdr.Offset = dosHeader.e_lfanew;

            UInt32 peSignature = memRdr.ReadUInt32();

            if (peSignature != 0x50450000)
            {
                throw new BadImageFormatException("PE: Invalid or Missing PE Signature");
            }

            COFFHeader coffHeader = memRdr.ReadStruct <COFFHeader>();

            if (coffHeader.Machine != 0x1F2)
            {
                throw new BadImageFormatException($"PE: Machine type does not match Xbox360 (found 0x{coffHeader.Machine:X})");
            }

            if ((coffHeader.Characteristics & 0x0100) == 0)
            {
                throw new BadImageFormatException("PE: Only 32-bit images are supported");
            }

            if (coffHeader.SizeOfOptionalHeader != 224)
            {
                throw new BadImageFormatException($"PE: Invalid size of optional header (got {coffHeader.SizeOfOptionalHeader}");
            }

            PEOptHeader optHeader = memRdr.ReadStruct <PEOptHeader>();

            if (optHeader.signature != 0x10b)
            {
                throw new BadImageFormatException($"PE: Invalid signature of optional header (got 0x{optHeader.signature})");
            }

            if (optHeader.Subsystem != IMAGE_SUBSYSTEM_XBOX)
            {
                throw new BadImageFormatException($"PE: Invalid subsystem (got {optHeader.Subsystem})");
            }

            xexData.peHeader = optHeader;

            uint extendedMemorySize = 0;
            uint numSections        = coffHeader.NumberOfSections;

            List <PESection> peSections = new List <PESection>();

            for (uint i = 0; i < numSections; i++)
            {
                COFFSection section = memRdr.ReadStruct <COFFSection>();

                string sectionName = Encoding.ASCII.GetString(section.Name).Trim('\0');

                uint lastMemoryAddress = section.VirtualAddress + section.VirtualSize;
                if (lastMemoryAddress > extendedMemorySize)
                {
                    extendedMemorySize = lastMemoryAddress;
                }

                if (section.SizeOfRawData == 0)
                {
                    decompilerEventListener.Info(new NullCodeLocation(""),
                                                 $"Skipping empty section {sectionName}"
                                                 );
                    continue;
                }

                byte[] sectionData = memRdr.ReadAt <byte[]>(section.PointerToRawData, rdr => rdr.ReadBytes(section.SizeOfRawData));

                AccessMode acc = AccessMode.Read;
                if (section.Flags.HasFlag(PESectionFlags.IMAGE_SCN_MEM_WRITE))
                {
                    acc |= AccessMode.Write;
                }
                if (section.Flags.HasFlag(PESectionFlags.IMAGE_SCN_MEM_EXECUTE))
                {
                    acc |= AccessMode.Execute;
                }

                PESection managedSection = new PESection(section);
                peSections.Add(managedSection);

                ImageSegment seg = new ImageSegment(sectionName, new MemoryArea(
                                                        new Address32(managedSection.PhysicalOffset + xexData.exe_address), sectionData
                                                        ), acc);
                segments.Add(seg);
            }

            if (extendedMemorySize > xexData.memorySize)
            {
                decompilerEventListener.Info(new NullCodeLocation(""),
                                             $"PE: Image sections extend beyond virtual memory range loaded from file ({extendedMemorySize} > {xexData.memorySize}). Extending by {extendedMemorySize - xexData.memorySize} bytes."
                                             );

                UInt32 oldMemorySize = xexData.memorySize;

                byte[] newMemoryData = new byte[extendedMemorySize];
                Array.Copy(xexData.memoryData, newMemoryData, xexData.memorySize);
                xexData.memorySize = extendedMemorySize;
                xexData.memoryData = newMemoryData;

                for (int i = 0; i < peSections.Count; i++)
                {
                    PESection section = peSections[i];

                    if (section.PhysicalSize == 0)
                    {
                        continue;
                    }

                    if (section.PhysicalSize + section.PhysicalOffset > fileDataSize)
                    {
                        decompilerEventListener.Warn(new NullCodeLocation(""),
                                                     $"PE: Section '{section.Name}' lies outside any phyisical data we have {section.PhysicalOffset} (size {section.PhysicalSize})"
                                                     );
                        continue;
                    }

                    if (section.VirtualOffset >= oldMemorySize)
                    {
                        uint sizeToCopy = section.PhysicalSize;
                        if (section.VirtualSize < sizeToCopy)
                        {
                            sizeToCopy = section.VirtualSize;
                        }

                        Array.Copy(
                            xexData.memoryData, section.PhysicalOffset,
                            newMemoryData, section.VirtualOffset,
                            sizeToCopy);
                    }
                }
            }
        }