Created
January 17, 2019 02:03
-
-
Save ryankurte/02a82cd8c741f5a63296f28a80b9605a to your computer and use it in GitHub Desktop.
Dynamic library hooking experiments in rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(never_type)] | |
use std::ffi::{CString, CStr, OsStr}; | |
use std::ptr; | |
extern crate libc; | |
use libc::{c_void, c_char, c_int,}; | |
#[repr(C)] pub struct Handle { _private: () } | |
#[link(name = "dl")] | |
extern "C" { | |
fn dlopen(filename: *const c_char, flag: c_int) -> *mut c_void; | |
fn dlerror() -> *const c_char; | |
fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void; | |
fn dlclose(handle: *mut c_void) -> c_int; | |
} | |
const RTLD_NOW: c_int = 2; | |
pub struct DynLib { | |
handle: *mut c_void, | |
} | |
pub type Error = String; | |
impl DynLib { | |
pub fn open<N: Into<String>>(name: N) -> Result<DynLib, Error> { | |
let name = CString::new(name.into()).unwrap(); | |
let handle = unsafe { | |
dlopen(name.as_ptr(), RTLD_NOW) | |
}; | |
if handle == 0 as *mut c_void { | |
DynLib::error("Error opening dynamic library")?; | |
} | |
Ok(DynLib{handle}) | |
} | |
fn error(msg: &str) -> Result<!, Error> { | |
let why = unsafe { | |
let s = dlerror(); | |
CStr::from_ptr(s).to_string_lossy().into_owned() | |
}; | |
Err(format!("{}: {}", msg, why)) | |
} | |
pub fn sym<N: Into<String>>(&mut self, name: N) -> Result<*mut c_void, Error> { | |
let name = CString::new(name.into()).unwrap(); | |
let handle = unsafe { | |
dlsym(self.handle, name.as_ptr()) | |
}; | |
if handle == 0 as *mut c_void { | |
DynLib::error("Error locating symbol")?; | |
} | |
Ok(handle) | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use super::*; | |
extern "C" fn new_open(path: *const c_char, flags: c_int) { | |
println!("Open!"); | |
} | |
#[test] | |
fn test_bindings() { | |
let mut dl = DynLib::open("/usr/lib/libc.dylib").expect("Error opening libc"); | |
let mut sym = dl.sym("open").expect("Error locating open()"); | |
unsafe { | |
sym = new_open as *mut c_void; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment