void parseSection64(uint protection, SegmentMap segmentMap) { var abSectname = rdr.ReadBytes(16); var abSegname = rdr.ReadBytes(16); ulong addr; ulong size; uint offset; uint align; uint reloff; uint nreloc; uint flags; uint reserved1; uint reserved2; uint reserved3; if (!rdr.TryReadUInt64(out addr) || !rdr.TryReadUInt64(out size) || !rdr.TryReadUInt32(out offset) || !rdr.TryReadUInt32(out align) || !rdr.TryReadUInt32(out reloff) || !rdr.TryReadUInt32(out nreloc) || !rdr.TryReadUInt32(out flags) || !rdr.TryReadUInt32(out reserved1) || !rdr.TryReadUInt32(out reserved2) || !rdr.TryReadUInt32(out reserved3)) { throw new BadImageFormatException("Could not read Mach-O section."); } var sectionName = GetAsciizString(abSectname); var segmentName = GetAsciizString(abSegname); Debug.Print("Found section '{0}' in segment '{1}, addr = 0x{2:X}, size = 0x{3:X}.", sectionName, segmentName, addr, size); AccessMode am = 0; if ((protection & VM_PROT_READ) != 0) { am |= AccessMode.Read; } if ((protection & VM_PROT_WRITE) != 0) { am |= AccessMode.Write; } if ((protection & VM_PROT_EXECUTE) != 0) { am |= AccessMode.Execute; } var bytes = rdr.CreateNew(this.ldr.RawImage, offset); var mem = new MemoryArea( Address.Ptr64(addr), bytes.ReadBytes((uint)size)); var imageSection = new ImageSegment( string.Format("{0},{1}", segmentName, sectionName), mem, am); //imageSection.setBss((section.flags & SECTION_TYPE) == S_ZEROFILL); //if (!imageSection.isBss()) { // auto pos = source_->pos(); // if (!source_->seek(section.offset)) { // throw ParseError("Could not seek to the beginning of the section's content."); // } // auto bytes = source_->read(section.size); // if (checked_cast<uint>(bytes.size()) != section.size) { // log_.warning("Could not read all the section's content."); // } else { // imageSection->setContent(std::move(bytes)); // } // source_->seek(pos); //} //sections_.push_back(imageSection.get()); //image_->addSection(std::move(imageSection)); segmentMap.AddSegment(imageSection); }
public override RelocationResults Relocate(Program program, Address addrLoad) { SegmentMap imageMap = segmentMap; EndianImageReader rdr = new LeImageReader(exe.RawImage, exe.e_lfaRelocations); var relocations = imgLoaded.Relocations; int i = exe.e_cRelocations; var segments = new Dictionary <Address, ushort>(); var linBase = addrLoad.ToLinear(); while (i != 0) { uint offset = rdr.ReadLeUInt16(); ushort segOffset = rdr.ReadLeUInt16(); offset += segOffset * 0x0010u; ushort seg = (ushort)(imgLoaded.ReadLeUInt16(offset) + addrLoad.Selector.Value); imgLoaded.WriteLeUInt16(offset, seg); relocations.AddSegmentReference(offset + linBase, seg); var segment = new ImageSegment( seg.ToString("X4"), Address.SegPtr(seg, 0), imgLoaded, AccessMode.ReadWriteExecute); segment = segmentMap.AddSegment(segment); segments[segment.Address] = seg; --i; } // Create an identifier for each segment. foreach (var de in segments) { var tmp = new TemporaryStorage( string.Format("seg{0:X4}", de.Value), 0, PrimitiveType.SegmentSelector); segmentMap.Segments[de.Key].Identifier = new Identifier( tmp.Name, PrimitiveType.SegmentSelector, tmp); } // Found the start address. Address addrStart = Address.SegPtr((ushort)(exe.e_cs + addrLoad.Selector.Value), exe.e_ip); segmentMap.AddSegment(new ImageSegment( addrStart.Selector.Value.ToString("X4"), Address.SegPtr(addrStart.Selector.Value, 0), imgLoaded, AccessMode.ReadWriteExecute)); DumpSegments(imageMap); var ep = new ImageSymbol(addrStart) { Type = SymbolType.Procedure, ProcessorState = arch.CreateProcessorState() }; var sym = platform.FindMainProcedure(program, addrStart); var results = new RelocationResults( new List <ImageSymbol> { ep }, new SortedList <Address, ImageSymbol> { { ep.Address, ep } }); if (sym != null) { results.Symbols[sym.Address] = sym; ep.NoDecompile = true; } LoadDebugSymbols(results.Symbols, addrLoad); return(results); }
public override SegmentMap LoadImageBytes(IPlatform platform, byte[] rawImage, Address addrPreferred) { var segMap = AllocateMemoryAreas( Segments .Where(p => IsLoadable(p.p_pmemsz, p.p_type)) .Select(p => Tuple.Create( platform.MakeAddressFromLinear(p.p_vaddr, false), (uint)p.p_pmemsz))); foreach (var ph in Segments) { DebugEx.Inform(ElfImageLoader.trace, "ph: addr {0:X8} filesize {0:X8} memsize {0:X8}", ph.p_vaddr, ph.p_filesz, ph.p_pmemsz); if (!IsLoadable(ph.p_pmemsz, ph.p_type)) { continue; } var vaddr = platform.MakeAddressFromLinear(ph.p_vaddr, false); segMap.TryGetLowerBound(vaddr, out var mem); if (ph.p_filesz > 0) { Array.Copy( rawImage, (long)ph.p_offset, mem.Bytes, vaddr - mem.BaseAddress, (long)ph.p_filesz); } } var segmentMap = new SegmentMap(addrPreferred); if (Sections.Count > 0) { foreach (var section in Sections) { if (section.Name == null || section.Address == null) { continue; } if (segMap.TryGetLowerBound(section.Address, out var mem) && section.Address < mem.EndAddress) { AccessMode mode = AccessModeOf(section.Flags); var seg = segmentMap.AddSegment(new ImageSegment( section.Name, section.Address, mem, mode) { Size = (uint)section.Size }); seg.Designer = CreateRenderer64(section); } else { //$TODO: warn } } } else { // There are stripped ELF binaries with 0 sections. If we have one // create a pseudo-section from the segMap. foreach (var segment in segMap) { var imgSegment = new ImageSegment( segment.Value.BaseAddress.GenerateName("seg", ""), segment.Value, AccessMode.ReadExecute) //$TODO: writeable segments. { Size = (uint)segment.Value.Length, }; segmentMap.AddSegment(imgSegment); } } segmentMap.DumpSections(); return(segmentMap); }
private IEnumerable <int> GetMatches(ImageSegment s, Core.Dfa.Automaton re) { var mem = (ByteMemoryArea)s.MemoryArea; return(re.GetMatches(mem.Bytes, 0)); }
private string DetermineFilename(ImageMapItem item, ImageSegment seg) { return(FilenameBasedOnSegment(item.Address, seg)); }
private ImageSegment [] ExtractSegments() { ImageSegment [] segs = new ImageSegment[map.Segments.Count]; map.Segments.Values.CopyTo(segs, 0); return(segs); }
public override void Render(ImageSegment segment, Program program, Formatter formatter) { ulong fileOffset = shdr.FileOffset; Render(fileOffset, formatter); }
public void TearDownStack(ImageSegment stackSeg) { }
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); } } } }
public override SegmentMap LoadImageBytes(IPlatform platform, byte[] rawImage, Address addrPreferred) { var segMap = AllocateMemoryAreas( Segments .Where(p => IsLoadable(p.p_pmemsz, p.p_type)) .OrderBy(p => p.p_vaddr) .Select(p => ( Address.Ptr32((uint)p.p_vaddr), (uint)p.p_pmemsz))); foreach (var ph in Segments) { ElfImageLoader.trace.Inform("ph: addr {0:X8} filesize {0:X8} memsize {0:X8}", ph.p_vaddr, ph.p_filesz, ph.p_pmemsz); if (!IsLoadable(ph.p_pmemsz, ph.p_type)) { continue; } var vaddr = Address.Ptr32((uint)ph.p_vaddr); segMap.TryGetLowerBound(vaddr, out var mem); if (ph.p_filesz > 0) { Array.Copy( rawImage, (long)ph.p_offset, mem.Bytes, vaddr - mem.BaseAddress, (long)ph.p_filesz); } } var segmentMap = new SegmentMap(addrPreferred); if (Sections.Count > 0) { foreach (var section in Sections) { if (string.IsNullOrEmpty(section.Name) || section.Address == null) { continue; } if (segMap.TryGetLowerBound(section.Address, out var mem) && section.Address - mem.BaseAddress < mem.Length) { AccessMode mode = AccessModeOf(section.Flags); var seg = segmentMap.AddSegment(new ImageSegment( section.Name, section.Address, mem, mode) { Size = (uint)section.Size }); seg.Designer = CreateRenderer(section, machine); } else { //$TODO: warn } } } else { // There are stripped ELF binaries with 0 sections. If we have one // create a pseudo-section from the segMap. foreach (var segment in segMap) { var elfSegment = this.GetSegmentByAddress(segment.Value.BaseAddress.ToLinear()); var imgSegment = new ImageSegment( segment.Value.BaseAddress.GenerateName("seg", ""), segment.Value, elfSegment != null ? elfSegment.GetAccessMode() : AccessMode.ReadExecute) { Size = (uint)segment.Value.Length, }; segmentMap.AddSegment(imgSegment); } } segmentMap.DumpSections(); return(segmentMap); }
private static bool SegmentNamedA5Init(ImageSegment segment) { return(segment.Name.Length >= 12 && segment.Name.Substring(5, 7) == "%A5Init"); }
public void Setup() { this.relocator = null; this.mem = new ByteMemoryArea(Address.Ptr32(0x00100000), new byte[4096]); this.a5world = new ImageSegment("A5World", mem, AccessMode.ReadWriteExecute); }
private bool TryFindSegment(Program program, string segName, out ImageSegment seg) { seg = program.SegmentMap.Segments.Values.FirstOrDefault(s => s.Name == segName); return(seg is not null); }
private void TearDownStack(ImageSegment stackSeg) { this.ImageMap.Segments.Remove(stackSeg.Address); }
private string DetermineFilename(ImageMapItem item, ImageSegment seg, string fileExtension) { return(FilenameBasedOnSegment(item.Address, seg, fileExtension)); }
public override void Render(ImageSegment segment, Program program, Formatter formatter) { throw new NotImplementedException(); }
private void PaintSegment(ImageSegment seg, Graphics g, Rectangle rc) { g.FillRectangle(Brushes.White, rc); g.DrawRectangle(seg == segSelected ? Pens.Red : Pens.Black, rc); }
public GlobalVariablesNodeDesigner(ImageSegment segment) { this.segment = segment; }
/// <summary> /// Disassemble every byte of the segment, marking those addresses /// that likely are code as MaybeCode, everything else as data. /// </summary> /// <remarks> /// The plan is to disassemble every location of the segment, building /// a reverse control graph. Any jump to an illegal address or any /// invalid instruction will result in an edge from "bad" to that /// instruction. /// </remarks> /// <param name="segment"></param> /// <returns>An array of bytes classifying each byte as code or data. /// </returns> public ScannedSegment ScanSegment(ImageSegment segment, ulong workToDo) { var G = new DiGraph <Address>(); G.AddNode(bad); var cbAlloc = Math.Min( segment.Size, segment.MemoryArea.EndAddress - segment.Address); var y = new byte[cbAlloc]; // Advance by the instruction granularity. var step = program.Architecture.InstructionBitSize / 8; var delaySlot = InstructionClass.None; for (var a = 0; a < y.Length; a += step) { y[a] = MaybeCode; var i = Dasm(segment, a); if (i == null) { AddEdge(G, bad, segment.Address + a); break; } if (IsInvalid(segment.MemoryArea, i)) { AddEdge(G, bad, i.Address); delaySlot = InstructionClass.None; y[a] = Data; } else { if (MayFallThrough(i)) { if (delaySlot != DT) { if (a + i.Length < y.Length) { // Still inside the segment. AddEdge(G, i.Address + i.Length, i.Address); } else { // Fell off segment, i must be a bad instruction. AddEdge(G, bad, i.Address); y[a] = Data; } } } if ((i.InstructionClass & InstructionClass.Transfer) != 0) { var addrDest = DestinationAddress(i); if (addrDest != null) { if (IsExecutable(addrDest)) { // call / jump destination is executable AddEdge(G, addrDest, i.Address); if ((i.InstructionClass & InstructionClass.Call) != 0) { int callTally; if (!this.possibleCallDestinationTallies.TryGetValue(addrDest, out callTally)) { callTally = 0; } this.possibleCallDestinationTallies[addrDest] = callTally + 1; } } else { // Jump to data / hyperspace. AddEdge(G, bad, i.Address); y[a] = Data; } } } // If this is a delayed unconditional branch... delaySlot = i.InstructionClass; } if (y[a] == MaybeCode) { instructions.Add(i.Address, i); } eventListener.ShowProgress("Shingle scanning", instructions.Count, (int)workToDo); } // Find all places that are reachable from "bad" addresses. // By transitivity, they must also be be bad. foreach (var a in new DfsIterator <Address>(G).PreOrder(bad)) { if (a != bad) { y[a - segment.Address] = Data; instructions.Remove(a); // Destination can't be a call destination. possibleCallDestinationTallies.Remove(a); } } // Build blocks out of sequences of instructions. var blocks = BuildBlocks(G, instructions); return(new ScannedSegment { Blocks = blocks, CodeFlags = y, }); }