Implement chain hooking

Chain hooking is a means which detects whether a hook is already
present, and instead of overwriting it, attempts to call the existing
hook functions in a chain.

There's two primary ways a function can be hooked:

- forward chain (overwrite the first 5 bytes to an long jump), or
- reverse chain (uses microsoft's built-in safe reverse-chaining
  bytecode before the function to allow safer hooking)

It takes in to account both hook types when looking for chains.  If it's
unsafe to do either of those types of hooks, it will revert to the
standard unhook/rehook method.