2016-02-04 1 views
0

J'ai une classe scellée avec une méthode publique à l'intérieur d'un assemblage, je voudrais ajouter un système de journalisation mais malheureusement je n'ai pas les sources. Donc j'essayais de détourner cette méthode sur une méthode de journalisation spécifique et d'appeler l'original en sortie. L'accrochage fonctionne correctement mais je ne suis pas en mesure d'obtenir n'importe quel type de paramètres ou au moins je reçois quelque chose de complètement faux.Hook une méthode gérée à l'exécution en C#

Je ne peux pas non plus utiliser d'injection ou de bibliothèques comme PostSharp, alors je me demande si ce genre de choses peut être réalisé en cours d'exécution ou est-ce que je peux abandonner?

Juste pour vous donner plus de détails que je vais coller certaines parties de code ci-dessous:

public Hook(Delegate target, Delegate hook) 
{ 
    this.target = Marshal.GetFunctionPointerForDelegate(target); 
    targetDelegate = target; 
    this.hook = Marshal.GetFunctionPointerForDelegate(hook); 

    originalBytes = new byte[6]; 
    Marshal.Copy(this.target, originalBytes, 0, 6); 

    byte[] hookPointerBytes = BitConverter.GetBytes(this.hook.ToInt32()); 
    // Jump 
    newBytes = new byte[] 
    { 
    0x68, hookPointerBytes[0], hookPointerBytes[1], hookPointerBytes[2], hookPointerBytes[3], 0xC3 
    }; 
} 

public object CallOriginal(params object[] args) 
{ 
    // Remove the patch 
    Uninstall(); 
    // Invoke the original method 
    object ret = targetDelegate.DynamicInvoke(args); 
    // Re-apply the patch 
    Install(); 
    return ret; 
} 


public sealed class Foo 
{ 
    public void DoSomething(Int32 value1) 
    { 
     // and here I am getting value1 = -1919988997 
     Console.WriteLine(value1); 
    } 
} 

class Program 
{ 
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    public delegate void DoSomethingDelegate(Int32 value1); 

    private static DoSomethingDelegate Original { get; set; } 
    private static DoSomethingDelegate Hooked { get; set; } 

    private static HookManager _hookManager; 

    public static void DoSomething(Int32 value1) 
    { 
     // This is called as well after foo.DoSomething but value1 is 251934152 
     Console.WriteLine("Hooked DoSomething: " + value1) ; 
     var hook = _hook["DoSomethingHook"]; 

     // Call the original Foo.DoSomething 
     hook.CallOriginal(value1); 
    } 

    static void Main(string[] args) 
    { 
     RuntimeHelpers.PrepareMethod(typeof(Foo).GetMethod("DoSomething").MethodHandle); 
     _hookManager = new HookManager(); 
     var originalPointer = typeof(Foo).GetMethod("DoSomething").MethodHandle.GetFunctionPointer(); 
     Original = (DoSomethingDelegate)Marshal.GetDelegateForFunctionPointer(originalPointer, typeof(DoSomethingDelegate)); 
     Hooked = DoSomething; 
     _hookManager.Add(Original, Hooked, "DoSomethingHook"); 

     // Call Hook method, HookManager it is just an extended dictionary... 
     _hookManager.InstallAll(); 

     var foo = new Foo(); 

     // Calling the original method here with 1 
     foo.DoSomething(1); 

     Console.ReadLine(); 
    } 
} 
+0

GetMethod vous donnera un MethodInfo toutes les informations sur la méthode, y compris les types de paramètres – Gusman

+0

Vous pouvez trouver cet article utile: http://www.codeproject.com/Articles/37549/CLR-Injection- Runtime-Method-Replacer – Amy

+0

Merci @Gusman, je l'ai déjà vu. Mais il remplace la méthode originale par une autre, ce n'est pas vraiment ce dont j'ai besoin –

Répondre

0

Solved Marshal.GetFunctionPointerForDelegate: Je ne peux pas utiliser cette méthode pour créer un délégué d'un pointeur de fonction à une autre délégué géré.

this.target = target.Method.MethodHandle.GetFunctionPointer(); //Marshal.GetFunctionPointerForDelegate(target); 
    targetDelegate = target; 
    this.hook = hook.Method.MethodHandle.GetFunctionPointer(); //Marshal.GetFunctionPointerForDelegate(hook);