2016-08-29 7 views
-1

런타임 중에 플러그인 로더 (예 : Bukkit for Minecraft)의 메서드를 바꾸려고합니다. 이 인스턴스에서는 어셈블리 파일을 직접 수정할 수 없습니다. 전체 목적은 메소드가 호출되는시기를 알 수 있도록하는 것입니다. 필요한 경우 취소하십시오. 플러그인이로드되면 다음 코드를 실행합니다.C# 메서드 변경 포인터 .NET 3.5

public static void PluginLoaded() 
{ 
    replace(); 
}  

public static void replace() 
{ 
    MethodInfo oldMethod, newMethod; 
    oldMethod = typeof(<other assembly>).GetMethod("<method name>", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic,null,new Type[]{typeof(ushort)},null); 
    newMethod = typeof(NewEvents).GetMethod("<method name>", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(ushort) }, null); 
    RuntimeHelpers.PrepareMethod(oldMethod.MethodHandle); 
    RuntimeHelpers.PrepareMethod(newMethod.MethodHandle); 

    ReplaceInner(oldMethod, newMethod); 
} 

static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject) 
{ 
    unsafe 
    { 
     if (IntPtr.Size == 4) 
     { 
      int* inj = (int*)methodToInject.MethodHandle.Value.ToPointer() + 2; 
      int* tar = (int*)methodToReplace.MethodHandle.Value.ToPointer() + 2; 
      *tar = *inj; 
     } 
     else 
     { 
      ulong* inj = (ulong*)methodToInject.MethodHandle.Value.ToPointer() + 1; 
      ulong* tar = (ulong*)methodToReplace.MethodHandle.Value.ToPointer() + 1; 
      *tar = *inj; 
     } 
    } 
} 

원래 프로그램이 변경된 메소드를 호출 할 때까지 제대로 작동합니다. 이렇게하면 전체 프로그램이 멈추고 access volation이됩니다. 이 문제를 어떻게 해결할 수 있습니까?

+0

내가 그것을 가지고 당신이 플러그인 아키텍처 응용 프로그램과 시도하고있다 메소드 호출을 플러그인으로 추적하기위한 래퍼 로직을 갖고 있습니까? Managed Extensibility Framework 또는 Microsoft Unity와 같은 종속성 주입 프레임 워크를 사용해 보셨습니까? 그것들은 동적으로로드 된 어셈블리 주위에 래퍼를 구현하여 이와 같은 작업을 수행 할 수있는 방법을 제공합니다. – ajawad987

+0

어떤 프레임 워크 버전입니까? –

+0

'RuntimeHelpers.PrepareMethod()'를 호출하지 않고 사용해보십시오. –

답변

2

제공 한 기능은 .Net 버전 4.0부터 시작하는 CLR의 메모리 매핑에만 해당됩니다. 옵션은 다음과 같습니다.

옵션 1. 컴퓨터에서 .NET Framework를 업그레이드합니다. 이렇게하면 Visual Studio를 업그레이드 할 필요없이 문제가 해결됩니다. https://www.microsoft.com/en-us/download/details.aspx?id=42643

옵션 2 업데이트는 .NET 프레임 워크 4.0 전에 유형 및 방법의 메모리 매핑을 반영하여 ReplaceInner() 방법 :

static void ReplaceInner(MethodInfo methodToReplace, MethodInfo methodToInject) 
{ 
    unsafe 
    { 
     if (IntPtr.Size == 4) 
     { 
      uint* tarPtr = (uint*)methodToReplace.MethodHandle.Value.ToPointer(); 
      uint* injPtr = (uint*)methodToInject.MethodHandle.Value.ToPointer(); 

      uint* tar = (uint*)*(tarPtr + 5) + 12; 
      uint* inj = (uint*)*(injPtr + 5) + 12; 
      *tar = *inj; 
     } 
     else 
     { 
      ulong* tarPtr = (ulong*)methodToReplace.MethodHandle.Value.ToPointer(); 
      ulong* injPtr = (ulong*)methodToInject.MethodHandle.Value.ToPointer(); 

      ulong* tar = (ulong*)*(tarPtr + 5) + 12; 
      ulong* inj = (ulong*)*(injPtr + 5) + 12; 
      *tar = *inj; 
     } 
    } 
} 
+0

@ 마이클 베커 나는 약간 코드를 변경했습니다. 이 시도. –

+0

@michaelbecker이 예외가 언제 발생 했습니까? 'ReplaceInner()'를 실행하거나 새로운 삽입 메소드를 호출 할 때? ReplaceInner()를 호출 할 때 –

+0

. 이 코드가 "* tar = * inj;"라고하는 것을 알아 냈습니다. (x64의 두 번째 메신저의 경우) –