Beispiel #1
0
        /// <summary>
        /// Writes the .sdata blob. We could write the data in any order, but we write the data in the same order as ILASM
        /// </summary>
        /// <param name="timestamp">PE timestamp</param>
        void WriteSdataBlob(uint timestamp)
        {
            var stream = new MemoryStream();
            var writer = new BinaryWriter(stream);

            // Write all vtables (referenced from the .text section)
            Debug.Assert((writer.BaseStream.Position & 7) == 0);
            foreach (var vtbl in vtables)
            {
                vtbl.SdataChunkOffset = (uint)writer.BaseStream.Position;
                foreach (var info in vtbl.Methods)
                {
                    info.ManagedVtblOffset = (uint)writer.BaseStream.Position;
                    writer.Write(0x06000000 + metaData.GetRid(info.Method));
                    if ((vtbl.Flags & VTableFlags._64Bit) != 0)
                    {
                        writer.Write(0U);
                    }
                }
            }

            var  namesBlob = new NamesBlob(1 == 2);
            int  nameIndex = 0;
            bool error     = false;

            foreach (var info in allMethodInfos)
            {
                var exportInfo = info.Method.ExportInfo;
                var name       = exportInfo.Name;
                if (name == null)
                {
                    if (exportInfo.Ordinal != null)
                    {
                        sortedOrdinalMethodInfos.Add(info);
                        continue;
                    }
                    name = info.Method.Name;
                }
                if (string.IsNullOrEmpty(name))
                {
                    error = true;
                    logError("Exported method name is null or empty, method: {0} (0x{1:X8})", info.Method, info.Method.MDToken.Raw);
                    continue;
                }
                info.NameOffset = namesBlob.GetMethodNameOffset(name, out info.NameBytes);
                info.NameIndex  = nameIndex++;
                sortedNameMethodInfos.Add(info);
            }
            Debug.Assert(error || sortedOrdinalMethodInfos.Count + sortedNameMethodInfos.Count == allMethodInfos.Count);
            sdataBytesInfo.MethodNameOffsets = namesBlob.GetMethodNameOffsets();
            Debug.Assert(sortedNameMethodInfos.Count == sdataBytesInfo.MethodNameOffsets.Length);
            sdataBytesInfo.moduleNameOffset = namesBlob.GetOtherNameOffset(moduleName);

            sortedOrdinalMethodInfos.Sort((a, b) => a.Method.ExportInfo.Ordinal.Value.CompareTo(b.Method.ExportInfo.Ordinal.Value));
            sortedNameMethodInfos.Sort((a, b) => CompareTo(a.NameBytes, b.NameBytes));

            int ordinalBase, nextFreeOrdinal;

            if (sortedOrdinalMethodInfos.Count == 0)
            {
                ordinalBase     = 0;
                nextFreeOrdinal = 0;
            }
            else
            {
                ordinalBase     = sortedOrdinalMethodInfos[0].Method.ExportInfo.Ordinal.Value;
                nextFreeOrdinal = sortedOrdinalMethodInfos[sortedOrdinalMethodInfos.Count - 1].Method.ExportInfo.Ordinal.Value + 1;
            }
            int nameFuncBaseIndex = nextFreeOrdinal - ordinalBase;
            int lastFuncIndex     = 0;

            for (int i = 0; i < sortedOrdinalMethodInfos.Count; i++)
            {
                int index = sortedOrdinalMethodInfos[i].Method.ExportInfo.Ordinal.Value - ordinalBase;
                sortedOrdinalMethodInfos[i].FunctionIndex = index;
                lastFuncIndex = index;
            }
            for (int i = 0; i < sortedNameMethodInfos.Count; i++)
            {
                lastFuncIndex = nameFuncBaseIndex + i;
                sortedNameMethodInfos[i].FunctionIndex = lastFuncIndex;
            }
            int funcSize = lastFuncIndex + 1;

            if (funcSize > 0x10000)
            {
                logError("Exported function array is too big");
                return;
            }

            // Write IMAGE_EXPORT_DIRECTORY
            Debug.Assert((writer.BaseStream.Position & 3) == 0);
            exportDirOffset = (uint)writer.BaseStream.Position;
            writer.Write(0U);                                      // Characteristics
            writer.Write(timestamp);
            writer.Write(0U);                                      // MajorVersion, MinorVersion
            sdataBytesInfo.exportDirModuleNameStreamOffset = (uint)writer.BaseStream.Position;
            writer.Write(0U);                                      // Name
            writer.Write(ordinalBase);                             // Base
            writer.Write((uint)funcSize);                          // NumberOfFunctions
            writer.Write(sdataBytesInfo.MethodNameOffsets.Length); // NumberOfNames
            sdataBytesInfo.exportDirAddressOfFunctionsStreamOffset = (uint)writer.BaseStream.Position;
            writer.Write(0U);                                      // AddressOfFunctions
            writer.Write(0U);                                      // AddressOfNames
            writer.Write(0U);                                      // AddressOfNameOrdinals

            sdataBytesInfo.addressOfFunctionsStreamOffset = (uint)writer.BaseStream.Position;
            WriteZeroes(writer, funcSize * 4);
            sdataBytesInfo.addressOfNamesStreamOffset = (uint)writer.BaseStream.Position;
            WriteZeroes(writer, sdataBytesInfo.MethodNameOffsets.Length * 4);
            sdataBytesInfo.addressOfNameOrdinalsStreamOffset = (uint)writer.BaseStream.Position;
            WriteZeroes(writer, sdataBytesInfo.MethodNameOffsets.Length * 2);
            sdataBytesInfo.namesBlobStreamOffset = (uint)writer.BaseStream.Position;
            namesBlob.Write(writer);

            sdataBytesInfo.Data = stream.ToArray();
        }
Beispiel #2
0
        /// <summary>
        /// Writes the .sdata blob. We could write the data in any order, but we write the data in the same order as ILASM
        /// </summary>
        /// <param name="timestamp">PE timestamp</param>
        void WriteSdataBlob(uint timestamp)
        {
            var stream = new MemoryStream();
            var writer = new BinaryWriter(stream);

            // Write all vtables (referenced from the .text section)
            Debug.Assert((writer.BaseStream.Position & 7) == 0);
            foreach (var vtbl in vtables)
            {
                vtbl.SdataChunkOffset = (uint)writer.BaseStream.Position;
                foreach (var info in vtbl.Methods)
                {
                    info.ManagedVtblOffset = (uint)writer.BaseStream.Position;
                    writer.Write(0x06000000 + metaData.GetRid(info.Method));
                    if ((vtbl.Flags & VTableFlags._64Bit) != 0)
                    {
                        writer.Write(0U);
                    }
                }
            }

            var namesBlob = new NamesBlob(1 == 2);
            int nameIndex = 0;

            foreach (var info in allMethodInfos)
            {
                var exportInfo = info.Method.ExportInfo;
                var name       = exportInfo.Name;
                if (name == null)
                {
                    if (exportInfo.Ordinal != null)
                    {
                        continue;
                    }
                    name = info.Method.Name;
                }
                if (string.IsNullOrEmpty(name))
                {
                    logError("Exported method name is null or empty, method: {0} (0x{1:X8})", info.Method, info.Method.MDToken.Raw);
                    continue;
                }
                info.NameOffset = namesBlob.GetMethodNameOffset(name, out info.NameBytes);
                info.NameIndex  = nameIndex++;
                sortedNameInfos.Add(info);
            }
            sdataBytesInfo.MethodNameOffsets = namesBlob.GetMethodNameOffsets();
            sdataBytesInfo.moduleNameOffset  = namesBlob.GetOtherNameOffset(moduleName);

            sortedNameInfos.Sort((a, b) => CompareTo(a.NameBytes, b.NameBytes));
            Debug.Assert(sortedNameInfos.Count == sdataBytesInfo.MethodNameOffsets.Length);

            uint ordinalBase = uint.MaxValue;

            foreach (var info in allMethodInfos)
            {
                if (info.Method.ExportInfo.Ordinal != null)
                {
                    ordinalBase = Math.Min(ordinalBase, info.Method.ExportInfo.Ordinal.Value);
                }
            }
            if (ordinalBase == uint.MaxValue)
            {
                ordinalBase = 0;
            }

            // Write IMAGE_EXPORT_DIRECTORY
            Debug.Assert((writer.BaseStream.Position & 3) == 0);
            exportDirOffset = (uint)writer.BaseStream.Position;
            writer.Write(0U);                                      // Characteristics
            writer.Write(timestamp);
            writer.Write(0U);                                      // MajorVersion, MinorVersion
            sdataBytesInfo.exportDirModuleNameStreamOffset = (uint)writer.BaseStream.Position;
            writer.Write(0U);                                      // Name
            writer.Write(ordinalBase);                             // Base
            writer.Write((uint)allMethodInfos.Count);              // NumberOfFunctions
            writer.Write(sdataBytesInfo.MethodNameOffsets.Length); // NumberOfNames
            sdataBytesInfo.exportDirAddressOfFunctionsStreamOffset = (uint)writer.BaseStream.Position;
            writer.Write(0U);                                      // AddressOfFunctions
            writer.Write(0U);                                      // AddressOfNames
            writer.Write(0U);                                      // AddressOfNameOrdinals

            sdataBytesInfo.addressOfFunctionsStreamOffset = (uint)writer.BaseStream.Position;
            WriteZeroes(writer, allMethodInfos.Count * 4);
            sdataBytesInfo.addressOfNamesStreamOffset = (uint)writer.BaseStream.Position;
            WriteZeroes(writer, sdataBytesInfo.MethodNameOffsets.Length * 4);
            sdataBytesInfo.addressOfNameOrdinalsStreamOffset = (uint)writer.BaseStream.Position;
            WriteZeroes(writer, sdataBytesInfo.MethodNameOffsets.Length * 2);
            sdataBytesInfo.namesBlobStreamOffset = (uint)writer.BaseStream.Position;
            namesBlob.Write(writer);

            sdataBytesInfo.Data = stream.ToArray();
        }