支持EvalStackObfus
parent
cbf9ab7d68
commit
67990f841a
|
@ -651,7 +651,7 @@ namespace Obfuz.Emit
|
||||||
}
|
}
|
||||||
case Code.Isinst:
|
case Code.Isinst:
|
||||||
{
|
{
|
||||||
PushStack(newPushedDatas, EvalDataType.Int32);
|
PushStack(newPushedDatas, EvalDataType.Ref);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Code.Unbox:
|
case Code.Unbox:
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4e82ef0b94e10314cbba0daabfdefe32
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,150 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using Obfuz.Conf;
|
||||||
|
using Obfuz.Settings;
|
||||||
|
using Obfuz.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
|
using UnityEditor.VersionControl;
|
||||||
|
|
||||||
|
namespace Obfuz.ObfusPasses.EvalStackObfus
|
||||||
|
{
|
||||||
|
struct ObfuscationRuleData
|
||||||
|
{
|
||||||
|
public readonly ObfuscationLevel obfuscationLevel;
|
||||||
|
public readonly float obfuscationPercentage;
|
||||||
|
public ObfuscationRuleData(ObfuscationLevel level, float percentage)
|
||||||
|
{
|
||||||
|
obfuscationLevel = level;
|
||||||
|
obfuscationPercentage = percentage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IObfuscationPolicy
|
||||||
|
{
|
||||||
|
bool NeedObfuscate(MethodDef method);
|
||||||
|
|
||||||
|
ObfuscationRuleData GetObfuscationRuleData(MethodDef method);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ObfuscationPolicyBase : IObfuscationPolicy
|
||||||
|
{
|
||||||
|
public abstract bool NeedObfuscate(MethodDef method);
|
||||||
|
|
||||||
|
public abstract ObfuscationRuleData GetObfuscationRuleData(MethodDef method);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfigurableObfuscationPolicy : ObfuscationPolicyBase
|
||||||
|
{
|
||||||
|
class ObfuscationRule : IRule<ObfuscationRule>
|
||||||
|
{
|
||||||
|
public ObfuscationLevel? obfuscationLevel;
|
||||||
|
public float? obfuscationPercentage;
|
||||||
|
|
||||||
|
public void InheritParent(ObfuscationRule parentRule)
|
||||||
|
{
|
||||||
|
if (obfuscationLevel == null)
|
||||||
|
obfuscationLevel = parentRule.obfuscationLevel;
|
||||||
|
if (obfuscationPercentage == null)
|
||||||
|
obfuscationPercentage = parentRule.obfuscationPercentage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MethodSpec : MethodRuleBase<ObfuscationRule>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class TypeSpec : TypeRuleBase<MethodSpec, ObfuscationRule>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
class AssemblySpec : AssemblyRuleBase<TypeSpec, MethodSpec, ObfuscationRule>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly ObfuscationRule s_default = new ObfuscationRule()
|
||||||
|
{
|
||||||
|
obfuscationLevel = ObfuscationLevel.Basic,
|
||||||
|
obfuscationPercentage = 0.5f,
|
||||||
|
};
|
||||||
|
|
||||||
|
private ObfuscationRule _global;
|
||||||
|
|
||||||
|
private readonly XmlAssemblyTypeMethodRuleParser<AssemblySpec, TypeSpec, MethodSpec, ObfuscationRule> _xmlParser;
|
||||||
|
|
||||||
|
private readonly Dictionary<MethodDef, ObfuscationRule> _methodRuleCache = new Dictionary<MethodDef, ObfuscationRule>();
|
||||||
|
|
||||||
|
public ConfigurableObfuscationPolicy(List<string> toObfuscatedAssemblyNames, List<string> xmlConfigFiles)
|
||||||
|
{
|
||||||
|
_xmlParser = new XmlAssemblyTypeMethodRuleParser<AssemblySpec, TypeSpec, MethodSpec, ObfuscationRule>(
|
||||||
|
toObfuscatedAssemblyNames, ParseObfuscationRule, ParseGlobal);
|
||||||
|
LoadConfigs(xmlConfigFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadConfigs(List<string> configFiles)
|
||||||
|
{
|
||||||
|
_xmlParser.LoadConfigs(configFiles);
|
||||||
|
|
||||||
|
if (_global == null)
|
||||||
|
{
|
||||||
|
_global = s_default;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_global.InheritParent(s_default);
|
||||||
|
}
|
||||||
|
_xmlParser.InheritParentRules(_global);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseGlobal(string configFile, XmlElement ele)
|
||||||
|
{
|
||||||
|
switch (ele.Name)
|
||||||
|
{
|
||||||
|
case "global": _global = ParseObfuscationRule(configFile, ele); break;
|
||||||
|
default: throw new Exception($"Invalid xml file {configFile}, unknown node {ele.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObfuscationLevel ParseObfuscationLevel(string str)
|
||||||
|
{
|
||||||
|
return (ObfuscationLevel)Enum.Parse(typeof(ObfuscationLevel), str);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObfuscationRule ParseObfuscationRule(string configFile, XmlElement ele)
|
||||||
|
{
|
||||||
|
var rule = new ObfuscationRule();
|
||||||
|
if (ele.HasAttribute("obfuscationLevel"))
|
||||||
|
{
|
||||||
|
rule.obfuscationLevel = ParseObfuscationLevel(ele.GetAttribute("obfuscationLevel"));
|
||||||
|
}
|
||||||
|
if (ele.HasAttribute("obfuscationPercentage"))
|
||||||
|
{
|
||||||
|
rule.obfuscationPercentage = float.Parse(ele.GetAttribute("obfuscationPercentage"));
|
||||||
|
}
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObfuscationRule GetMethodObfuscationRule(MethodDef method)
|
||||||
|
{
|
||||||
|
if (!_methodRuleCache.TryGetValue(method, out var rule))
|
||||||
|
{
|
||||||
|
rule = _xmlParser.GetMethodRule(method, s_default);
|
||||||
|
_methodRuleCache[method] = rule;
|
||||||
|
}
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool NeedObfuscate(MethodDef method)
|
||||||
|
{
|
||||||
|
ObfuscationRule rule = GetMethodObfuscationRule(method);
|
||||||
|
return rule.obfuscationLevel.Value > ObfuscationLevel.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ObfuscationRuleData GetObfuscationRuleData(MethodDef method)
|
||||||
|
{
|
||||||
|
var rule = GetMethodObfuscationRule(method);
|
||||||
|
return new ObfuscationRuleData(rule.obfuscationLevel.Value, rule.obfuscationPercentage.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8a2603d51f31a134d90599d33664f6c7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,225 @@
|
||||||
|
using dnlib.DotNet.Emit;
|
||||||
|
using Obfuz.Utils;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Obfuz.ObfusPasses.EvalStackObfus
|
||||||
|
{
|
||||||
|
class DefaultObfuscator : ObfuscatorBase
|
||||||
|
{
|
||||||
|
public override bool ObfuscateInt(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||||
|
{
|
||||||
|
IRandom random = ctx.localRandom;
|
||||||
|
switch (random.NextInt(4))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// x = x + a
|
||||||
|
int a = 0;
|
||||||
|
float constProbability = 0f;
|
||||||
|
ConstObfusUtil.LoadConstInt(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// x = x * a * ra
|
||||||
|
int a = random.NextInt() | 0x1; // Ensure a is not zero
|
||||||
|
int ra = MathUtil.ModInverse32(a);
|
||||||
|
float constProbability = 0.5f;
|
||||||
|
ConstObfusUtil.LoadConstInt(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstInt(ra, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// x = (x * a + b) * ra - (b * ra)
|
||||||
|
int a = random.NextInt() | 0x1; // Ensure a is not zero
|
||||||
|
int ra = MathUtil.ModInverse32(a);
|
||||||
|
int b = random.NextInt();
|
||||||
|
int b_ra = -b * ra;
|
||||||
|
float constProbability = 0.5f;
|
||||||
|
ConstObfusUtil.LoadConstInt(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstInt(b, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
ConstObfusUtil.LoadConstInt(ra, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstInt(b_ra, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
// x = ((x + a) * b + c) * rb - (a*b + c) * rb
|
||||||
|
int a = random.NextInt();
|
||||||
|
int b = random.NextInt() | 0x1; // Ensure b is not zero
|
||||||
|
int rb = MathUtil.ModInverse32(b);
|
||||||
|
int c = random.NextInt();
|
||||||
|
int r = -(a * b + c) * rb;
|
||||||
|
float constProbability = 0.5f;
|
||||||
|
ConstObfusUtil.LoadConstInt(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
ConstObfusUtil.LoadConstInt(b, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstInt(c, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
ConstObfusUtil.LoadConstInt(rb, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstInt(r, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ObfuscateLong(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||||
|
{
|
||||||
|
IRandom random = ctx.localRandom;
|
||||||
|
switch (random.NextInt(4))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// x = x + a
|
||||||
|
long a = 0;
|
||||||
|
float constProbability = 0f;
|
||||||
|
ConstObfusUtil.LoadConstLong(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// x = x * a * ra
|
||||||
|
long a = random.NextLong() | 0x1L; // Ensure a is not zero
|
||||||
|
long ra = MathUtil.ModInverse64(a);
|
||||||
|
float constProbability = 0.5f;
|
||||||
|
ConstObfusUtil.LoadConstLong(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstLong(ra, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// x = (x * a + b) * ra - (b * ra)
|
||||||
|
long a = random.NextLong() | 0x1L; // Ensure a is not zero
|
||||||
|
long ra = MathUtil.ModInverse64(a);
|
||||||
|
long b = random.NextLong();
|
||||||
|
long b_ra = -b * ra;
|
||||||
|
float constProbability = 0.5f;
|
||||||
|
ConstObfusUtil.LoadConstLong(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstLong(b, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
ConstObfusUtil.LoadConstLong(ra, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstLong(b_ra, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
// x = ((x + a) * b + c) * rb - (a*b + c) * rb
|
||||||
|
long a = random.NextLong();
|
||||||
|
long b = random.NextLong() | 0x1L; // Ensure b is not zero
|
||||||
|
long rb = MathUtil.ModInverse64(b);
|
||||||
|
long c = random.NextLong();
|
||||||
|
long r = -(a * b + c) * rb;
|
||||||
|
float constProbability = 0.5f;
|
||||||
|
ConstObfusUtil.LoadConstLong(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
ConstObfusUtil.LoadConstLong(b, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstLong(c, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
ConstObfusUtil.LoadConstLong(rb, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
ConstObfusUtil.LoadConstLong(r, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ObfuscateFloat(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||||
|
{
|
||||||
|
IRandom random = ctx.localRandom;
|
||||||
|
switch (random.NextInt(3))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// x = x + 0f
|
||||||
|
float a = 0.0f;
|
||||||
|
float constProbability = 0f;
|
||||||
|
ConstObfusUtil.LoadConstFloat(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// x = x * 1f;
|
||||||
|
float a = 1.0f;
|
||||||
|
float constProbability = 0f;
|
||||||
|
ConstObfusUtil.LoadConstFloat(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// x = (x + a) * b; a = 0.0f, b = 1.0f
|
||||||
|
float a = 0.0f;
|
||||||
|
float b = 1.0f;
|
||||||
|
float constProbability = 0f;
|
||||||
|
ConstObfusUtil.LoadConstFloat(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
ConstObfusUtil.LoadConstFloat(b, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ObfuscateDouble(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx)
|
||||||
|
{
|
||||||
|
IRandom random = ctx.localRandom;
|
||||||
|
switch (random.NextInt(3))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// x = x + 0.0
|
||||||
|
double a = 0.0;
|
||||||
|
float constProbability = 0f;
|
||||||
|
ConstObfusUtil.LoadConstDouble(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// x = x * 1.0;
|
||||||
|
double a = 1.0;
|
||||||
|
float constProbability = 0f;
|
||||||
|
ConstObfusUtil.LoadConstDouble(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
// x = (x + a) * b; a = 0.0, b = 1.0
|
||||||
|
double a = 0.0;
|
||||||
|
double b = 1.0;
|
||||||
|
float constProbability = 0f;
|
||||||
|
ConstObfusUtil.LoadConstDouble(a, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Add));
|
||||||
|
ConstObfusUtil.LoadConstDouble(b, random, constProbability, ctx.constFieldAllocator, outputInsts);
|
||||||
|
outputInsts.Add(Instruction.Create(OpCodes.Mul));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5200244f403139c40b578b2e845508f2
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,117 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using dnlib.DotNet.Emit;
|
||||||
|
using Obfuz.Data;
|
||||||
|
using Obfuz.Emit;
|
||||||
|
using Obfuz.Settings;
|
||||||
|
using Obfuz.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Obfuz.ObfusPasses.EvalStackObfus
|
||||||
|
{
|
||||||
|
class ObfusMethodContext
|
||||||
|
{
|
||||||
|
public MethodDef method;
|
||||||
|
public EvalStackCalculator evalStackCalculator;
|
||||||
|
public LocalVariableAllocator localVariableAllocator;
|
||||||
|
public IRandom localRandom;
|
||||||
|
public EncryptionScopeInfo encryptionScope;
|
||||||
|
public DefaultMetadataImporter importer;
|
||||||
|
public ModuleConstFieldAllocator constFieldAllocator;
|
||||||
|
public float obfuscationPercentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class EvalStackObfusPass : ObfuscationMethodPassBase
|
||||||
|
{
|
||||||
|
private readonly EvalStackObfuscationSettingsFacade _settings;
|
||||||
|
|
||||||
|
private IObfuscationPolicy _obfuscationPolicy;
|
||||||
|
private IObfuscator _obfuscator;
|
||||||
|
|
||||||
|
public EvalStackObfusPass(EvalStackObfuscationSettingsFacade settings)
|
||||||
|
{
|
||||||
|
_settings = settings;
|
||||||
|
_obfuscator = new DefaultObfuscator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ObfuscationPassType Type => ObfuscationPassType.EvalStackObfus;
|
||||||
|
|
||||||
|
public override void Start()
|
||||||
|
{
|
||||||
|
ObfuscationPassContext ctx = ObfuscationPassContext.Current;
|
||||||
|
_obfuscationPolicy = new ConfigurableObfuscationPolicy(
|
||||||
|
ctx.coreSettings.assembliesToObfuscate,
|
||||||
|
_settings.ruleFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Stop()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool NeedObfuscateMethod(MethodDef method)
|
||||||
|
{
|
||||||
|
return _obfuscationPolicy.NeedObfuscate(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool TryObfuscateInstruction(Instruction inst, EvalDataType dataType, List<Instruction> outputInstructions, ObfusMethodContext ctx)
|
||||||
|
{
|
||||||
|
switch (dataType)
|
||||||
|
{
|
||||||
|
case EvalDataType.Int32: return _obfuscator.ObfuscateInt(inst, outputInstructions, ctx);
|
||||||
|
case EvalDataType.Int64: return _obfuscator.ObfuscateLong(inst, outputInstructions, ctx);
|
||||||
|
case EvalDataType.Float: return _obfuscator.ObfuscateFloat(inst, outputInstructions, ctx);
|
||||||
|
case EvalDataType.Double: return _obfuscator.ObfuscateDouble(inst, outputInstructions, ctx);
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ObfuscateData(MethodDef method)
|
||||||
|
{
|
||||||
|
Debug.Log($"Obfuscating method: {method.FullName} with EvalStackObfusPass");
|
||||||
|
IList<Instruction> instructions = method.Body.Instructions;
|
||||||
|
var outputInstructions = new List<Instruction>();
|
||||||
|
var totalFinalInstructions = new List<Instruction>();
|
||||||
|
|
||||||
|
ObfuscationPassContext ctx = ObfuscationPassContext.Current;
|
||||||
|
var calc = new EvalStackCalculator(method);
|
||||||
|
var encryptionScope = ctx.encryptionScopeProvider.GetScope(method.Module);
|
||||||
|
var ruleData = _obfuscationPolicy.GetObfuscationRuleData(method);
|
||||||
|
var localRandom = encryptionScope.localRandomCreator(MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(method));
|
||||||
|
var obfusMethodCtx = new ObfusMethodContext
|
||||||
|
{
|
||||||
|
method = method,
|
||||||
|
evalStackCalculator = calc,
|
||||||
|
localVariableAllocator = new LocalVariableAllocator(method),
|
||||||
|
encryptionScope = encryptionScope,
|
||||||
|
constFieldAllocator = ctx.constFieldAllocator.GetModuleAllocator(method.Module),
|
||||||
|
localRandom = localRandom,
|
||||||
|
importer = ctx.moduleEntityManager.GetDefaultModuleMetadataImporter(method.Module, ctx.encryptionScopeProvider),
|
||||||
|
obfuscationPercentage = ruleData.obfuscationPercentage,
|
||||||
|
};
|
||||||
|
for (int i = 0; i < instructions.Count; i++)
|
||||||
|
{
|
||||||
|
Instruction inst = instructions[i];
|
||||||
|
totalFinalInstructions.Add(inst);
|
||||||
|
if (calc.TryGetPushResult(inst, out EvalDataType dataType) && localRandom.NextInPercentage(ruleData.obfuscationPercentage))
|
||||||
|
{
|
||||||
|
outputInstructions.Clear();
|
||||||
|
if (TryObfuscateInstruction(inst, dataType, outputInstructions, obfusMethodCtx))
|
||||||
|
{
|
||||||
|
totalFinalInstructions.AddRange(outputInstructions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instructions.Clear();
|
||||||
|
foreach (var obInst in totalFinalInstructions)
|
||||||
|
{
|
||||||
|
instructions.Add(obInst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9fa7d3313f260794da2cc36dadaf4fb4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -0,0 +1,26 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
using dnlib.DotNet.Emit;
|
||||||
|
using Obfuz.Emit;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Obfuz.ObfusPasses.EvalStackObfus
|
||||||
|
{
|
||||||
|
interface IObfuscator
|
||||||
|
{
|
||||||
|
bool ObfuscateInt(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||||
|
|
||||||
|
bool ObfuscateLong(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||||
|
|
||||||
|
bool ObfuscateFloat(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||||
|
|
||||||
|
bool ObfuscateDouble(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ObfuscatorBase : IObfuscator
|
||||||
|
{
|
||||||
|
public abstract bool ObfuscateInt(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||||
|
public abstract bool ObfuscateLong(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||||
|
public abstract bool ObfuscateFloat(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||||
|
public abstract bool ObfuscateDouble(Instruction inst, List<Instruction> outputInsts, ObfusMethodContext ctx);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 17a9f3181d9711f4ca1d0cfb9e813bb0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -115,7 +115,7 @@ namespace Obfuz.ObfusPasses.ExprObfus
|
||||||
|
|
||||||
protected override void ObfuscateData(MethodDef method)
|
protected override void ObfuscateData(MethodDef method)
|
||||||
{
|
{
|
||||||
Debug.Log($"Obfuscating method: {method.FullName} with ExprObfusPass");
|
//Debug.Log($"Obfuscating method: {method.FullName} with ExprObfusPass");
|
||||||
IList<Instruction> instructions = method.Body.Instructions;
|
IList<Instruction> instructions = method.Body.Instructions;
|
||||||
var outputInstructions = new List<Instruction>();
|
var outputInstructions = new List<Instruction>();
|
||||||
var totalFinalInstructions = new List<Instruction>();
|
var totalFinalInstructions = new List<Instruction>();
|
||||||
|
|
|
@ -14,11 +14,12 @@ namespace Obfuz.ObfusPasses
|
||||||
CallObfus = 0x200,
|
CallObfus = 0x200,
|
||||||
ExprObfus = 0x400,
|
ExprObfus = 0x400,
|
||||||
ControlFlowObfus = 0x800,
|
ControlFlowObfus = 0x800,
|
||||||
|
EvalStackObfus = 0x1000,
|
||||||
|
|
||||||
AllObfus = SymbolObfus | CallObfus | ExprObfus | ControlFlowObfus,
|
AllObfus = SymbolObfus | CallObfus | ExprObfus | ControlFlowObfus | EvalStackObfus,
|
||||||
AllEncrypt = ConstEncrypt | FieldEncrypt,
|
AllEncrypt = ConstEncrypt | FieldEncrypt,
|
||||||
|
|
||||||
MethodBodyObfusOrEncrypt = ConstEncrypt | CallObfus | ExprObfus | ControlFlowObfus,
|
MethodBodyObfusOrEncrypt = ConstEncrypt | CallObfus | ExprObfus | ControlFlowObfus | EvalStackObfus,
|
||||||
|
|
||||||
All = ~0,
|
All = ~0,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using Obfuz.ObfusPasses;
|
using Obfuz.ObfusPasses;
|
||||||
using Obfuz.ObfusPasses.CallObfus;
|
using Obfuz.ObfusPasses.CallObfus;
|
||||||
using Obfuz.ObfusPasses.ConstEncrypt;
|
using Obfuz.ObfusPasses.ConstEncrypt;
|
||||||
|
using Obfuz.ObfusPasses.EvalStackObfus;
|
||||||
using Obfuz.ObfusPasses.ExprObfus;
|
using Obfuz.ObfusPasses.ExprObfus;
|
||||||
using Obfuz.ObfusPasses.FieldEncrypt;
|
using Obfuz.ObfusPasses.FieldEncrypt;
|
||||||
using Obfuz.ObfusPasses.SymbolObfus;
|
using Obfuz.ObfusPasses.SymbolObfus;
|
||||||
|
@ -169,6 +170,10 @@ namespace Obfuz
|
||||||
{
|
{
|
||||||
builder.AddPass(new ConstEncryptPass(settings.constEncryptSettings.ToFacade()));
|
builder.AddPass(new ConstEncryptPass(settings.constEncryptSettings.ToFacade()));
|
||||||
}
|
}
|
||||||
|
if (obfuscationPasses.HasFlag(ObfuscationPassType.EvalStackObfus))
|
||||||
|
{
|
||||||
|
builder.AddPass(new EvalStackObfusPass(settings.evalStackObfusSettings.ToFacade()));
|
||||||
|
}
|
||||||
if (obfuscationPasses.HasFlag(ObfuscationPassType.FieldEncrypt))
|
if (obfuscationPasses.HasFlag(ObfuscationPassType.FieldEncrypt))
|
||||||
{
|
{
|
||||||
builder.AddPass(new FieldEncryptPass(settings.fieldEncryptSettings.ToFacade()));
|
builder.AddPass(new FieldEncryptPass(settings.fieldEncryptSettings.ToFacade()));
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Obfuz.Settings
|
||||||
|
{
|
||||||
|
|
||||||
|
public class EvalStackObfuscationSettingsFacade
|
||||||
|
{
|
||||||
|
public List<string> ruleFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class EvalStackObfuscationSettings
|
||||||
|
{
|
||||||
|
[Tooltip("rule config xml files")]
|
||||||
|
public string[] ruleFiles;
|
||||||
|
|
||||||
|
public EvalStackObfuscationSettingsFacade ToFacade()
|
||||||
|
{
|
||||||
|
return new EvalStackObfuscationSettingsFacade
|
||||||
|
{
|
||||||
|
ruleFiles = new List<string>(ruleFiles ?? Array.Empty<string>()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3c985896b3a4ef84292cb0cfbc79dc10
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -28,6 +28,9 @@ namespace Obfuz.Settings
|
||||||
[Tooltip("const encryption settings")]
|
[Tooltip("const encryption settings")]
|
||||||
public ConstEncryptionSettings constEncryptSettings;
|
public ConstEncryptionSettings constEncryptSettings;
|
||||||
|
|
||||||
|
[Tooltip("eval stack obfuscation settings")]
|
||||||
|
public EvalStackObfuscationSettings evalStackObfusSettings;
|
||||||
|
|
||||||
[Tooltip("field encryption settings")]
|
[Tooltip("field encryption settings")]
|
||||||
public FieldEncryptionSettings fieldEncryptSettings;
|
public FieldEncryptionSettings fieldEncryptSettings;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ namespace Obfuz.Settings
|
||||||
|
|
||||||
private SerializedProperty _symbolObfusSettings;
|
private SerializedProperty _symbolObfusSettings;
|
||||||
private SerializedProperty _constEncryptSettings;
|
private SerializedProperty _constEncryptSettings;
|
||||||
|
private SerializedProperty _evalStackObfusSettings;
|
||||||
private SerializedProperty _fieldEncryptSettings;
|
private SerializedProperty _fieldEncryptSettings;
|
||||||
private SerializedProperty _callObfusSettings;
|
private SerializedProperty _callObfusSettings;
|
||||||
private SerializedProperty _exprObfusSettings;
|
private SerializedProperty _exprObfusSettings;
|
||||||
|
@ -65,6 +66,7 @@ namespace Obfuz.Settings
|
||||||
|
|
||||||
_symbolObfusSettings = _serializedObject.FindProperty("symbolObfusSettings");
|
_symbolObfusSettings = _serializedObject.FindProperty("symbolObfusSettings");
|
||||||
_constEncryptSettings = _serializedObject.FindProperty("constEncryptSettings");
|
_constEncryptSettings = _serializedObject.FindProperty("constEncryptSettings");
|
||||||
|
_evalStackObfusSettings = _serializedObject.FindProperty("evalStackObfusSettings");
|
||||||
_exprObfusSettings = _serializedObject.FindProperty("exprObfusSettings");
|
_exprObfusSettings = _serializedObject.FindProperty("exprObfusSettings");
|
||||||
_fieldEncryptSettings = _serializedObject.FindProperty("fieldEncryptSettings");
|
_fieldEncryptSettings = _serializedObject.FindProperty("fieldEncryptSettings");
|
||||||
_callObfusSettings = _serializedObject.FindProperty("callObfusSettings");
|
_callObfusSettings = _serializedObject.FindProperty("callObfusSettings");
|
||||||
|
@ -88,6 +90,7 @@ namespace Obfuz.Settings
|
||||||
|
|
||||||
EditorGUILayout.PropertyField(_symbolObfusSettings);
|
EditorGUILayout.PropertyField(_symbolObfusSettings);
|
||||||
EditorGUILayout.PropertyField(_constEncryptSettings);
|
EditorGUILayout.PropertyField(_constEncryptSettings);
|
||||||
|
EditorGUILayout.PropertyField(_evalStackObfusSettings);
|
||||||
EditorGUILayout.PropertyField(_exprObfusSettings);
|
EditorGUILayout.PropertyField(_exprObfusSettings);
|
||||||
EditorGUILayout.PropertyField(_fieldEncryptSettings);
|
EditorGUILayout.PropertyField(_fieldEncryptSettings);
|
||||||
EditorGUILayout.PropertyField(_callObfusSettings);
|
EditorGUILayout.PropertyField(_callObfusSettings);
|
||||||
|
|
Loading…
Reference in New Issue