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
------------
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
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
------------
* 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
(sometimes compilers generate code like this), then you will not be able
to hook it.
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
of `subhook_jmp64`).
* 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
memory as executable, which prevents the use of trampolines.
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