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 14/week @ 2024-03-11 22/week @ 2024-03-18 16/week @ 2024-03-25 41/week @ 2024-04-01 26/week @ 2024-04-08 27/week @ 2024-04-15 203/week @ 2024-04-22 24/week @ 2024-04-29 21/week @ 2024-05-06 13/week @ 2024-05-13 121/week @ 2024-05-20 31/week @ 2024-05-27 33/week @ 2024-06-03 14/week @ 2024-06-10 10/week @ 2024-06-17 17/week @ 2024-06-24

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许可证要求;

依赖项