Get in losers we are hooking the procedural linkage tables
Projects I referenced while working on this. - [Plthook by Kubo] https://github.com/kubo/plthook - [Bhook by bytedance] https://github.com/bytedance/bhook
By crawling the dynamically loaded objects of an executable we can hook exported functions. Generally, PLT hooking is an ideal solution for hooking given you can guarantee a Unix Like environment. This library does not do any inline hooking, so there is no architecture (i686, arm, etc.) specific assembly magic going on, making cross compatibility very easy. There IS architecture specific constants, but its very minimal.
Ye this library supports two target operating systems: Linux and Android; So, android is unix like but has a separate linker implemention called Bionic. At the ground floor, both are still linking shared objects in elf format; but the library has to change how it crawls the dynamially loaded objects.
Video game modding, reverse engineering, etc - Can hook networking calls: recv / send - Rendering calls: eglSwapBuffers / video game overlays
Here we are hooking our own executables usages of libc puts
```rust
unsafe fn putshooked(input: *const libc::cchar) -> libc::cint { let cstr: &std::ffi::CStr = unsafe { std::ffi::CStr::fromptr(input) }; let strslice: &str = cstr.tostr().unwrap(); println!("Puts C was hooked. Intercepted: {:#?}", str_slice); 0 }
fn getmutmap<'a>() -> plt::MutableLinkMap<'a> { use plt::LinkMapBacked; let linkmap = plt::LinkMapView::fromaddress(main as *mut libc::cvoid as usize).expect("open link map"); plt::MutableLinkMap::fromview(link_map) }
fn main() -> Result<(), Box
Below you can see it works on both debug and release build.
shell
Finished dev [unoptimized + debuginfo] target(s) in 0.32s
Running `target/debug/examples/libc_puts`
Puts C was hooked. Intercepted: "Hello"
shell
Finished release [optimized] target(s) in 8.09s
Running `target/release/examples/libc_puts`
Puts C was hooked. Intercepted: "Hello"