L'objectif de cette bibliothèque est de rendre l'analyse statique et dynamique (débogage) plus difficile.
La bibliothèque cible les environnements Linux.
Il est actuellement basé sur l'astuce anti-analyse ptrace et fournit les principales caractéristiques suivantes:
Invocation directe du système sans s'appuyer sur LIBC (cela rend le mécanisme de contournement LD_PRELOAD INEFFICATIF);
L'obscurcissement des appels système qui rend plus difficile l'ingénierie inverse statique (cette fonctionnalité est actuellement prise en charge uniquement dans x86_64 );
Plusieurs invocations Syscall ptrace . Chaque appel à ptrace doit renvoyer la valeur attendue (c'est-à-dire 0 à la première invocation et -1 par la suite) et contribue au calcul d'une valeur " offset " qui, à la fin de la chaîne d'appel ptrace , doit correspondre à une valeur attendue (voir ici). Si PTRACE renvoie une valeur inattendue ou si la valeur " offset " ne correspond pas, le processus est terminé;
«Ptrace» est appelé en boucles imbriquées. Les boucles sont déroulées et le nombre d'itérations est randomisé à chaque compilation. De plus, la valeur " offset " est également radomisée à chaque itération;
Le code généré peut être obscurci encore plus en permettant la fonction obfuscate qui s'appuie sur Goldberg Crate;
Pour utiliser la caisse, ajoutez-le à vos dépendances:
[dependencies]
debugoff = { version = "0.2.1, features = ["obfuscate"] }
Pour activer également l'appel d'appel du système, utilisez la fonction syscallobf (il s'agit d'une fonctionnalité expérimentale et n'affectez que des binaires ciblant l'architecture x86_64 ):
[dependencies]
debugoff = { version = "0.2.1, features = ["obfuscate", "syscallobf"] }
Étant donné que la bibliothèque génère du code aléatoire à chaque compilation, assurez-vous de tout reconstruire à chaque fois. Quelque chose comme ça:
cargo clean
cargo build --release
Le décapage des symboles de la version de version est également une bonne idée:
[profile.release]
debug = false
strip = "symbols"
panic = "abort"
Dans l'exemple ci-dessous, debugoff n'est utilisé que lorsque le système d'exploitation cible est Linux et uniquement pour les versions de libération (de cette manière, lorsque le code est compilé en mode Debug, il peut être débogué sans avoir besoin de contourner 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!" ) ;
}Voir d'autres exemples dans le répertoire des exemples qui peuvent être construits avec:
cargo build --release --features obfuscate,syscallobf --examples Si nous construisons le code suivant (qui n'utilise pas DebugOff ) en mode de libération:
use std :: time :: SystemTime ;
fn main ( ) {
println ! (
"Time: {}" ,
SystemTime :: now ( )
. duration_since ( SystemTime :: UNIX_EPOCH )
. unwrap ( )
. as_millis ( )
) ;
println ! ( "Example complete!" ) ;
} Il s'agit du graphique de fonction correspondant de la fonction main :
.
Si nous construisons le même code à l'aide DebugOff avec la fonctionnalité 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!" ) ;
} Il s'agit du graphique de fonction obscurci de la fonction main :
.
Dans cet exemple particulier, tout le code généré par DebugOff a été incliné dans la fonction main . Cela n'est pas garanti d'être toujours le cas car les fonctions en instruction peuvent être influencées par de nombreux facteurs comme les emplacements où DebugOff est appelé et la version de la chaîne d'outils utilisé pour construire le projet. Dans d'autres cas, le graphique de fonction résultant pourrait être plus simple que celui rapporté dans l'exemple mais, en tout cas, plus complexe que celui généré lorsque DebugOff n'est pas utilisé.
Licencié sous:
obfuscate est activée;obfuscate n'est pas activée; x86_64 );