void InitializeRawRow() { if (rawRow != null) { return; } rawRow = readerModule.TablesStream.ReadFieldRow(rid); }
/// <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); }
// 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; } } }
/// <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); } } } }
public int GetHashCode(RawFieldRow obj) => (int)obj.Flags + rol(obj.Name, 3) + rol(obj.Signature, 7);
public bool Equals(RawFieldRow x, RawFieldRow y) => x.Flags == y.Flags && x.Name == y.Name && x.Signature == y.Signature;
public bool Equals(RawFieldRow x, RawFieldRow y) { return(x.Flags == y.Flags && x.Name == y.Name && x.Signature == y.Signature); }
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); } }
static uint ReadFieldColumnMethod(ref RawFieldRow row, int index) => row[index];
public int GetHashCode(RawFieldRow obj) { return(obj.Flags + rol(obj.Name, 3) + rol(obj.Signature, 7)); }