diff --git a/Confuser.Protections/Compress/Compressor.cs b/Confuser.Protections/Compress/Compressor.cs index ac02083bb..3d8eb1d82 100644 --- a/Confuser.Protections/Compress/Compressor.cs +++ b/Confuser.Protections/Compress/Compressor.cs @@ -56,8 +56,17 @@ protected override void Pack(ConfuserContext context, ProtectionParameters param ModuleDefMD originModule = context.Modules[ctx.ModuleIndex]; ctx.OriginModuleDef = originModule; + var stubModule = new ModuleDefUser(ctx.ModuleName, originModule.Mvid, originModule.CorLibTypes.AssemblyRef); - ctx.Assembly.Modules.Insert(0, stubModule); + if (ctx.CompatMode) { + var assembly = new AssemblyDefUser(originModule.Assembly); + assembly.Name += ".cr"; + assembly.Modules.Add(stubModule); + } + else { + ctx.Assembly.Modules.Insert(0, stubModule); + ImportAssemblyTypeReferences(originModule, stubModule); + } stubModule.Characteristics = originModule.Characteristics; stubModule.Cor20HeaderFlags = originModule.Cor20HeaderFlags; stubModule.Cor20HeaderRuntimeVersion = originModule.Cor20HeaderRuntimeVersion; @@ -70,7 +79,6 @@ protected override void Pack(ConfuserContext context, ProtectionParameters param stubModule.RuntimeVersion = originModule.RuntimeVersion; stubModule.TablesHeaderVersion = originModule.TablesHeaderVersion; stubModule.Win32Resources = originModule.Win32Resources; - ImportAssemblyTypeReferences(originModule, stubModule); InjectStub(context, ctx, parameters, stubModule); @@ -186,7 +194,9 @@ void InjectStub(ConfuserContext context, CompressorContext compCtx, ProtectionPa var rt = context.Registry.GetService(); RandomGenerator random = context.Registry.GetService().GetRandomGenerator(Id); var comp = context.Registry.GetService(); - IEnumerable defs = InjectHelper.Inject(rt.GetRuntimeType("Confuser.Runtime.Compressor"), stubModule.GlobalType, stubModule); + + var rtType = rt.GetRuntimeType(compCtx.CompatMode ? "Confuser.Runtime.CompressorCompat" : "Confuser.Runtime.Compressor"); + IEnumerable defs = InjectHelper.Inject(rtType, stubModule.GlobalType, stubModule); switch (parameters.GetParameter(context, context.CurrentModule, "key", Mode.Normal)) { case Mode.Normal: diff --git a/Confuser.Protections/Compress/CompressorContext.cs b/Confuser.Protections/Compress/CompressorContext.cs index 0d85a280f..e3e34642e 100644 --- a/Confuser.Protections/Compress/CompressorContext.cs +++ b/Confuser.Protections/Compress/CompressorContext.cs @@ -18,6 +18,7 @@ internal class CompressorContext { public string ModuleName; public byte[] OriginModule; public ModuleDef OriginModuleDef; + public bool CompatMode; public byte[] Encrypt(ICompressionService compress, byte[] data, uint seed, Action progressFunc) { data = (byte[])data.Clone(); diff --git a/Confuser.Protections/Compress/ExtractPhase.cs b/Confuser.Protections/Compress/ExtractPhase.cs index 14c092965..02d7f8453 100644 --- a/Confuser.Protections/Compress/ExtractPhase.cs +++ b/Confuser.Protections/Compress/ExtractPhase.cs @@ -37,18 +37,20 @@ protected override void Execute(ConfuserContext context, ProtectionParameters pa if (isExe) { var ctx = new CompressorContext { ModuleIndex = context.CurrentModuleIndex, - Assembly = context.CurrentModule.Assembly + Assembly = context.CurrentModule.Assembly, + CompatMode = parameters.GetParameter(context, null, "compat", false) }; context.Annotations.Set(context, Compressor.ContextKey, ctx); ctx.ModuleName = context.CurrentModule.Name; - context.CurrentModule.Name = "koi"; - ctx.EntryPoint = context.CurrentModule.EntryPoint; - context.CurrentModule.EntryPoint = null; - ctx.Kind = context.CurrentModule.Kind; - context.CurrentModule.Kind = ModuleKind.NetModule; + + if (!ctx.CompatMode) { + context.CurrentModule.Name = "koi"; + context.CurrentModule.EntryPoint = null; + context.CurrentModule.Kind = ModuleKind.NetModule; + } context.CurrentModuleWriterListener.OnWriterEvent += new ResourceRecorder(ctx, context.CurrentModule).OnWriterEvent; } diff --git a/Confuser.Protections/Compress/StubProtection.cs b/Confuser.Protections/Compress/StubProtection.cs index 0fb6fedc0..a15d7af68 100644 --- a/Confuser.Protections/Compress/StubProtection.cs +++ b/Confuser.Protections/Compress/StubProtection.cs @@ -42,7 +42,8 @@ protected override void Initialize(ConfuserContext context) { } protected override void PopulatePipeline(ProtectionPipeline pipeline) { - pipeline.InsertPreStage(PipelineStage.Inspection, new InjPhase(this)); + if (!ctx.CompatMode) + pipeline.InsertPreStage(PipelineStage.Inspection, new InjPhase(this)); pipeline.InsertPostStage(PipelineStage.BeginModule, new SigPhase(this)); } @@ -96,6 +97,9 @@ protected override void Execute(ConfuserContext context, ProtectionParameters pa uint rid = writer.MetaData.TablesHeap.StandAloneSigTable.Add(new RawStandAloneSigRow(blob)); Debug.Assert((0x11000000 | rid) == prot.ctx.KeyToken); + if (prot.ctx.CompatMode) + return; + // Add File reference byte[] hash = SHA1.Create().ComputeHash(prot.ctx.OriginModule); uint hashBlob = writer.MetaData.BlobHeap.Add(hash); diff --git a/Confuser.Runtime/Compressor.Compat.cs b/Confuser.Runtime/Compressor.Compat.cs new file mode 100644 index 000000000..735acba12 --- /dev/null +++ b/Confuser.Runtime/Compressor.Compat.cs @@ -0,0 +1,109 @@ +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; + +namespace Confuser.Runtime { + internal static class CompressorCompat { + static byte[] key; + + static GCHandle Decrypt(uint[] data, uint seed) { + var w = new uint[0x10]; + var k = new uint[0x10]; + ulong s = seed; + for (int i = 0; i < 0x10; i++) { + s = (s * s) % 0x143fc089; + k[i] = (uint)s; + w[i] = (uint)((s * s) % 0x444d56fb); + } + Mutation.Crypt(w, k); + Array.Clear(k, 0, 0x10); + + var b = new byte[data.Length << 2]; + uint h = 0; + for (int i = 0; i < data.Length; i++) { + uint d = data[i] ^ w[i & 0xf]; + w[i & 0xf] = (w[i & 0xf] ^ d) + 0x3ddb2819; + b[h + 0] = (byte)(d >> 0); + b[h + 1] = (byte)(d >> 8); + b[h + 2] = (byte)(d >> 16); + b[h + 3] = (byte)(d >> 24); + h += 4; + } + Array.Clear(w, 0, 0x10); + byte[] j = Lzma.Decompress(b); + Array.Clear(b, 0, b.Length); + + GCHandle g = GCHandle.Alloc(j, GCHandleType.Pinned); + var z = (uint)(s % 0x8a5cb7); + for (int i = 0; i < j.Length; i++) { + j[i] ^= (byte)s; + if ((i & 0xff) == 0) + s = (s * s) % 0x8a5cb7; + } + return g; + } + + [STAThread] + static int Main(string[] args) { + var l = (uint)Mutation.KeyI0; + uint[] q = Mutation.Placeholder(new uint[Mutation.KeyI0]); + + GCHandle h = Decrypt(q, (uint)Mutation.KeyI1); + var b = (byte[])h.Target; + Assembly a = Assembly.Load(b); + Array.Clear(b, 0, b.Length); + h.Free(); + Array.Clear(q, 0, q.Length); + + var m = typeof(CompressorCompat).Module; + key = m.ResolveSignature(Mutation.KeyI2); + AppDomain.CurrentDomain.AssemblyResolve += Resolve; + + MethodBase e = a.ManifestModule.ResolveMethod(key[0] | (key[1] << 8) | (key[2] << 16) | (key[3] << 24)); + var g = new object[e.GetParameters().Length]; + if (g.Length != 0) + g[0] = args; + object r = e.Invoke(null, g); + if (r is int) + return (int)r; + return 0; + } + + static Assembly Resolve(object sender, ResolveEventArgs e) { + byte[] b = Encoding.UTF8.GetBytes(new AssemblyName(e.Name).FullName.ToUpperInvariant()); + + Stream m = null; + if (b.Length + 4 <= key.Length) { + for (int i = 0; i < b.Length; i++) + b[i] *= key[i + 4]; + string n = Convert.ToBase64String(b); + m = Assembly.GetEntryAssembly().GetManifestResourceStream(n); + } + if (m != null) { + var d = new uint[m.Length >> 2]; + var t = new byte[0x100]; + int r; + int o = 0; + while ((r = m.Read(t, 0, 0x100)) > 0) { + Buffer.BlockCopy(t, 0, d, o, r); + o += r; + } + uint s = 0x6fff61; + foreach (byte c in b) + s = s * 0x5e3f1f + c; + GCHandle h = Decrypt(d, s); + + var f = (byte[])h.Target; + Assembly a = Assembly.Load(f); + Array.Clear(f, 0, f.Length); + h.Free(); + Array.Clear(d, 0, d.Length); + + return a; + } + return null; + } + } +} \ No newline at end of file diff --git a/Confuser.Runtime/Confuser.Runtime.csproj b/Confuser.Runtime/Confuser.Runtime.csproj index 676dfe258..5fe5d23da 100644 --- a/Confuser.Runtime/Confuser.Runtime.csproj +++ b/Confuser.Runtime/Confuser.Runtime.csproj @@ -53,6 +53,7 @@ +