Example #1
0
 void InitializeRawRow()
 {
     if (rawRow != null)
     {
         return;
     }
     rawRow = readerModule.TablesStream.ReadFieldRow(rid);
 }
Example #2
0
        /// <summary>
        /// Reads a raw <c>Field</c> row or returns false if the row doesn't exist
        /// </summary>
        /// <param name="rid">Row ID</param>
        /// <param name="row">Row data</param>
        /// <returns></returns>
        public bool TryReadFieldRow(uint rid, out RawFieldRow row)
        {
            var table = FieldTable;

            if (table.IsInvalidRID(rid))
            {
                row = default;
                return(false);
            }
            var reader = table.DataReader;

            reader.Position = (rid - 1) * (uint)table.TableInfo.RowSize;
            row             = new RawFieldRow(
                reader.Unsafe_ReadUInt16(),
                table.Column1.Unsafe_Read24(ref reader),
                table.Column2.Unsafe_Read24(ref reader));
            return(true);
        }
Example #3
0
        // Token: 0x0600019A RID: 410 RVA: 0x00061B74 File Offset: 0x0005FD74
        private void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e)
        {
            ModuleWriterBase moduleWriterBase = (ModuleWriterBase)sender;
            bool             flag             = e.WriterEvent == ModuleWriterEvent.MDBeginAddResources;

            if (flag)
            {
                this.ctx.Context.CheckCancellation();
                this.ctx.Context.Logger.Debug("Encrypting resources...");
                bool flag2 = this.ctx.Context.Packer != null;
                List <EmbeddedResource> list = this.ctx.Module.Resources.OfType <EmbeddedResource>().ToList <EmbeddedResource>();
                bool flag3 = !flag2;
                if (flag3)
                {
                    this.ctx.Module.Resources.RemoveWhere((Resource res) => res is EmbeddedResource);
                }
                string    text      = this.ctx.Name.RandomName(RenameMode.Letters);
                PublicKey publicKey = null;
                bool      flag4     = moduleWriterBase.TheOptions.StrongNameKey != null;
                if (flag4)
                {
                    publicKey = PublicKeyBase.CreatePublicKey(moduleWriterBase.TheOptions.StrongNameKey.PublicKey);
                }
                AssemblyDefUser assemblyDefUser = new AssemblyDefUser(text, new Version(0, 0), publicKey);
                assemblyDefUser.Modules.Add(new ModuleDefUser(text + ".dll"));
                ModuleDef manifestModule = assemblyDefUser.ManifestModule;
                assemblyDefUser.ManifestModule.Kind = ModuleKind.Dll;
                AssemblyRefUser asmRef = new AssemblyRefUser(manifestModule.Assembly);
                bool            flag5  = !flag2;
                if (flag5)
                {
                    foreach (EmbeddedResource embeddedResource in list)
                    {
                        embeddedResource.Attributes = ManifestResourceAttributes.Public;
                        manifestModule.Resources.Add(embeddedResource);
                        this.ctx.Module.Resources.Add(new AssemblyLinkedResource(embeddedResource.Name, asmRef, embeddedResource.Attributes));
                    }
                }
                byte[] array;
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    manifestModule.Write(memoryStream, new ModuleWriterOptions
                    {
                        StrongNameKey = moduleWriterBase.TheOptions.StrongNameKey
                    });
                    array = memoryStream.ToArray();
                }
                array = this.ctx.Context.Registry.GetService <ICompressionService>().Compress(array, delegate(double progress)
                {
                    this.ctx.Context.Logger.Progress((int)(progress * 10000.0), 10000);
                });
                this.ctx.Context.Logger.EndProgress();
                this.ctx.Context.CheckCancellation();
                uint num = (uint)((array.Length + 3) / 4);
                num = (num + 15u & 4294967280u);
                uint[] array2 = new uint[num];
                Buffer.BlockCopy(array, 0, array2, 0, array.Length);
                Debug.Assert(num % 16u == 0u);
                uint   num2   = this.ctx.Random.NextUInt32() | 16u;
                uint[] array3 = new uint[16];
                uint   num3   = num2;
                for (int i = 0; i < 16; i++)
                {
                    num3     ^= num3 >> 13;
                    num3     ^= num3 << 25;
                    num3     ^= num3 >> 27;
                    array3[i] = num3;
                }
                byte[] array4 = new byte[array2.Length * 4];
                int    j;
                for (j = 0; j < array2.Length; j += 16)
                {
                    uint[] src = this.ctx.ModeHandler.Encrypt(array2, j, array3);
                    for (int k = 0; k < 16; k++)
                    {
                        array3[k] ^= array2[j + k];
                    }
                    Buffer.BlockCopy(src, 0, array4, j * 4, 64);
                }
                Debug.Assert(j == array2.Length);
                uint       num4       = (uint)array4.Length;
                TablesHeap tablesHeap = moduleWriterBase.MetaData.TablesHeap;
                tablesHeap.ClassLayoutTable[moduleWriterBase.MetaData.GetClassLayoutRid(this.ctx.DataType)].ClassSize = num4;
                RawFieldRow rawFieldRow = tablesHeap.FieldTable[moduleWriterBase.MetaData.GetRid(this.ctx.DataField)];
                rawFieldRow.Flags     |= 256;
                this.encryptedResource = moduleWriterBase.Constants.Add(new ByteArrayChunk(array4), 8u);
                MutationHelper.InjectKeys(this.ctx.InitMethod, new int[]
                {
                    0,
                    1
                }, new int[]
                {
                    (int)(num4 / 4u),
                    (int)num2
                });
            }
            else
            {
                bool flag6 = e.WriterEvent == ModuleWriterEvent.EndCalculateRvasAndFileOffsets;
                if (flag6)
                {
                    TablesHeap tablesHeap2 = moduleWriterBase.MetaData.TablesHeap;
                    tablesHeap2.FieldRVATable[moduleWriterBase.MetaData.GetFieldRVARid(this.ctx.DataField)].RVA = (uint)this.encryptedResource.RVA;
                }
            }
        }
Example #4
0
        /// <summary>
        /// Patches all columns and blob signatures that reference a moved TypeDef so they reference the new TypeRef
        /// </summary>
        void PatchTypeTokenReferences(TypeDef nonNestedEditedType)
        {
            if (remappedTypeTokens.Count == 0)
            {
                return;
            }

            // NOTE: We don't patch the following:
            //	- Method bodies
            //	- All MemberRefs referenced by method bodies
            //	- StandAloneSig.Signature. It's only used by method bodies
            //	- MethodSpec.Instantiation. It's only used by method bodies
            //	- Custom attribute blobs. Could reference the edited type but not likely to cause a problem.
            //	- Marshal blobs. Could reference the edited type but not likely to cause a problem.
            //	  The MD writer doesn't write the FieldMarshal table.

            var tablesHeap = mdEditor.TablesHeap;

            var typeSigDict     = new Dictionary <uint, uint>();
            var callConvSigDict = new Dictionary <uint, uint>();

            MDTable    table;
            byte *     p;
            int        rowSize;
            ColumnInfo column, column2;
            uint       i, codedToken, newToken, sig, newSig, rid;
            MDToken    token;

            // Patch the TypeDef table
            {
                table   = mdEditor.RealMetadata.TablesStream.TypeDefTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[3];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.TypeDefTable.Get(i + 1);
                        row = new RawTypeDefRow(row.Flags, row.Name, row.Namespace, CodedToken.TypeDefOrRef.Encode(newToken), row.FieldList, row.MethodList);
                        tablesHeap.TypeDefTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the Field table
            {
                table   = mdEditor.RealMetadata.TablesStream.FieldTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[2];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    sig    = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    newSig = PatchCallingConventionSignature(callConvSigDict, sig);
                    if (newSig != sig)
                    {
                        var row = tablesHeap.FieldTable.Get(i + 1);
                        row = new RawFieldRow(row.Flags, row.Name, newSig);
                        tablesHeap.FieldTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the Method table
            {
                table   = mdEditor.RealMetadata.TablesStream.MethodTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[4];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    sig    = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    newSig = PatchCallingConventionSignature(callConvSigDict, sig);
                    if (newSig != sig)
                    {
                        var row = tablesHeap.MethodTable.Get(i + 1);
                        row = new RawMethodRow(row.RVA, row.ImplFlags, row.Flags, row.Name, newSig, row.ParamList);
                        tablesHeap.MethodTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the InterfaceImpl table
            {
                table   = mdEditor.RealMetadata.TablesStream.InterfaceImplTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[1];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.InterfaceImplTable.Get(i + 1);
                        row = new RawInterfaceImplRow(row.Class, CodedToken.TypeDefOrRef.Encode(newToken));
                        tablesHeap.InterfaceImplTable.Set(i + 1, ref row);
                    }
                }
            }

            //TODO: PERF: If needed, this table could mostly be skipped. We only need to update refs from:
            //			CustomAttribute.Type, MethodImpl.MethodBody, MethodImpl.MethodDeclaration
            //		CustomAttribute.Type almost never references the edited type, and if it does, the
            //		edited type, or any of its nested types, is an attribute. Quick test: this block
            //		took ~25% of the total time (patch file, write new MD, test file was dnSpy.exe = 3.3MB).
            // Patch the MemberRef table
            {
                table   = mdEditor.RealMetadata.TablesStream.MemberRefTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[0];
                column2 = table.Columns[2];
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.MemberRefParent.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    rid = i + 1;
                    RawMemberRefRow row;
                    switch (token.Table)
                    {
                    case Table.TypeRef:
                    case Table.TypeDef:
                    case Table.TypeSpec:
                        if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                        {
                            row = tablesHeap.MemberRefTable.Get(rid);
                            row = new RawMemberRefRow(CodedToken.MemberRefParent.Encode(newToken), row.Name, row.Signature);
                            tablesHeap.MemberRefTable.Set(rid, ref row);
                        }
                        break;

                    case Table.ModuleRef:
                        if (nonNestedEditedType.IsGlobalModuleType && CheckResolutionScopeIsSameModule(token, nonNestedEditedType.Module))
                        {
                            if (remappedTypeTokens.TryGetValue(nonNestedEditedType.MDToken.Raw, out newToken))
                            {
                                row = tablesHeap.MemberRefTable.Get(rid);
                                row = new RawMemberRefRow(CodedToken.MemberRefParent.Encode(newToken), row.Name, row.Signature);
                                tablesHeap.MemberRefTable.Set(rid, ref row);
                            }
                        }
                        break;

                    case Table.Method:
                        break;

                    default:
                        Debug.Fail("Impossible");
                        break;
                    }

                    sig    = column2.Size == 2 ? *(ushort *)(p + column2.Offset) : *(uint *)(p + column2.Offset);
                    newSig = PatchCallingConventionSignature(callConvSigDict, sig);
                    if (sig != newSig)
                    {
                        row = tablesHeap.MemberRefTable.Get(rid);
                        row = new RawMemberRefRow(row.Class, row.Name, newSig);
                        tablesHeap.MemberRefTable.Set(rid, ref row);
                    }
                }
            }

            // Patch the Event table
            {
                table   = mdEditor.RealMetadata.TablesStream.EventTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[2];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.EventTable.Get(i + 1);
                        row = new RawEventRow(row.EventFlags, row.Name, CodedToken.TypeDefOrRef.Encode(newToken));
                        tablesHeap.EventTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the Property table
            {
                table   = mdEditor.RealMetadata.TablesStream.PropertyTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[2];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    sig    = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    newSig = PatchCallingConventionSignature(callConvSigDict, sig);
                    if (newSig != sig)
                    {
                        var row = tablesHeap.PropertyTable.Get(i + 1);
                        row = new RawPropertyRow(row.PropFlags, row.Name, newSig);
                        tablesHeap.PropertyTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the TypeSpec table
            {
                table   = mdEditor.RealMetadata.TablesStream.TypeSpecTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[0];
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    sig    = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    newSig = PatchTypeSignature(typeSigDict, sig);
                    if (newSig != sig)
                    {
                        var row = new RawTypeSpecRow(newSig);
                        tablesHeap.TypeSpecTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the GenericParam table
            if (mdEditor.RealMetadata.TablesStream.GenericParamTable.Columns.Count == 5)
            {
                table   = mdEditor.RealMetadata.TablesStream.GenericParamTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[4];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.GenericParamTable.Get(i + 1);
                        row = new RawGenericParamRow(row.Number, row.Flags, row.Owner, row.Name, CodedToken.TypeDefOrRef.Encode(newToken));
                        tablesHeap.GenericParamTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the GenericParamConstraint table
            {
                table   = mdEditor.RealMetadata.TablesStream.GenericParamConstraintTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[1];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.GenericParamConstraintTable.Get(i + 1);
                        row = new RawGenericParamConstraintRow(row.Owner, CodedToken.TypeDefOrRef.Encode(newToken));
                        tablesHeap.GenericParamConstraintTable.Set(i + 1, ref row);
                    }
                }
            }
        }
Example #5
0
 public int GetHashCode(RawFieldRow obj) =>
 (int)obj.Flags +
 rol(obj.Name, 3) +
 rol(obj.Signature, 7);
Example #6
0
 public bool Equals(RawFieldRow x, RawFieldRow y) =>
 x.Flags == y.Flags &&
 x.Name == y.Name &&
 x.Signature == y.Signature;
Example #7
0
 public bool Equals(RawFieldRow x, RawFieldRow y)
 {
     return(x.Flags == y.Flags &&
            x.Name == y.Name &&
            x.Signature == y.Signature);
 }
Example #8
0
        void OnWriterEvent(object sender, ModuleWriterEventArgs e)
        {
            var writer = (ModuleWriterBase)sender;

            if (e.Event == ModuleWriterEvent.MDBeginAddResources)
            {
                ctx.Context.CheckCancellation();
                ctx.Context.Logger.Debug("Encrypting resources...");
                bool hasPacker = ctx.Context.Packer != null;

                List <EmbeddedResource> resources = ctx.Module.Resources.OfType <EmbeddedResource>().ToList();
                if (!hasPacker)
                {
                    ctx.Module.Resources.RemoveWhere(res => res is EmbeddedResource);
                }

                // move resources
                string    asmName = ctx.Name.RandomName(RenameMode.Letters);
                PublicKey pubKey  = null;
                if (writer.TheOptions.StrongNamePublicKey != null)
                {
                    pubKey = PublicKeyBase.CreatePublicKey(writer.TheOptions.StrongNamePublicKey.CreatePublicKey());
                }
                else if (writer.TheOptions.StrongNameKey != null)
                {
                    pubKey = PublicKeyBase.CreatePublicKey(writer.TheOptions.StrongNameKey.PublicKey);
                }
                var assembly = new AssemblyDefUser(asmName, new Version(0, 0), pubKey);
                assembly.Modules.Add(new ModuleDefUser(asmName + ".dll"));
                ModuleDef module = assembly.ManifestModule;
                assembly.ManifestModule.Kind = ModuleKind.Dll;
                var asmRef = new AssemblyRefUser(module.Assembly);
                if (!hasPacker)
                {
                    foreach (EmbeddedResource res in resources)
                    {
                        res.Attributes = ManifestResourceAttributes.Public;
                        module.Resources.Add(res);
                        ctx.Module.Resources.Add(new AssemblyLinkedResource(res.Name, asmRef, res.Attributes));
                    }
                }
                byte[] moduleBuff;
                using (var ms = new MemoryStream()) {
                    var options = new ModuleWriterOptions(module)
                    {
                        StrongNameKey       = writer.TheOptions.StrongNameKey,
                        StrongNamePublicKey = writer.TheOptions.StrongNamePublicKey,
                        DelaySign           = writer.TheOptions.DelaySign
                    };
                    module.Write(ms, options);
                    moduleBuff = ms.ToArray();
                }

                // compress
                moduleBuff = ctx.Context.Registry.GetService <ICompressionService>().Compress(
                    moduleBuff,
                    progress => ctx.Context.Logger.Progress((int)(progress * 10000), 10000));
                ctx.Context.Logger.EndProgress();
                ctx.Context.CheckCancellation();

                uint compressedLen = (uint)(moduleBuff.Length + 3) / 4;
                compressedLen = (compressedLen + 0xfu) & ~0xfu;
                var compressedBuff = new uint[compressedLen];
                Buffer.BlockCopy(moduleBuff, 0, compressedBuff, 0, moduleBuff.Length);
                Debug.Assert(compressedLen % 0x10 == 0);

                // encrypt
                uint keySeed = ctx.Random.NextUInt32() | 0x10;
                var  key     = new uint[0x10];
                uint state   = keySeed;
                for (int i = 0; i < 0x10; i++)
                {
                    state ^= state >> 13;
                    state ^= state << 25;
                    state ^= state >> 27;
                    key[i] = state;
                }

                var encryptedBuffer = new byte[compressedBuff.Length * 4];
                int buffIndex       = 0;
                while (buffIndex < compressedBuff.Length)
                {
                    uint[] enc = ctx.ModeHandler.Encrypt(compressedBuff, buffIndex, key);
                    for (int j = 0; j < 0x10; j++)
                    {
                        key[j] ^= compressedBuff[buffIndex + j];
                    }
                    Buffer.BlockCopy(enc, 0, encryptedBuffer, buffIndex * 4, 0x40);
                    buffIndex += 0x10;
                }
                Debug.Assert(buffIndex == compressedBuff.Length);
                var size = (uint)encryptedBuffer.Length;

                TablesHeap tblHeap = writer.Metadata.TablesHeap;

                uint classLayoutRid           = writer.Metadata.GetClassLayoutRid(ctx.DataType);
                RawClassLayoutRow classLayout = tblHeap.ClassLayoutTable[classLayoutRid];
                tblHeap.ClassLayoutTable[classLayoutRid] = new RawClassLayoutRow(classLayout.PackingSize, size, classLayout.Parent);

                uint        dataFieldRid = writer.Metadata.GetRid(ctx.DataField);
                RawFieldRow dataField    = tblHeap.FieldTable[dataFieldRid];
                tblHeap.FieldTable[dataFieldRid] = new RawFieldRow((ushort)(dataField.Flags | (ushort)FieldAttributes.HasFieldRVA), dataField.Name, dataField.Signature);
                encryptedResource = writer.Constants.Add(new ByteArrayChunk(encryptedBuffer), 8);

                // inject key values
                MutationHelper.InjectKeys(ctx.InitMethod,
                                          new[] { 0, 1 },
                                          new[] { (int)(size / 4), (int)(keySeed) });
            }
            else if (e.Event == ModuleWriterEvent.EndCalculateRvasAndFileOffsets)
            {
                TablesHeap     tblHeap     = writer.Metadata.TablesHeap;
                uint           fieldRvaRid = writer.Metadata.GetFieldRVARid(ctx.DataField);
                RawFieldRVARow fieldRva    = tblHeap.FieldRVATable[fieldRvaRid];
                tblHeap.FieldRVATable[fieldRvaRid] = new RawFieldRVARow((uint)encryptedResource.RVA, fieldRva.Field);
            }
        }
Example #9
0
 static uint ReadFieldColumnMethod(ref RawFieldRow row, int index) => row[index];
Example #10
0
 public int GetHashCode(RawFieldRow obj)
 {
     return(obj.Flags +
            rol(obj.Name, 3) +
            rol(obj.Signature, 7));
 }