重构CallObfusPass代码

main
walon 2025-06-30 20:02:49 +08:00
parent 52d9ee1349
commit 9b9eb6d12d
3 changed files with 138 additions and 103 deletions

View File

@ -7,19 +7,21 @@ using System.Collections.Generic;
namespace Obfuz.ObfusPasses.CallObfus namespace Obfuz.ObfusPasses.CallObfus
{ {
public class CallObfusPass : BasicBlockObfuscationPassBase public class CallObfusPass : BasicBlockObfuscationPassBase
{ {
private readonly CallObfuscationSettingsFacade _settings; private readonly CallObfuscationSettingsFacade _settings;
private readonly SpecialWhiteListMethodCalculator _specialWhiteListMethodCache;
private IObfuscator _dynamicProxyObfuscator; private IObfuscator _dynamicProxyObfuscator;
private IObfuscationPolicy _dynamicProxyPolicy; private IObfuscationPolicy _dynamicProxyPolicy;
private readonly CachedDictionary<IMethod, bool> _specialwhiteListMethodCache;
public override ObfuscationPassType Type => ObfuscationPassType.CallObfus; public override ObfuscationPassType Type => ObfuscationPassType.CallObfus;
public CallObfusPass(CallObfuscationSettingsFacade settings) public CallObfusPass(CallObfuscationSettingsFacade settings)
{ {
_settings = settings; _settings = settings;
_specialwhiteListMethodCache = new CachedDictionary<IMethod, bool>(MethodEqualityComparer.CompareDeclaringTypes, this.ComputeIsInWhiteList); _specialWhiteListMethodCache = new SpecialWhiteListMethodCalculator(settings.obfuscateCallToMethodInMscorlib);
} }
public override void Stop() public override void Stop()
@ -39,106 +41,6 @@ namespace Obfuz.ObfusPasses.CallObfus
return _dynamicProxyPolicy.NeedObfuscateCallInMethod(method); return _dynamicProxyPolicy.NeedObfuscateCallInMethod(method);
} }
private static readonly HashSet<string> _specialTypeFullNames = new HashSet<string>
{
"System.Enum",
"System.Delegate",
"System.MulticastDelegate",
"Obfuz.EncryptionService`1",
};
private static readonly HashSet<string> _specialMethodNames = new HashSet<string>
{
"GetEnumerator", // List<T>.Enumerator.GetEnumerator()
".ctor", // constructor
};
private static readonly HashSet<string> _specialMethodFullNames = new HashSet<string>
{
"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, protected override bool TryObfuscateInstruction(MethodDef callerMethod, Instruction inst, BasicBlock block,
int instructionIndex, IList<Instruction> globalInstructions, List<Instruction> outputInstructions, List<Instruction> totalFinalInstructions) int instructionIndex, IList<Instruction> globalInstructions, List<Instruction> outputInstructions, List<Instruction> totalFinalInstructions)
{ {
@ -173,7 +75,7 @@ namespace Obfuz.ObfusPasses.CallObfus
} }
if (_specialwhiteListMethodCache.GetValue(calledMethod)) if (_specialWhiteListMethodCache.IsInWhiteList(calledMethod))
{ {
return false; return false;
} }

View File

@ -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<IMethod, bool> _specialWhiteListMethodCache;
public SpecialWhiteListMethodCalculator(bool obfuscateCallToMethodInMscorlib)
{
_obfuscateCallToMethodInMscorlib = obfuscateCallToMethodInMscorlib;
_specialWhiteListMethodCache = new CachedDictionary<IMethod, bool>(MethodEqualityComparer.CompareDeclaringTypes, this.ComputeIsInWhiteList);
}
public bool IsInWhiteList(IMethod calledMethod)
{
return _specialWhiteListMethodCache.GetValue(calledMethod);
}
private static readonly HashSet<string> _specialTypeFullNames = new HashSet<string>
{
"System.Enum",
"System.Delegate",
"System.MulticastDelegate",
"Obfuz.EncryptionService`1",
};
private static readonly HashSet<string> _specialMethodNames = new HashSet<string>
{
"GetEnumerator", // List<T>.Enumerator.GetEnumerator()
".ctor", // constructor
};
private static readonly HashSet<string> _specialMethodFullNames = new HashSet<string>
{
"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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 904e80c4b98911c40b6a9173ca24f3ee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: