重构 DataVirtualizationPass,移除重复代码
parent
7eb4b57b16
commit
b604810171
|
@ -37,8 +37,10 @@ namespace Obfuz.DynamicProxy
|
||||||
return _dynamicProxyPolicy.NeedDynamicProxyCallInMethod(method);
|
return _dynamicProxyPolicy.NeedDynamicProxyCallInMethod(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool TryObfuscateInstruction(MethodDef method, Instruction inst, IList<Instruction> instructions, int instructionIndex, List<Instruction> obfuscatedInstructions)
|
protected override bool TryObfuscateInstruction(MethodDef method, Instruction inst, IList<Instruction> instructions, int instructionIndex,
|
||||||
|
List<Instruction> outputInstructions, List<Instruction> totalFinalInstructions)
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
switch (inst.OpCode.Code)
|
switch (inst.OpCode.Code)
|
||||||
{
|
{
|
||||||
case Code.Call:
|
case Code.Call:
|
||||||
|
@ -48,7 +50,7 @@ namespace Obfuz.DynamicProxy
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_dynamicProxyObfuscator.Obfuscate(method, calledMethod, false, obfuscatedInstructions);
|
_dynamicProxyObfuscator.Obfuscate(method, calledMethod, false, outputInstructions);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Code.Callvirt:
|
case Code.Callvirt:
|
||||||
|
@ -62,7 +64,7 @@ namespace Obfuz.DynamicProxy
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_dynamicProxyObfuscator.Obfuscate(method, calledMethod, true, obfuscatedInstructions);
|
_dynamicProxyObfuscator.Obfuscate(method, calledMethod, true, outputInstructions);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default: return false;
|
default: return false;
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace Obfuz.Emit
|
||||||
|
|
||||||
public DynamicProxyMethodData Allocate(IMethod method)
|
public DynamicProxyMethodData Allocate(IMethod method)
|
||||||
{
|
{
|
||||||
return null;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Done()
|
public void Done()
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using System;
|
using dnlib.DotNet;
|
||||||
|
using dnlib.DotNet.Emit;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
@ -6,12 +8,9 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Obfuz.ExprObfuscation
|
namespace Obfuz.ExprObfuscation
|
||||||
{
|
{
|
||||||
public class ExprObfuscationPass : ObfuscationPassBase
|
public class ExprObfuscationPass : MethodBodyObfuscationPassBase
|
||||||
{
|
{
|
||||||
public override void Process(ObfuscatorContext ctx)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Start(ObfuscatorContext ctx)
|
public override void Start(ObfuscatorContext ctx)
|
||||||
{
|
{
|
||||||
|
@ -22,5 +21,15 @@ namespace Obfuz.ExprObfuscation
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool NeedObfuscateMethod(MethodDef method)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool TryObfuscateInstruction(MethodDef callingMethod, Instruction inst, IList<Instruction> instructions, int instructionIndex, List<Instruction> outputInstructions, List<Instruction> totalFinalInstructions)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,8 @@ namespace Obfuz
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected abstract bool TryObfuscateInstruction(MethodDef callingMethod, Instruction inst, IList<Instruction> instructions, int instructionIndex, List<Instruction> outputInstructions);
|
protected abstract bool TryObfuscateInstruction(MethodDef callingMethod, Instruction inst, IList<Instruction> instructions, int instructionIndex,
|
||||||
|
List<Instruction> outputInstructions, List<Instruction> totalFinalInstructions);
|
||||||
|
|
||||||
private void ObfuscateData(MethodDef method)
|
private void ObfuscateData(MethodDef method)
|
||||||
{
|
{
|
||||||
|
@ -45,18 +46,23 @@ namespace Obfuz
|
||||||
for (int i = 0; i < instructions.Count; i++)
|
for (int i = 0; i < instructions.Count; i++)
|
||||||
{
|
{
|
||||||
Instruction inst = instructions[i];
|
Instruction inst = instructions[i];
|
||||||
totalFinalInstructions.Add(inst);
|
outputInstructions.Clear();
|
||||||
if (TryObfuscateInstruction(method, inst, instructions, i, outputInstructions))
|
if (TryObfuscateInstruction(method, inst, instructions, i, outputInstructions, totalFinalInstructions))
|
||||||
{
|
{
|
||||||
// current instruction may be the target of control flow instruction, so we can't remove it directly.
|
// 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
|
// we replace it with nop now, then remove it in CleanUpInstructionPass
|
||||||
inst.OpCode = outputInstructions[0].OpCode;
|
inst.OpCode = outputInstructions[0].OpCode;
|
||||||
inst.Operand = outputInstructions[0].Operand;
|
inst.Operand = outputInstructions[0].Operand;
|
||||||
|
totalFinalInstructions.Add(inst);
|
||||||
for (int k = 1; k < outputInstructions.Count; k++)
|
for (int k = 1; k < outputInstructions.Count; k++)
|
||||||
{
|
{
|
||||||
totalFinalInstructions.Add(outputInstructions[k]);
|
totalFinalInstructions.Add(outputInstructions[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
totalFinalInstructions.Add(inst);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instructions.Clear();
|
instructions.Clear();
|
||||||
|
|
|
@ -11,7 +11,7 @@ using UnityEngine.Assertions;
|
||||||
namespace Obfuz.Virtualization
|
namespace Obfuz.Virtualization
|
||||||
{
|
{
|
||||||
|
|
||||||
public class DataVirtualizationPass : ObfuscationPassBase
|
public class DataVirtualizationPass : MethodBodyObfuscationPassBase
|
||||||
{
|
{
|
||||||
private IDataObfuscationPolicy _dataObfuscatorPolicy;
|
private IDataObfuscationPolicy _dataObfuscatorPolicy;
|
||||||
private IDataObfuscator _dataObfuscator;
|
private IDataObfuscator _dataObfuscator;
|
||||||
|
@ -27,159 +27,113 @@ namespace Obfuz.Virtualization
|
||||||
_dataObfuscator.Stop();
|
_dataObfuscator.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Process(ObfuscatorContext ctx)
|
protected override bool NeedObfuscateMethod(MethodDef method)
|
||||||
{
|
{
|
||||||
foreach (var ass in ctx.assemblies)
|
return _dataObfuscatorPolicy.NeedObfuscateMethod(method);
|
||||||
{
|
|
||||||
// ToArray to avoid modify list exception
|
|
||||||
foreach (TypeDef type in ass.module.GetTypes().ToArray())
|
|
||||||
{
|
|
||||||
if (type.Name.StartsWith("$Obfuz$"))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// ToArray to avoid modify list exception
|
|
||||||
foreach (MethodDef method in type.Methods.ToArray())
|
|
||||||
{
|
|
||||||
if (!method.HasBody || method.Name.StartsWith("$Obfuz$") || !_dataObfuscatorPolicy.NeedObfuscateMethod(method))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// TODO if isGeneratedBy Obfuscator, continue
|
|
||||||
ObfuscateData(method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ObfuscateData(MethodDef method)
|
protected override bool TryObfuscateInstruction(MethodDef method, Instruction inst, IList<Instruction> instructions, int instructionIndex,
|
||||||
|
List<Instruction> outputInstructions, List<Instruction> totalFinalInstructions)
|
||||||
{
|
{
|
||||||
IList<Instruction> instructions = method.Body.Instructions;
|
switch (inst.OpCode.OperandType)
|
||||||
var obfuscatedInstructions = new List<Instruction>();
|
|
||||||
var resultInstructions = new List<Instruction>();
|
|
||||||
for (int i = 0; i < instructions.Count; i++)
|
|
||||||
{
|
{
|
||||||
Instruction inst = instructions[i];
|
case OperandType.InlineI:
|
||||||
bool obfuscated = false;
|
case OperandType.InlineI8:
|
||||||
switch (inst.OpCode.OperandType)
|
case OperandType.ShortInlineI:
|
||||||
|
case OperandType.ShortInlineR:
|
||||||
|
case OperandType.InlineR:
|
||||||
{
|
{
|
||||||
case OperandType.InlineI:
|
object operand = inst.Operand;
|
||||||
case OperandType.InlineI8:
|
if (operand is int)
|
||||||
case OperandType.ShortInlineI:
|
|
||||||
case OperandType.ShortInlineR:
|
|
||||||
case OperandType.InlineR:
|
|
||||||
{
|
{
|
||||||
obfuscatedInstructions.Clear();
|
int value = (int)operand;
|
||||||
object operand = inst.Operand;
|
if (_dataObfuscatorPolicy.NeedObfuscateInt(method, value))
|
||||||
if (operand is int)
|
|
||||||
{
|
{
|
||||||
int value = (int)operand;
|
_dataObfuscator.ObfuscateInt(method, value, outputInstructions);
|
||||||
if (_dataObfuscatorPolicy.NeedObfuscateInt(method, value))
|
return true;
|
||||||
{
|
|
||||||
_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:
|
else if (operand is sbyte)
|
||||||
{
|
{
|
||||||
obfuscatedInstructions.Clear();
|
int value = (sbyte)operand;
|
||||||
//RuntimeHelpers.InitializeArray
|
if (_dataObfuscatorPolicy.NeedObfuscateInt(method, value))
|
||||||
string value = (string)inst.Operand;
|
|
||||||
if (_dataObfuscatorPolicy.NeedObfuscateString(method, value))
|
|
||||||
{
|
{
|
||||||
_dataObfuscator.ObfuscateString(method, value, obfuscatedInstructions);
|
_dataObfuscator.ObfuscateInt(method, value, outputInstructions);
|
||||||
obfuscated = true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case OperandType.InlineMethod:
|
else if (operand is byte)
|
||||||
{
|
{
|
||||||
if (((IMethod)inst.Operand).FullName == "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)")
|
int value = (byte)operand;
|
||||||
|
if (_dataObfuscatorPolicy.NeedObfuscateInt(method, value))
|
||||||
{
|
{
|
||||||
Instruction prevInst = instructions[i - 1];
|
_dataObfuscator.ObfuscateInt(method, value, outputInstructions);
|
||||||
if (prevInst.OpCode.Code == Code.Ldtoken)
|
return true;
|
||||||
{
|
|
||||||
IField rvaField = (IField)prevInst.Operand;
|
|
||||||
FieldDef ravFieldDef = rvaField.ResolveFieldDefThrow();
|
|
||||||
byte[] data = ravFieldDef.InitialValue;
|
|
||||||
if (data != null && _dataObfuscatorPolicy.NeedObfuscateArray(method, data))
|
|
||||||
{
|
|
||||||
// remove prev ldtoken instruction
|
|
||||||
Assert.AreEqual(Code.Ldtoken, resultInstructions[resultInstructions.Count - 1].OpCode.Code);
|
|
||||||
resultInstructions.RemoveAt(resultInstructions.Count - 1);
|
|
||||||
_dataObfuscator.ObfuscateBytes(method, data, obfuscatedInstructions);
|
|
||||||
obfuscated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else if (operand is long)
|
||||||
|
{
|
||||||
|
long value = (long)operand;
|
||||||
|
if (_dataObfuscatorPolicy.NeedObfuscateLong(method, value))
|
||||||
|
{
|
||||||
|
_dataObfuscator.ObfuscateLong(method, value, outputInstructions);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (operand is float)
|
||||||
|
{
|
||||||
|
float value = (float)operand;
|
||||||
|
if (_dataObfuscatorPolicy.NeedObfuscateFloat(method, value))
|
||||||
|
{
|
||||||
|
_dataObfuscator.ObfuscateFloat(method, value, outputInstructions);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (operand is double)
|
||||||
|
{
|
||||||
|
double value = (double)operand;
|
||||||
|
if (_dataObfuscatorPolicy.NeedObfuscateDouble(method, value))
|
||||||
|
{
|
||||||
|
_dataObfuscator.ObfuscateDouble(method, value, outputInstructions);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
resultInstructions.Add(inst);
|
case OperandType.InlineString:
|
||||||
if (obfuscated)
|
|
||||||
{
|
{
|
||||||
// current instruction may be the target of control flow instruction, so we can't remove it directly.
|
//RuntimeHelpers.InitializeArray
|
||||||
// we replace it with nop now, then remove it in CleanUpInstructionPass
|
string value = (string)inst.Operand;
|
||||||
inst.OpCode = obfuscatedInstructions[0].OpCode;
|
if (_dataObfuscatorPolicy.NeedObfuscateString(method, value))
|
||||||
inst.Operand = obfuscatedInstructions[0].Operand;
|
|
||||||
for (int k = 1; k < obfuscatedInstructions.Count; k++)
|
|
||||||
{
|
{
|
||||||
resultInstructions.Add(obfuscatedInstructions[k]);
|
_dataObfuscator.ObfuscateString(method, value, outputInstructions);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
case OperandType.InlineMethod:
|
||||||
|
{
|
||||||
instructions.Clear();
|
if (((IMethod)inst.Operand).FullName == "System.Void System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)")
|
||||||
foreach (var obInst in resultInstructions)
|
{
|
||||||
{
|
Instruction prevInst = instructions[instructionIndex - 1];
|
||||||
instructions.Add(obInst);
|
if (prevInst.OpCode.Code == Code.Ldtoken)
|
||||||
|
{
|
||||||
|
IField rvaField = (IField)prevInst.Operand;
|
||||||
|
FieldDef ravFieldDef = rvaField.ResolveFieldDefThrow();
|
||||||
|
byte[] data = ravFieldDef.InitialValue;
|
||||||
|
if (data != null && _dataObfuscatorPolicy.NeedObfuscateArray(method, data))
|
||||||
|
{
|
||||||
|
// remove prev ldtoken instruction
|
||||||
|
Assert.AreEqual(Code.Ldtoken, totalFinalInstructions[totalFinalInstructions.Count - 1].OpCode.Code);
|
||||||
|
totalFinalInstructions.RemoveAt(totalFinalInstructions.Count - 1);
|
||||||
|
_dataObfuscator.ObfuscateBytes(method, data, outputInstructions);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue