5 个版本
0.2.2 | 2022年12月26日 |
---|---|
0.2.1 | 2022年7月13日 |
0.2.0 | 2022年7月11日 |
0.1.1 | 2022年7月4日 |
0.1.0 | 2022年6月28日 |
#401 在 开发工具
83 每月下载量
用于 4 crates
1MB
1K SLoC
DebugOff 库
Linux 防分析 Rust 库
该库的目的是使静态和动态(调试)分析更加困难。
该库针对 Linux 环境。
它目前基于 ptrace
防分析技巧,并提供以下主要功能
-
直接调用系统调用而不依赖于 libc(这使得 LD_PRELOAD 绕过机制无效);
-
系统调用混淆,使静态逆向工程更加困难(此功能目前仅在
x86_64
上支持); -
多次
ptrace
系统调用。每次对ptrace
的调用都必须返回预期的值(即,第一次调用返回 0,之后返回 -1),并有助于计算一个 "offset
" 值,在ptrace
调用链结束时必须匹配预期的值(请参阅这里)。如果 ptrace 返回意外的值或 "offset
" 值不匹配,则终止进程; -
'ptrace' 在嵌套循环中被调用。循环被展开,每次编译时迭代次数随机化。此外,在每次迭代中也随机化 "
offset
" 值; -
通过启用
obfuscate
功能(该功能依赖于goldberg crate),可以进一步混淆生成的代码;
要使用该包,将其添加到依赖项中
[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"
使用示例
在下面的示例中,仅在目标操作系统为 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!");
}
请参阅示例目录中的其他示例,这些示例可以使用
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
功能时,GPL-3.0; - 当
obfuscate
功能未启用时,MIT;
待办事项
- 为其他架构实现系统调用混淆(因为目前只有
x86_64
支持系统调用混淆); - 确定性构建;
- 通过在内部实现混淆功能以移除对goldberg的依赖,以取消GPL-3.0许可证要求;