Ejemplo n.º 1
0
        private static void RealMain(Options options)
        {
            try {
                using var reader = new PdbFileReader(options.InputFile);
                if (options.Verbose)
                {
                    foreach (var item in from item in reader.PublicSymbols where !item.Name.StartsWith("_") orderby item.RelativeVirtualAddress select item)
                    {
                        Console.WriteLine("{0}:{1:X8} {2}", item.Segment, item.RelativeVirtualAddress, options.Demangle ? item.GetUndecoratedName() : item.Name);
                    }
                }
                else
                {
                    var syms = from item in reader.PublicSymbols
                               where !item.Name.StartsWith("_")
                               select item;
                    Console.WriteLine("Symbol FullCount: {0}", syms.Count());
                    Console.WriteLine("Symbol DistinctCount: {0}", syms.Distinct(new SymbolEqualityComparer()).Count());

                    var functions = reader.Functions;
                    Console.WriteLine("Functions FullCount: {0}", functions.Count());
                }
            } catch (Exception e) {
                Console.WriteLine(e.ToString());
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbPointerType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 /// <param name="elementType">PDB type of object pointed to.</param>
 /// <param name="size">The type size in bytes.</param>
 /// <param name="isLValueReference"><c>true</c> if pointer is L-value reference</param>
 /// <param name="isRValueReference"><c>true</c> if pointer is R-value reference</param>
 internal PdbPointerType(PdbFileReader pdb, TypeIndex typeIndex, ModifierOptions modifierOptions, TypeIndex elementType, ulong size, bool isLValueReference, bool isRValueReference)
     : base(pdb, typeIndex, modifierOptions, pdb[elementType].Name + "*", size)
 {
     ElementType       = pdb[elementType];
     IsLValueReference = isLValueReference;
     IsRValueReference = isRValueReference;
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="tagRecord">The tag record.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 /// <param name="size">The type size in bytes.</param>
 internal PdbUserDefinedType(PdbFileReader pdb, TypeIndex typeIndex, TagRecord tagRecord, ModifierOptions modifierOptions, ulong size)
     : base(pdb, typeIndex, modifierOptions, tagRecord.Name.String, size)
 {
     TagRecord               = tagRecord;
     fieldsCache             = SimpleCache.CreateWithContext(this, CallEnumerateFields);
     staticFieldsCache       = SimpleCache.CreateWithContext(this, CallEnumerateStaticFields);
     baseClassesCache        = SimpleCache.CreateWithContext(this, CallEnumerateBaseClasses);
     virtualBaseClassesCache = SimpleCache.CreateWithContext(this, CallEnumerateVirtualBaseClasses);
 }
Ejemplo n.º 4
0
        public BookFile Read(string filepath)
        {
            BookFile mobi = null;

            var reader = new PdbFileReader(filepath);

            mobi          = reader.ReadMobiFile();
            mobi.FilePath = filepath;

            return(mobi);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Gets the type name from array record.
        /// </summary>
        /// <param name="pdb">The PDB file reader.</param>
        /// <param name="arrayRecord">The array record.</param>
        private static string GetTypeName(PdbFileReader pdb, ArrayRecord arrayRecord)
        {
            PdbType elementType = pdb[arrayRecord.ElementType];

            if (elementType.Size == 0)
            {
                return($"{elementType.Name}[]");
            }

            ulong elements = arrayRecord.Size / elementType.Size;

            return($"{elementType.Name}[{elements}]");
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbSimpleType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 internal PdbSimpleType(PdbFileReader pdb, TypeIndex typeIndex, ModifierOptions modifierOptions)
     : base(pdb, typeIndex, modifierOptions, typeIndex.SimpleTypeName, GetSize(typeIndex))
 {
 }
Ejemplo n.º 7
0
        private static void RealMain(Config config, bool verbose)
        {
            // Copy input file to output file, so we do not need to touch input file again
            File.Copy(config.InputFile, config.OutputFile, true);
            using var file   = File.Open(config.OutputFile, FileMode.Open, FileAccess.ReadWrite);
            using var exp    = File.CreateText(config.DefFile);
            using var action = new PEAction(file);
            using var pdb    = new PdbFileReader(config.PdbFile);
            using var db     = new SQLiteConnection("" + new SQLiteConnectionStringBuilder
            {
                DataSource    = config.FilterOutDatabase,
                SyncMode      = SynchronizationModes.Off,
                NoSharedFlags = true,
                FailIfMissing = false
            });
            db.Open();
            var filterout = new SortedDictionary <string, uint>(StringComparer.Ordinal);
            var symdb     = new SymbolDatabase();

            Console.WriteLine("filtering ({0})", pdb.PublicSymbols.Length);

            // Collect all symbols
            Parallel.ForEach(pdb.PublicSymbols, (item) => {
                if (config.Filter?.Filter(item.IsCode, item.Name) ?? true)
                {
                    lock (symdb) { symdb.Add((uint)item.RelativeVirtualAddress, item.Name); }
                }
                else
                {
                    lock (filterout) { filterout.Add(item.Name, (uint)item.RelativeVirtualAddress); }
                }
            });

            Console.WriteLine("symbols collected: {0}, filtered: {1}", symdb.Count(), filterout.Count());

            // Exclude imported symbols
            foreach (var sym in action.GetImportSymbols())
            {
                if (symdb.RemoveName(sym) && verbose)
                {
                    Console.WriteLine("Removed {0}", sym);
                }
                else if (filterout.Remove(sym) && verbose)
                {
                    Console.WriteLine("Removed {0} (filtered)", sym);
                }
            }

            Console.WriteLine("symbols fixed: {0}, filtered fixed: {1}", symdb.Count(), filterout.Count());

            // Write to filter out db
            using (var transition = db.BeginTransaction()) {
                using (var dropCommand = db.CreateCommand()) {
                    dropCommand.CommandText = "DROP TABLE IF EXISTS symbols";
                    dropCommand.Transaction = transition;
                    dropCommand.ExecuteNonQuery();
                }
                using (var createCommand = db.CreateCommand()) {
                    createCommand.CommandText = "CREATE TABLE symbols(symbol TEXT PRIMARY KEY, rva INTEGER) WITHOUT ROWID";
                    createCommand.Transaction = transition;
                    createCommand.ExecuteNonQuery();
                }
                using (var insertCommand = db.CreateCommand()) {
                    insertCommand.CommandText = "INSERT INTO symbols VALUES ($symbol, $rva)";
                    insertCommand.Transaction = transition;
                    foreach (var item in filterout)
                    {
                        insertCommand.Parameters.AddWithValue("$symbol", item.Key);
                        insertCommand.Parameters.AddWithValue("$rva", item.Value);
                        insertCommand.ExecuteNonQuery();
                        insertCommand.Parameters.Clear();
                        insertCommand.Reset();
                    }
                }
                transition.Commit();
            }

            // Build cache
            var cache  = symdb.ToArray();
            var sorted = symdb.Build();

            // Print exported symbols
            exp.Write("LIBRARY " + config.DllName + "\n");
            exp.Write("EXPORTS\n");
            foreach (var(name, idx) in sorted)
            {
                exp.Write(string.Format("\t{0}\n", name));
            }

            Console.WriteLine("starting rebuild PE file");

            // Calculate append length
            uint length            = 0;
            var  expdirlength      = (uint)Marshal.SizeOf <ExportDir>();
            var  dllnamelength     = (uint)(config.DllName.Length + 1);
            var  NumberOfFunctions = (uint)cache.Count();
            var  functionslength   = NumberOfFunctions * 4;
            var  NumberOfNames     = (uint)cache.Select(item => item.Value.Count).Aggregate(0, (a, b) => a + b);
            var  ordinalslength    = NumberOfNames * 2;
            var  nameslength       = NumberOfNames * 4;
            var  stringslength     = (uint)sorted.Select(kv => kv.Key.Length + 1).Aggregate(0, (a, b) => a + b);

            Console.WriteLine("NumberOfFunctions: {0}", NumberOfFunctions);
            Console.WriteLine("NumberOfNames: {0}", NumberOfNames);
            Console.WriteLine("Length Of ExportDir: {0}", expdirlength);
            Console.WriteLine("Length Of DllName: {0}", dllnamelength);
            Console.WriteLine("Length Of Functions: {0}", functionslength);
            Console.WriteLine("Length Of Ordinals: {0}", ordinalslength);
            Console.WriteLine("Length Of Names: {0}", nameslength);
            Console.WriteLine("Length Of Strings: {0}", stringslength);
            length = expdirlength + dllnamelength + functionslength + ordinalslength + nameslength + stringslength;
            Console.WriteLine("Addition length: {0}", length);

            // Start modify header
            var VirtualEnd   = action.GetEnding();
            var OriginalSize = (uint)file.Length;

            action.PatchNtHeader(GetAlign(length));
            action.PatchDir(0, VirtualEnd, length);
            {
                var header = new SectionHeader {
                };
                header.SetName(".hacked");
                header.Misc.VirtualSize = length;
                header.VirtualAddress   = VirtualEnd;
                header.SizeOfRawData    = GetAlign(length);
                header.PointerToRawData = OriginalSize;
                header.Characteristics  = 0x40000040;
                action.AppendSection(header);
            }

            // Write export table
            file.SetLength(OriginalSize + GetAlign(length));
            {
                var expdir = new ExportDir {
                };
                expdir.Name = VirtualEnd + expdirlength;
                expdir.Base = 1;
                expdir.NumberOfFunctions  = NumberOfFunctions;
                expdir.NumberOfNames      = NumberOfNames;
                expdir.AddressOfFunctions = VirtualEnd + expdirlength + dllnamelength;
                expdir.AddressOfOrdinals  = VirtualEnd + expdirlength + dllnamelength + functionslength;
                expdir.AddressOfNames     = VirtualEnd + expdirlength + dllnamelength + functionslength + ordinalslength + stringslength;
                action.WriteExport(expdir);
            }
            action.Writer.WriteByteString(config.DllName);
            foreach (var(key, _) in cache)
            {
                action.Writer.WriteStruct(new RVA {
                    Value = key
                });
            }
            foreach (var(_, idx) in sorted)
            {
                action.Writer.WriteStruct(new Ordinal {
                    Value = idx
                });
            }
            {
                var strscache = new List <uint>();
                var baseoff   = (uint)file.Position;
                var baserva   = VirtualEnd + expdirlength + dllnamelength + functionslength + ordinalslength;
                foreach (var(name, _) in sorted)
                {
                    strscache.Add((uint)file.Position - baseoff + baserva);
                    if (verbose)
                    {
                        Console.WriteLine("{0:X8} -> {1:X8}", file.Position, file.Position - baseoff + baserva);
                    }
                    action.Writer.WriteByteString(name);
                }

                foreach (var add in strscache)
                {
                    action.Writer.WriteStruct(new RVA {
                        Value = add
                    });
                }

                Console.WriteLine("VirtualEnd: {0} {0:X8}", VirtualEnd);
                Console.WriteLine("OriginalSize: {0} {0:X8}", OriginalSize);
                Console.WriteLine("RealAppend: {0} {0:X8}", file.Position - OriginalSize);
            }
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="unionRecord">The union record.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 internal PdbUnionType(PdbFileReader pdb, TypeIndex typeIndex, UnionRecord unionRecord, ModifierOptions modifierOptions)
     : base(pdb, typeIndex, unionRecord, modifierOptions, unionRecord.Size)
 {
     UnionRecord = unionRecord;
 }
Ejemplo n.º 9
0
        public void TestPdb(int pdbIndex)
        {
            if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
            {
                return;
            }

            string         pdbPath = GetPdbPath(pdbIndex);
            IDiaDataSource dia     = DiaLoader.CreateDiaSource();
            IDiaSession    diaSession;

            dia.loadDataFromPdb(pdbPath);
            dia.openSession(out diaSession);
            using (PdbFileReader pdb = new PdbFileReader(pdbPath))
            {
                // Verify UDTs
                IReadOnlyList <PdbType> pdbUdts = pdb.UserDefinedTypes;
                IDiaSymbol[]            diaUdts = diaSession.globalScope.GetChildren(SymTagEnum.UDT)
                                                  .Concat(diaSession.globalScope.GetChildren(SymTagEnum.Enum))
                                                  .OrderBy(s => s.constType ? 1 : 0) // Order so that we move types with ModifierRecord to the back
                                                  .ThenBy(s => s.unalignedType ? 1 : 0)
                                                  .ThenBy(s => s.volatileType ? 1 : 0)
                                                  .ToArray();
                HashSet <Tuple <uint, PdbType> > checkedTypes = new HashSet <Tuple <uint, PdbType> >();
                HashSet <string>             checkedUdts      = new HashSet <string>();
                Dictionary <string, PdbType> pdbTypesByName   = new Dictionary <string, PdbType>();

                foreach (PdbType pdbType in pdbUdts)
                {
                    if (!pdbTypesByName.ContainsKey(pdbType.Name))
                    {
                        pdbTypesByName.Add(pdbType.Name, pdbType);
                    }
                }

                foreach (IDiaSymbol diaType in diaUdts)
                {
                    string name = diaType.name;

                    if (!checkedUdts.Contains(name))
                    {
                        PdbType pdbType = pdbTypesByName[name];

                        CompareTypes(diaType, pdbType, checkedTypes);
                        checkedUdts.Add(name);
                    }
                }

                // Verify global variables
                IDiaSymbol[] diaGlobalVariables = diaSession.globalScope.GetChildren(SymTagEnum.Data).Where(s => s.locationType == LocationType.Static).ToArray();

                Assert.Equal(diaGlobalVariables.Length, pdb.GlobalVariables.Length);
                for (int i = 0; i < diaGlobalVariables.Length; i++)
                {
                    IDiaSymbol        diaGlobalVariable = diaGlobalVariables[i];
                    PdbGlobalVariable pdbGlobalVariable = pdb.GlobalVariables[i];

                    Assert.Equal(diaGlobalVariable.name, pdbGlobalVariable.Name);
                    Assert.Equal(diaGlobalVariable.addressSection, pdbGlobalVariable.Segment);
                    Assert.Equal(diaGlobalVariable.addressOffset, pdbGlobalVariable.Offset);
                    Assert.Equal(diaGlobalVariable.relativeVirtualAddress, pdbGlobalVariable.RelativeVirtualAddress);
                    CompareTypes(diaGlobalVariable.type, pdbGlobalVariable.Type, checkedTypes);
                }

                // Verify functions
                IDiaSymbol[] diaFunctions = diaSession.globalScope.GetChildren(SymTagEnum.Function)
                                            .OrderBy(d => d.name)
                                            .ThenBy(d => d.relativeVirtualAddress).ToArray();
                PdbFunction[] pdbFunctions = pdb.Functions
                                             .OrderBy(p => p.Name)
                                             .ThenBy(p => p.RelativeVirtualAddress).ToArray();

                Assert.Equal(diaFunctions.Length, pdbFunctions.Length);
                for (int i = 0; i < diaFunctions.Length; i++)
                {
                    IDiaSymbol  diaFunction = diaFunctions[i];
                    PdbFunction pdbFunction = pdbFunctions[i];

                    Assert.Equal(diaFunction.name, pdbFunction.Name);
                    Assert.Equal(diaFunction.addressSection, pdbFunction.Segment);
                    Assert.Equal(diaFunction.addressOffset, pdbFunction.Offset);
                    Assert.Equal(diaFunction.customCallingConvention, pdbFunction.HasCustomCallingConvention);
                    Assert.Equal(diaFunction.farReturn, pdbFunction.HasFarReturn);
                    Assert.Equal(diaFunction.framePointerPresent, pdbFunction.HasFramePointer);
                    Assert.Equal(diaFunction.interruptReturn, pdbFunction.HasInterruptReturn);
                    Assert.Equal(diaFunction.length, pdbFunction.CodeSize);
                    Assert.Equal(diaFunction.noInline, pdbFunction.IsNoInline);
                    Assert.Equal(diaFunction.notReached, pdbFunction.IsUnreachable);
                    Assert.Equal(diaFunction.noReturn, pdbFunction.IsNoReturn);
                    Assert.Equal(diaFunction.optimizedCodeDebugInfo, pdbFunction.HasOptimizedDebugInfo);
                    Assert.Equal(diaFunction.relativeVirtualAddress, pdbFunction.RelativeVirtualAddress);
                    CompareTypes(diaFunction.type, pdbFunction.FunctionType, checkedTypes);
                    //Assert.Equal(diaFunction.get_undecoratedNameEx(UndecoratedNameOptions.Complete), pdbFunction.GetUndecoratedName(NameUndecorator.Flags.Complete));
                    // TODO: hasAlloca
                    // TODO: hasEH
                    // TODO: hasEHa
                    // TODO: hasInlAsm
                    // TODO: hasLongJump
                    // TODO: hasSecurityChecks
                    // TODO: hasSEH
                    // TODO: hasSetJump
                    // TODO: intro
                    // TODO: InlSpec
                    // TODO: isNaked
                    // TODO: isStatic
                    // TODO: locationType
                    // TODO: noStackOrdering
                    // TODO: pure
                    // TODO: token
                    // TODO: virtual
                    // TODO: virtualBaseOffset
                }

                // Verify publics
                IDiaSymbol[] diaPublicSymbols = diaSession.globalScope.GetChildren(SymTagEnum.PublicSymbol).ToArray();

                Assert.Equal(diaPublicSymbols.Length, pdb.PublicSymbols.Length);
                for (int i = 0; i < diaPublicSymbols.Length; i++)
                {
                    IDiaSymbol      diaPublicSymbol = diaPublicSymbols[i];
                    PdbPublicSymbol pdbPublicSymbol = pdb.PublicSymbols[i];

                    Assert.Equal(diaPublicSymbol.name, pdbPublicSymbol.Name);
                    Assert.Equal(diaPublicSymbol.addressSection, pdbPublicSymbol.Segment);
                    Assert.Equal(diaPublicSymbol.addressOffset, pdbPublicSymbol.Offset);
                    Assert.Equal(diaPublicSymbol.relativeVirtualAddress, pdbPublicSymbol.RelativeVirtualAddress);
                    Assert.Equal(diaPublicSymbol.code, pdbPublicSymbol.IsCode);
                    Assert.Equal(diaPublicSymbol.function, pdbPublicSymbol.IsFunction);
                    Assert.Equal(diaPublicSymbol.managed, pdbPublicSymbol.IsManaged);
                    Assert.Equal(diaPublicSymbol.msil, pdbPublicSymbol.IsMsil);
                    Assert.Equal(LocationType.Static, diaPublicSymbol.locationType);
                    Assert.True(CompareUndecoratedNames(pdbPublicSymbol.Name, diaPublicSymbol.get_undecoratedNameEx(UndecoratedNameOptions.Complete), pdbPublicSymbol.GetUndecoratedName(NameUndecorator.Flags.Complete)));
                    //Assert.Equal(diaPublicSymbol.get_undecoratedNameEx(UndecoratedNameOptions.Complete), pdbPublicSymbol.GetUndecoratedName(NameUndecorator.Flags.Complete));
                    // TODO: diaPublicSymbol.length
                }
            }
        }
Ejemplo n.º 10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="enumRecord">The enum record.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 internal PdbEnumType(PdbFileReader pdb, TypeIndex typeIndex, EnumRecord enumRecord, ModifierOptions modifierOptions)
     : base(pdb, typeIndex, enumRecord, modifierOptions, pdb[enumRecord.UnderlyingType].Size)
 {
     EnumRecord  = enumRecord;
     valuesCache = SimpleCache.CreateWithContext(this, CallEnumerateValues);
 }
Ejemplo n.º 11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbFunctionType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="procedureRecord">The procedure record.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 internal PdbFunctionType(PdbFileReader pdb, TypeIndex typeIndex, ProcedureRecord procedureRecord, ModifierOptions modifierOptions)
     : base(pdb, typeIndex, modifierOptions, string.Empty, 0)
 {
     ProcedureRecord = procedureRecord;
     argumentsCache  = SimpleCache.CreateWithContext(this, CallEnumerateArguments);
 }
Ejemplo n.º 12
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbArrayType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="arrayRecord">The array record.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 internal PdbArrayType(PdbFileReader pdb, TypeIndex typeIndex, ArrayRecord arrayRecord, ModifierOptions modifierOptions)
     : base(pdb, typeIndex, modifierOptions, GetTypeName(pdb, arrayRecord), arrayRecord.Size)
 {
     ArrayRecord = arrayRecord;
 }
Ejemplo n.º 13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbSimplePointerType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 internal PdbSimplePointerType(PdbFileReader pdb, TypeIndex typeIndex, ModifierOptions modifierOptions)
     : base(pdb, typeIndex, modifierOptions, new TypeIndex(typeIndex.SimpleKind), GetPointerSize(typeIndex), isLValueReference: false, isRValueReference: false)
 {
 }
Ejemplo n.º 14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="classRecord">The class record.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 internal PdbClassType(PdbFileReader pdb, TypeIndex typeIndex, ClassRecord classRecord, ModifierOptions modifierOptions)
     : base(pdb, typeIndex, classRecord, modifierOptions, classRecord.Size)
 {
     ClassRecord = classRecord;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="PdbComplexPointerType"/> class.
 /// </summary>
 /// <param name="pdb">The PDB file reader.</param>
 /// <param name="typeIndex">Type index.</param>
 /// <param name="pointerRecord">The pointer record.</param>
 /// <param name="modifierOptions">The modifier options.</param>
 internal PdbComplexPointerType(PdbFileReader pdb, TypeIndex typeIndex, PointerRecord pointerRecord, ModifierOptions modifierOptions)
     : base(pdb, typeIndex, CombineModifierOptions(modifierOptions, pointerRecord), pointerRecord.ReferentType, GetPointerSize(pointerRecord), pointerRecord.Mode == PointerMode.LValueReference, pointerRecord.Mode == PointerMode.RValueReference)
 {
     PointerRecord = pointerRecord;
 }