/// <summary> /// Builds the program constructor. /// </summary> /// <param name="assembly">The assembly.</param> /// <param name="programType">Type of the program.</param> /// <param name="assemblyLock">The assembly lock.</param> /// <param name="executingAssembly">The executing assembly.</param> /// <param name="loadedAssemblies">The loaded assemblies.</param> /// <param name="currentDomain">The current domain.</param> /// <param name="eventHandler">The event handler.</param> /// <param name="assemblyResolve">The assembly resolve.</param> /// <param name="getExecutingAssembly">The get executing assembly.</param> /// <param name="resolveMethod">The resolve method.</param> private static void BuildProgramConstructor(AssemblyDefinition assembly, TypeDefinition programType, FieldReference assemblyLock, FieldReference executingAssembly, FieldReference loadedAssemblies, MethodReference currentDomain, MethodReference eventHandler, MethodReference assemblyResolve, MethodReference getExecutingAssembly, MethodReference resolveMethod) { var body = assembly.CreateDefaultConstructor(programType); body.MaxStackSize = 4; body.InitLocals = true; body.Variables.Add(new VariableDefinition(assembly.Import(typeof(AppDomain)))); var il = body.GetILProcessor(); //Inject anti reflector code InjectAntiReflectorCode(il, il.Create(OpCodes.Ldarg_0)); //define the assembly lock var objConstructor = assembly.Import(typeof(object).GetConstructor(Type.EmptyTypes)); il.Append(il.Create(OpCodes.Newobj, objConstructor)); il.Append(il.Create(OpCodes.Stfld, assemblyLock)); il.Append(OpCodes.Ldarg_0); il.Append(il.Create(OpCodes.Call, objConstructor)); il.Append(OpCodes.Nop); il.Append(OpCodes.Nop); il.Append(OpCodes.Ldarg_0); var cacheConstructor = assembly.Import(typeof(Dictionary<string, Assembly>).GetConstructor(Type.EmptyTypes)); il.Append(il.Create(OpCodes.Newobj, cacheConstructor)); il.Append(il.Create(OpCodes.Stfld, loadedAssemblies)); il.Append(OpCodes.Ldarg_0); il.Append(il.Create(OpCodes.Call, getExecutingAssembly)); il.Append(il.Create(OpCodes.Stfld, executingAssembly)); il.Append(il.Create(OpCodes.Call, currentDomain)); il.Append(OpCodes.Stloc_0); il.Append(OpCodes.Ldloc_0); il.Append(OpCodes.Ldarg_0); il.Append(il.Create(OpCodes.Ldftn, resolveMethod)); il.Append(il.Create(OpCodes.Newobj, eventHandler)); il.Append(il.Create(OpCodes.Callvirt, assemblyResolve)); il.Append(OpCodes.Nop); il.Append(OpCodes.Nop); il.Append(OpCodes.Ret); }
/// <summary> /// Builds the main entry point to the bootstrapper. /// </summary> /// <param name="context">The context.</param> /// <param name="assembly">The assembly.</param> /// <param name="passwordKey">The password key.</param> /// <param name="salt">The salt.</param> private static void BuildBootstrapper(ICloakContext context, AssemblyDefinition assembly, string passwordKey, Guid salt) { //See http://blog.paul-mason.co.nz/2010/02/tamper-proofing-implementation-part-2.html //First create the actual program runner #if USE_FRIENDLY_NAMING TypeDefinition programType = new TypeDefinition("ProgramRunner", "NCloak.Bootstrapper.Internal", TypeAttributes.NotPublic | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.Serializable | TypeAttributes.BeforeFieldInit, assembly.Import(typeof(object))); #else TypeDefinition programType = new TypeDefinition(context.NameManager.GenerateName(NamingTable.Type), context.NameManager.GenerateName(NamingTable.Type), TypeAttributes.NotPublic | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.Serializable | TypeAttributes.BeforeFieldInit, assembly.Import(typeof(object))); #endif assembly.MainModule.Types.Add(programType); //Add the class level fields #if USE_FRIENDLY_NAMING string assembliesLoadedVariableName = "assembliesLoaded"; string assemblyLockVariableName = "assemblyLock"; string executingAssemblyVariableName = "executingAssembly"; string loadedAssembliesVariableName = "loadedAssemblies"; #else string assembliesLoadedVariableName = context.NameManager.GenerateName(NamingTable.Field); string assemblyLockVariableName = context.NameManager.GenerateName(NamingTable.Field); string executingAssemblyVariableName = context.NameManager.GenerateName(NamingTable.Field); string loadedAssembliesVariableName = context.NameManager.GenerateName(NamingTable.Field); #endif var assembliesLoaded = new FieldDefinition(assembliesLoadedVariableName, FieldAttributes.Private, assembly.Import(typeof(bool))); var assemblyLock = new FieldDefinition(assemblyLockVariableName, FieldAttributes.Private | FieldAttributes.InitOnly, assembly.Import(typeof(object))); var executingAssembly = new FieldDefinition(executingAssemblyVariableName, FieldAttributes.Private | FieldAttributes.InitOnly, assembly.Import(typeof(Assembly))); var loadedAssemblies = new FieldDefinition(loadedAssembliesVariableName,FieldAttributes.Private | FieldAttributes.InitOnly, assembly.Import(typeof(Dictionary<string, Assembly>))); programType.Fields.Add(assembliesLoaded); programType.Fields.Add(assemblyLock); programType.Fields.Add(executingAssembly); programType.Fields.Add(loadedAssemblies); //Get some method references we share MethodReference currentDomain = assembly.Import(typeof(AppDomain).GetProperty("CurrentDomain").GetGetMethod()); MethodReference eventHandler = assembly.Import(typeof(ResolveEventHandler).GetConstructor(new[] { typeof(object), typeof(IntPtr) })); MethodReference assemblyResolve = assembly.Import(typeof(AppDomain).GetEvent("AssemblyResolve").GetAddMethod()); MethodReference getExecutingAssembly = assembly.Import(typeof(Assembly).GetMethod("GetExecutingAssembly")); //Define decrypt data method var decryptMethod = BuildDecryptMethod(context, assembly); programType.Methods.Add(decryptMethod); //Define hash data method var hashMethod = BuildHashMethod(context, assembly); programType.Methods.Add(hashMethod); //Define load assembly var loadAssemblyMethod = BuildLoadAssemblyMethod(context, assembly, loadedAssemblies, executingAssembly, decryptMethod, hashMethod, passwordKey, salt); programType.Methods.Add(loadAssemblyMethod); //Define load type method var loadTypeMethod = BuildLoadTypeMethod(context, assembly, loadAssemblyMethod); programType.Methods.Add(loadTypeMethod); //Define load assemblies method var loadAssembliesMethod = BuildLoadAssembliesMethod(context, assembly, executingAssembly, loadAssemblyMethod); programType.Methods.Add(loadAssembliesMethod); //Define resolve method var resolveMethod = BuildResolveMethod(context, assembly, assemblyLock, assembliesLoaded, loadAssembliesMethod); programType.Methods.Add(resolveMethod); //Define start method var startMethod = BuildStartMethod(context, assembly, executingAssembly, assembliesLoaded, loadTypeMethod, loadAssembliesMethod); programType.Methods.Add(startMethod); //Now define a constructor BuildProgramConstructor(assembly, programType, assemblyLock, executingAssembly, loadedAssemblies, currentDomain, eventHandler, assemblyResolve, getExecutingAssembly, resolveMethod); //Now create a type to hold the entry point #if USE_FRIENDLY_NAMING TypeDefinition entryType = new TypeDefinition("Program", "NCloak.Bootstrapper", TypeAttributes.NotPublic | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit, assembly.Import(typeof(object))); #else TypeDefinition entryType = new TypeDefinition(context.NameManager.GenerateName(NamingTable.Type), context.NameManager.GenerateName(NamingTable.Type), TypeAttributes.NotPublic | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit, assembly.Import(typeof(object))); #endif assembly.MainModule.Types.Add(entryType); //Create a default constructor var ctor = assembly.CreateDefaultConstructor(entryType); ctor.MaxStackSize = 8; var il = ctor.GetILProcessor(); InjectAntiReflectorCode(il, il.Create(OpCodes.Ldarg_0)); var objectCtor = assembly.Import(typeof (object).GetConstructor(Type.EmptyTypes)); il.Append(il.Create(OpCodes.Call, objectCtor)); il.Append(OpCodes.Ret); //Create an entry point var mainMethod = BuildMainMethod(assembly, context, programType, getExecutingAssembly, currentDomain, eventHandler, assemblyResolve, resolveMethod, startMethod); entryType.Methods.Add(mainMethod); }