#process #memory #secure #content #system-api #hardening

no-std secmem-proc

通过系统API进行进程加固

8个版本

0.3.3 2024年1月17日
0.3.2 2023年7月1日
0.3.1 2023年5月4日
0.3.0 2022年11月25日
0.1.0 2021年11月3日

64操作系统

Download history 825/week @ 2024-04-07 743/week @ 2024-04-14 938/week @ 2024-04-21 1169/week @ 2024-04-28 918/week @ 2024-05-05 1214/week @ 2024-05-12 669/week @ 2024-05-19 572/week @ 2024-05-26 1033/week @ 2024-06-02 591/week @ 2024-06-09 630/week @ 2024-06-16 1222/week @ 2024-06-23 276/week @ 2024-06-30 1086/week @ 2024-07-07 802/week @ 2024-07-14 1061/week @ 2024-07-21

3,287 每月下载量
2 crates 中使用

MIT/Apache

91KB
1.5K SLoC

secmem-proc 许可证: MIT OR Apache-2.0 secmem-proc on crates.io secmem-proc on docs.rs 源代码仓库 Rust 版本: 1.65.0

secmem-proc 是一个crate,旨在通过系统API加固进程以抵御在同一系统上运行的 低权限 攻击者尝试获取当前进程的秘密内存内容。更具体地说,该crate禁用核心转储,尽力禁用跟踪其的能力,并尽可能检测已附加的跟踪器。

注意:该crate所做的只是 加固,即它试图让攻击更难。它绝对不能保证任何安全性!特别是,当攻击者在执行 harden_process 之前将ptrace附加到进程时,进程就失败了。这个crate不能替代正确加固您的操作系统(配置)!

请注意,加固进程也会严重限制调试它的能力。因此,建议您只加固发布构建,而不是调试构建。

Windows

在Windows上,harden_process 为进程设置了一个严重受限的DACL。 (更精确地说,只有 PROCESS_QUERY_LIMITED_INFORMATIONPROCESS_TERMINATESYNCHRONIZE 权限被启用。) 这可能过于严格,以至于无法让应用程序正确运行。当需要更多权限时,可以使用 win_acl 模块中的安全API创建和设置自定义DACL。

在Windows上,这个crate通过依赖windows crate依赖于std

示例

以下示例中,某个应用程序的main函数调用此crate提供的main hardening函数:harden_process。这将在目标平台上执行所有可用的hardening步骤(除了不稳定的步骤)。当其中一个hardening步骤失败或检测到调试器时,该函数返回错误。建议在任何错误发生时终止应用程序。

fn main() {
    // call `secmem_proc::harden_process` before doing anything else, to harden the process
    // against low-privileged attackers trying to obtain secret parts of memory which will
    // be handled by the process
    if let Err(e) = secmem_proc::harden_process() {
        println!("ERROR: could not harden process, exiting");
        println!("ERROR: {}", e);
        return;
    }
    // rest of your program
}

也可以配置要执行哪些类型的hardening步骤。为此,可以使用config中的API。以下是一个示例:

fn main() {
    // harden before doing anything else
    let mut config = secmem_proc::Config::DEFAULT;
    config.set_anti_tracing(false);
    config.set_fs(false);
    if let Err(e) = config.harden_process() {
        println!("ERROR: could not harden process, exiting");
        println!("ERROR: {}", e);
        return;
    }
    // rest of your program
}

在最后一个示例中,我们使用win_acl API在Windows上设置自定义DACL。在示例中,我们除了默认权限外,还授予了PROCESS_CREATE_THREAD权限。请注意,在这种情况下,同样可以使用Config::set_win_dacl_custom_user_perm实现,这显然要简单得多。然而,下面的方法要灵活得多。

#[cfg(windows)]
fn set_windows_dacl() -> secmem_proc::Result {
    use windows::Win32::System::Threading::{
        PROCESS_CREATE_THREAD, PROCESS_QUERY_LIMITED_INFORMATION, PROCESS_SYNCHRONIZE,
        PROCESS_TERMINATE,
    };

    use secmem_proc::win_acl::{AddAllowAceAcl, EmptyAcl, TokenUser};

    // First obtain the SID of the process user
    let user = TokenUser::process_user()?;
    let sid = user.sid();

    // Now specify the ACL we want to create
    // Only things explicitly allowed with `AddAllowAceAcl` will be allowed; noting else
    let acl_spec = EmptyAcl;
    let access_mask = PROCESS_QUERY_LIMITED_INFORMATION
        | PROCESS_TERMINATE
        | PROCESS_SYNCHRONIZE
        | PROCESS_CREATE_THREAD;
    let acl_spec = AddAllowAceAcl::new(acl_spec, access_mask, sid);

    // Create ACL and set as process DACL
    let acl = acl_spec.create()?;
    acl.set_process_dacl_protected()?;
    Ok(())
}

fn main() {
    // harden before doing anything else
    let mut config = secmem_proc::Config::DEFAULT;
    #[cfg(windows)]
    config.set_win_dacl_custom_fn(set_windows_dacl);
    config.set_fs(false);
    if let Err(e) = config.harden_process() {
        println!("ERROR: could not harden process, exiting");
        println!("ERROR: {}", e);
        return;
    }
    // rest of your program
}

Cargo功能

  • std(默认):启用需要std的功能。目前需要用于Error实现、Linux上的反跟踪通过/proc/self/status和测试。此功能默认启用。
  • unstable:启用依赖于未记录或不稳定的操作系统/平台细节的功能。此功能仅启用对这些功能的支持;要实际启用这些反调试方法,必须在配置中专门启用。
  • dev:此功能启用运行测试套件所需的所有功能,并且仅应为此目的启用。

实现

  • 使用prctl在Linux上禁用进程的ptrace和core dumps
  • 使用procctl在FreeBSD上禁用进程的ptrace和core dumps
  • 使用ptrace在macos上禁用ptrace
  • 使用rlimit在POSIX系统上禁用进程的core dumps
  • 在Windows上为进程设置受限DACL
  • 当启用std功能时,通过读取/proc/self/status在Linux上检测调试器(std,反跟踪)
  • 使用IsDebuggerPresentCheckRemoteDebuggerPresent在Windows上检测调试器(反跟踪)
  • 启用unstable后,在Windows上隐藏线程以防止调试器调试(unstable,反跟踪)
  • 启用unstable后,通过从内核结构KUSER_SHARED_DATA读取来检测Windows上的调试器(unstable,反跟踪)

反跟踪

此crate使用的强化方法可以分为两组:

  • 与安全相关的进程强化,以及
  • 反跟踪。

两种方法之间的区别在于线程模型。进程加固通常假设进程尚未受到攻击,例如尚未被跟踪。加固方法随后对进程的配置进行修改,以限制其他进程对其的访问,例如禁用进程跟踪或禁用核心转储。反跟踪假设进程已经被恶意进程(恶意软件)跟踪/调试。目标则是检测跟踪器/调试器。反跟踪方法总是可以被跟踪器/调试器绕过,尽管其中一些比其他方法更难绕过。(Windows上不稳定的KUSER_SHARED_DATA反跟踪方法就是一个难以绕过的例子。)可以使用以下方式禁用反跟踪:Config::set_anti_tracing(false)

待办事项

  • 改进测试(具体如何?)

依赖关系

~2–40MB
~630K SLoC