Skip to content

Instantly share code, notes, and snippets.

@ryankurte
Created January 17, 2019 02:03
Show Gist options
  • Save ryankurte/02a82cd8c741f5a63296f28a80b9605a to your computer and use it in GitHub Desktop.
Save ryankurte/02a82cd8c741f5a63296f28a80b9605a to your computer and use it in GitHub Desktop.
Dynamic library hooking experiments in rust
#![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