diff --git a/.gitignore b/.gitignore index beadc33d..fbc51a80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Visual Studio Cache files (starting with VS 2015) .vs/ +.temp # Launch Settings launchSettings.json diff --git a/Confuser.Protections/AntiTamper/AntiMode.cs b/Confuser.Protections/AntiTamper/AntiMode.cs index 5df4cdf6..4c28ea83 100644 --- a/Confuser.Protections/AntiTamper/AntiMode.cs +++ b/Confuser.Protections/AntiTamper/AntiMode.cs @@ -16,6 +16,7 @@ namespace Confuser.Protections.AntiTamper { internal class AntiMode : IModeHandler { uint c; + uint feedback; IKeyDeriver deriver; List methods; @@ -31,6 +32,7 @@ public void HandleInject(AntiTamperProtection parent, ConfuserContext context, P x = random.NextUInt32(); c = random.NextUInt32(); v = random.NextUInt32(); + feedback = random.NextUInt32(); name1 = random.NextUInt32() & 0x7f7f7f7f; name2 = random.NextUInt32() & 0x7f7f7f7f; @@ -77,8 +79,8 @@ public void HandleInject(AntiTamperProtection parent, ConfuserContext context, P initMethod.Body.Instructions.Add(instr); MutationHelper.InjectKeys(initMethod, - new[] { 0, 1, 2, 3, 4 }, - new[] { (int)(name1 * name2), (int)z, (int)x, (int)c, (int)v }); + new[] { 0, 1, 2, 3, 4, 5 }, + new[] { (int)(name1 * name2), (int)z, (int)x, (int)c, (int)v, (int)feedback }); var name = context.Registry.GetService(); var marker = context.Registry.GetService(); @@ -219,7 +221,7 @@ void EncryptSection(ModuleWriterBase writer) { for (uint i = 0; i < encSize; i++) { uint data = reader.ReadUInt32(); result[i] = data ^ key[i & 0xf]; - key[i & 0xf] = (key[i & 0xf] ^ data) + 0x3dbb2819; + key[i & 0xf] = (key[i & 0xf] ^ data) + feedback; } var byteResult = new byte[encSize << 2]; Buffer.BlockCopy(result, 0, byteResult, 0, byteResult.Length); diff --git a/Confuser.Protections/AntiTamper/NormalMode.cs b/Confuser.Protections/AntiTamper/NormalMode.cs index 7818271a..b73f57e2 100644 --- a/Confuser.Protections/AntiTamper/NormalMode.cs +++ b/Confuser.Protections/AntiTamper/NormalMode.cs @@ -16,6 +16,7 @@ namespace Confuser.Protections.AntiTamper { internal class NormalMode : IModeHandler { uint c; + uint feedback; IKeyDeriver deriver; List methods; @@ -31,6 +32,7 @@ public void HandleInject(AntiTamperProtection parent, ConfuserContext context, P x = random.NextUInt32(); c = random.NextUInt32(); v = random.NextUInt32(); + feedback = random.NextUInt32(); name1 = random.NextUInt32() & 0x7f7f7f7f; name2 = random.NextUInt32() & 0x7f7f7f7f; @@ -77,8 +79,8 @@ public void HandleInject(AntiTamperProtection parent, ConfuserContext context, P initMethod.Body.Instructions.Add(instr); MutationHelper.InjectKeys(initMethod, - new[] { 0, 1, 2, 3, 4 }, - new[] { (int)(name1 * name2), (int)z, (int)x, (int)c, (int)v }); + new[] { 0, 1, 2, 3, 4, 5 }, + new[] { (int)(name1 * name2), (int)z, (int)x, (int)c, (int)v, (int)feedback }); var name = context.Registry.GetService(); var marker = context.Registry.GetService(); @@ -220,7 +222,7 @@ void EncryptSection(ModuleWriterBase writer) { for (uint i = 0; i < encSize; i++) { uint data = reader.ReadUInt32(); result[i] = data ^ key[i & 0xf]; - key[i & 0xf] = (key[i & 0xf] ^ data) + 0x3dbb2819; + key[i & 0xf] = (key[i & 0xf] ^ data) + feedback; } var byteResult = new byte[encSize << 2]; Buffer.BlockCopy(result, 0, byteResult, 0, byteResult.Length); diff --git a/Confuser.Protections/Constants/CEContext.cs b/Confuser.Protections/Constants/CEContext.cs index c6feeb21..3e9254a4 100644 --- a/Confuser.Protections/Constants/CEContext.cs +++ b/Confuser.Protections/Constants/CEContext.cs @@ -35,6 +35,7 @@ internal class CEContext { public TypeDef CfgCtxType; public MethodDef CfgCtxCtor; public MethodDef CfgCtxNext; + public uint CfgCtxMultiplier; public Dictionary>> ReferenceRepl; } diff --git a/Confuser.Protections/Constants/ReferenceReplacer.cs b/Confuser.Protections/Constants/ReferenceReplacer.cs index 901cd76c..7083ea06 100644 --- a/Confuser.Protections/Constants/ReferenceReplacer.cs +++ b/Confuser.Protections/Constants/ReferenceReplacer.cs @@ -51,11 +51,11 @@ struct CFGState { public uint C; public uint D; - public CFGState(uint seed) { - A = seed *= 0x21412321; - B = seed *= 0x21412321; - C = seed *= 0x21412321; - D = seed *= 0x21412321; + public CFGState(uint seed, uint mult) { + A = seed *= mult; + B = seed *= mult; + C = seed *= mult; + D = seed *= mult; } public void UpdateExplicit(int id, uint value) { @@ -136,6 +136,15 @@ static void InjectStateType(CEContext ctx) { ctx.CfgCtxCtor = ctx.CfgCtxType.FindMethod(".ctor"); ctx.CfgCtxNext = ctx.CfgCtxType.FindMethod("Next"); + // Randomize the CFG state multiplier so the baked-in 0x21412321 literal + // no longer fingerprints the output. Must stay odd (invertible mod 2^32) and + // match the obfuscator-side CFGState computation (see CFGState.ctor). + ctx.CfgCtxMultiplier = ctx.Random.NextUInt32() | 1; + foreach (var instr in ctx.CfgCtxCtor.Body.Instructions) { + if (instr.OpCode == OpCodes.Ldc_I4 && (int)instr.Operand == 0x21412321) + instr.Operand = (int)ctx.CfgCtxMultiplier; + } + ctx.Name.MarkHelper(ctx.CfgCtxType, ctx.Marker, ctx.Protection); foreach (var def in ctx.CfgCtxType.Fields) ctx.Name.MarkHelper(def, ctx.Marker, ctx.Protection); @@ -212,7 +221,7 @@ static void InsertEmptyStateUpdate(CFGContext ctx, ControlFlowBlock block) { if (!ctx.StatesMap.TryGetValue(key.ExitState, out exit)) { // Create new exit state from random seed var seed = ctx.Random.NextUInt32(); - exit = new CFGState(seed); + exit = new CFGState(seed, ctx.Ctx.CfgCtxMultiplier); body.Instructions.Insert(targetIndex++, first = Instruction.Create(OpCodes.Ldloca, ctx.StateVariable)); body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Ldc_I4, (int)seed)); body.Instructions.Insert(targetIndex++, Instruction.Create(OpCodes.Call, ctx.Ctx.CfgCtxCtor)); @@ -301,7 +310,7 @@ static uint InsertStateGetAndUpdate(CFGContext ctx, ref int index, BlockKeyType if (targetState == null) { // Create new exit state from random seed var seed = ctx.Random.NextUInt32(); - currentState = new CFGState(seed); + currentState = new CFGState(seed, ctx.Ctx.CfgCtxMultiplier); body.Instructions.Insert(index++, Instruction.Create(OpCodes.Ldloca, ctx.StateVariable)); body.Instructions.Insert(index++, Instruction.Create(OpCodes.Dup)); body.Instructions.Insert(index++, Instruction.Create(OpCodes.Ldc_I4, (int)seed)); @@ -398,7 +407,7 @@ static void ReplaceCFG(MethodDef method, List> // Create new entry state uint blockSeed = ctx.Random.NextUInt32(); - currentState = new CFGState(blockSeed); + currentState = new CFGState(blockSeed, ctx.CfgCtxMultiplier); cfgCtx.StatesMap[key.EntryState] = currentState; var index = graph.Body.Instructions.IndexOf(graph[blockRef.Key].Header); diff --git a/Confuser.Runtime/AntiTamper.Anti.cs b/Confuser.Runtime/AntiTamper.Anti.cs index f1be244c..7a0a88e7 100644 --- a/Confuser.Runtime/AntiTamper.Anti.cs +++ b/Confuser.Runtime/AntiTamper.Anti.cs @@ -27,6 +27,7 @@ static unsafe void Initialize() { uint l = 0; var r = (uint*)(p + 0x18 + o); uint z = (uint)Mutation.KeyI1, x = (uint)Mutation.KeyI2, c = (uint)Mutation.KeyI3, v = (uint)Mutation.KeyI4; + uint fb = (uint)Mutation.KeyI5; CheckRemoteDebuggerPresent(Process.GetCurrentProcess().Handle, ref isDebuggerPresent); if (isDebuggerPresent) Environment.FailFast(null); @@ -80,7 +81,7 @@ static unsafe void Initialize() { uint h = 0; for (uint i = 0; i < l; i++) { *e ^= y[h & 0xf]; - y[h & 0xf] = (y[h & 0xf] ^ (*e++)) + 0x3dbb2819; + y[h & 0xf] = (y[h & 0xf] ^ (*e++)) + fb; CheckRemoteDebuggerPresent(Process.GetCurrentProcess().Handle, ref isDebuggerPresent); if (isDebuggerPresent) Environment.FailFast(null); diff --git a/Confuser.Runtime/AntiTamper.Normal.cs b/Confuser.Runtime/AntiTamper.Normal.cs index 6fc882ff..1e09da85 100644 --- a/Confuser.Runtime/AntiTamper.Normal.cs +++ b/Confuser.Runtime/AntiTamper.Normal.cs @@ -20,6 +20,7 @@ static unsafe void Initialize() { uint l = 0; var r = (uint*)(p + 0x18 + o); uint z = (uint)Mutation.KeyI1, x = (uint)Mutation.KeyI2, c = (uint)Mutation.KeyI3, v = (uint)Mutation.KeyI4; + uint fb = (uint)Mutation.KeyI5; for (int i = 0; i < s; i++) { uint g = (*r++) * (*r++); if (g == (uint)Mutation.KeyI0) { @@ -60,7 +61,7 @@ static unsafe void Initialize() { uint h = 0; for (uint i = 0; i < l; i++) { *e ^= y[h & 0xf]; - y[h & 0xf] = (y[h & 0xf] ^ (*e++)) + 0x3dbb2819; + y[h & 0xf] = (y[h & 0xf] ^ (*e++)) + fb; h++; } }