backup
walon 2025-04-21 21:02:47 +08:00
parent 33a4f1bf2f
commit 35df6e520d
19 changed files with 301 additions and 8 deletions

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz
{
public class CleanUpInstructionPass : ObfuscationPassBase
{
public override void Process(ObfuscatorContext ctx)
{
// TODO remove all nop instructions
}
public override void Start(ObfuscatorContext ctx)
{
}
public override void Stop(ObfuscatorContext ctx)
{
}
}
}

View File

@ -2,13 +2,10 @@
{
public abstract class ObfuscationPassBase : IObfuscationPass
{
public virtual void Start(ObfuscatorContext ctx)
{
}
public abstract void Start(ObfuscatorContext ctx);
public abstract void Stop(ObfuscatorContext ctx);
public virtual void Stop(ObfuscatorContext ctx)
{
}
public abstract void Process(ObfuscatorContext ctx);
}
}

View File

@ -46,6 +46,7 @@ namespace Obfuz
_pipeline.AddPass(new DataVirtualizationPass());
_pipeline.AddPass(new RenameSymbolPass());
_pipeline.AddPass(new CleanUpInstructionPass());
_ctx = new ObfuscatorContext

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Virtualization
{
public class ConfigDataObfuscationPolicy : DataObfuscationPolicyBase
{
}
}

View File

@ -0,0 +1,37 @@
using dnlib.DotNet;
namespace Obfuz.Virtualization
{
public abstract class DataObfuscationPolicyBase : IDataObfuscationPolicy
{
public virtual bool NeedObfuscateMethod(MethodDef method)
{
return true;
}
public virtual bool NeedObfuscateInt(MethodDef method, int value)
{
return true;
}
public virtual bool NeedObfuscateLong(MethodDef method, long value)
{
return true;
}
public virtual bool NeedObfuscateFloat(MethodDef method, float value)
{
return true;
}
public virtual bool NeedObfuscateDouble(MethodDef method, double value)
{
return true;
}
public virtual bool NeedObfuscateString(MethodDef method, string value)
{
return true;
}
}
}

View File

@ -1,16 +1,149 @@
using System;
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Virtualization
{
public class DataVirtualizationPass : ObfuscationPassBase
{
public override void Process(ObfuscatorContext ctx)
private IDataObfuscationPolicy _dataObfuscatorPolicy;
private IDataObfuscator _dataObfuscator;
public override void Start(ObfuscatorContext ctx)
{
_dataObfuscatorPolicy = new ConfigDataObfuscationPolicy();
_dataObfuscator = new DefaultDataObfuscator();
}
public override void Stop(ObfuscatorContext ctx)
{
}
public override void Process(ObfuscatorContext ctx)
{
foreach (var ass in ctx.assemblies)
{
foreach (TypeDef type in ass.module.GetTypes())
{
foreach (MethodDef method in type.Methods)
{
if (!method.HasBody && !_dataObfuscatorPolicy.NeedObfuscateMethod(method))
{
continue;
}
// TODO if isGeneratedBy Obfuscator, continue
ObfuscateData(method);
}
}
}
}
private void ObfuscateData(MethodDef method)
{
IList<Instruction> instructions = method.Body.Instructions;
var obfuscatedInstructions = new List<Instruction>();
var resultInstructions = new List<Instruction>();
for (int i = 0; i < instructions.Count; )
{
Instruction inst = instructions[i];
bool obfuscated = false;
switch (inst.OpCode.OperandType)
{
case OperandType.InlineI:
case OperandType.ShortInlineI:
case OperandType.ShortInlineR:
case OperandType.InlineR:
{
obfuscatedInstructions.Clear();
object operand = inst.Operand;
if (operand is int)
{
int value = (int)operand;
if (_dataObfuscatorPolicy.NeedObfuscateInt(method, value))
{
_dataObfuscator.ObfuscateInt(method, value, obfuscatedInstructions);
obfuscated = true;
}
}
else if (operand is sbyte)
{
int value = (sbyte)operand;
if (_dataObfuscatorPolicy.NeedObfuscateInt(method, value))
{
_dataObfuscator.ObfuscateInt(method, value, obfuscatedInstructions);
obfuscated = true;
}
}
else if (operand is byte)
{
int value = (byte)operand;
if (_dataObfuscatorPolicy.NeedObfuscateInt(method, value))
{
_dataObfuscator.ObfuscateInt(method, value, obfuscatedInstructions);
obfuscated = true;
}
}
else if (operand is long)
{
long value = (long)operand;
if (_dataObfuscatorPolicy.NeedObfuscateLong(method, value))
{
_dataObfuscator.ObfuscateLong(method, value, obfuscatedInstructions);
obfuscated = true;
}
}
else if (operand is float)
{
float value = (float)operand;
if (_dataObfuscatorPolicy.NeedObfuscateFloat(method, value))
{
_dataObfuscator.ObfuscateFloat(method, value, obfuscatedInstructions);
obfuscated = true;
}
}
else if (operand is double)
{
double value = (double)operand;
if (_dataObfuscatorPolicy.NeedObfuscateDouble(method, value))
{
_dataObfuscator.ObfuscateDouble(method, value, obfuscatedInstructions);
obfuscated = true;
}
}
break;
}
case OperandType.InlineString:
{
//RuntimeHelpers.InitializeArray
string value = (string)inst.Operand;
if (_dataObfuscatorPolicy.NeedObfuscateString(method, value))
{
_dataObfuscator.ObfuscateString(method, value, obfuscatedInstructions);
obfuscated = true;
}
break;
}
default: throw new NotSupportedException($"Unsupported operand type: {inst.OpCode.OperandType} for instruction: {inst}");
}
resultInstructions.Add(inst);
i++;
if (obfuscated)
{
// current instruction may be the target of control flow instruction, so we can't remove it directly.
// we replace it with nop now, then remove it in CleanUpInstructionPass
inst.OpCode = OpCodes.Nop;
inst.Operand = null;
resultInstructions.AddRange(obfuscatedInstructions);
i += obfuscatedInstructions.Count + 1;
}
}
}
}
}

View File

@ -0,0 +1,40 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using System;
using System.Collections.Generic;
namespace Obfuz.Virtualization
{
public class DefaultDataObfuscator : IDataObfuscator
{
public bool ObfuscateInt(MethodDef method, int value, List<Instruction> obfuscatedInstructions)
{
return false;
}
public bool TryObfuscateLong(MethodDef method, long value, List<Instruction> obfuscatedInstructions)
{
return false;
}
public bool TryObfuscateFloat(MethodDef method, float value, List<Instruction> obfuscatedInstructions)
{
return false;
}
public bool TryObfuscateDouble(MethodDef method, double value, List<Instruction> obfuscatedInstructions)
{
return false;
}
public bool TryObfuscateBytes(MethodDef method, Array value, List<Instruction> obfuscatedInstructions)
{
return false;
}
public bool TryObfuscateString(MethodDef method, string value, List<Instruction> obfuscatedInstructions)
{
return false;
}
}
}

View File

@ -0,0 +1,24 @@
using dnlib.DotNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz.Virtualization
{
public interface IDataObfuscationPolicy
{
bool NeedObfuscateMethod(MethodDef method);
bool NeedObfuscateInt(MethodDef method, int value);
bool NeedObfuscateLong(MethodDef method, long value);
bool NeedObfuscateFloat(MethodDef method, float value);
bool NeedObfuscateDouble(MethodDef method, double value);
bool NeedObfuscateString(MethodDef method, string value);
}
}

View File

@ -0,0 +1,23 @@
using dnlib.DotNet;
using dnlib.DotNet.Emit;
using System;
using System.Collections.Generic;
namespace Obfuz.Virtualization
{
public interface IDataObfuscator
{
void ObfuscateInt(MethodDef method, int value, List<Instruction> obfuscatedInstructions);
void ObfuscateLong(MethodDef method, long value, List<Instruction> obfuscatedInstructions);
void ObfuscateFloat(MethodDef method, float value, List<Instruction> obfuscatedInstructions);
void ObfuscateDouble(MethodDef method, double value, List<Instruction> obfuscatedInstructions);
void ObfuscateString(MethodDef method, string value, List<Instruction> obfuscatedInstructions);
void ObfuscateBytes(MethodDef method, Array value, List<Instruction> obfuscatedInstructions);
}
}