private void AppendRelocationSection(UnmanagedDataReader s, DataSectionDescription relocationSection) { uint delta; uint offset = GetVirtualRelativeAddress(relocationSection.VirtualAddress, out delta); ReaderWithOffsetArgs arg; RelocationSection section; if (offset == 0) { return; } // read the info: s.Jump(offset); // add all sections: section = new RelocationSection(); arg = new ReaderWithOffsetArgs(s, offset, delta, section); while (Append <RelocationSection.ImageBaseRelocation, WindowsPortableExecutable, ReaderWithOffsetArgs> (s, this, arg)) { } // append relocation section when any data was read from file: if (section.Count > 0) { section.UpdateFileInfo(RelocationSection.DefaultName, offset, s.CurrentOffset - offset); section.UpdateVirtualInfo(offset, s.CurrentOffset - offset); Add(section); } }
/// <summary> /// Init constructor of ReaderWithOffset. /// </summary> public ReaderWithOffsetArgs(UnmanagedDataReader source, uint offset, uint delta, object tag) { this.source = source; this.offset = offset; this.delta = delta; this.tag = tag; }
bool IBinaryAppender <RelocationSection.ImageBaseRelocation, ReaderWithOffsetArgs> .Attach(ref RelocationSection.ImageBaseRelocation s, uint size, ReaderWithOffsetArgs arg) { UnmanagedDataReader r = arg.Source; RelocationSection section = arg.Tag as RelocationSection; RelocationDescription desc; ushort data = 0; RelocationType type; uint count; uint offset; // validate input data: if (s.SizeOfBlock == 0 || s.VirtualAddress == 0 || section == null) { return(false); } // append data to section: count = (s.SizeOfBlock - (uint)Marshal.SizeOf(typeof(RelocationSection.ImageBaseRelocation))) / (uint)Marshal.SizeOf(typeof(ushort)); if (count > 0) { desc = new RelocationDescription(s.VirtualAddress, s.SizeOfBlock); for (uint i = 0; i < count; i++) { if (r.Read(ref data)) { type = (RelocationType)((data & 0xF000) >> 12); offset = (uint)(data & 0x0FFF); if (type == RelocationType.BasedHighAdjust) { if (r.Read(ref data)) { offset += ((uint)data) << 12; count--; } } desc.Add(new RelocationItem(type, offset)); } else { break; } } // if data is defined inside the given description: if (desc.Count > 0) { section.Add(desc); } } return(true); }
/// <summary> /// Extracts info about Import section. /// </summary> private void AppendImportSection(UnmanagedDataReader s, DataSectionDescription importSection, DataSectionDescription importBoundSection, NtHeaderSection ntSection) { ImportFunctionSection ifs = new ImportFunctionSection(); uint delta; uint offset = GetVirtualRelativeAddress(importSection.VirtualAddress, out delta); if (offset == 0 || ntSection == null) { return; } // analize data inside given section: ReaderWithOffsetArgs arg = new ReaderWithOffsetArgs(s, offset, delta, ifs); // read the info: s.Jump(offset); while (Append <ImportFunctionModule.ImageImportDescriptor, WindowsPortableExecutable, ReaderWithOffsetArgs> (s, this, arg)) { // store the current location: offset = s.CurrentOffset; // read functions assigned to given module: if (ntSection.MachineType == MachineType.Intel_x86) { ReadImportData <ImportFunctionModule.ImageImportData32, WindowsPortableExecutable>(s, arg.Tag as ImportFunctionModule); } else if (ntSection.MachineType == MachineType.Intel_x64) { ReadImportData <ImportFunctionModule.ImageImportData64, WindowsPortableExecutable>(s, arg.Tag as ImportFunctionModule); } // restore the offset: s.Jump(offset); arg.Tag = ifs; } // check if there is additional bound-import infor available and read it: if (importBoundSection != null) { ReaderWithOffsetArgs iArg = new ReaderWithOffsetArgs(s, importBoundSection.VirtualAddress, 0, ifs); s.Jump(importBoundSection.VirtualAddress); while (Append <ImportFunctionModule.ImageBoundImportDescription, WindowsPortableExecutable, ReaderWithOffsetArgs>(s, this, iArg)) { } } // if import section was correctly filled by at least one element then store it: if (ifs.Count > 0) { ifs.UpdateFileInfo(ImportFunctionSection.DefaultName, offset, s.LastReadSize * (uint)ifs.Count); ifs.UpdateVirtualInfo(importSection.VirtualAddress, importSection.Size); Add(ifs); } }
/// <summary> /// Loads proper binary sections based on given source. /// </summary> protected override void Load(UnmanagedDataReader s, BinaryLoadArgs e) { WindowsPortableExecutableLoadArgs a = e as WindowsPortableExecutableLoadArgs ?? new WindowsPortableExecutableLoadArgs(); ///////////////////////////////////////// // detect file type: // is it a .lib file? string text = s.ReadStringAnsiAt(0, LibHeaderNameLength); if (text == LibHeaderName) { LoadLibBinary(s, a); } // read MS-DOS compatible header and based on that // try to detect values of the fields correct for specific formats: DosHeaderSection dosSection = Read <DosHeaderSection.ImageDosHeader, DosHeaderSection>(s, false); if (dosSection == null) { return; } // load data as exe/dll binary: if (dosSection.IsExecutable) { Add(dosSection); // jump to new NT header: if (s.Jump(dosSection.NtHeaderAddress) == uint.MaxValue) { return; } LoadExeBinary(s, a); return; } // load debug file: if (dosSection.IsDebugBinary) { s.UndoRead(); LoadDbgBinary(s, a); return; } // load data as object binary: if (dosSection.IsObjectBinary) { s.UndoRead(); LoadObjBinary(s, a); return; } }
private void AppendResourceSection(UnmanagedDataReader s, DataSectionDescription resourceSection) { uint delta; uint offset = GetVirtualRelativeAddress(resourceSection.VirtualAddress, out delta); if (offset == 0) { return; } }
/// <summary> /// Load section descriptions from given file. /// </summary> public void Load(string fileName, BinaryLoadArgs e) { fullPath = Path.GetFullPath(fileName); name = Path.GetFileName(fileName); if (File.Exists(fullPath)) { if (e == null || e.UseMapping) { // create readers: UnmanagedDataReader s; FileSharedMemory fs = null; try { fs = new FileSharedMemory(fullPath, (e == null || e.IsReadOnlyMode ? SharedMemory.AccessTypes.ReadOnly : SharedMemory.AccessTypes.ReadWrite)); s = new UnmanagedDataReader(fs.Address, fs.Size); // and parse the file: Load(s, e); } finally { if (fs != null) { fs.Close(); } } } else { // read brutally the whole file into memory and parse: byte[] x = File.ReadAllBytes(fullPath); // check if not empty: if (x.Length > 0) { IntPtr p = Marshal.AllocHGlobal(x.Length); if (p != IntPtr.Zero) { Marshal.Copy(x, 0, p, x.Length); Load(new UnmanagedDataReader(p, (uint)x.Length), e); Marshal.FreeHGlobal(p); } } } } }
/// <summary> /// Reads given structure and appends info to given section. /// </summary> protected static bool Append <T, S, Z>(UnmanagedDataReader source, S section, Z arg) where T : struct where S : class, IBinaryAppender <T, Z> { T headerElement = new T(); // load native type: if (section != null && source.Read(ref headerElement)) { return(section.Attach(ref headerElement, source.LastReadSize, arg)); } // return failure: return(false); }
/// <summary> /// Extracts info about Export section. /// </summary> private void AppendExportSection(UnmanagedDataReader s, DataSectionDescription exportSection) { uint delta; uint offset = GetVirtualRelativeAddress(exportSection.VirtualAddress, out delta); if (offset == 0) { return; } // read the info: s.Jump(offset); Append <ExportFunctionSection.ImageExportDirectory, WindowsPortableExecutable, ReaderWithOffsetArgs> (s, this, new ReaderWithOffsetArgs(s, offset, delta, exportSection)); }
/// <summary> /// Attaches 64-bit specific info about imported functions. /// </summary> private bool AttachImportData(ref ImportFunctionModule.ImageImportData64 r, UnmanagedDataReader s, uint delta, ImportFunctionModule m) { if (m == null) { return(false); } // check if there is any data attached: if (r.OrdinalOrAddressOfData == 0) { return(false); } if (r.IsOrdinal) { ImportFunctionModule.ImageImportData64 thunk = new ImportFunctionModule.ImageImportData64(); if (s.ReadAt(ref thunk, m.FirstThunk - delta)) { m.Add(new ImportFunctionDescription(r.Ordinal, m.IsBinded ? thunk.OrdinalOrAddressOfData : 0)); } } else { ImportFunctionModule.ImageImportByName funName = new ImportFunctionModule.ImageImportByName(); ImportFunctionModule.ImageImportData64 thunk = new ImportFunctionModule.ImageImportData64(); if (s.ReadAt(ref thunk, m.FirstThunk - delta)) { if (s.ReadAt(ref funName, (uint)r.OrdinalOrAddressOfData - delta)) { m.Add(new ImportFunctionDescription( s.ReadStringAnsiAt((uint)r.OrdinalOrAddressOfData - delta + sizeof(short)), m.IsBinded ? thunk.OrdinalOrAddressOfData : 0, (uint)funName.Hint)); } } } return(true); }
/// <summary> /// Reads detailed data of imported elements. /// </summary> private void ReadImportData <T, S>(UnmanagedDataReader s, ImportFunctionModule m) where T : struct where S : class, IBinaryAppender <T, ReaderWithOffsetArgs> { if (m != null) { uint xDelta; uint xOffset = GetVirtualRelativeAddress(m.NextModuleAddress, out xDelta); if (xOffset != 0) { s.Jump(xOffset); while (Append <T, S, ReaderWithOffsetArgs> (s, this as S, new ReaderWithOffsetArgs(s, xOffset, xDelta, m))) { m.FirstThunk += s.LastReadSize; } } } }
/// <summary> /// Reads given structure from specified source. /// </summary> protected S Read <T, S>(UnmanagedDataReader source, bool canStore) where T : struct where S : BinarySection, IBinaryConverter <T>, new() { T headerNativeType = new T(); // load native data: if (source.Read(ref headerNativeType)) { S section = new S(); if (section.Convert(ref headerNativeType, source.LastReadStartOffset, source.LastReadSize)) { if (canStore) { Add(section); } return(section); } } // return failure in reading: return(null); }
/// <summary> /// Loads proper binary sections based on given source. /// </summary> protected abstract void Load(UnmanagedDataReader s, BinaryLoadArgs e);
/// <summary> /// Reads given structure from specified source. /// </summary> protected S Read <T, S>(UnmanagedDataReader source) where T : struct where S : BinarySection, IBinaryConverter <T>, new() { return(Read <T, S>(source, true)); }
/// <summary> /// Loads binary as Visual Studio C++ .lib file. /// </summary> private void LoadLibBinary(UnmanagedDataReader s, WindowsPortableExecutableLoadArgs e) { }
/// <summary> /// Loads a binary data as a Windows COFF Portable Executable. /// </summary> private void LoadExeBinary(UnmanagedDataReader s, WindowsPortableExecutableLoadArgs e) { NtHeaderSection ntSection; NtOptionalHeaderSection ntOptionalSection; DataHeaderSection dataSection; // read Win NT compatible header: ntSection = Read <NtHeaderSection.ImageNtHeader, NtHeaderSection>(s); if (ntSection == null) { return; } // detect the type of optional header: ushort magicNumber = 0; if (!s.Read(ref magicNumber)) { return; } // undo the last read: s.UndoRead(); // now parse the corresponding sections: if (magicNumber == NtOptionalHeaderSection.OptionalHeader32Magic) { ntOptionalSection = Read <NtOptionalHeaderSection.ImageOptionalHeader32, NtOptionalHeaderSection>(s); } else if (magicNumber == NtOptionalHeaderSection.OptionalHeader64Magic) { ntOptionalSection = Read <NtOptionalHeaderSection.ImageOptionalHeader64, NtOptionalHeaderSection>(s); } else { ntOptionalSection = Read <NtOptionalHeaderSection.ImageOptionalHeaderROM, NtOptionalHeaderSection>(s); } // and read specified number of other section locations: if (ntOptionalSection != null) { for (uint i = 0; i < ntOptionalSection.DataDirectoryCount; i++) { if (!Append <DataSectionDescription.ImageDataDirectory, WindowsPortableExecutable, DirectoryEntry> (s, this, (DirectoryEntry)i)) { return; } } } // read data sections: for (uint i = 0; i < ntSection.DataSectionCount; i++) { dataSection = Read <DataHeaderSection.ImageSectionHeader, DataHeaderSection>(s); if (dataSection == null) { break; } dataSections.Add(dataSection); } if (knownSections != null) { if (e.LoadExports) { // add export information section: DataSectionDescription exportSection; if (knownSections.TryGetValue(DirectoryEntry.Export, out exportSection)) { AppendExportSection(s, exportSection); } } if (e.LoadImports) { // add import information section: DataSectionDescription importSection; DataSectionDescription importBoundSection; if (knownSections.TryGetValue(DirectoryEntry.Import, out importSection)) { knownSections.TryGetValue(DirectoryEntry.BoundImport, out importBoundSection); AppendImportSection(s, importSection, importBoundSection, ntSection); } } if (e.LoadResources) { // add resources information section: DataSectionDescription resourceSection; if (knownSections.TryGetValue(DirectoryEntry.Resource, out resourceSection)) { AppendResourceSection(s, resourceSection); } } if (e.LoadBaseRelocations) { // add relocation information section: DataSectionDescription relocationSection; if (knownSections.TryGetValue(DirectoryEntry.BaseRelocationTable, out relocationSection)) { AppendRelocationSection(s, relocationSection); } } } // remove temporary data: knownSections = null; dataSections = null; }