Skip to main content

Crate ib_hook

Crate ib_hook 

Source
Expand description

Windows binary and system hooking library.

Features:

§Inline hooking

  • Supported CPU architectures: x86, x64, ARM64.
  • no_std and depend on Ntdll.dll only.

See inline module for more details. Here is a quick example:

// cargo add ib-hook --features inline
use ib_hook::inline::InlineHook;

extern "system" fn original(x: u32) -> u32 { x + 1 }

// Hook the function with a detour
extern "system" fn hooked(x: u32) -> u32 { x + 0o721 }
let mut hook = InlineHook::<extern "system" fn(u32) -> u32>::new_enabled(original, hooked).unwrap();

// Now calls to original are redirected to hooked
assert_eq!(original(0x100), 721); // redirected to hooked: 0x100 + 0o721 = 721

// Access original via trampoline
assert_eq!(hook.trampoline()(0x100), 0x101); // 0x100 + 1

// Disable the hook manually (or automatically on drop)
hook.disable().unwrap();
assert_eq!(original(0x100), 0x101); // back to original

§DLL injection

Inject DLL into processes with optional RPC and auto self unload.

  • Optional RPC with serde input and output.
  • RAII (drop guard) design with optional leak().
  • Single DLL injection / Multiple DLL injection manager.
  • Optioanlly, in the DLL, unload self automatically if the injector process aborted.

See inject::dll module for more details. Here is a quick example:

use ib_hook::inject::dll::app::{DllApp, DllInjectionVec};

struct MyDll;
impl DllApp for MyDll {
    const APPLY: &str = "apply_hook";
    type Input = String;
    type Output = ();
}

// Inject into all processes named Notepad.exe
let mut injections = DllInjectionVec::<MyDll>::new();
injections.inject_with_process_name("Notepad.exe")
    .dll_path(std::path::Path::new("hook.dll"))
    .apply(&"input".into())
    .on_error(|pid, err| ())
    .call()
    .unwrap();

// Eject all manually or let drop handle it
injections.eject().on_error(|pid, err| ()).call();

§Windows shell hook (WH_SHELL)

Monitor window operations: creating, activating, title redrawing, monitor changing…

See windows::shell module for more details. Here is a quick example:

use ib_hook::windows::shell::{ShellHook, ShellHookMessage};
{
    let hook = ShellHook::new(Box::new(|msg: ShellHookMessage| {
        println!("{msg:?}");
        false
    }))
    .unwrap();

    // Perform window operations to see received events...
    std::thread::sleep(std::time::Duration::from_secs(30));
}
// Shell hook unregistered

See also ib-shell: Some desktop environment libraries, mainly for Windows Shell.

§GUI process watcher

Monitor GUI processes.

See process module for more details. Here is a quick example:

use ib_hook::process::{GuiProcessEvent, GuiProcessWatcher};

let watcher = GuiProcessWatcher::new(Box::new(|event| {
    println!("Process event: {event:?}");
})).unwrap();

println!("Monitoring GUI processes...");
std::thread::sleep(std::time::Duration::from_secs(60));

Apply a function on every existing and new GUI process exactly once:

// cargo add ib-hook --features sysinfo
use ib_hook::process::GuiProcessWatcher;

let _watcher = GuiProcessWatcher::for_each(|pid| println!("pid: {pid}"))
    .filter_image_path(|path| {
        path.and_then(|p| p.file_name())
            .is_some_and(|n| n.to_ascii_lowercase() == "notepad.exe")
    })
    .build();
std::thread::sleep(std::time::Duration::from_secs(60));

§Crate features

  • std (enabled by default)std dependency.
  • inline — Inline hooking.
  • sysinfosysinfo dependency for some extra process utilities.
  • inject-dll — The injection part of DLL injection.
  • inject-dll-dll — The DLL part of DLL injection.
  • serdeserde support.
  • tracing — Logging via tracing, mainly for debugging.

Modules§

inject
Process/code/DLL injection.
inlineinline
Inline hooking.
process
Process utilities.
windows
Windows system hooks.

Macros§

export_apply
Usage:
spawn_wait_and_free_current_module_once
Auto self unload, i.e. wait for the injector process and unload self.

Traits§

FnPtr
Marker trait for function pointers (fn).