El objetivo de esta biblioteca es dificultar el análisis estático y dinámico (depuración).
La biblioteca se dirige a los entornos de Linux.
Actualmente se basa en el truco anti-análisis ptrace y proporciona las siguientes características principales:
Invocación directa de syscall sin confiar en libc (esto hace que el mecanismo de derivación LD_PReload sea ineficaz);
La ofuscación de llamadas del sistema que dificulta la ingeniería inversa estática (esta característica actualmente es compatible solo en x86_64 );
Múltiples invocaciones de syscall ptrace . Cada llamada a ptrace debe devolver el valor esperado (es decir, 0 en la primera invocación y -1 a partir de entonces) y contribuye al cálculo de un valor de " offset " que, al final de la cadena de llamadas ptrace , debe coincidir con un valor esperado (ver aquí). Si Ptrace devuelve un valor no expetido o el valor de " offset " no coincide, el proceso se finaliza;
'Ptrace' se llama en bucles anidados. Los bucles se desactivan y el número de iteraciones se aleatoriza en cada compilación. Además, también el valor de " offset " se radomiza en cada iteración;
El código generado se puede ofuscar aún más al permitir la característica obfuscate que se basa en Goldberg Crate;
Para usar la caja, agrégalo a sus dependencias:
[dependencies]
debugoff = { version = "0.2.1, features = ["obfuscate"] }
Para habilitar también la ofuscación de llamadas del sistema, use la función syscallobf (esta es una característica experimental y afecta solo binarios dirigidos a la arquitectura x86_64 ):
[dependencies]
debugoff = { version = "0.2.1, features = ["obfuscate", "syscallobf"] }
Dado que la biblioteca genera código aleatorio en cada compilación, asegúrese de reconstruir todo cada vez. Algo como esto:
cargo clean
cargo build --release
Desmirar los símbolos de la construcción de lanzamiento también es una buena idea:
[profile.release]
debug = false
strip = "symbols"
panic = "abort"
En el ejemplo a continuación, debugoff se usa solo cuando el sistema operativo de destino es Linux y solo para compilaciones de lanzamiento (de esta manera, cuando el código se compila en el modo de depuración, se puede depurar sin la necesidad de omitir debugoff ).
// Include only for Linux and when building in release mode
# [ cfg ( target_os = "linux" ) ]
# [ cfg ( not ( debug_assertions ) ) ]
use debugoff ;
use std :: time :: SystemTime ;
fn main ( ) {
// Call only for Linux and when building in release mode
# [ cfg ( target_os = "linux" ) ]
# [ cfg ( not ( debug_assertions ) ) ]
debugoff :: multi_ptraceme_or_die ( ) ;
println ! (
"Time: {}" ,
SystemTime :: now ( )
. duration_since ( SystemTime :: UNIX_EPOCH )
. unwrap ( )
. as_millis ( )
) ;
// Call only for Linux and when building in release mode
# [ cfg ( target_os = "linux" ) ]
# [ cfg ( not ( debug_assertions ) ) ]
debugoff :: multi_ptraceme_or_die ( ) ;
println ! ( "Example complete!" ) ;
}Vea otros ejemplos en el directorio de ejemplos que se puede construir con:
cargo build --release --features obfuscate,syscallobf --examples Si construimos el siguiente código (que no usa DebugOff ) en modo de lanzamiento:
use std :: time :: SystemTime ;
fn main ( ) {
println ! (
"Time: {}" ,
SystemTime :: now ( )
. duration_since ( SystemTime :: UNIX_EPOCH )
. unwrap ( )
. as_millis ( )
) ;
println ! ( "Example complete!" ) ;
} Este es el gráfico de la función correspondiente de la función main :
.
Si construimos el mismo código utilizando la función DebugOff con obfuscate :
# [ cfg ( target_os = "linux" ) ]
# [ cfg ( not ( debug_assertions ) ) ]
use debugoff ;
use std :: time :: SystemTime ;
fn main ( ) {
# [ cfg ( target_os = "linux" ) ]
# [ cfg ( not ( debug_assertions ) ) ]
debugoff :: multi_ptraceme_or_die ( ) ;
println ! (
"Time: {}" ,
SystemTime :: now ( )
. duration_since ( SystemTime :: UNIX_EPOCH )
. unwrap ( )
. as_millis ( )
) ;
# [ cfg ( target_os = "linux" ) ]
# [ cfg ( not ( debug_assertions ) ) ]
debugoff :: multi_ptraceme_or_die ( ) ;
println ! ( "Example complete!" ) ;
} Este es el gráfico de la función ofuscada de la función main :
.
En este ejemplo particular, todo el código generado por DebugOff se ingresó en la función main . No se garantiza que este sea siempre el caso porque las funciones que se encuentran en línea pueden estar influenciadas por muchos factores como los lugares donde se llama a DebugOff y la versión de cadena de herramientas utilizada para construir el proyecto. En otros casos, el gráfico de la función resultante podría ser más simple que el informado en el ejemplo, pero, en cualquier caso, más complejo que el generado cuando no se usa DebugOff .
Licenciado bajo:
obfuscate está habilitada;obfuscate no está habilitada; x86_64 );