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)); }
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)); }
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); }
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); }
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); }
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)); }
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)); }
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); }
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); }
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("-", "") ); } }
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); } } } }