このライブラリの目標は、静的および動的(デバッグ)分析の両方をより困難にすることです。
ライブラリはLinux環境をターゲットにしています。
現在、 ptrace抗分析トリックに基づいており、次の主な機能を提供します。
LIBCに依存せずに直接Syscallの呼び出し(これにより、LD_PRELOADバイパスメカニズムが効果的ではありません);
静的リバースエンジニアリングをより困難にするシステムコール難読化(この機能は現在、 x86_64でのみサポートされています)。
複数のptrace syscallの呼び出し。 ptraceへの各呼び出しは、期待値(すなわち、最初の呼び出しで0、その後-1)を返す必要があり、 ptraceコールチェーンの最後に期待値と一致する必要がある「 offset 」値の計算に貢献する必要があります(こちらを参照)。 ptraceが未知の値を返すか、「 offset 」値が一致しない場合、プロセスは終了します。
「Ptrace」はネストされたループで呼ばれます。ループは展開され、反復数は各コンピレーションでランダム化されます。さらに、「 offset 」値も各反復でラドミングされます。
生成されたコードは、Goldberg Crateに依存するobfuscate機能を有効にすることで、さらに難読化できます。
クレートを使用するには、依存関係に追加します。
[dependencies]
debugoff = { version = "0.2.1, features = ["obfuscate"] }
また、システムコールの難読化を有効にするには、 syscallobf機能を使用します(これは実験機能であり、 x86_64アーキテクチャをターゲットとするバイナリのみに影響します):
[dependencies]
debugoff = { version = "0.2.1, features = ["obfuscate", "syscallobf"] }
ライブラリが各コンピレーションでランダムコードを生成することを考えると、毎回すべてを再構築してください。このようなもの:
cargo clean
cargo build --release
リリースビルドからシンボルをストリッピングすることも良い考えです:
[profile.release]
debug = false
strip = "symbols"
panic = "abort"
以下の例では、ターゲットOSがLinuxであり、リリースビルドのみの場合にのみdebugoffが使用されます(この方法では、コードがデバッグモードでコンパイルされたときに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!" ) ;
}Examplesディレクトリの他の例を参照してください。
cargo build --release --features obfuscate,syscallobf --examplesリリースモードで次のコード( DebugOff使用しない)を構築する場合:
use std :: time :: SystemTime ;
fn main ( ) {
println ! (
"Time: {}" ,
SystemTime :: now ( )
. duration_since ( SystemTime :: UNIX_EPOCH )
. unwrap ( )
. as_millis ( )
) ;
println ! ( "Example complete!" ) ;
}これは、 main関数の対応する関数グラフです。
。
DebugOffを使用して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!" ) ;
}これは、 main関数の難読化された関数グラフです。
。
この特定の例では、 DebugOffによって生成されたすべてのコードがmain関数にインラリングされていました。関数のインラインは、 DebugOffが呼び出される場所やプロジェクトの構築に使用されるツールチェーンバージョンのような多くの要因に影響を与える可能性があるため、これは常にそうであることが保証されていません。他のケースでは、結果の関数グラフは、例で報告されているものよりも単純になる可能性がありますが、いずれにしても、 DebugOff使用されないときに生成されたものよりも複雑です。
ライセンス:
obfuscate機能が有効になっている場合。obfuscate機能が有効になっていない場合。 x86_64に対してのみサポートされています)。