private int D3D9ResetDetour(IntPtr instance, ref NativeAPI.PresentParameters presentationParameters) { if (OnResetDevice != null) OnResetDevice(instance); return Reset(instance, ref presentationParameters); }
/// <summary> /// Loads the given driver into the kernel and immediately marks it for deletion. /// The installed driver will be registered with the service control manager under the /// <paramref name="InDriverName"/> you specify. /// Please note that you should use <see cref="IsX64System"/> to find out which /// driver to load. Even if your process is running on 32-Bit this does not mean, /// that the OS kernel is running on 32-Bit! /// </summary> /// <param name="InDriverPath"></param> /// <param name="InDriverName"></param> public static void InstallDriver( String InDriverPath, String InDriverName) { NativeAPI.RhInstallDriver(InDriverPath, InDriverName); }
int D3D9CreateDeviceDetour(IntPtr instance, uint adapter, uint deviceType, IntPtr focusWindow, uint behaviorFlags, ref NativeAPI.PresentParameters presentationParameters, out IntPtr returnedDeviceInterface) { // Invoke original create device function and retrieve the created device var result = Direct3D9CreateDevice(instance, adapter, deviceType, focusWindow, behaviorFlags, ref presentationParameters, out returnedDeviceInterface); Direct3DDevice9 = returnedDeviceInterface; Hwnd = focusWindow; if (hook_end_scene == null) { // Hook WndProc old_wndproc = NativeAPI.GetWindowLong(focusWindow, NativeAPI.GWL_WNDPROC); wnd_proc_delegate = new NativeAPI.WndProcDelegate(WndProcDetour); NativeAPI.SetWindowLong(focusWindow, NativeAPI.GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(wnd_proc_delegate)); // Hook EndScene var end_scene_pointer = Misc.GetVTableFunction(Direct3DDevice9, NativeAPI.EndSceneOffset); EndScene = Misc.GetDelegate<NativeAPI.Direct3D9EndScene>(end_scene_pointer); hook_end_scene = LocalHook.Create(end_scene_pointer, new NativeAPI.Direct3D9EndScene(EndSceneCallback), this); hook_end_scene.ThreadACL.SetExclusiveACL(new Int32[] { }); } if (hook_reset == null) { // Hook Reset var reset_pointer = Misc.GetVTableFunction(Direct3DDevice9, NativeAPI.ResetOffset); Reset = Misc.GetDelegate<NativeAPI.Direct3D9ResetDelegate>(reset_pointer); hook_reset = LocalHook.Create(reset_pointer, new NativeAPI.Direct3D9ResetDelegate(D3D9ResetDetour), this); hook_reset.ThreadACL.SetExclusiveACL(new Int32[] { }); } try { if (OnCreateDevice != null) OnCreateDevice(); } catch (Exception e) { MessageBox.Show(e.ToString()); } return result; }
/// <summary> /// Returns the current native system thread ID. /// </summary> /// <remarks> /// Even if currently each dedicated managed /// thread (not a thread from a <see cref="ThreadPool"/>) exactly maps to one native /// system thread, this behavior may change in future versions. /// If you would like to have unintercepted threads, you should make sure that they are /// dedicated ones, e.g. derived from <see cref="Thread"/>. /// </remarks> /// <returns>The native system thread ID.</returns> public static Int32 GetCurrentThreadId() { return(NativeAPI.GetCurrentThreadId()); }
/// <summary> /// Installs the EasyHook support driver. After this step you may use /// <see cref="InstallDriver"/> to install your kernel mode hooking component. /// </summary> public static void InstallSupportDriver() { NativeAPI.RhInstallSupportDriver(); }
/// <summary> /// Returns the current native system process ID. /// </summary> /// <returns>The native system process ID.</returns> public static Int32 GetCurrentProcessId() { return(NativeAPI.GetCurrentProcessId()); }
internal static void InjectEx( Int32 InHostPID, Int32 InTargetPID, Int32 InWakeUpTID, Int32 InNativeOptions, String InLibraryPath_x86, String InLibraryPath_x64, Boolean InCanBypassWOW64, Boolean InCanCreateService, params Object[] InPassThruArgs) { MemoryStream PassThru = new MemoryStream(); ManagedRemoteInfo RemoteInfo = new ManagedRemoteInfo(); BinaryFormatter Format = new BinaryFormatter(); Int32 NtStatus; HelperServiceInterface.BeginInjection(InTargetPID); try { RemoteInfo = new ManagedRemoteInfo(); RemoteInfo.HostPID = InHostPID; RemoteInfo.UserParams = InPassThruArgs; GCHandle hPassThru = PrepareInjection( RemoteInfo, ref InLibraryPath_x86, ref InLibraryPath_x64, PassThru); /* * Inject library... */ try { switch (NtStatus = NativeAPI.RhInjectLibraryEx( InTargetPID, InWakeUpTID, NativeAPI.EASYHOOK_INJECT_MANAGED | InNativeOptions, typeof(Config).Assembly.Location, typeof(Config).Assembly.Location, hPassThru.AddrOfPinnedObject(), (int)PassThru.Length)) { case NativeAPI.STATUS_WOW_ASSERTION: { // Use helper application to bypass WOW64... if (InCanBypassWOW64) { WOW64Bypass.Inject( InHostPID, InTargetPID, InWakeUpTID, InNativeOptions, InLibraryPath_x86, InLibraryPath_x64, InPassThruArgs); } else { throw new AccessViolationException("Unable to inject library into target process."); } } break; case NativeAPI.STATUS_ACCESS_DENIED: { // Use service and try again... if (InCanCreateService) { ServiceMgmt.Inject( InHostPID, InTargetPID, InWakeUpTID, InNativeOptions, InLibraryPath_x86, InLibraryPath_x64, InPassThruArgs); } else { NativeAPI.Force(NtStatus); } } break; case NativeAPI.STATUS_SUCCESS: { // wait for injection completion HelperServiceInterface.WaitForInjection(InTargetPID); } break; default: { NativeAPI.Force(NtStatus); } break; } } finally { hPassThru.Free(); } } finally { HelperServiceInterface.EndInjection(InTargetPID); } }
/// <summary> /// If the library was injected with <see cref="CreateAndInject"/>, this will /// finally start the current process. You should call this method in the library /// <c>Run()</c> method after all hooks have been installed. /// </summary> public static void WakeUpProcess() { NativeAPI.RhWakeUpProcess(); }
/// <summary> /// RIP relocation is disabled by default. If you want to enable it, /// just call this method which will attach a debugger to the current /// process. There may be circumstances under which this might fail /// and this is why it is not done by default. On 32-Bit system this /// method will always succeed and do nothing... /// </summary> public static void EnableRIPRelocation() { NativeAPI.DbgAttachDebugger(); }
/// <summary> /// REQUIRES ADMIN PRIVILEGES. Installs EasyHook and all given user NET assemblies into the GAC and /// ensures that all references are cleaned up if the installing application /// is shutdown. Cleanup does not depend on the calling application... /// </summary> /// <remarks> /// <para> /// ATTENTION: There are some problems when debugging processes whose libraries /// are added to the GAC. Visual Studio won't start the debug session! There is /// only one chance for you to workaround this issue if you want to install /// libraries AND debug them simultanously. This is simply to debug only one process /// which is the default setting of Visual Studio. Because the libraries are added /// to the GAC AFTER Visual Studio has initialized the debug session, there won't be /// any conflicts; at least so far... /// </para> /// <para> /// In debug versions of EasyHook, you may also check the "Application" event log, which holds additional /// information /// about the GAC registration, after calling this method. In general this method works /// transactionally. This means if something goes wrong, the GAC state of all related libraries /// won't be violated! /// </para> /// <para> /// The problem with NET assemblies is that the CLR only searches the GAC and /// directories starting with the application base directory for assemblies. /// To get injected assemblies working either all of them have to be located /// under the target base directory (which is not suitable in most cases) or /// reside in the GAC. /// </para> /// <para> /// EasyHook provides a way to automatically register all of its own assemblies /// and custom ones temporarily in the GAC. It also ensures /// that all of these assemblies are removed if the installing process exists. /// So you don't need to care about and may write applications according to /// the XCOPY standard. If your application ships with an installer, you may /// statically install all of your assemblies and the ones of EasyHook into the /// GAC. In this case just don't call <see cref="Register" />. /// </para> /// <para> /// Of course EasyHook does also take care of multiple processes using the same /// injection libraries. So if two processes are sharing some of those DLLs, /// a stable reference counter ensures that the libraries are kept in the GAC /// if one process is terminated while the other continues running and so continues /// holding a proper GAC reference. /// </para> /// <para> /// Please note that in order to add your library to the GAC, it has to be a valid /// NET assembly and expose a so called "Strong Name". Assemblies without a strong /// name will be rejected by this method! /// </para> /// </remarks> /// <param name="InDescription"> /// A description under which the installed files should be referenced. /// </param> /// <param name="InUserAssemblies"> /// A list of user assemblies as relative or absolute paths. /// </param> /// <exception cref="System.IO.FileNotFoundException"> /// At least one of the files specified could not be found! /// </exception> /// <exception cref="BadImageFormatException"> /// Unable to load at least one of the given files for reflection. /// </exception> /// <exception cref="ArgumentException"> /// At least one of the given files does not have a strong name. /// </exception> public static void Register( String InDescription, params String[] InUserAssemblies) { var AsmList = new List <Assembly>(); var RemovalList = ""; var InstallList = new List <String>(); /* * Read and validate config file... */ var Files = new List <string>(); Files.Add(typeof(Config).Assembly.Location); Files.AddRange(InUserAssemblies); for (var i = 0; i < Files.Count; i++) { Assembly Entry; var AsmPath = Path.GetFullPath(Files[i]); if (!File.Exists(AsmPath)) { throw new FileNotFoundException("The given assembly \"" + Files[i] + "\" (\"" + AsmPath + "\") does not exist."); } // just validate that this is a NET assembly with valid metadata... try { Entry = Assembly.ReflectionOnlyLoadFrom(AsmPath); } catch (Exception ExtInfo) { throw new BadImageFormatException("Unable to load given assembly \"" + Files[i] + "\" (\"" + AsmPath + "\") for reflection. Is this a valid NET assembly?", ExtInfo); } // is strongly named? (required for GAC) var Name = AssemblyName.GetAssemblyName(AsmPath); if ((Name.Flags & AssemblyNameFlags.PublicKey) == 0) { throw new ArgumentException("The given user library \"" + Files[i] + "\" is not strongly named!"); } AsmList.Add(Entry); InstallList.Add(AsmPath); RemovalList += " \"" + Name.Name + "\""; } /* * Install assemblies into GAC ... */ // create unique installation identifier var IdentData = new Byte[30]; new RNGCryptoServiceProvider().GetBytes(IdentData); // run cleanup service InDescription = InDescription.Replace('"', '\''); RunCommand( "GACRemover", false, false, GetDependantSvcExecutableName(), Process.GetCurrentProcess().Id.ToString() + " \"" + Convert.ToBase64String(IdentData) + "\" \"" + InDescription + "\"" + RemovalList); // install assemblies NativeAPI.GacInstallAssemblies( InstallList.ToArray(), InDescription, Convert.ToBase64String(IdentData)); }