diff --git a/EatPdb/PEAction.cs b/EatPdb/PEAction.cs index 9a88b77..2f4cb7f 100644 --- a/EatPdb/PEAction.cs +++ b/EatPdb/PEAction.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; -using System.Text; namespace EatPdb { + internal class PEAction : IDisposable { private readonly FileStream File; private readonly DataDir[] Dirs; @@ -89,4 +89,4 @@ internal IEnumerable GetImportSymbols() { public void Dispose() => Reader.Dispose(); } -} +} \ No newline at end of file diff --git a/EatPdb/Program.cs b/EatPdb/Program.cs index 8e8b836..3baec56 100644 --- a/EatPdb/Program.cs +++ b/EatPdb/Program.cs @@ -8,25 +8,35 @@ using System.Runtime.InteropServices; namespace EatPdb { - class Program { + + internal class Program { + public class Options { + [Option('i', "Input", Required = true, HelpText = "Input File")] public string InputFile { get; set; } + [Option('p', "Pdb", HelpText = "Pdb File")] public string PdbFile { get; set; } + [Option('o', "Ouput", Required = true, HelpText = "Output File")] public string OuputFile { get; set; } + [Option("DllName", HelpText = "DllName")] public string DllName { get; set; } + [Option('d', "Definition", HelpText = "Module-Definition file")] public string Definition { get; set; } + [Option('v', "Verbose", Default = false, HelpText = "Verbose Output")] public bool Verbose { get; set; } } - static void Main(string[] args) => Parser.Default.ParseArguments(args) + + private static void Main(string[] args) => Parser.Default.ParseArguments(args) .WithParsed(RealMain); private static uint GetAlign(uint length, uint align = 512) => length % align == 0 ? length : (length / align + 1) * align; + private static void RealMain(Options options) { try { if (options.PdbFile == null) @@ -141,4 +151,4 @@ private static void RealMain(Options options) { } } } -} +} \ No newline at end of file diff --git a/EatPdb/SymbolDatabase.cs b/EatPdb/SymbolDatabase.cs index f793ac0..048b5f2 100644 --- a/EatPdb/SymbolDatabase.cs +++ b/EatPdb/SymbolDatabase.cs @@ -4,9 +4,11 @@ using System.Linq; namespace EatPdb { + internal class SymbolDatabase : IEnumerable>> { private readonly SortedDictionary> fullmap = new SortedDictionary>(); private readonly SortedDictionary revmap = new SortedDictionary(); + public void Add(uint RVA, string name) { if (fullmap.TryGetValue(RVA, out var set)) set.Add(name); @@ -44,4 +46,4 @@ public KeyValuePair[] Build() { return ret.ToArray(); } } -} +} \ No newline at end of file diff --git a/PEReader/Program.cs b/PEReader/Program.cs index 8a49351..d092163 100644 --- a/PEReader/Program.cs +++ b/PEReader/Program.cs @@ -1,16 +1,21 @@ using CommandLine; +using PESupport; using System; using System.IO; -using PESupport; namespace PEReader { - class Program { + + internal class Program { + public class Options { + [Option('i', "Input", Required = true, HelpText = "Input File")] public string InputFile { get; set; } } - static void Main(string[] args) => Parser.Default.ParseArguments(args) + + private static void Main(string[] args) => Parser.Default.ParseArguments(args) .WithParsed(RealMain); + private static readonly string[] DataDirName = new string[]{ "Export", "Import", @@ -29,6 +34,7 @@ static void Main(string[] args) => Parser.Default.ParseArguments(args) "COMRuntimedescriptor", "Reserved", }; + private static void RealMain(Options options) { try { using var file = File.OpenRead(options.InputFile); @@ -113,7 +119,7 @@ private static void RealMain(Options options) { if (thunk.TryGetOrdinal(out var ord)) { Console.WriteLine("#{0}", ord); } else { - file.SeekRVA(resolver, (uint)thunk.Value); + file.SeekRVA(resolver, (uint) thunk.Value); var hint = reader.ReadStruct().Hint; Console.WriteLine("\t{0:X4}:{1}", hint, reader.ReadByteString()); } @@ -125,4 +131,4 @@ private static void RealMain(Options options) { } } } -} +} \ No newline at end of file diff --git a/PESupport/AddressResolver.cs b/PESupport/AddressResolver.cs index 7715857..f1372c8 100644 --- a/PESupport/AddressResolver.cs +++ b/PESupport/AddressResolver.cs @@ -2,16 +2,21 @@ using System.Collections.Generic; namespace PESupport { + public class AddressResolver { private readonly List Sections; [Serializable] private class AddressNotFoundException : Exception { - public AddressNotFoundException(uint RVA) : base(string.Format("RVA {0} not mapped in this PE file", RVA)) { } + + public AddressNotFoundException(uint RVA) : base(string.Format("RVA {0} not mapped in this PE file", RVA)) { + } } public AddressResolver(uint number) => Sections = new List(); + public void Put(SectionHeader header) => Sections.Add(header); + public SectionHeader GetSection(uint RVA) { foreach (var secheader in Sections) { if (secheader.VirtualAddress <= RVA && secheader.VirtualAddress + secheader.Misc.VirtualSize > RVA) { @@ -20,6 +25,7 @@ public SectionHeader GetSection(uint RVA) { } throw new AddressNotFoundException(RVA); } + public uint Resolve(uint RVA) { foreach (var secheader in Sections) { if (secheader.VirtualAddress <= RVA && secheader.VirtualAddress + secheader.Misc.VirtualSize > RVA) { @@ -28,6 +34,7 @@ public uint Resolve(uint RVA) { } throw new AddressNotFoundException(RVA); } + public uint RevResolve(uint FOA) { foreach (var secheader in Sections) { if (secheader.PointerToRawData <= FOA && secheader.Misc.VirtualSize > FOA) { @@ -37,4 +44,4 @@ public uint RevResolve(uint FOA) { throw new AddressNotFoundException(FOA); } } -} +} \ No newline at end of file diff --git a/PESupport/BinaryEx.cs b/PESupport/BinaryEx.cs index 7ffe2c3..19cadb7 100644 --- a/PESupport/BinaryEx.cs +++ b/PESupport/BinaryEx.cs @@ -2,7 +2,9 @@ using System.Text; namespace PESupport { + public static class BinaryEx { + public static string ReadByteString(this BinaryReader reader) { var builder = new StringBuilder(); while (true) { @@ -13,12 +15,15 @@ public static string ReadByteString(this BinaryReader reader) { } return builder.ToString(); } + public static void WriteByteString(this BinaryWriter writer, string data) { var bytes = Encoding.ASCII.GetBytes(data); writer.Write(bytes); writer.Write((byte) 0); } + public static T ReadStruct(this BinaryReader reader) where T : unmanaged => StructOP.Read(reader); + public static void WriteStruct(this BinaryWriter reader, T input) where T : unmanaged => StructOP.Write(input, reader); } -} +} \ No newline at end of file diff --git a/PESupport/FileEx.cs b/PESupport/FileEx.cs index 15ffbf8..811b319 100644 --- a/PESupport/FileEx.cs +++ b/PESupport/FileEx.cs @@ -1,7 +1,9 @@ using System.IO; namespace PESupport { + public static class FileEx { + public static void SeekRVA(this FileStream file, AddressResolver resolver, uint RVA) => file.Seek(resolver.Resolve(RVA), SeekOrigin.Begin); } -} +} \ No newline at end of file diff --git a/PESupport/PESupport.cs b/PESupport/PESupport.cs index 6fe2a70..599e4f3 100644 --- a/PESupport/PESupport.cs +++ b/PESupport/PESupport.cs @@ -34,6 +34,7 @@ public struct NtHeader { public OptionalHeader OptionalHeader; public bool CheckHealth() => Signature == 0x4550 && FileHeader.Machine == 0x8664 && OptionalHeader.Magic == 0x20B; + public void AssertHealth() { if (!CheckHealth()) throw new NotSupportedException("x86_64 PE file expected"); @@ -126,8 +127,10 @@ public unsafe void SetName(string name) { [StructLayout(LayoutKind.Explicit)] public unsafe struct SectionHeaderMisc { + [FieldOffset(0)] public uint PhysicalAddress; + [FieldOffset(0)] public uint VirtualSize; } @@ -171,6 +174,7 @@ public struct ImportDirThunk { public ulong Value; public bool IsEmpty() => Value == 0; + public bool TryGetOrdinal(out uint ordinal) { if ((Value & 0x8000000000000000) != 0) { ordinal = (uint) Value; @@ -185,4 +189,4 @@ public bool TryGetOrdinal(out uint ordinal) { public struct ImportDirThunkHint { public ushort Hint; } -} +} \ No newline at end of file diff --git a/PESupport/StructOP.cs b/PESupport/StructOP.cs index f1a5caa..3604c5c 100644 --- a/PESupport/StructOP.cs +++ b/PESupport/StructOP.cs @@ -2,8 +2,10 @@ using System.Runtime.InteropServices; namespace PESupport { + internal static class StructOP where T : unmanaged { private static readonly int Size = Marshal.SizeOf(); + public static unsafe T Read(BinaryReader reader) { T val; var ptr = (byte*) &val; @@ -11,10 +13,11 @@ public static unsafe T Read(BinaryReader reader) { *ptr++ = reader.ReadByte(); return val; } + public static unsafe void Write(T input, BinaryWriter writer) { var ptr = (byte*) &input; for (uint i = 0; i < Size; i++) writer.Write(*ptr++); } } -} +} \ No newline at end of file diff --git a/PdbReader/Program.cs b/PdbReader/Program.cs index feb9abd..103294e 100644 --- a/PdbReader/Program.cs +++ b/PdbReader/Program.cs @@ -1,27 +1,36 @@ -using System; -using System.Linq; +using CommandLine; using SharpPdb.Native; -using CommandLine; +using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Linq; namespace PdbReader { - class Program { + + internal class Program { + public class Options { + [Option('v', "Verbose", Default = false, HelpText = "Verbose output")] public bool Verbose { get; set; } + [Option('d', "Demangle", Default = false, HelpText = "Demangle function name")] public bool Demangle { get; set; } + [Option('i', "Input", Required = true, HelpText = "Input File")] public string InputFile { get; set; } } - static void Main(string[] args) => Parser.Default.ParseArguments(args) + + private static void Main(string[] args) => Parser.Default.ParseArguments(args) .WithParsed(RealMain); private class SymbolEqualityComparer : IEqualityComparer { + public bool Equals([AllowNull] PdbPublicSymbol x, [AllowNull] PdbPublicSymbol y) => x.RelativeVirtualAddress == y.RelativeVirtualAddress; + public int GetHashCode([DisallowNull] PdbPublicSymbol obj) => obj.RelativeVirtualAddress.GetHashCode(); } + private static void RealMain(Options options) { try { using var reader = new PdbFileReader(options.InputFile); @@ -40,4 +49,4 @@ private static void RealMain(Options options) { } } } -} +} \ No newline at end of file