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开发工具

Download history • Rust 包仓库 14/week @ 2024-03-11 • Rust 包仓库 22/week @ 2024-03-18 • Rust 包仓库 16/week @ 2024-03-25 • Rust 包仓库 41/week @ 2024-04-01 • Rust 包仓库 26/week @ 2024-04-08 • Rust 包仓库 27/week @ 2024-04-15 • Rust 包仓库 203/week @ 2024-04-22 • Rust 包仓库 24/week @ 2024-04-29 • Rust 包仓库 21/week @ 2024-05-06 • Rust 包仓库 13/week @ 2024-05-13 • Rust 包仓库 121/week @ 2024-05-20 • Rust 包仓库 31/week @ 2024-05-27 • Rust 包仓库 33/week @ 2024-06-03 • Rust 包仓库 14/week @ 2024-06-10 • Rust 包仓库 10/week @ 2024-06-17 • Rust 包仓库 17/week @ 2024-06-24 • Rust 包仓库

83 每月下载量
用于 4 crates

GPL-3.0 OR MIT 和可能 GPL-3.0

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函数的对应函数图

Executable build without DebugOff.

如果我们使用DebugOffobfuscate功能构建相同的代码

#[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函数的混淆函数图

Executable build with DebugOff.

在这个特定的示例中,由DebugOff生成的所有代码都被内联在main函数中。这并不保证总是如此,因为函数的内联可能受许多因素的影响,如DebugOff被调用的位置和用于构建项目的工具链版本。在其他情况下,生成的函数图可能比示例中报告的更简单,但无论如何,都比不使用DebugOff时生成的更复杂。

许可证

许可下

  • 当启用obfuscate功能时,GPL-3.0;
  • obfuscate功能启用时,MIT;

待办事项

  • 为其他架构实现系统调用混淆(因为目前只有x86_64支持系统调用混淆);
  • 确定性构建;
  • 通过在内部实现混淆功能以移除对goldberg的依赖,以取消GPL-3.0许可证要求;

依赖项