public SocketHookHosting(HookOptions options, IHookLifetimeService hookLifetime, ISocketHookService hookService, IHostEnvironment env) { _isProduction = env.IsProduction(); _socketHookService = hookService; _hookLifetime = hookLifetime; _options = options; }
public HookDelegateEmitter(string name, IEnumerable <ParameterDefinition> parameters, TypeDefinition returnType, HookOptions flags, ModuleDefinition module) { this._name = name; this._parameters = parameters; this._flags = flags; this._module = module; this._returnType = returnType; }
public HookDelegateEmitter(string prefix, MethodDefinition method, HookOptions flags) { this._name = prefix + method.GetSafeName(); this._flags = flags; this._parameters = method.Parameters; this._module = method.Module; this._returnType = method.ReturnType; }
public static string DisplayValue(HookOptions opts) { switch (opts) { case HookOptions.IgnoreInjected: return "Ignore Injected Events"; case HookOptions.All: return "All"; default: return "None"; } }
public static string DisplayValue(HookOptions opts) { switch (opts) { case HookOptions.IgnoreInjected: return("Ignore Injected Events"); case HookOptions.All: return("All"); default: return("None"); } }
/// <summary> /// Generates a hook that is called before any native code /// </summary> /// <param name="method">Method to generate the hook in</param> /// <param name="options">Configurable hook options</param> /// <returns>A <see cref="MergableMethod"/> instance</returns> public static MergableMethod GenerateBeginHook ( this MethodDefinition method, HookOptions options = HookOptions.Default, VariableDefinition result_variable = null ) { // emit call at offset 0 // add or get the types where we are storing out auto generated hooks & their delegates var hooks_type = method.DeclaringType.GetHooksType(); var hooks_delegates_type = method.DeclaringType.GetHooksDelegateType(); // generate the hook handler delegate var hook_delegate_emitter = new HookDelegateEmitter("OnPre", method, options); var hook_handler = hook_delegate_emitter.Emit(); hooks_delegates_type.NestedTypes.Add(hook_handler); // generate the api hook external modules can attach to var hook_field = new FieldDefinition("Pre" + method.GetSafeName(), FieldAttributes.Public | FieldAttributes.Static, hook_handler); hooks_type.Fields.Add(hook_field); // generate the call to the delegate var hook_emitter = new HookEmitter(hook_field, method, (options & HookOptions.Cancellable) != 0, (options & HookOptions.ReferenceParameters) != 0, result_variable ); var result = hook_emitter.Emit(); //instructions.MergeInto(method, 0); // end of method var invoke_method = hook_handler.Resolve().Method("Invoke"); if (invoke_method.ReturnType.FullName != "System.Void") { result.Instructions = result.Instructions.Concat(new[] { Instruction.Create(OpCodes.Brtrue_S, method.Body.Instructions.First()), Instruction.Create(OpCodes.Br_S, method.Body.Instructions.Last()) }); } return(result); }
/// <summary> /// Start the engine at your project startup. /// It's could be OwinStartup class or Global.asax or WebApiConfig.cs for web projects /// or /// Could be Program.cs for Desktop projects /// </summary> /// <param name="_Options"></param> /// <param name="_MainAssembly"></param> public static void Start(HookOptions _Options, Assembly _MainAssembly) { Options = _Options; try { Assembly currentAssembly = _MainAssembly; var findedActions = currentAssembly.GetTypes() .SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static)) .Where(m => !m.GetCustomAttributes(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), true).Any() && m.IsDefined(typeof(HookEngineAppStartupMethod), true) ) .Select(x => new { Type = x.DeclaringType, Class = x.DeclaringType.Name, Action = x.Name }) .OrderBy(x => x.Class).ThenBy(x => x.Action).ToList(); foreach (var findedAction in findedActions) { findedAction.Type.InvokeMember(findedAction.Action, BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, null); } } catch (Exception e) { if (Options.ThrowErrors) { throw e; } } }
/// <summary> /// Generates a hook that is called after native code /// </summary> /// <param name="method">Method to generate the hook in</param> /// <param name="options">Configurable hook options</param> /// <returns>A <see cref="MergableMethod"/> instance</returns> public static MergableMethod GenerateHook ( this IEnumerable <ParameterDefinition> parameters, string name, TypeDefinition parentType, TypeDefinition returnType, HookOptions flags, ModuleDefinition module, HookOptions options = HookOptions.Post, VariableDefinition result_variable = null ) { // emit call at each ret instruction // add or get the types where we are storing out auto generated hooks & their delegates var hooks_type = parentType.GetHooksType(); var hooks_delegates_type = parentType.GetHooksDelegateType(); // generate the hook handler delegate var hook_delegate_emitter = new HookDelegateEmitter("On" + name, parameters, returnType, options, module); var hook_handler = hook_delegate_emitter.Emit(); hooks_delegates_type.NestedTypes.Add(hook_handler); // generate the api hook external modules can attach to var hook_field = new FieldDefinition(name, FieldAttributes.Public | FieldAttributes.Static, hook_handler); hooks_type.Fields.Add(hook_field); // generate the call to the delegate var hook_emitter = new HookEmitter(hook_field, parameters, false, false, result_variable); var result = hook_emitter.Emit(); // end of method return(result); }
/// <summary> /// Generates a hook that is called after native code /// </summary> /// <param name="method">Method to generate the hook in</param> /// <param name="options">Configurable hook options</param> /// <returns>A <see cref="MergableMethod"/> instance</returns> public static MergableMethod GenerateEndHook ( this MethodDefinition method, HookOptions options = HookOptions.Default, VariableDefinition result_variable = null ) { // emit call at each ret instruction // add or get the types where we are storing out auto generated hooks & their delegates var hooks_type = method.DeclaringType.GetHooksType(); var hooks_delegates_type = method.DeclaringType.GetHooksDelegateType(); // generate the hook handler delegate var hook_delegate_emitter = new HookDelegateEmitter("OnPost", method, options & ~( HookOptions.ReferenceParameters | HookOptions.Cancellable )); var hook_handler = hook_delegate_emitter.Emit(); hooks_delegates_type.NestedTypes.Add(hook_handler); // generate the api hook external modules can attach to var hook_field = new FieldDefinition("Post" + method.GetSafeName(), FieldAttributes.Public | FieldAttributes.Static, hook_handler); hooks_type.Fields.Add(hook_field); // generate the call to the delegate var hook_emitter = new HookEmitter(hook_field, method, false, false, result_variable); var result = hook_emitter.Emit(); // end of method return(result); }
public WinEventHook(Process process, int?threadId, WinEvent minEvent, WinEvent maxEvent, HookOptions options = HookOptions.None, SynchronizationContext syncCtx = null) { if (!(syncCtx != null || !options.HasFlag(HookOptions.AsyncCallbacks))) { throw new ArgumentException("Contract assertion not met: syncCtx != null || !options.HasFlag(HookOptions.AsyncCallbacks)", nameof(syncCtx)); } this.thCreated = Thread.CurrentThread; this.Observers = new List <IObserver <WinEventEventArgs> >(); this.Process = process; this.ThreadID = threadId; this.MinEvent = minEvent; this.MaxEvent = maxEvent; this.SyncCtx = syncCtx; this.CallbackContext = options.HasFlag(HookOptions.AsyncCallbacks) ? new Action <Action>(CallbackAsync) : new Action <Action>(CallbackSyncIfNeeded); // EventProcHandle is the callback to CLR code, and must be valid. We take a new GCRoot // and only release once a successfull Unhook occurs this.EventProcHandle = new NativeMethods.WinEventProc(Hook_EventProc); this.EventProcHandleGCRoot = GCHandle.Alloc(EventProcHandle); if (!options.HasFlag(HookOptions.StartDisabled)) { StartInternal(); } }
public WinEventHook(Process process, int?threadId, WinEvent minEvent, WinEvent maxEvent, HookOptions options) : this(process, threadId, minEvent, maxEvent, options, null) { }
/// <summary> /// Adds configurable hooks into each method of the query /// </summary> /// <param name="results">Methods to be hooked</param> /// <param name="options">Hook options</param> /// <returns>The existing <see cref="QueryResult"/> instance</returns> public static QueryResult Hook(this QueryResult results, HookOptions options = HookOptions.Default) { var context = results .Select(x => x.Instance as MethodDefinition) .Where( x => x != null && x.HasBody && !x.DeclaringType.IsInterface && x.GenericParameters.Count == 0 ); foreach (var method in context) { var new_method = method.Clone(); // rename method to be suffixed with Direct method.Name += "Direct"; method.Name = method.GetSafeName(); method.DeclaringType.Methods.Add(new_method); method.Attributes &= ~MethodAttributes.Virtual; method.Attributes &= ~MethodAttributes.SpecialName; method.Attributes &= ~MethodAttributes.RTSpecialName; method.Overrides.Clear(); method.CustomAttributes.Clear(); method.SecurityDeclarations.Clear(); method.ReplaceWith(new_method); var processor = new_method.Body.GetILProcessor(); var ins_return = Instruction.Create(OpCodes.Ret); processor.Append(ins_return); var call_emitter = new CallEmitter(method, new_method.Body.Instructions.First()); var call = call_emitter.Emit(); VariableDefinition return_variable = null; var nop = call.Instructions .SingleOrDefault(x => x.OpCode == OpCodes.Pop); // expect one here as the CallEmitter should only handle one. if it changes this needs to change if (nop != null) { return_variable = new VariableDefinition(method.ReturnType); new_method.Body.Variables.Add(return_variable); nop.Operand = return_variable; nop.OpCode = OpCodes.Stloc_S; } call.MergeInto(new_method, 0); if ((options & HookOptions.Pre) != 0) { var hook = new_method.GenerateBeginHook(options, return_variable); if ((options & HookOptions.Cancellable) != 0 && (options & HookOptions.AlterResult) == 0 && method.ReturnType.FullName != "System.Void") { // TODO: this functionality will be desired - idea: just generate the "default(T)" // what to do if you get here: add HookFlags.AlterResult to your flags or don't try cancelling throw new NotSupportedException("Attempt to cancel a non-void method without allowing the callback to alter the result."); } hook.MergeInto(new_method, 0); } if ((options & HookOptions.Post) != 0) { var hook = new_method.GenerateEndHook(options, return_variable); //var last_ret = new_method.Body.Instructions.Last(x => x.OpCode == OpCodes.Ret); //last_ret.ReplaceTransfer(hook.Instructions.First(), new_method); hook.MergeInto(new_method, call.Instructions.Last().Next); } if (return_variable != null) { var ins_return_variable = Instruction.Create(OpCodes.Ldloc, return_variable); processor.InsertBefore(ins_return, ins_return_variable); ins_return.ReplaceTransfer(ins_return_variable, new_method); } // for all classes (not structs) we need to move the base type constructor over to the new // method before any of our hook code is executed. if (new_method.IsConstructor && new_method.HasThis && !new_method.DeclaringType.IsValueType) { var instructions = method.Body.Instructions.TakeWhile( x => x.Previous == null || x.Previous.OpCode != OpCodes.Call || (x.Previous.Operand as MethodReference).FullName != method.DeclaringType.BaseType.Resolve().Method(".ctor").FullName ); foreach (var instruction in instructions.Reverse()) { method.Body.Instructions.Remove(instruction); new_method.Body.Instructions.Insert(0, instruction); } } } return(results); }