2023-05-23 17:21:14 +03:00
pub mod injector ;
2023-06-03 01:52:10 +03:00
#[ cfg(feature = " frida " ) ]
pub mod frida_handler ;
2024-02-27 03:01:29 +02:00
// #[cfg(feature = "dotnet")]
// pub mod cs;
2024-04-13 03:24:16 +03:00
#[ cfg(not(windows)) ]
pub mod symbols ;
2023-05-23 17:21:14 +03:00
2024-02-27 03:01:29 +02:00
pub use injector ::attach_self ;
2023-05-23 17:21:14 +03:00
2024-02-27 03:01:29 +02:00
#[ cfg(all(unix, not(test), not(feature = " dotnet " ))) ]
2023-05-23 17:21:14 +03:00
use ctor ::ctor ;
2024-02-27 03:01:29 +02:00
#[ cfg(all(unix, not(test), not(feature = " dotnet " ))) ]
2023-05-23 17:21:14 +03:00
#[ ctor ]
fn _start ( ) {
2023-05-27 16:38:27 +03:00
println! ( " [+] frida-deepfreeze-rs library injected " ) ;
attach_self ( ) ;
}
// For some reason ctor doesn't work on Windows - it hangs the process
// during DeviceManager::obtain. DllMain works fine though.
2024-02-27 03:01:29 +02:00
#[ cfg(all(any(windows, feature = " dotenv " ), not(test))) ]
2023-05-27 16:38:27 +03:00
use std ::ffi ::c_void ;
2024-02-27 03:01:29 +02:00
#[ cfg(all(any(windows, feature = " dotenv " ), not(test))) ]
2023-05-27 16:38:27 +03:00
use winapi ::um ::winnt ::DLL_PROCESS_ATTACH ;
2023-06-03 01:52:10 +03:00
2024-02-27 03:01:29 +02:00
#[ cfg(all(any(windows, feature = " dotenv " ), not(test))) ]
2023-05-27 21:45:02 +03:00
use winapi ::um ::libloaderapi ::LoadLibraryA ;
2023-05-27 16:38:27 +03:00
2024-02-27 03:01:29 +02:00
#[ cfg(all(any(windows, feature = " dotenv " ), not(test))) ]
2023-05-27 16:38:27 +03:00
#[ no_mangle ]
#[ allow(non_snake_case, unused_variables) ]
2024-02-27 03:01:29 +02:00
pub extern " system " fn DllMain ( dll_module : * mut c_void , call_reason : u32 , _ : * mut ( ) ) -> bool {
2023-05-27 16:38:27 +03:00
match call_reason {
DLL_PROCESS_ATTACH = > {
println! ( " [+] frida-deepfreeze-rs DLL injected " ) ;
2023-06-03 01:52:10 +03:00
2024-02-27 03:01:29 +02:00
unsafe { LoadLibraryA ( env! ( " LIB_NAME " ) . as_ptr ( ) as * const i8 ) ; }
println! ( " [+] Original DLL {} loaded " , env! ( " LIB_NAME " ) ) ;
2023-06-03 01:52:10 +03:00
2023-05-27 16:38:27 +03:00
attach_self ( ) ;
}
// Maybe we should detach? Is it useful?
_ = > ( )
}
true
2023-05-23 17:21:14 +03:00
}
2023-06-03 18:02:46 +03:00
#[ cfg(test) ]
mod tests {
use pretty_assertions ::assert_eq ;
use std ::process ::Command ;
2023-06-05 15:17:52 +03:00
#[ cfg(all(windows, feature = " frida " )) ]
2023-06-03 18:02:46 +03:00
use std ::fs ;
#[ test ]
#[ cfg(feature = " frida " ) ]
fn test_frida_on_load ( ) {
let lib_status = Command ::new ( " cargo " )
. arg ( " build " )
. arg ( " --lib " )
. 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 " , [ ] ) ) ;
" #)
. status ( )
. expect ( " Failed to build dynamic library " ) ;
assert! ( lib_status . success ( ) , " Failed to build dynamic library " ) ;
let bin_status = Command ::new ( " cargo " )
. arg ( " run " )
. arg ( " --manifest-path " )
. arg ( " tests/mybin/Cargo.toml " )
. arg ( " --target-dir " )
. arg ( " target/test_frida_on_load " )
. env ( " RUSTFLAGS " , " -C link-arg=-Wl,--no-as-needed -C link-arg=-lfrida_deepfreeze_rs " )
. status ( )
. expect ( " Failed to build mybin " ) ;
assert_eq! ( bin_status . code ( ) . unwrap ( ) , 40 , " Failed to replace foo() " ) ;
2023-06-03 18:13:37 +03:00
}
#[ test ]
#[ cfg(all(windows, feature = " frida " )) ]
fn test_frida_on_load ( ) {
let bin_exec = Command ::new ( " cargo " )
. arg ( " build " )
. arg ( " --manifest-path " )
. arg ( " tests/mybin/Cargo.toml " )
. arg ( " --target-dir " )
. arg ( " target/test_frida_on_load " ) ;
let lib_status = Command ::new ( " cargo " )
. arg ( " build " )
. arg ( " --lib " )
. arg ( " --target-dir " )
. arg ( " target/test_frida_on_load " )
. env ( " DLL_PROXY " , " target/test_frida_on_load/debug/deps/mylib.dll " )
. 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 " , [ ] ) ) ;
" #)
. status ( )
. expect ( " Failed to build dynamic library " ) ;
assert! ( lib_status . success ( ) , " Failed to build dynamic library " ) ;
fs ::rename ( " target/test_frida_on_load/debug/deps/mylib.dll " , " target/test_frida_on_load/debug/mylib-orig.dll " ) . expect ( " Failed to rename original DLL " ) ;
fs ::rename ( " target/test_frida_on_load/debug/frida_deepfreeze_rs.dll " , " target/test_frida_on_load/debug/mylib.dll " ) . expect ( " Failed to rename deepfreeze DLL " ) ;
let bin_status = bin_exec . status ( ) . expect ( " Failed to build mybin " ) ;
assert_eq! ( bin_status . code ( ) . unwrap ( ) , 40 , " Failed to replace foo() " ) ;
2023-06-03 18:02:46 +03:00
}
}