From b6a48d51554be683c6ec2732cd4be784fee90cef Mon Sep 17 00:00:00 2001 From: Dimitris Zervas Date: Sun, 14 Apr 2024 15:16:40 +0300 Subject: [PATCH] Fix frida_code_file, initial config support Signed-off-by: Dimitris Zervas --- Cargo.lock | 75 ++++++++++++++++++++ Cargo.toml | 2 + build.rs | 104 ++++++++++++++++++++++------ examples/cs/Example.sln | 48 ------------- examples/cs/My/MyClass.cs | 19 ----- examples/cs/My/MyClass.csproj | 10 --- examples/cs/Other/OtherClass.cs | 11 --- examples/cs/Other/OtherClass.csproj | 7 -- examples/cs/README.md | 17 ----- src/injector.rs | 6 +- src/lib.rs | 10 +-- 11 files changed, 166 insertions(+), 143 deletions(-) delete mode 100644 examples/cs/Example.sln delete mode 100644 examples/cs/My/MyClass.cs delete mode 100644 examples/cs/My/MyClass.csproj delete mode 100644 examples/cs/Other/OtherClass.cs delete mode 100644 examples/cs/Other/OtherClass.csproj delete mode 100644 examples/cs/README.md diff --git a/Cargo.lock b/Cargo.lock index bc713a5..f6e792e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,6 +160,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.8" @@ -231,6 +237,7 @@ dependencies = [ "pretty_assertions", "serde", "serde_json", + "toml", "winapi", "windows-sys 0.52.0", ] @@ -329,6 +336,12 @@ dependencies = [ "scroll", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "hermit-abi" version = "0.3.8" @@ -450,6 +463,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -913,6 +936,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1058,6 +1090,40 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tower" version = "0.4.13" @@ -1416,6 +1482,15 @@ version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" +[[package]] +name = "winnow" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/Cargo.toml b/Cargo.toml index 7c670e6..838f38f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,8 @@ ctor = "0.2.7" [build-dependencies] goblin = "0.8.0" build-target = "0.4" +serde = { version = "1.0", features = ["derive"] } +toml = "0.8.12" [dev-dependencies] pretty_assertions = "1.4.0" diff --git a/build.rs b/build.rs index 2ebb264..de4e839 100644 --- a/build.rs +++ b/build.rs @@ -1,26 +1,79 @@ +use serde::Deserialize; + use std::env; use std::path::Path; +#[derive(Debug, Deserialize)] +pub struct Hook { + pub name: String, + pub args: Vec, + pub ret: String, + pub code: String, +} + +#[derive(Debug, Deserialize)] +pub struct Config { + pub dll_proxy: Option, + pub frida_code: Option, + pub frida_code_file: Option, + pub target_exec: Option, + pub target_process: Option, + + pub hooks: Vec, +} + +impl Default for Config { + fn default() -> Self { + println!("cargo:rerun-if-env-changed=FRIDA_CODE"); + println!("cargo:rerun-if-env-changed=FRIDA_CODE_FILE"); + println!("cargo:rerun-if-env-changed=DLL_PROXY"); + println!("cargo:rerun-if-env-changed=TARGET_PROCESS"); + println!("cargo:rerun-if-env-changed=TARGET_SPAWN"); + + Self { + dll_proxy : env::var("DLL_PROXY").ok(), + frida_code : env::var("FRIDA_CODE").ok(), + frida_code_file: env::var("FRIDA_CODE_FILE").ok(), + target_exec : env::var("TARGET_SPAWN").ok(), + target_process : env::var("TARGET_PROCESS").ok(), + + hooks: Vec::new(), + } + } +} + +impl Config { + pub fn get_frida_code(&self) -> String { + if self.frida_code.is_some() && self.frida_code_file.is_some() { + panic!("Both frida_code and frida_code_file set. Please set one of them."); + } + + let code = if let Some(frida_code) = &self.frida_code { + frida_code.clone() + } else if let Some(frida_code_file) = &self.frida_code_file { + std::fs::read_to_string(frida_code_file).expect("Failed to read frida_code_file") + } else { + panic!("No frida_code or frida_code_file set. Please set one of them."); + }; + + code.replace("\n", "\\n") + } +} + fn main() { - println!("cargo:rerun-if-env-changed=FRIDA_CODE"); - println!("cargo:rerun-if-env-changed=FRIDA_CODE_FILE"); - println!("cargo:rerun-if-env-changed=DLL_PROXY"); + println!("cargo:rerun-if-env-changed=CONFIG_FILE"); - if env::var("FRIDA_CODE").is_err() && env::var("FRIDA_CODE_FILE").is_err() { - panic!("No FRIDA_CODE or FRIDA_CODE_FILE set. Please set one of them."); - } + let config = if let Ok(config_file) = env::var("CONFIG_FILE") { + let config_file = std::fs::read_to_string(config_file).expect("Failed to read CONFIG_FILE"); + toml::from_str::(&config_file).expect("Failed to parse CONFIG_FILE") + } else { + Config::default() + }; - if env::var("FRIDA_CODE").is_ok() && env::var("FRIDA_CODE_FILE").is_ok() { - panic!("Both FRIDA_CODE and FRIDA_CODE_FILE set. Please set one of them."); - } + println!(r#"cargo:rustc-env=FRIDA_CODE={}"#, config.get_frida_code()); - if let Ok(frida_code_file) = env::var("FRIDA_CODE_FILE") { - let frida_code = std::fs::read_to_string(frida_code_file).expect("Failed to read FRIDA_CODE_FILE"); - println!("cargo:rustc-env=FRIDA_CODE={}", frida_code); - } - - let Ok(lib_path) = env::var("DLL_PROXY") else { - println!("cargo:warning=No DLL_PROXY set, the resulting library has to be manually injected or compiled into the target binary/process"); + let Some(lib_path) = config.dll_proxy else { + println!("cargo:warning=No dll_proxy set, the resulting library has to be manually injected or compiled into the target binary/process"); return; }; @@ -28,14 +81,19 @@ fn main() { panic!("Dll proxying mode is only supported on Windows."); } + dll_proxy_linker_flags(&lib_path, config.hooks); +} + +fn dll_proxy_linker_flags(lib_path: &str, _hooks: Vec) { use goblin::Object; - println!("cargo:rerun-if-changed={}", &lib_path); + + println!("cargo:rerun-if-changed={lib_path}"); let path = Path::new(&lib_path); let lib_filename = path.file_name().unwrap().to_str().unwrap(); - let lib_bytes = std::fs::read(path).expect(format!("Failed to open given library file {}", &lib_filename).as_str()); - let object = Object::parse(&lib_bytes).expect(format!("Failed to parse given libary file {}", &lib_filename).as_str()); + let lib_bytes = std::fs::read(path).expect(format!("Failed to open given library file {lib_filename}").as_str()); + let object = Object::parse(&lib_bytes).expect(format!("Failed to parse given libary file {lib_filename}").as_str()); let Object::PE(pe) = object else { panic!("Only PE (.dll) files are supported in this mode."); @@ -45,10 +103,10 @@ fn main() { let lib_name = pe.name.expect("Couldn't read the name of the DLL. Is it a .NET DLL? It's not supported").replace(".dll", ""); 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); + println!("cargo:warning=Exported function: {e} => {lib_name}-orig.{e}"); + println!("cargo:rustc-link-arg=/export:{e}={lib_name}-orig.{e}"); } - println!("cargo:warning=Expected library name: {}-orig.dll", lib_name); - println!("cargo:rustc-env=LIB_NAME={}-orig.dll", lib_name); + println!("cargo:warning=Expected library name: {lib_name}-orig.dll"); + println!("cargo:rustc-env=LIB_NAME={lib_name}-orig.dll"); } diff --git a/examples/cs/Example.sln b/examples/cs/Example.sln deleted file mode 100644 index daaae02..0000000 --- a/examples/cs/Example.sln +++ /dev/null @@ -1,48 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MyClass", "My\MyClass.csproj", "{F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OtherClass", "Other\OtherClass.csproj", "{EAA4714F-3F2E-4801-81B7-9BC502347B53}" -EndProject -Global - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Debug|x64.ActiveCfg = Debug|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Debug|x64.Build.0 = Debug|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Debug|x86.ActiveCfg = Debug|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Debug|x86.Build.0 = Debug|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Release|Any CPU.Build.0 = Release|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Release|x64.ActiveCfg = Release|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Release|x64.Build.0 = Release|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Release|x86.ActiveCfg = Release|Any CPU - {F480EEA9-B211-4BDF-A364-8B8D1B6F4FCE}.Release|x86.Build.0 = Release|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Debug|x64.ActiveCfg = Debug|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Debug|x64.Build.0 = Debug|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Debug|x86.ActiveCfg = Debug|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Debug|x86.Build.0 = Debug|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Release|Any CPU.Build.0 = Release|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Release|x64.ActiveCfg = Release|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Release|x64.Build.0 = Release|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Release|x86.ActiveCfg = Release|Any CPU - {EAA4714F-3F2E-4801-81B7-9BC502347B53}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/examples/cs/My/MyClass.cs b/examples/cs/My/MyClass.cs deleted file mode 100644 index 0ba4934..0000000 --- a/examples/cs/My/MyClass.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using OtherNamespace; - -namespace MyNamespace { - public class MyClass { - // This method will be called by native code inside the target process… - public static int MyMethod(String pwzArgument) { - System.Console.WriteLine("Hello World from C# {0}", pwzArgument); - return 0; - } - - public static void Main() { - int my = MyMethod("from Main()"); - System.Console.WriteLine("MyMethod returned {0}", my); - int other = OtherNamespace.OtherClass.OtherMethod(); - System.Console.WriteLine("OtherMethod returned {0}", other); - } - } -} diff --git a/examples/cs/My/MyClass.csproj b/examples/cs/My/MyClass.csproj deleted file mode 100644 index 587dbaf..0000000 --- a/examples/cs/My/MyClass.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - net8.0 - Exe - - - - - - diff --git a/examples/cs/Other/OtherClass.cs b/examples/cs/Other/OtherClass.cs deleted file mode 100644 index 2ccd8a6..0000000 --- a/examples/cs/Other/OtherClass.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace OtherNamespace { - public class OtherClass { - // This method will be called by native code inside the target process… - public static int OtherMethod() { - System.Console.WriteLine("Goodbye World from C#"); - return 1; - } - } -} diff --git a/examples/cs/Other/OtherClass.csproj b/examples/cs/Other/OtherClass.csproj deleted file mode 100644 index 4893ead..0000000 --- a/examples/cs/Other/OtherClass.csproj +++ /dev/null @@ -1,7 +0,0 @@ - - - net8.0 - Library - OtherNamespace - - diff --git a/examples/cs/README.md b/examples/cs/README.md deleted file mode 100644 index 329bddf..0000000 --- a/examples/cs/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# C# Example - -To compile: - -```sh -sudo pacman -S dotnet-host dotnet-runtime dotnet-sdk -dotnet build -``` - -To run: - -```sh -./My/bin/Debug/net8.0/MyClass -# or -sudo pacman -S mono -mono My/bin/Debug/net8.0/MyClass.dll -``` diff --git a/src/injector.rs b/src/injector.rs index d9d8435..2bccc6a 100644 --- a/src/injector.rs +++ b/src/injector.rs @@ -9,11 +9,11 @@ use crate::frida_handler::attach_pid as frida_attach_pid; pub extern "C" fn attach(pid: u32) { #[cfg(feature = "frida")] { - let frida_code = env!("FRIDA_CODE"); + let frida_code = env!("FRIDA_CODE").replace("\\n", "\n"); #[cfg(windows)] - std::thread::spawn(move || frida_attach_pid(frida_code, pid)); + std::thread::spawn(move || frida_attach_pid(&frida_code, pid)); #[cfg(not(windows))] - frida_attach_pid(frida_code, pid); + frida_attach_pid(&frida_code, pid); } } diff --git a/src/lib.rs b/src/lib.rs index fd3e0d6..43a1473 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,11 +39,11 @@ mod tests { .arg("--target-dir") .arg("target/test_frida_on_load") .env("FRIDA_CODE", r#" - const foo = Module.getExportByName(null, "mylib_foo"); - Interceptor.replace(foo, new NativeCallback(function () { - console.log("replaced foo() called"); - return 40; - }, "uint8", [])); +const foo = Module.getExportByName(null, "mylib_foo"); +Interceptor.replace(foo, new NativeCallback(function () { + console.log("replaced foo() called"); + return 40; +}, "uint8", [])); "#) .status() .unwrap();