diff --git a/README.md b/README.md index 4aff241..faa82f4 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,9 @@ variable or as a file using the `FRIDA_CODE_FILE` environment variable. ### Standalone executable +The standalone executable is the easiest to use. You just run it with a PID and +it will inject itself and run the frida script. + ```bash git clone https://github.com/dzervas/frida-deepfreeze-rs FRIDA_CODE='console.log("Hello world from frida-deepfreeze-rs!")' cargo run --bin standalone -- 1234 @@ -36,6 +39,9 @@ The binary is located at `target/debug/standalone` (`.exe` for windows). ### Shared library +The shared library is a bit more complicated to use. You have to inject it to +a process using a tool like `LD_PRELOAD` (linux) or `rundll32.exe` (windows). + ```bash git clone https://github.com/dzervas/frida-deepfreeze-rs FRIDA_CODE='console.log("Hello world from frida-deepfreeze-rs!")' cargo build --lib @@ -46,14 +52,15 @@ LD_PRELOAD=target/debug/libfrida_deepfreeze_rs.so cat The resulting library is located at `target/debug/libfrida_deepfreeze_rs.so` (`.dll` for windows). You can inject it using your favorite injector. -There are two exported functions: +There are two exported functions that you can call from the library to inject: ```c void inject(uint32_t pid); // Run the frida script in the process with the given pid void inject_self(); // Run the frida script in the process that called the function ``` -By default, on load the library will call `inject_self()`. +By default (so `DllMain` in windows and `.ctor` on unix), on load the library +will call `inject_self()` so you can just inject it and it will run the script. ### DLL Proxying diff --git a/build.rs b/build.rs index 5552fa2..26e011b 100644 --- a/build.rs +++ b/build.rs @@ -8,7 +8,7 @@ fn main() { if let Ok(lib_path) = env::var("DLL_PROXY") { println!("cargo:rerun-if-changed={}", &lib_path); - use goblin::Object::{self, PE}; + use goblin::Object; let path = std::path::Path::new(&lib_path); let lib_filename = path.file_name().unwrap().to_str().unwrap(); @@ -17,22 +17,49 @@ fn main() { let object = Object::parse(&lib_bytes).expect(format!("Failed to parse given libary file {}", &lib_filename).as_str()); let (exports, lib_name): (Vec<&str>, String) = match object { - PE(o) => + #[cfg(target_os = "windows")] + Object::PE(o) => { (o.exports .iter() .map(|e| e.name.unwrap()) .collect(), - o.name.unwrap().replace(".dll", "")), + o.name.expect("Couldn't read the name of the DLL. Is it a .NET DLL? It's not supported").replace(".dll", "")) + } + #[cfg(target_os = "linux")] + Object::Elf(o) => { + (o.dynsyms + .iter() + .filter(|e| e.is_function() && !e.is_import()) + .map(|e| o.dynstrtab.get_at(e.st_name).unwrap()) + .collect(), + o.soname.expect("Couldn't read the name of the SO.").replace(".so", "")) + }, + // #[cfg(target_os = "darwin")] + // Object::Mach(goblin::mach::Mach::Binary(o)) => { + // (o.dynsyms + // .iter() + // .filter(|e| e.is_function() && !e.is_import()) + // .map(|e| o.dynstrtab.get_at(e.st_name).unwrap()) + // .collect(), + // o.name.expect("Couldn't read the name of the DLL. Is it a .NET DLL? It's not supported").replace(".dll", "")) + // }, _ => { - println!("Only DLL files are supported"); + println!("Only PE (.dll) and ELF (.so) files are supported in their respective target platforms."); std::process::exit(1); }, }; + #[cfg(target_os = "windows")] for e in exports.iter() { println!("cargo:warning=Exported function: {} => {}-orig.{}", e, lib_name, e); println!("cargo:rustc-link-arg=/export:{}={}-orig.{}", e, lib_name, e); } + + #[cfg(not(target_os = "windows"))] + for e in exports.iter() { + println!("cargo:warning=Exported function: {}", e); + } + println!("cargo:warning=Expected library name: {}-orig.dll", lib_name); println!("cargo:rustc-env=LIB_NAME={}-orig.dll", lib_name); }