Improved self-protection of Confuser runtime

This commit is contained in:
Martin Karing 2020-04-11 18:09:00 +02:00
Родитель 56558b54f9
Коммит 7dd2eb75c3
4 изменённых файлов: 87 добавлений и 4 удалений

Просмотреть файл

@ -535,8 +535,9 @@ namespace Confuser.Core {
targetBody.Variables.Add(local.Value);
// Nop the call
int index = targetBody.Instructions.IndexOf(callInstruction);
targetBody.Instructions[index++].OpCode = OpCodes.Nop;
int index = targetBody.Instructions.IndexOf(callInstruction) + 1;
callInstruction.OpCode = OpCodes.Nop;
callInstruction.Operand = null;
var afterIndex = targetBody.Instructions[index];
// Find Exception handler index

Просмотреть файл

@ -155,7 +155,7 @@ namespace Confuser.Core {
/// <summary>
/// Returns a new string in which all occurrences of a specified string in
/// <paramref name="str" /><paramref name="str" /> are replaced with another specified string.
/// <paramref name="str" /> are replaced with another specified string.
/// </summary>
/// <returns>
/// A <see cref="string" /> equivalent to <paramref name="str" /> but with all instances of
@ -233,4 +233,4 @@ namespace Confuser.Core {
logger.EndProgress();
}
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
using System.Diagnostics.CodeAnalysis;
using Confuser.Core;
namespace Confuser.Protections {
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global", Justification = "Instantiated by reflection.")]
internal sealed class HardeningComponent : ConfuserComponent {
/// <inheritdoc />
public override string Name => "Protection Hardening";
/// <inheritdoc />
public override string Description => "This component improves the protection code, making it harder to circumvent it.";
/// <inheritdoc />
public override string Id => "harden";
/// <inheritdoc />
public override string FullId => "Cx.Harden";
/// <inheritdoc />
protected override void Initialize(ConfuserContext context) { }
/// <inheritdoc />
protected override void PopulatePipeline(ProtectionPipeline pipeline) =>
pipeline.InsertPreStage(PipelineStage.OptimizeMethods, new HardeningPhase(this));
}
}

Просмотреть файл

@ -0,0 +1,56 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Confuser.Core;
using Confuser.Core.Services;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
namespace Confuser.Protections {
internal sealed class HardeningPhase : ProtectionPhase {
//private new HardeningComponent Parent => (HardeningComponent)base.Parent;
/// <inheritdoc />
[SuppressMessage("ReSharper", "SuggestBaseTypeForParameter")]
public HardeningPhase(HardeningComponent parent) : base(parent) { }
/// <inheritdoc />
public override ProtectionTargets Targets => ProtectionTargets.Modules;
/// <inheritdoc />
public override string Name => "Hardening Phase";
/// <inheritdoc />
public override bool ProcessAll => true;
/// <inheritdoc />
protected override void Execute(ConfuserContext context, ProtectionParameters parameters) {
foreach (var module in parameters.Targets.OfType<ModuleDef>())
HardenMethod(context, module);
}
private static void HardenMethod(ConfuserContext context, ModuleDef module) {
var cctor = module.GlobalType.FindStaticConstructor();
if (cctor == null) {
context.Logger.Debug("No .cctor containing protection code found. Nothing to do.");
return;
}
if (!cctor.HasBody || !cctor.Body.HasInstructions) return;
var marker = context.Registry.GetService<IMarkerService>();
var instructions = cctor.Body.Instructions;
for (var i = instructions.Count - 1; i >= 0; i--) {
if (instructions[i].OpCode.Code != Code.Call) continue;
if (!(instructions[i].Operand is MethodDef targetMethod)) continue;
if (!targetMethod.IsStatic || targetMethod.DeclaringType != module.GlobalType) continue;
if (!marker.IsMarked(targetMethod) || !(marker.GetHelperParent(targetMethod) is Protection protection)) continue;
// Resource protection needs to rewrite the method during the write phase. Not compatible!
if (protection.FullId.Equals(ResourceProtection._FullId)) continue;
cctor.Body.MergeCall(instructions[i]);
targetMethod.DeclaringType.Methods.Remove(targetMethod);
}
}
}
}