1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*!
Windows binary and system hooking library.
Features:
- [Inline hooking](#inline-hooking):
Hook functions on x86/x64/ARM64, `no_std` and `Ntdll.dll` only.
- [DLL injection](#dll-injection):
Inject DLL into processes with optional RPC and auto self unload.
- [Windows shell hook (`WH_SHELL`)](#windows-shell-hook-wh_shell):
Monitor window operations: creating, activating, title redrawing, monitor changing...
- [GUI process watcher](#gui-process-watcher):
Monitor GUI processes.
## 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:
```no_run
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:
```no_run
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.](https://github.com/Chaoses-Ib/ib-shell)
## GUI process watcher
Monitor GUI processes.
See [`process`] module for more details. Here is a quick example:
```no_run
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:
```no_run
// 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
*/
/// Marker trait for [function pointers (`fn`)](https://doc.rust-lang.org/nightly/core/primitive.fn.html).