subhook/README.md

144 lines
3.9 KiB
Markdown
Raw Normal View History

2015-01-16 13:23:52 +00:00
[![Build Status][build_status]][build]
2015-02-16 16:04:57 +00:00
[![Build Status - Windows][build_status_win]][build_win]
2015-01-15 17:45:26 +00:00
SubHook is a super-simple hooking library for C and C++ that works on Windows,
Linux and macOS. It supports x86 only (32-bit and 64-bit).
2013-06-26 07:15:37 +00:00
2018-09-01 11:19:53 +00:00
Installation
------------
2018-09-06 17:52:15 +00:00
Simply copy the files to your project and include subhook.c in your build.
The other source files wil be `#included` by the main C file automatically
2018-09-01 11:19:53 +00:00
depending on the OS and achitecture.
Use of CMake is not mandatory, the library can be built wihtout it (no extra
build configuration required).
2013-01-13 17:02:16 +00:00
Examples
--------
2013-09-26 20:44:02 +00:00
In the following examples `foo` is some function or a function pointer that
takes a single argument of type `int` and uses the same calling convention
as `my_foo` (depends on compiler).
2013-01-14 21:40:12 +00:00
2014-11-26 18:07:51 +00:00
### Basic usage
2013-01-13 17:02:16 +00:00
```c
2013-01-14 21:40:12 +00:00
#include <stdio.h>
2013-01-13 17:02:16 +00:00
#include <subhook.h>
2013-12-05 17:00:59 +00:00
subhook_t foo_hook;
2013-01-13 17:02:16 +00:00
2013-01-14 21:40:12 +00:00
void my_foo(int x) {
2014-11-26 18:07:51 +00:00
/* Remove the hook so that you can call the original function. */
2013-01-13 17:02:16 +00:00
subhook_remove(foo_hook);
2013-01-14 21:40:12 +00:00
printf("foo(%d) called\n", x);
foo(x);
2013-01-13 17:02:16 +00:00
2014-11-26 18:07:51 +00:00
/* Install the hook back to intercept further calls. */
2013-01-13 17:02:16 +00:00
subhook_install(foo_hook);
}
int main() {
2014-11-26 18:07:51 +00:00
/* Create a hook that will redirect all foo() calls to to my_foo(). */
2016-08-15 14:05:37 +00:00
foo_hook = subhook_new((void *)foo, (void *)my_foo, 0);
2013-01-13 17:02:16 +00:00
2014-11-26 18:07:51 +00:00
/* Install it. */
2013-01-13 17:02:16 +00:00
subhook_install(foo_hook);
2013-12-04 19:04:59 +00:00
2014-11-26 18:07:51 +00:00
foo(123);
/* Remove the hook and free memory when you're done. */
subhook_remove(foo_hook);
subhook_free(foo_hook);
2013-01-13 17:02:16 +00:00
}
```
2014-11-26 18:07:51 +00:00
### Trampolines
Using trampolines allows you to jump to the original code without removing
and re-installing hooks every time your function gets called.
```c
typedef void (*foo_func)(int x);
void my_foo(int x) {
printf("foo(%d) called\n", x);
/* Call foo() via trampoline. */
((foo_func)subhook_get_trampoline(foo_hook))(x);
}
int main() {
/* Same code as in previous example. */
}
```
2016-08-15 14:05:37 +00:00
Please note that subhook has a very simple length disassmebler engine (LDE)
that works only with most common prologue instructions like push, mov, call,
etc. When it encounters an unknown instruction subhook_get_trampoline() will
return NULL.
2014-11-26 18:07:51 +00:00
2013-01-13 17:02:16 +00:00
### C++
```c++
2013-01-14 21:40:12 +00:00
#include <iostream>
2013-01-13 17:02:16 +00:00
#include <subhook.h>
2016-08-15 14:05:37 +00:00
subhook::Hook foo_hook;
subhook::Hook foo_hook_tr;
2014-11-26 18:07:51 +00:00
typedef void (*foo_func)(int x);
2013-01-13 17:02:16 +00:00
2013-01-14 21:40:12 +00:00
void my_foo(int x) {
2016-08-15 14:05:37 +00:00
// ScopedHookRemove removes the specified hook and automatically re-installs
// it when the objectt goes out of scope (thanks to C++ destructors).
subhook::ScopedHookRemove remove(&foo_hook);
2013-01-13 17:02:16 +00:00
std::cout << "foo(" << x << ") called" << std::endl;
2014-11-26 18:07:51 +00:00
foo(x + 1);
2013-01-13 17:02:16 +00:00
}
2014-11-26 18:07:51 +00:00
void my_foo_tr(int x) {
std::cout << "foo(" << x << ") called" << std::endl;
2014-11-26 18:07:51 +00:00
// Call the original function via trampoline.
((foo_func)foo_hook_tr.GetTrampoline())(x + 1);
2013-01-13 17:02:16 +00:00
}
2014-11-26 18:07:51 +00:00
int main() {
foo_hook.Install((void *)foo, (void *)my_foo);
2015-01-16 13:08:54 +00:00
foo_hook_tr.Install((void *)foo, (void *)my_foo_tr);
2014-11-26 18:07:51 +00:00
}
2013-01-13 17:02:16 +00:00
```
2013-01-14 21:40:12 +00:00
2018-08-31 18:51:43 +00:00
Known issues
------------
2018-09-06 17:52:15 +00:00
* If a target function (the function you are hooking) is less than N bytes
in length, for example if it's a short 2-byte jump to a nearby location
2018-08-31 18:51:43 +00:00
(sometimes compilers generate code like this), then you will not be able
to hook it.
2018-09-06 17:52:15 +00:00
N is 5 by default (1-byte jmp opcode + 32-bit offset), but it you enable
the use of 64-bit offsets in 64-bit mode N becomes 14 (see the definition
2018-08-31 18:51:43 +00:00
of `subhook_jmp64`).
2018-09-06 17:52:15 +00:00
* Some systems protect executable code form being modified at runtime, which
will not allow you to install hooks, or don't allow to mark heap-allocated
2018-08-31 18:51:43 +00:00
memory as executable, which prevents the use of trampolines.
2018-09-06 17:52:15 +00:00
2018-08-31 18:51:43 +00:00
For example, on Fedora you can have such problems because of SELinux (though
you can disable it or exclude your files).
2015-03-22 10:49:31 +00:00
License
-------
Licensed under the 2-clause BSD license.
2015-01-16 13:23:52 +00:00
[build]: https://travis-ci.org/Zeex/subhook
[build_status]: https://travis-ci.org/Zeex/subhook.svg?branch=master
2015-02-16 16:04:57 +00:00
[build_win]: https://ci.appveyor.com/project/Zeex/subhook/branch/master
[build_status_win]: https://ci.appveyor.com/api/projects/status/q5sp0p8ahuqfh8e4/branch/master?svg=true