"ptrace()" was casually mentioned by Giles.   But I think it deserved a whole section by itself.   "ptrace()" is a system call API provided by OS (Linux and all UNIX have it, and so do Windows) to exert debug control over another process.   When you used PTRACE_ATTACH (as part of ptrace()) to attach to another process, the kernel will pause the CPU running that process completely, allowing you to make changes to ANY part of the process: CPU, any registers, any part of that process memory etc.   That is how dynamic inline hooking work.    (ptrace() attach, modify binary in-memory, and then ptrace() unattached).   As far as I know, all dynamic modification of another process has to use ptrace() - as that is the only mechanism provided by kernel to guarantee integrity via system call at this point.

But recently similar API like utrace() is popping up, and so 
inline hooking is also theoretically possible:

http://landley.net/kdocs/ols/2007/ols2007v1-pages-215-224.pdf

For kernel hooking, there are many methods:   syscall, interrupt, and inline hooking.   This is for interrupt hooking:

http://mammon.github.io/Text/linux_hooker.txt