diff --git a/.gitmodules b/.gitmodules index 235b722db..e69de29bb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "dnlib"] - path = dnlib -url=../dnlib.git \ No newline at end of file diff --git a/Confuser.Core/Confuser.Core.csproj b/Confuser.Core/Confuser.Core.csproj index a804950dd..becce7afe 100644 --- a/Confuser.Core/Confuser.Core.csproj +++ b/Confuser.Core/Confuser.Core.csproj @@ -17,10 +17,7 @@ - - - - + diff --git a/Confuser.Core/ConfuserEngine.cs b/Confuser.Core/ConfuserEngine.cs index 2034a37c3..8749b498d 100644 --- a/Confuser.Core/ConfuserEngine.cs +++ b/Confuser.Core/ConfuserEngine.cs @@ -94,11 +94,12 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token) var asmResolver = new AssemblyResolver(); asmResolver.EnableTypeDefCache = true; asmResolver.DefaultModuleContext = new ModuleContext(asmResolver); + asmResolver.EnableFrameworkRedirect = false; context.Resolver = asmResolver; context.BaseDirectory = Path.Combine(Environment.CurrentDirectory, context.Project.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar); context.OutputDirectory = Path.Combine(context.Project.BaseDirectory, context.Project.OutputDirectory.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar); foreach (string probePath in context.Project.ProbePaths) - asmResolver.PostSearchPaths.Insert(0, Path.Combine(context.BaseDirectory, probePath)); + asmResolver.PreSearchPaths.Add(Path.Combine(context.BaseDirectory, probePath)); context.CheckCancellation(); @@ -384,6 +385,8 @@ static void EndModule(ConfuserContext context) { if (!Path.IsPathRooted(output)) output = Path.Combine(Environment.CurrentDirectory, output); output = Utils.GetRelativePath(output, context.BaseDirectory); + if (Path.IsPathRooted(output)) + output = Path.GetFileName(output); } else { output = context.CurrentModule.Name; diff --git a/Confuser.Core/Helpers/InjectHelper.cs b/Confuser.Core/Helpers/InjectHelper.cs index cc86ad740..b84008dc5 100644 --- a/Confuser.Core/Helpers/InjectHelper.cs +++ b/Confuser.Core/Helpers/InjectHelper.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using dnlib.DotNet; using dnlib.DotNet.Emit; @@ -59,10 +60,9 @@ static FieldDefUser Clone(FieldDef origin) { /// The new TypeDef. static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx) { TypeDef ret; - IDnlibDef existing; - if (!ctx.Map.TryGetValue(typeDef, out existing)) { + if (!ctx.MemberMap.TryGetValue(typeDef, out var existing)) { ret = Clone(typeDef); - ctx.Map[typeDef] = ret; + ctx.MemberMap[typeDef] = ret; } else ret = (TypeDef)existing; @@ -71,10 +71,10 @@ static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx) { ret.NestedTypes.Add(PopulateContext(nestedType, ctx)); foreach (MethodDef method in typeDef.Methods) - ret.Methods.Add((MethodDef)(ctx.Map[method] = Clone(method))); + ret.Methods.Add((MethodDef)(ctx.MemberMap[method] = Clone(method))); foreach (FieldDef field in typeDef.Fields) - ret.Fields.Add((FieldDef)(ctx.Map[field] = Clone(field))); + ret.Fields.Add((FieldDef)(ctx.MemberMap[field] = Clone(field))); return ret; } @@ -85,12 +85,12 @@ static TypeDef PopulateContext(TypeDef typeDef, InjectContext ctx) { /// The origin TypeDef. /// The injection context. static void CopyTypeDef(TypeDef typeDef, InjectContext ctx) { - var newTypeDef = (TypeDef)ctx.Map[typeDef]; + var newTypeDef = (TypeDef)ctx.MemberMap[typeDef]; - newTypeDef.BaseType = (ITypeDefOrRef)ctx.Importer.Import(typeDef.BaseType); + newTypeDef.BaseType = ctx.Importer.Import(typeDef.BaseType); foreach (InterfaceImpl iface in typeDef.Interfaces) - newTypeDef.Interfaces.Add(new InterfaceImplUser((ITypeDefOrRef)ctx.Importer.Import(iface.Interface))); + newTypeDef.Interfaces.Add(new InterfaceImplUser(ctx.Importer.Import(iface.Interface))); } /// @@ -99,7 +99,7 @@ static void CopyTypeDef(TypeDef typeDef, InjectContext ctx) { /// The origin MethodDef. /// The injection context. static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) { - var newMethodDef = (MethodDef)ctx.Map[methodDef]; + var newMethodDef = (MethodDef)ctx.MemberMap[methodDef]; newMethodDef.Signature = ctx.Importer.Import(methodDef.Signature); newMethodDef.Parameters.UpdateParameterTypes(); @@ -151,7 +151,7 @@ static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) { foreach (ExceptionHandler eh in methodDef.Body.ExceptionHandlers) newMethodDef.Body.ExceptionHandlers.Add(new ExceptionHandler(eh.HandlerType) { - CatchType = eh.CatchType == null ? null : (ITypeDefOrRef)ctx.Importer.Import(eh.CatchType), + CatchType = eh.CatchType == null ? null : ctx.Importer.Import(eh.CatchType), TryStart = (Instruction)bodyMap[eh.TryStart], TryEnd = (Instruction)bodyMap[eh.TryEnd], HandlerStart = (Instruction)bodyMap[eh.HandlerStart], @@ -169,7 +169,7 @@ static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) { /// The origin FieldDef. /// The injection context. static void CopyFieldDef(FieldDef fieldDef, InjectContext ctx) { - var newFieldDef = (FieldDef)ctx.Map[fieldDef]; + var newFieldDef = (FieldDef)ctx.MemberMap[fieldDef]; newFieldDef.Signature = ctx.Importer.Import(fieldDef.Signature); } @@ -192,8 +192,8 @@ static void Copy(TypeDef typeDef, InjectContext ctx, bool copySelf) { foreach (FieldDef field in typeDef.Fields) CopyFieldDef(field, ctx); - } - + } + /// /// Injects the specified TypeDef to another module. /// @@ -204,9 +204,22 @@ public static TypeDef Inject(TypeDef typeDef, ModuleDef target) { var ctx = new InjectContext(typeDef.Module, target); PopulateContext(typeDef, ctx); Copy(typeDef, ctx, true); - return (TypeDef)ctx.Map[typeDef]; - } - + return (TypeDef)ctx.MemberMap[typeDef]; + } + + /// + /// Imports a as a . This will be either + /// a or a . + /// + /// The source module. + /// The method + /// The imported method or null if is invalid + /// or if we failed to import the method + public static IMethod Import(ModuleDef target, MethodBase methodBase) { + var ctx = new InjectContext(null, target); + return ctx.Importer.Import(methodBase); + } + /// /// Injects the specified MethodDef to another module. /// @@ -215,9 +228,9 @@ public static TypeDef Inject(TypeDef typeDef, ModuleDef target) { /// The injected MethodDef. public static MethodDef Inject(MethodDef methodDef, ModuleDef target) { var ctx = new InjectContext(methodDef.Module, target); - ctx.Map[methodDef] = Clone(methodDef); + ctx.MemberMap[methodDef] = Clone(methodDef); CopyMethodDef(methodDef, ctx); - return (MethodDef)ctx.Map[methodDef]; + return (MethodDef)ctx.MemberMap[methodDef]; } /// @@ -229,20 +242,20 @@ public static MethodDef Inject(MethodDef methodDef, ModuleDef target) { /// Injected members. public static IEnumerable Inject(TypeDef typeDef, TypeDef newType, ModuleDef target) { var ctx = new InjectContext(typeDef.Module, target); - ctx.Map[typeDef] = newType; + ctx.MemberMap[typeDef] = newType; PopulateContext(typeDef, ctx); Copy(typeDef, ctx, false); - return ctx.Map.Values.Except(new[] { newType }); + return ctx.MemberMap.Values.Except(new[] { newType }).OfType(); } /// /// Context of the injection process. /// - class InjectContext : ImportResolver { + class InjectContext : ImportMapper { /// /// The mapping of origin definitions to injected definitions. /// - public readonly Dictionary Map = new Dictionary(); + public readonly Dictionary MemberMap = new Dictionary(); /// /// The module which source type originated from. @@ -259,6 +272,10 @@ class InjectContext : ImportResolver { /// readonly Importer importer; + private readonly AssemblyRef netstandardRef; + private readonly AssemblyRef mscorlibRef; + private readonly AssemblyRef corelibRef; + /// /// Initializes a new instance of the class. /// @@ -267,8 +284,11 @@ class InjectContext : ImportResolver { public InjectContext(ModuleDef module, ModuleDef target) { OriginModule = module; TargetModule = target; - importer = new Importer(target, ImporterOptions.TryToUseTypeDefs); - importer.Resolver = this; + importer = new Importer(target, ImporterOptions.TryToUseTypeDefs, new GenericParamContext(), this); + + netstandardRef = TryResolveAssembly("netstandard"); + mscorlibRef = TryResolveAssembly("mscorlib"); + corelibRef = TryResolveAssembly("System.Private.CoreLib"); } /// @@ -277,27 +297,131 @@ public InjectContext(ModuleDef module, ModuleDef target) { /// The importer. public Importer Importer { get { return importer; } - } + } + + /// + public override ITypeDefOrRef Map(ITypeDefOrRef source) { + if (MemberMap.TryGetValue(source, out var result)) + return (ITypeDefOrRef)result; + + //HACK: for netcore + //System.Enviroment and System.AppDomain is in System.Runtime.Extensions/mscorlib/netstandard + //System.Runtime.InteropServices.Marshal is in System.Runtime.InteropServices/mscorlib/netstandard + if (source.IsTypeRef && OriginModule?.CorLibTypes.AssemblyRef != TargetModule.CorLibTypes.AssemblyRef) { + var sourceRef = (TypeRef)source; + TypeRef destRef = TryResolveType(sourceRef, TargetModule.CorLibTypes.AssemblyRef, false) ?? + TryResolveType(sourceRef, netstandardRef, true) ?? + TryResolveType(sourceRef, mscorlibRef, true) ?? + TryResolveType(sourceRef, TryResolveAssembly(sourceRef.DefinitionAssembly.Name), false) ?? + TryResolveType(sourceRef, corelibRef, false); + + if (destRef != null) { + var stack = new Stack(2); + stack.Push(destRef); + TypeRef cur = destRef; + do { + var scope = cur.ResolutionScope; + stack.Push(scope); + cur = scope as TypeRef; + } while (cur != null); + do { + TargetModule.UpdateRowId(stack.Pop()); + } while (stack.Count > 0); + } + + MemberMap[source] = destRef; + return destRef; + } + return null; + } + + TypeRef TryResolveType(TypeRef sourceRef, AssemblyRef scope, bool followForward) { + if (scope == null) + return null; + + var typeRef = Import2(sourceRef, scope); + + var scopeDef = TargetModule.Context.AssemblyResolver.Resolve(typeRef.DefinitionAssembly, TargetModule); + if (scopeDef != null) { + if (scopeDef.TypeExists(typeRef)) + return typeRef; + var sigComparer = new SigComparer(SigComparerOptions.DontCompareTypeScope); + var exportType = scopeDef.Modules.SelectMany(m => m.ExportedTypes).Where(et => sigComparer.Equals(et, typeRef)).FirstOrDefault(); + if (exportType != null) { + if (followForward && (corelibRef == null || exportType.Implementation.Name != corelibRef.Name)) + return exportType.ToTypeRef(); + else + return typeRef; + } + } + + return null; + } + + AssemblyRef TryResolveAssembly(UTF8String name) { + return TargetModule.GetAssemblyRef(name) ?? TargetModule.Context.AssemblyResolver.Resolve(new AssemblyRefUser(name), TargetModule).ToAssemblyRef(); + } + + TypeRef Import2(TypeRef type, IResolutionScope scope) { + if (type is null) + return null; + TypeRef result; + + var declaringType = type.DeclaringType; + if (!(declaringType is null)) + result = new TypeRefUser(TargetModule, type.Namespace, type.Name, Import2(declaringType, scope)); + else + result = new TypeRefUser(TargetModule, type.Namespace, type.Name, scope); + + return result; + } + /// - public override TypeDef Resolve(TypeDef typeDef) { - if (Map.ContainsKey(typeDef)) - return (TypeDef)Map[typeDef]; + public override IMethod Map(MethodDef source) { + if (MemberMap.TryGetValue(source, out var result)) + return (MethodDef)result; return null; } /// - public override MethodDef Resolve(MethodDef methodDef) { - if (Map.ContainsKey(methodDef)) - return (MethodDef)Map[methodDef]; + public override IField Map(FieldDef source) { + if (MemberMap.ContainsKey(source)) + return (FieldDef)MemberMap[source]; return null; } - /// - public override FieldDef Resolve(FieldDef fieldDef) { - if (Map.ContainsKey(fieldDef)) - return (FieldDef)Map[fieldDef]; - return null; + public override TypeRef Map(Type source) { + if (MemberMap.TryGetValue(source, out var result)) + return (TypeRef)result; + + if (OriginModule?.CorLibTypes.AssemblyRef != TargetModule.CorLibTypes.AssemblyRef) { + var sourceRef = (TypeRef)TargetModule.Import(source); + TypeRef destRef = TryResolveType(sourceRef, TargetModule.CorLibTypes.AssemblyRef, false) ?? + TryResolveType(sourceRef, netstandardRef, true) ?? + TryResolveType(sourceRef, mscorlibRef, true) ?? + TryResolveType(sourceRef, TryResolveAssembly(sourceRef.DefinitionAssembly.Name), false) ?? + TryResolveType(sourceRef, corelibRef, false); + + if (destRef != null) { + var stack = new Stack(2); + stack.Push(destRef); + TypeRef cur = destRef; + do { + var scope = cur.ResolutionScope; + stack.Push(scope); + cur = scope as TypeRef; + } while (cur != null); + do { + TargetModule.UpdateRowId(stack.Pop()); + } while (stack.Count > 0); + + MemberMap[source] = destRef; + return destRef; + } + } + + return null; } } } diff --git a/Confuser.Protections/Compress/Compressor.cs b/Confuser.Protections/Compress/Compressor.cs index c08e140cc..9a833c86d 100644 --- a/Confuser.Protections/Compress/Compressor.cs +++ b/Confuser.Protections/Compress/Compressor.cs @@ -62,12 +62,20 @@ protected override void Pack(ConfuserContext context, ProtectionParameters param var assembly = new AssemblyDefUser(originModule.Assembly); assembly.Name += ".cr"; assembly.Modules.Add(stubModule); + var targetFramework = originModule.Assembly.CustomAttributes.FirstOrDefault(ca => ca.TypeFullName == "System.Runtime.Versioning.TargetFrameworkAttribute"); + if (targetFramework != null) { + var attrType = stubModule.CorLibTypes.GetTypeRef("System.Runtime.Versioning", "TargetFrameworkAttribute"); + var ctorSig = MethodSig.CreateInstance(stubModule.CorLibTypes.Void, stubModule.CorLibTypes.String); + assembly.CustomAttributes.Add(new CustomAttribute( + new MemberRefUser(stubModule, ".ctor", ctorSig, attrType), new CAArgument[] { new CAArgument(stubModule.CorLibTypes.String, targetFramework.ConstructorArguments[0].Value) })); + } } else { ctx.Assembly.Modules.Insert(0, stubModule); ImportAssemblyTypeReferences(originModule, stubModule); } stubModule.Characteristics = originModule.Characteristics; + stubModule.Context = originModule.Context; stubModule.Cor20HeaderFlags = originModule.Cor20HeaderFlags; stubModule.Cor20HeaderRuntimeVersion = originModule.Cor20HeaderRuntimeVersion; stubModule.DllCharacteristics = originModule.DllCharacteristics; @@ -196,7 +204,7 @@ void InjectData(ModuleDef stubModule, MethodDef method, byte[] data) { repl.AddRange(arg); repl.Add(Instruction.Create(OpCodes.Dup)); repl.Add(Instruction.Create(OpCodes.Ldtoken, dataField)); - repl.Add(Instruction.Create(OpCodes.Call, stubModule.Import( + repl.Add(Instruction.Create(OpCodes.Call, InjectHelper.Import(stubModule, typeof(RuntimeHelpers).GetMethod("InitializeArray")))); return repl.ToArray(); }); @@ -301,7 +309,7 @@ void ImportAssemblyTypeReferences(ModuleDef originModule, ModuleDef stubModule) } } - class KeyInjector : IModuleWriterListener { + class KeyInjector { readonly CompressorContext ctx; public KeyInjector(CompressorContext ctx) { @@ -312,7 +320,7 @@ public void WriterEvent(object sender, ModuleWriterEventArgs args) { OnWriterEvent(args.Writer, args.Event); } - public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) { + private void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) { if (evt == ModuleWriterEvent.MDBeginCreateTables) { // Add key signature uint sigBlob = writer.Metadata.BlobHeap.Add(ctx.KeySig); diff --git a/Confuser.Protections/Constants/EncodePhase.cs b/Confuser.Protections/Constants/EncodePhase.cs index 65d7ba7f4..36d33622e 100644 --- a/Confuser.Protections/Constants/EncodePhase.cs +++ b/Confuser.Protections/Constants/EncodePhase.cs @@ -121,7 +121,7 @@ protected override void Execute(ConfuserContext context, ProtectionParameters pa repl.AddRange(arg); repl.Add(Instruction.Create(OpCodes.Dup)); repl.Add(Instruction.Create(OpCodes.Ldtoken, moduleCtx.DataField)); - repl.Add(Instruction.Create(OpCodes.Call, moduleCtx.Module.Import( + repl.Add(Instruction.Create(OpCodes.Call, InjectHelper.Import(moduleCtx.Module, typeof(RuntimeHelpers).GetMethod("InitializeArray")))); return repl.ToArray(); }); diff --git a/Confuser.Protections/Resources/InjectPhase.cs b/Confuser.Protections/Resources/InjectPhase.cs index 540591750..e76920edb 100644 --- a/Confuser.Protections/Resources/InjectPhase.cs +++ b/Confuser.Protections/Resources/InjectPhase.cs @@ -136,7 +136,7 @@ void MutateInitializer(REContext moduleCtx, MethodDef decomp) { repl.AddRange(arg); repl.Add(Instruction.Create(OpCodes.Dup)); repl.Add(Instruction.Create(OpCodes.Ldtoken, moduleCtx.DataField)); - repl.Add(Instruction.Create(OpCodes.Call, moduleCtx.Module.Import( + repl.Add(Instruction.Create(OpCodes.Call, InjectHelper.Import(moduleCtx.Module, typeof(RuntimeHelpers).GetMethod("InitializeArray")))); return repl.ToArray(); }); diff --git a/Confuser.Renamer/GenericArgumentResolver.cs b/Confuser.Renamer/GenericArgumentResolver.cs index 396bacc49..cf72eda0c 100644 --- a/Confuser.Renamer/GenericArgumentResolver.cs +++ b/Confuser.Renamer/GenericArgumentResolver.cs @@ -6,7 +6,7 @@ namespace Confuser.Renamer { /// /// Resolves generic arguments /// - public struct GenericArgumentResolver { + public ref struct GenericArgumentResolver { GenericArguments genericArguments; RecursionCounter recursionCounter; @@ -53,8 +53,6 @@ public static MethodSig Resolve(MethodSig methodSig, IList typeGenArgs) } bool ReplaceGenericArg(ref TypeSig typeSig) { - if (genericArguments == null) - return false; TypeSig newTypeSig = genericArguments.Resolve(typeSig); if (newTypeSig != typeSig) { typeSig = newTypeSig; @@ -156,4 +154,4 @@ TypeSig ResolveGenericArgs(TypeSig typeSig) { return result; } } -} \ No newline at end of file +} diff --git a/Confuser.Renamer/GenericArguments.cs b/Confuser.Renamer/GenericArguments.cs new file mode 100644 index 000000000..7bb0e731a --- /dev/null +++ b/Confuser.Renamer/GenericArguments.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using dnlib.DotNet; + +// This file is originally from dnlib. Find the original source here: +// https://github.com/0xd4d/dnlib/blob/a75105a4600b5641e42e6ac36847661ae9383701/src/DotNet/GenericArguments.cs +// Find the original license of this file here: +// https://github.com/0xd4d/dnlib/blob/a75105a4600b5641e42e6ac36847661ae9383701/LICENSE.txt +namespace Confuser.Renamer { + /// + /// Replaces generic type/method var with its generic argument + /// + internal ref struct GenericArguments { +#pragma warning disable 649 // Default value is okay. + private GenericArgumentsStack _typeArgsStack; + private GenericArgumentsStack _methodArgsStack; +#pragma warning restore 649 + + /// + /// Pushes generic arguments + /// + /// The generic arguments + public void PushTypeArgs(IList typeArgs) => _typeArgsStack.Push(typeArgs); + + /// + /// Pops generic arguments + /// + /// The popped generic arguments + public IList PopTypeArgs() => _typeArgsStack.Pop(); + + /// + /// Pushes generic arguments + /// + /// The generic arguments + public void PushMethodArgs(IList methodArgs) => _methodArgsStack.Push(methodArgs); + + /// + /// Pops generic arguments + /// + /// The popped generic arguments + public IList PopMethodArgs() => _methodArgsStack.Pop(); + + /// + /// Replaces a generic type/method var with its generic argument (if any). If + /// isn't a generic type/method var or if it can't + /// be resolved, it itself is returned. Else the resolved type is returned. + /// + /// Type signature + /// New which is never null unless + /// is null + public TypeSig Resolve(TypeSig typeSig) { + if (typeSig == null) + return null; + + var sig = typeSig; + + if (sig is GenericMVar genericMVar) { + var newSig = _methodArgsStack.Resolve(genericMVar.Number, false); + if (newSig == null || newSig == sig) + return sig; + return newSig; + } + + if (sig is GenericVar genericVar) { + var newSig = _typeArgsStack.Resolve(genericVar.Number, true); + if (newSig == null || newSig == sig) + return sig; + return newSig; + } + + return sig; + } + + private ref struct GenericArgumentsStack { + private List> _argsStack; + + /// + /// Pushes generic arguments + /// + /// The generic arguments + public void Push(IList args) => (_argsStack ?? (_argsStack = new List>())).Add(args); + + /// + /// Pops generic arguments + /// + /// The popped generic arguments + public IList Pop() { + if (_argsStack == null) throw new IndexOutOfRangeException(); + + int index = _argsStack.Count - 1; + var result = _argsStack[index]; + _argsStack.RemoveAt(index); + return result; + } + + /// + /// Resolves a generic argument + /// + /// Generic variable number + /// + /// A or if none was found + public TypeSig Resolve(uint number, bool isTypeVar) { + if (_argsStack == null) return null; + + TypeSig result = null; + for (int i = _argsStack.Count - 1; i >= 0; i--) { + var args = _argsStack[i]; + if (number >= args.Count) + return null; + var typeSig = args[(int)number]; + if (!(typeSig is GenericSig genericVar) || genericVar.IsTypeVar != isTypeVar) + return typeSig; + result = genericVar; + number = genericVar.Number; + } + return result; + } + } + } +} diff --git a/Confuser.Renamer/RecursionCounter.cs b/Confuser.Renamer/RecursionCounter.cs new file mode 100644 index 000000000..d0898c566 --- /dev/null +++ b/Confuser.Renamer/RecursionCounter.cs @@ -0,0 +1,52 @@ +using System; +using System.Globalization; + +// This file is originally from dnlib. Find the original source here: +// https://github.com/0xd4d/dnlib/blob/a75105a4600b5641e42e6ac36847661ae9383701/src/DotNet/RecursionCounter.cs +// Find the original license of this file here: +// https://github.com/0xd4d/dnlib/blob/a75105a4600b5641e42e6ac36847661ae9383701/LICENSE.txt +namespace Confuser.Renamer { + /// + /// Recursion counter + /// + internal ref struct RecursionCounter { + /// + /// Max recursion count. If this is reached, we won't continue, and will use a default value. + /// + private const int MAX_RECURSION_COUNT = 100; + + /// + /// Gets the recursion counter + /// + private int Counter { get; set; } + + /// + /// Increments if it's not too high. ALL instance methods + /// that can be called recursively must call this method and + /// (if this method returns ) + /// + /// if it was incremented and caller can continue, if + /// it was not incremented and the caller must return to its caller. + public bool Increment() { + if (Counter >= MAX_RECURSION_COUNT) + return false; + Counter++; + return true; + } + + /// + /// Must be called before returning to caller if + /// returned . + /// + public void Decrement() { +#if DEBUG + if (Counter <= 0) + throw new InvalidOperationException("recursionCounter <= 0"); +#endif + Counter--; + } + + /// + public override string ToString() => Counter.ToString(CultureInfo.InvariantCulture); + } +} diff --git a/Confuser.Runtime/Compressor.Compat.cs b/Confuser.Runtime/Compressor.Compat.cs index 74afa433e..961822d3d 100644 --- a/Confuser.Runtime/Compressor.Compat.cs +++ b/Confuser.Runtime/Compressor.Compat.cs @@ -45,6 +45,8 @@ static GCHandle Decrypt(uint[] data, uint seed) { return g; } + static Func assemblyLoad = Assembly.Load; + [STAThread] static int Main(string[] args) { var l = (uint)Mutation.KeyI0; @@ -52,7 +54,16 @@ static int Main(string[] args) { GCHandle h = Decrypt(q, (uint)Mutation.KeyI1); var b = (byte[])h.Target; - Assembly a = Assembly.Load(b); + + var assemblyLoadCtx = Type.GetType("System.Runtime.Loader.AssemblyLoadContext"); + if (assemblyLoadCtx != null) { + var assemblyLoadCtxDef = assemblyLoadCtx.GetProperty("Default")?.GetValue(null); + var assemblyLoadCtxLoad = assemblyLoadCtx.GetMethod("LoadFromStream", new Type[] { typeof(Stream) }); + if (assemblyLoadCtxDef != null && assemblyLoadCtxLoad != null) { + assemblyLoad = (datas) => (Assembly)assemblyLoadCtxLoad.Invoke(assemblyLoadCtxDef, new object[] { new MemoryStream(datas) }); + } + } + Assembly a = assemblyLoad(b); Array.Clear(b, 0, b.Length); h.Free(); Array.Clear(q, 0, q.Length); @@ -96,7 +107,7 @@ static Assembly Resolve(object sender, ResolveEventArgs e) { GCHandle h = Decrypt(d, s); var f = (byte[])h.Target; - Assembly a = Assembly.Load(f); + Assembly a = assemblyLoad(f); Array.Clear(f, 0, f.Length); h.Free(); Array.Clear(d, 0, d.Length); diff --git a/Confuser2.mono.sln b/Confuser2.mono.sln index c7d7613f9..c32f95e0d 100644 --- a/Confuser2.mono.sln +++ b/Confuser2.mono.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Confuser.Core", "Confuser.Core\Confuser.Core.csproj", "{BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dnlib", "dnlib\src\dnlib.csproj", "{FDFC1237-143F-4919-8318-4926901F4639}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Confuser.Protections", "Confuser.Protections\Confuser.Protections.csproj", "{3EAB01B5-9B49-48D8-BFA1-5493B26CCB71}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Confuser.CLI", "Confuser.CLI\Confuser.CLI.csproj", "{CE61ADEE-C032-43EC-ACD8-E4A742F894A3}" @@ -28,10 +26,6 @@ Global {BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92}.Debug|Any CPU.Build.0 = Debug|Any CPU {BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92}.Release|Any CPU.ActiveCfg = Release|Any CPU {BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92}.Release|Any CPU.Build.0 = Release|Any CPU - {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FDFC1237-143F-4919-8318-4926901F4639}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FDFC1237-143F-4919-8318-4926901F4639}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FDFC1237-143F-4919-8318-4926901F4639}.Release|Any CPU.Build.0 = Release|Any CPU {3EAB01B5-9B49-48D8-BFA1-5493B26CCB71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3EAB01B5-9B49-48D8-BFA1-5493B26CCB71}.Debug|Any CPU.Build.0 = Debug|Any CPU {3EAB01B5-9B49-48D8-BFA1-5493B26CCB71}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/Confuser2.sln b/Confuser2.sln index 4cce04805..14a885ca3 100644 --- a/Confuser2.sln +++ b/Confuser2.sln @@ -52,8 +52,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinFormsRenaming", "Tests\W EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinFormsRenaming.Test", "Tests\WinFormsRenaming.Test\WinFormsRenaming.Test.csproj", "{6C8ECB51-EECE-49C3-89EC-CB0AAECCFF7E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dnlib", "dnlib\src\dnlib.csproj", "{18A3AD8D-DBF6-4489-A407-2972272CC6CB}" -EndProject Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "VisualBasicRenamingResx", "Tests\VisualBasicRenamingResx\VisualBasicRenamingResx.vbproj", "{4B2CE997-8157-40B4-B42F-51CE33954AAC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VisualBasicRenamingResx.Test", "Tests\VisualBasicRenamingResx.Test\VisualBasicRenamingResx.Test.csproj", "{40C6A1BB-69AA-4869-81EE-41917D0B009A}" @@ -152,10 +150,6 @@ Global {6C8ECB51-EECE-49C3-89EC-CB0AAECCFF7E}.Debug|Any CPU.Build.0 = Debug|Any CPU {6C8ECB51-EECE-49C3-89EC-CB0AAECCFF7E}.Release|Any CPU.ActiveCfg = Release|Any CPU {6C8ECB51-EECE-49C3-89EC-CB0AAECCFF7E}.Release|Any CPU.Build.0 = Release|Any CPU - {18A3AD8D-DBF6-4489-A407-2972272CC6CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {18A3AD8D-DBF6-4489-A407-2972272CC6CB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {18A3AD8D-DBF6-4489-A407-2972272CC6CB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {18A3AD8D-DBF6-4489-A407-2972272CC6CB}.Release|Any CPU.Build.0 = Release|Any CPU {4B2CE997-8157-40B4-B42F-51CE33954AAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4B2CE997-8157-40B4-B42F-51CE33954AAC}.Debug|Any CPU.Build.0 = Debug|Any CPU {4B2CE997-8157-40B4-B42F-51CE33954AAC}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/Tests/Confuser.Core.Test/Confuser.Core.Test.csproj b/Tests/Confuser.Core.Test/Confuser.Core.Test.csproj index f557cc315..ee65caf4c 100644 --- a/Tests/Confuser.Core.Test/Confuser.Core.Test.csproj +++ b/Tests/Confuser.Core.Test/Confuser.Core.Test.csproj @@ -15,7 +15,6 @@ - diff --git a/Tests/Confuser.Renamer.Test/Confuser.Renamer.Test.csproj b/Tests/Confuser.Renamer.Test/Confuser.Renamer.Test.csproj index fcf6aaf54..32ba2da37 100644 --- a/Tests/Confuser.Renamer.Test/Confuser.Renamer.Test.csproj +++ b/Tests/Confuser.Renamer.Test/Confuser.Renamer.Test.csproj @@ -16,7 +16,6 @@ - diff --git a/dnlib b/dnlib deleted file mode 160000 index a42ef1eda..000000000 --- a/dnlib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a42ef1eda187cae5920e59856009510b66b97a97 diff --git a/docs/docs.shfbproj b/docs/docs.shfbproj index fdf1b78bd..83a874a1d 100644 --- a/docs/docs.shfbproj +++ b/docs/docs.shfbproj @@ -80,10 +80,6 @@ Confuser.Core {BEB67A6E-4C54-4DE5-8C6B-2C12F44A7B92} - - dnlib - {FDFC1237-143F-4919-8318-4926901F4639} -