public void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e) { if (e.WriterEvent == ModuleWriterEvent.MDEndAddResources) { var writer = (ModuleWriterBase)sender; ctx.ManifestResources = new List<Tuple<uint, uint, string>>(); Dictionary<uint, byte[]> stringDict = writer.MetaData.StringsHeap.GetAllRawData().ToDictionary(pair => pair.Key, pair => pair.Value); foreach (RawManifestResourceRow resource in writer.MetaData.TablesHeap.ManifestResourceTable) ctx.ManifestResources.Add(Tuple.Create(resource.Offset, resource.Flags, Encoding.UTF8.GetString(stringDict[resource.Name]))); ctx.EntryPointToken = writer.MetaData.GetToken(ctx.EntryPoint).Raw; } }
void InjectNativeCode(object sender, ModuleWriterListenerEventArgs e) { var writer = (ModuleWriterBase)sender; if (e.WriterEvent == ModuleWriterEvent.MDEndWriteMethodBodies) { for (int n = 0; n < nativeCodes.Count; n++) nativeCodes[n] = new Tuple<MethodDef, byte[], MethodBody>( nativeCodes[n].Item1, nativeCodes[n].Item2, writer.MethodBodies.Add(new MethodBody(nativeCodes[n].Item2))); } else if (e.WriterEvent == ModuleWriterEvent.EndCalculateRvasAndFileOffsets) { foreach (var native in nativeCodes) { uint rid = writer.MetaData.GetRid(native.Item1); writer.MetaData.TablesHeap.MethodTable[rid].RVA = (uint)native.Item3.RVA; } } }
private void EncodeField(object sender, ModuleWriterListenerEventArgs e) { var writer = (ModuleWriter)sender; if (e.WriterEvent == ModuleWriterEvent.MDMemberDefRidsAllocated) { Dictionary<TypeDef, Func<int, int>> keyFuncs = keyAttrs .Where(entry => entry != null) .ToDictionary(entry => entry.Item1, entry => entry.Item2); foreach (FieldDesc desc in fieldDescs) { uint token = writer.MetaData.GetToken(desc.Method).Raw; uint key = encodeCtx.Random.NextUInt32() | 1; // CA CustomAttribute ca = desc.Field.CustomAttributes[0]; int encodedKey = keyFuncs[(TypeDef)ca.AttributeType]((int)MathsUtils.modInv(key)); ca.ConstructorArguments.Add(new CAArgument(encodeCtx.Module.CorLibTypes.Int32, encodedKey)); token *= key; // Encoding token = (uint)desc.InitDesc.Encoding.Encode(desc.InitDesc.Method, encodeCtx, (int)token); // Field name var name = new char[5]; name[desc.InitDesc.OpCodeIndex] = (char)((byte)desc.OpCode ^ desc.OpKey); byte[] nameKey = encodeCtx.Random.NextBytes(4); uint encodedNameKey = 0; for (int i = 0; i < 4; i++) { // No zero bytes while (nameKey[i] == 0) nameKey[i] = encodeCtx.Random.NextByte(); name[desc.InitDesc.TokenNameOrder[i]] = (char)nameKey[i]; encodedNameKey |= (uint)nameKey[i] << desc.InitDesc.TokenByteOrder[i]; } desc.Field.Name = new string(name); // Field sig FieldSig sig = desc.Field.FieldSig; uint encodedToken = (token - writer.MetaData.GetToken(((CModOptSig)sig.Type).Modifier).Raw) ^ encodedNameKey; var extra = new byte[8]; extra[0] = 0xc0; extra[3] = (byte)(encodedToken >> desc.InitDesc.TokenByteOrder[3]); extra[4] = 0xc0; extra[5] = (byte)(encodedToken >> desc.InitDesc.TokenByteOrder[2]); extra[6] = (byte)(encodedToken >> desc.InitDesc.TokenByteOrder[1]); extra[7] = (byte)(encodedToken >> desc.InitDesc.TokenByteOrder[0]); sig.ExtraData = extra; } } }
void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e) { var writer = (ModuleWriterBase)sender; if (e.WriterEvent == ModuleWriterEvent.MDEndCreateTables) { CreateSections(writer); } else if (e.WriterEvent == ModuleWriterEvent.BeginStrongNameSign) { EncryptSection(writer); } }
void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e) { var writer = (ModuleWriterBase)sender; if (e.WriterEvent == ModuleWriterEvent.MDBeginWriteMethodBodies) { context.Logger.Debug("Extracting method bodies..."); CreateSection(writer); } else if (e.WriterEvent == ModuleWriterEvent.BeginStrongNameSign) { context.Logger.Debug("Encrypting method section..."); EncryptSection(writer); } }
void OnWriterEvent(object sender, ModuleWriterListenerEventArgs e) { var writer = (ModuleWriterBase)sender; if (e.WriterEvent == 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.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()) { module.Write(ms, new ModuleWriterOptions { StrongNameKey = writer.TheOptions.StrongNameKey }); 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; tblHeap.ClassLayoutTable[writer.MetaData.GetClassLayoutRid(ctx.DataType)].ClassSize = size; tblHeap.FieldTable[writer.MetaData.GetRid(ctx.DataField)].Flags |= (ushort)FieldAttributes.HasFieldRVA; 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.WriterEvent == ModuleWriterEvent.EndCalculateRvasAndFileOffsets) { TablesHeap tblHeap = writer.MetaData.TablesHeap; tblHeap.FieldRVATable[writer.MetaData.GetFieldRVARid(ctx.DataField)].RVA = (uint)encryptedResource.RVA; } }
void InjectNativeCode(object sender, ModuleWriterListenerEventArgs e) { var writer = (ModuleWriterBase)sender; if (e.WriterEvent == ModuleWriterEvent.MDEndWriteMethodBodies) { codeChunk = writer.MethodBodies.Add(new MethodBody(code)); } else if (e.WriterEvent == ModuleWriterEvent.EndCalculateRvasAndFileOffsets) { uint rid = writer.MetaData.GetRid(native); writer.MetaData.TablesHeap.MethodTable[rid].RVA = (uint)codeChunk.RVA; } }