/// <summary> /// Reads all directory entries from the passed in debug directory entry. /// </summary> /// <param name="debugDirectoryEntry">The debug directory entry.</param> /// <returns>The parsed debug directory entries.</returns> private DebugDirectory[] ReadDebugDirectories(DirectoryEntry debugDirectoryEntry) { // there might not be a debug directory, in which case return an empty list if (debugDirectoryEntry.RelativeVirtualAddress == 0) { return(new DebugDirectory[0]); } BinaryReader reader = this.ReadAtRelativeVirtualAddress(debugDirectoryEntry.RelativeVirtualAddress, debugDirectoryEntry.Size); int countDirectories = (int)(debugDirectoryEntry.Size / PEImageReader.SizeofDebugDirectory); DebugDirectory[] debugDirectories = new DebugDirectory[countDirectories]; for (int i = 0; i < countDirectories; i++) { debugDirectories[i] = new DebugDirectory(); debugDirectories[i].Characteristics = reader.ReadUInt32(); debugDirectories[i].TimeDateStamp = reader.ReadUInt32(); debugDirectories[i].MajorVersion = reader.ReadUInt16(); debugDirectories[i].MinorVersion = reader.ReadUInt16(); debugDirectories[i].Type = (ImageDebugType)reader.ReadUInt32(); debugDirectories[i].SizeOfData = reader.ReadUInt32(); debugDirectories[i].AddressOfRawData = reader.ReadUInt32(); debugDirectories[i].PointerToRawData = reader.ReadUInt32(); } return(debugDirectories); }
public void WhenIReadTheDebugDirectory() { var fileName = ScenarioContext.Current.Get <string>("FileName"); var filePath = string.Format(@".\TestArtifacts\{0}", fileName); if (!File.Exists(filePath)) { filePath = string.Format(@".\{0}", fileName); Console.WriteLine(string.Format(@"File not Found: .\TestArtifacts\{0}", fileName)); } try { using (FileStream inputFile = File.OpenRead(filePath)) { var optionalHeaderDataDirectories = ScenarioContext.Current.Get <OptionalHeaderDataDirectories>("OptionalHeaderDataDirectories"); var sectionTables = ScenarioContext.Current.Get <List <SectionTable> >("SectionTables"); inputFile.Position = DebugDirectory.StartingPosition(optionalHeaderDataDirectories, sectionTables); DebugDirectory?debugDirectory = inputFile.ReadStructure <DebugDirectory>(); ScenarioContext.Current.Add("DebugDirectory", debugDirectory.Value); } } catch { ScenarioContext.Current.Add("DebugDirectory", new DebugDirectory { }); } }
public async Task <DataContent> GetContentAsync() { if (VirtualAddress == 0 || Size == 0) { return(null); } switch (DirectoryType) { case DataDirectoryType.LoadConfigTable: return(await LoadConfigurationDirectory.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.TLSTable: return(await TLSDirectory.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.CertificateTable: return(await Certificate.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.CLRRuntimeHeader: return(await CLR.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.Debug: return(await DebugDirectory.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.BaseRelocationTable: return(await RelocationTable.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.ExportTable: return(await ExportDirectory.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.ImportTable: return(await ImportDirectory.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.DelayImportDescriptor: return(await DelayedImportDirectory.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.ExceptionTable: return(await ExceptionTable.GetAsync(_image).ConfigureAwait(false)); case DataDirectoryType.ResourceTable: return(await ResourceDirectory.GetAsync(_image).ConfigureAwait(false)); default: { var calc = _image.GetCalculator(); var fileOffset = calc.RVAToOffset(VirtualAddress); var va = _imageBase + VirtualAddress; var location = new Location(_image, fileOffset, VirtualAddress, va, Size, Size); return(new DataContent(_image, this, location)); } } }
/// <summary>Extract PDB file identity from the given exe file.</summary> /// <param name="exeFile"></param> /// <returns>The PDB file name or a null reference if no PDB related information /// has been found in the exe file.</returns> public static string GetPdbFileInfoFromExe(FileInfo exeFile, out Guid id, out uint age) { if (null == exeFile) { throw new ArgumentNullException(); } if (!exeFile.Exists) { throw new FileNotFoundException(); } using (LoadedImage exeModule = new LoadedImage(exeFile)) { IDataDirectory debugDataDirectory = exeModule.NTHeader[DataDirectoryKind.DebuggingInformation]; if (null != debugDataDirectory) { IntPtr nativeDebugData = exeModule.MapRva(debugDataDirectory.RelativeVirtualAddress); int debugDataDirectoryOffset = 0; while (debugDataDirectoryOffset < debugDataDirectory.Size) { IDebugDirectory candidate = new DebugDirectory(nativeDebugData, ref debugDataDirectoryOffset); if (DebugInformationType.Codeview != candidate.Type) { continue; } // Based on undocumented CV_INFO_PDB70 structure. IntPtr cvRawData = exeModule.MapRva(candidate.AddressOfRawData); int rawDataOffset = 0; uint cvSignature = ImageHelpers.ReadUint32(cvRawData, ref rawDataOffset); if (Constants.RSDSSignature != cvSignature) { continue; } id = new Guid(ImageHelpers.ReadBytes(cvRawData, 16, ref rawDataOffset)); age = ImageHelpers.ReadUint32(cvRawData, ref rawDataOffset); return(Marshal.PtrToStringAnsi(cvRawData + rawDataOffset)); // CV_INFO_PDB70, *PCV_INFO_PDB70; } } } // Not found. Return default values. id = Guid.Empty; age = 0; return(null); } }
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; }
/// <summary> /// Reads the code view debug data from the specified set of debug directories. /// </summary> /// <param name="debugDirectories">The set of debug directories.</param> /// <param name="endAddress">End Address of the image.</param> /// <returns>The code view if found, null otherwise.</returns> private CodeViewDebugData GetCodeViewDebugData(DebugDirectory[] debugDirectories, IntPtr endAddress) { foreach (DebugDirectory debugDirectory in debugDirectories) { if (debugDirectory.Type != ImageDebugType.CodeView) { continue; } if (debugDirectory.SizeOfData > 1000) { return null; } BinaryReader reader = this.ReadAtRelativeVirtualAddress((int)debugDirectory.AddressOfRawData, (int)debugDirectory.SizeOfData); int signature = reader.ReadInt32(); if (signature != PEImageReader.CodeViewSignature) { return null; } CodeViewDebugData codeView = new CodeViewDebugData( new Guid(reader.ReadBytes(16)), (int)reader.ReadUInt32(), this.ReadNullTerminatedUTF8String(reader), endAddress); return codeView; } return null; }
/// <summary> /// Reads all directory entries from the passed in debug directory entry. /// </summary> /// <param name="debugDirectoryEntry">The debug directory entry.</param> /// <returns>The parsed debug directory entries.</returns> private DebugDirectory[] ReadDebugDirectories(DirectoryEntry debugDirectoryEntry) { // there might not be a debug directory, in which case return an empty list if (debugDirectoryEntry.RelativeVirtualAddress == 0) { return new DebugDirectory[0]; } BinaryReader reader = this.ReadAtRelativeVirtualAddress(debugDirectoryEntry.RelativeVirtualAddress, debugDirectoryEntry.Size); int countDirectories = (int)(debugDirectoryEntry.Size / PEImageReader.SizeofDebugDirectory); DebugDirectory[] debugDirectories = new DebugDirectory[countDirectories]; for (int i = 0; i < countDirectories; i++) { debugDirectories[i] = new DebugDirectory(); debugDirectories[i].Characteristics = reader.ReadUInt32(); debugDirectories[i].TimeDateStamp = reader.ReadUInt32(); debugDirectories[i].MajorVersion = reader.ReadUInt16(); debugDirectories[i].MinorVersion = reader.ReadUInt16(); debugDirectories[i].Type = (ImageDebugType)reader.ReadUInt32(); debugDirectories[i].SizeOfData = reader.ReadUInt32(); debugDirectories[i].AddressOfRawData = reader.ReadUInt32(); debugDirectories[i].PointerToRawData = reader.ReadUInt32(); } return debugDirectories; }