Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

One hook for multiple targets - feature request #35

Open
marcin-szmagara opened this issue Sep 23, 2022 · 2 comments
Open

One hook for multiple targets - feature request #35

marcin-szmagara opened this issue Sep 23, 2022 · 2 comments

Comments

@marcin-szmagara
Copy link

Given a list of function addresses at runtime I need to log whenever any of them is called. I believe the best way to do this would be to hook the functions with a logger hook. After some discussion it looks like this ideally would be enabled by a hooking library.

However, with current API of this library, it is impossible to have one hook function for multiple targets, as the hook function does not have the information about the hooked function (in particular its address).

I would like to propose a feature, that would make it possible not only to write this:

void hook(int arg1, int arg2)
{
  ...
  original_function(arg1, arg2);
}

but also this:

void multihook(fun_ptr_t ptr, int arg1, int arg2)
{
  ...
  ptr(arg1, arg2)
}

The address of the original function could be passed in any other way, not necessarily as the first argument.

Could this be implemented as part of this library? If so, what would be the best way to approach it?

@kubo
Copy link
Owner

kubo commented Sep 24, 2022

Adding a new argument is impossible without knowledge about number of original function's arguments and their types (integer or floating point number). Instead of it, thread-local storage is available for that purpose.

Funchook hooks functions by replacing first few bytes at the beginning of the original functions. (See http://jbremer.org/x86-api-hooking-demystified/#ah-basic) On x86_64, the code size of jump instruction is 5 when the distance from source to destination is between 2 gigabytes. Otherwise it is 14 to jump to any address.

Funchook uses 5-byte code when the distance from the original function to the hook function is less than 2 gigabytes. Otherwise, it allocates memory near the original function and uses 5-byte code to jump from the original to the newly allocated memory and 14-byte code to jump from the memory to the hook function. The code in the memory is called as "transit" in funchook.

I think that the feature can be implemented.

  1. Use "transit" even when the distance is less than 2 gigabytes.
  2. Change "transit" as follows.
    1. Push registers (RDI, RSI, RDX, RCX, R8, R9, R10, AL on linux x86_64) on the stack.
    2. Call the following function with the address of funchook_entry_t, which is got by lea number(%rip), %rdi.
      // linux
      static pthread_key_t funchook_entry_tls_key; // This is initialized somewhere.
      void set_trampoline_function_address(void *addr) {
         pthread_setspecific(funchook_entry_tls_key, addr);
      }
    3. Pop registers from the stack.
    4. Jump to a hook function.
  3. Add the following function to get a trampoline function.
    void* funchook_get_trampoline() {
       funchook_entry_t *entry = (funchook_entry_t *)pthread_getspecific(funchook_entry_tls_key);
       return entry != NULL ? (void*)entry->trampoline ? NULL;
    }

@marcin-szmagara
Copy link
Author

Many thanks, works great for me. I think this can be closed with 2.0.0 release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants