diff --git a/DotNetDetour/AssemblyUtil.cs b/DotNetDetour/AssemblyUtil.cs index 1e7cb62..71838f1 100644 --- a/DotNetDetour/AssemblyUtil.cs +++ b/DotNetDetour/AssemblyUtil.cs @@ -124,7 +124,7 @@ public static IEnumerable GetImplementedObjectsByInterface GetImplementedObjectsByInterface(this Assembly assembly, Type targetType) where TBaseInterface : class { - Type[] arrType = assembly.GetExportedTypes(); + Type[] arrType = assembly.GetTypes(); var result = new List(); diff --git a/DotNetDetour/DetourWays/NativeDetourFor32Bit.cs b/DotNetDetour/DetourWays/NativeDetourFor32Bit.cs index fdaf7ad..5d097c1 100644 --- a/DotNetDetour/DetourWays/NativeDetourFor32Bit.cs +++ b/DotNetDetour/DetourWays/NativeDetourFor32Bit.cs @@ -16,68 +16,97 @@ namespace DotNetDetour.DetourWays /// /// inline hook,通过修改函数的前5字节指令为jmp target_addr实现 /// - public unsafe class NativeDetourFor32Bit: IDetour + public unsafe class NativeDetourFor32Bit : IDetour { //protected byte[] originalInstrs = new byte[5]; protected byte[] newInstrs = { 0xE9, 0x90, 0x90, 0x90, 0x90 }; //jmp target - protected byte* srcPtr; + protected byte* rawMethodPtr; public NativeDetourFor32Bit() { } - public virtual void Patch(MethodInfo src, MethodInfo dest,MethodInfo ori) + public virtual bool Patch(MethodBase rawMethod/*要hook的目标函数*/, + MethodInfo customImplMethod/*用户定义的函数,可以调用占位函数来实现对原函数的调用*/, + MethodInfo placeholder/*占位函数*/) { //确保jit过了 - var typeHandles = src.DeclaringType.GetGenericArguments().Select(t => t.TypeHandle).ToArray(); - RuntimeHelpers.PrepareMethod(src.MethodHandle, typeHandles); - - srcPtr = (byte*)src.MethodHandle.GetFunctionPointer().ToPointer(); - var destPtr = (byte*)dest.MethodHandle.GetFunctionPointer().ToPointer(); - if (ori != null) + var typeHandles = rawMethod.DeclaringType.GetGenericArguments().Select(t => t.TypeHandle).ToArray(); + RuntimeHelpers.PrepareMethod(rawMethod.MethodHandle, typeHandles); + + rawMethodPtr = (byte*)rawMethod.MethodHandle.GetFunctionPointer().ToPointer(); + + var customImplMethodPtr = (byte*)customImplMethod.MethodHandle.GetFunctionPointer().ToPointer(); + //生成跳转指令,使用相对地址,用于跳转到用户定义函数 + fixed (byte* newInstrPtr = newInstrs) + { + *(uint*)(newInstrPtr + 1) = (uint)customImplMethodPtr - (uint)rawMethodPtr - 5; + } + + //因测试项目的特殊性,确保测试项目代码不会重入 + if (IsDetourInstalled()) { - CreateOriginalMethod(ori); //生成原函数 + return false; } - fixed (byte* newInstrPtr=newInstrs) + + //将对占位函数的调用指向原函数,实现调用占位函数即调用原始函数的功能 + if (placeholder != null) { - *(uint*)(newInstrPtr + 1) = (uint)destPtr - (uint)srcPtr - 5; + MakePlacholderMethodCallPointsToRawMethod(placeholder); } + + + //并且将对原函数的调用指向跳转指令,以此实现将对原始目标函数的调用跳转到用户定义函数执行的目的 Patch(); + return true; } protected virtual void Patch() { uint oldProtect; //系统方法没有写权限,需要修改页属性 - NativeAPI.VirtualProtect((IntPtr)srcPtr, 5, Protection.PAGE_EXECUTE_READWRITE, out oldProtect); + NativeAPI.VirtualProtect((IntPtr)rawMethodPtr, 5, Protection.PAGE_EXECUTE_READWRITE, out oldProtect); for (int i = 0; i < newInstrs.Length; i++) { - *(srcPtr + i) = newInstrs[i]; + *(rawMethodPtr + i) = newInstrs[i]; } } - protected virtual void CreateOriginalMethod(MethodInfo method) + /// + /// 将对placeholder的调用指向原函数 + /// + /// + protected virtual void MakePlacholderMethodCallPointsToRawMethod(MethodInfo placeholder) { uint oldProtect; - var needSize = LDasm.SizeofMin5Byte(srcPtr); + var needSize = LDasm.SizeofMin5Byte(rawMethodPtr); var total_length = (int)needSize + 5; byte[] code = new byte[total_length]; IntPtr ptr = Marshal.AllocHGlobal(total_length); //code[0] = 0xcc;//调试用 for (int i = 0; i < needSize; i++) { - code[i] = srcPtr[i]; + code[i] = rawMethodPtr[i]; } code[needSize] = 0xE9; fixed (byte* p = &code[needSize + 1]) { - *((uint*)p) = (uint)srcPtr - (uint)ptr - 5; + *((uint*)p) = (uint)rawMethodPtr - (uint)ptr - 5; } Marshal.Copy(code, 0, ptr, total_length); NativeAPI.VirtualProtect(ptr, (uint)total_length, Protection.PAGE_EXECUTE_READWRITE, out oldProtect); - RuntimeHelpers.PrepareMethod(method.MethodHandle); - *((uint*)method.MethodHandle.Value.ToPointer() + 2) = (uint)ptr; + RuntimeHelpers.PrepareMethod(placeholder.MethodHandle); + *((uint*)placeholder.MethodHandle.Value.ToPointer() + 2) = (uint)ptr; } + public virtual bool IsDetourInstalled() + { + byte[] v = new byte[newInstrs.Length]; + for (int i = 0; i < v.Length; i++) + { + v[i] = *(rawMethodPtr + i); + } + return v.SequenceEqual(newInstrs); + } } } diff --git a/DotNetDetour/DetourWays/NativeDetourFor64Bit.cs b/DotNetDetour/DetourWays/NativeDetourFor64Bit.cs index 680510f..fc0f04f 100644 --- a/DotNetDetour/DetourWays/NativeDetourFor64Bit.cs +++ b/DotNetDetour/DetourWays/NativeDetourFor64Bit.cs @@ -21,18 +21,18 @@ public unsafe class NativeDetourFor64Bit : NativeDetourFor32Bit 0xC2,0x08,0x00 //ret 8 }; - protected override void CreateOriginalMethod(MethodInfo method) + protected override void MakePlacholderMethodCallPointsToRawMethod(MethodInfo method) { uint oldProtect; - var needSize = LDasm.SizeofMin5Byte(srcPtr); + var needSize = LDasm.SizeofMin5Byte(rawMethodPtr); byte[] src_instr = new byte[needSize]; for (int i = 0; i < needSize; i++) { - src_instr[i] = srcPtr[i]; + src_instr[i] = rawMethodPtr[i]; } fixed (byte* p = &jmp_inst[3]) { - *((ulong*)p) = (ulong)(srcPtr + needSize); + *((ulong*)p) = (ulong)(rawMethodPtr + needSize); } var totalLength = src_instr.Length + jmp_inst.Length; IntPtr ptr = Marshal.AllocHGlobal(totalLength); diff --git a/DotNetDetour/DotNetDetour.csproj b/DotNetDetour/DotNetDetour.csproj index a8bb5fc..a6aa03d 100644 --- a/DotNetDetour/DotNetDetour.csproj +++ b/DotNetDetour/DotNetDetour.csproj @@ -57,6 +57,12 @@ + + + README.md + + +