diff --git a/Editor/ObfusPasses/CallObfus/CallObfusPass.cs b/Editor/ObfusPasses/CallObfus/CallObfusPass.cs index 7786450..15299c2 100644 --- a/Editor/ObfusPasses/CallObfus/CallObfusPass.cs +++ b/Editor/ObfusPasses/CallObfus/CallObfusPass.cs @@ -7,19 +7,21 @@ using System.Collections.Generic; namespace Obfuz.ObfusPasses.CallObfus { + public class CallObfusPass : BasicBlockObfuscationPassBase { private readonly CallObfuscationSettingsFacade _settings; + private readonly SpecialWhiteListMethodCalculator _specialWhiteListMethodCache; + private IObfuscator _dynamicProxyObfuscator; private IObfuscationPolicy _dynamicProxyPolicy; - private readonly CachedDictionary _specialwhiteListMethodCache; public override ObfuscationPassType Type => ObfuscationPassType.CallObfus; public CallObfusPass(CallObfuscationSettingsFacade settings) { _settings = settings; - _specialwhiteListMethodCache = new CachedDictionary(MethodEqualityComparer.CompareDeclaringTypes, this.ComputeIsInWhiteList); + _specialWhiteListMethodCache = new SpecialWhiteListMethodCalculator(settings.obfuscateCallToMethodInMscorlib); } public override void Stop() @@ -39,106 +41,6 @@ namespace Obfuz.ObfusPasses.CallObfus return _dynamicProxyPolicy.NeedObfuscateCallInMethod(method); } - - private static readonly HashSet _specialTypeFullNames = new HashSet - { - "System.Enum", - "System.Delegate", - "System.MulticastDelegate", - "Obfuz.EncryptionService`1", - }; - - private static readonly HashSet _specialMethodNames = new HashSet - { - "GetEnumerator", // List.Enumerator.GetEnumerator() - ".ctor", // constructor - }; - - private static readonly HashSet _specialMethodFullNames = new HashSet - { - "System.Reflection.MethodBase.GetCurrentMethod", - "System.Reflection.Assembly.GetCallingAssembly", - "System.Reflection.Assembly.GetExecutingAssembly", - "System.Reflection.Assembly.GetEntryAssembly", - }; - - private bool ComputeIsInWhiteList(IMethod calledMethod) - { - MethodDef calledMethodDef = calledMethod.ResolveMethodDef(); - // mono has more strict access control, calls non-public method will raise exception. - if (PlatformUtil.IsMonoBackend()) - { - if (calledMethodDef != null && (!calledMethodDef.IsPublic || !IsTypeSelfAndParentPublic(calledMethodDef.DeclaringType))) - { - return true; - } - } - - ITypeDefOrRef declaringType = calledMethod.DeclaringType; - TypeSig declaringTypeSig = calledMethod.DeclaringType.ToTypeSig(); - declaringTypeSig = declaringTypeSig.RemovePinnedAndModifiers(); - switch (declaringTypeSig.ElementType) - { - case ElementType.ValueType: - case ElementType.Class: - { - break; - } - case ElementType.GenericInst: - { - if (MetaUtil.ContainsContainsGenericParameter(calledMethod)) - { - return true; - } - break; - } - default: return true; - } - - TypeDef typeDef = declaringType.ResolveTypeDef(); - - if (!_settings.obfuscateCallToMethodInMscorlib && typeDef.Module.IsCoreLibraryModule == true) - { - return true; - } - - if (typeDef.IsDelegate || typeDef.IsEnum) - return true; - - string fullName = typeDef.FullName; - if (_specialTypeFullNames.Contains(fullName)) - { - return true; - } - //if (fullName.StartsWith("System.Runtime.CompilerServices.")) - //{ - // return true; - //} - - string methodName = calledMethod.Name; - if (_specialMethodNames.Contains(methodName)) - { - return true; - } - - string methodFullName = $"{fullName}.{methodName}"; - if (_specialMethodFullNames.Contains(methodFullName)) - { - return true; - } - return false; - } - - private bool IsTypeSelfAndParentPublic(TypeDef type) - { - if (type.DeclaringType != null && !IsTypeSelfAndParentPublic(type.DeclaringType)) - { - return false; - } - - return type.IsPublic; - } - protected override bool TryObfuscateInstruction(MethodDef callerMethod, Instruction inst, BasicBlock block, int instructionIndex, IList globalInstructions, List outputInstructions, List totalFinalInstructions) { @@ -173,7 +75,7 @@ namespace Obfuz.ObfusPasses.CallObfus } - if (_specialwhiteListMethodCache.GetValue(calledMethod)) + if (_specialWhiteListMethodCache.IsInWhiteList(calledMethod)) { return false; } diff --git a/Editor/ObfusPasses/CallObfus/SpecialWhiteListMethodCalculator.cs b/Editor/ObfusPasses/CallObfus/SpecialWhiteListMethodCalculator.cs new file mode 100644 index 0000000..5f52792 --- /dev/null +++ b/Editor/ObfusPasses/CallObfus/SpecialWhiteListMethodCalculator.cs @@ -0,0 +1,122 @@ +using dnlib.DotNet; +using Obfuz.Utils; +using System.Collections.Generic; + +namespace Obfuz.ObfusPasses.CallObfus +{ + class SpecialWhiteListMethodCalculator + { + private readonly bool _obfuscateCallToMethodInMscorlib; + private readonly CachedDictionary _specialWhiteListMethodCache; + + public SpecialWhiteListMethodCalculator(bool obfuscateCallToMethodInMscorlib) + { + _obfuscateCallToMethodInMscorlib = obfuscateCallToMethodInMscorlib; + _specialWhiteListMethodCache = new CachedDictionary(MethodEqualityComparer.CompareDeclaringTypes, this.ComputeIsInWhiteList); + } + + public bool IsInWhiteList(IMethod calledMethod) + { + return _specialWhiteListMethodCache.GetValue(calledMethod); + } + + private static readonly HashSet _specialTypeFullNames = new HashSet + { + "System.Enum", + "System.Delegate", + "System.MulticastDelegate", + "Obfuz.EncryptionService`1", + }; + + private static readonly HashSet _specialMethodNames = new HashSet + { + "GetEnumerator", // List.Enumerator.GetEnumerator() + ".ctor", // constructor + }; + + private static readonly HashSet _specialMethodFullNames = new HashSet + { + "System.Reflection.MethodBase.GetCurrentMethod", + "System.Reflection.Assembly.GetCallingAssembly", + "System.Reflection.Assembly.GetExecutingAssembly", + "System.Reflection.Assembly.GetEntryAssembly", + }; + + private bool ComputeIsInWhiteList(IMethod calledMethod) + { + MethodDef calledMethodDef = calledMethod.ResolveMethodDef(); + // mono has more strict access control, calls non-public method will raise exception. + if (PlatformUtil.IsMonoBackend()) + { + if (calledMethodDef != null && (!calledMethodDef.IsPublic || !IsTypeSelfAndParentPublic(calledMethodDef.DeclaringType))) + { + return true; + } + } + + ITypeDefOrRef declaringType = calledMethod.DeclaringType; + TypeSig declaringTypeSig = calledMethod.DeclaringType.ToTypeSig(); + declaringTypeSig = declaringTypeSig.RemovePinnedAndModifiers(); + switch (declaringTypeSig.ElementType) + { + case ElementType.ValueType: + case ElementType.Class: + { + break; + } + case ElementType.GenericInst: + { + if (MetaUtil.ContainsContainsGenericParameter(calledMethod)) + { + return true; + } + break; + } + default: return true; + } + + TypeDef typeDef = declaringType.ResolveTypeDef(); + + if (!_obfuscateCallToMethodInMscorlib && typeDef.Module.IsCoreLibraryModule == true) + { + return true; + } + + if (typeDef.IsDelegate || typeDef.IsEnum) + return true; + + string fullName = typeDef.FullName; + if (_specialTypeFullNames.Contains(fullName)) + { + return true; + } + //if (fullName.StartsWith("System.Runtime.CompilerServices.")) + //{ + // return true; + //} + + string methodName = calledMethod.Name; + if (_specialMethodNames.Contains(methodName)) + { + return true; + } + + string methodFullName = $"{fullName}.{methodName}"; + if (_specialMethodFullNames.Contains(methodFullName)) + { + return true; + } + return false; + } + + private bool IsTypeSelfAndParentPublic(TypeDef type) + { + if (type.DeclaringType != null && !IsTypeSelfAndParentPublic(type.DeclaringType)) + { + return false; + } + + return type.IsPublic; + } + } +} diff --git a/Editor/ObfusPasses/CallObfus/SpecialWhiteListMethodCalculator.cs.meta b/Editor/ObfusPasses/CallObfus/SpecialWhiteListMethodCalculator.cs.meta new file mode 100644 index 0000000..b1228ec --- /dev/null +++ b/Editor/ObfusPasses/CallObfus/SpecialWhiteListMethodCalculator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 904e80c4b98911c40b6a9173ca24f3ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: