Rust符号执行与CFI分析库symbolic-cfi的使用,提供控制流完整性和二进制分析功能

Rust符号执行与CFI分析库symbolic-cfi的使用,提供控制流完整性和二进制分析功能

安装

在你的项目目录中运行以下Cargo命令:

cargo add symbolic-cfi

或者在Cargo.toml中添加以下行:

symbolic-cfi = "12.16.1"

示例代码

下面是一个使用symbolic-cfi进行控制流完整性(CFI)分析的完整示例:

use symbolic_cfi::{CfiCache, ObjectLike};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 加载二进制文件
    let data = std::fs::read("example_binary")?;
    let object = ObjectLike::parse(&data)?;

    // 创建CFI缓存
    let cfi_cache = CfiCache::from_object(&object)?;

    // 获取函数的CFI信息
    if let Some(cfi_info) = cfi_cache.get(0x1234) { // 0x1234是函数地址
        println!("CFI信息:");
        println!("  Stack pointer adjustment: {}", cfi_info.stack_pointer_adjustment);
        println!("  Return address register: {}", cfi_info.return_address_register);
        
        for rule in &cfi_info.rules {
            println!("  Register {}: {}", rule.register, rule.expression);
        }
    } else {
        println!("在地址0x1234未找到CFI信息");
    }

    Ok(())
}

完整示例代码

以下是一个更完整的示例,展示了如何使用symbolic-cfi分析二进制文件的控制流信息:

use symbolic_cfi::{CfiCache, ObjectLike};
use std::path::Path;

fn analyze_binary_cfi(binary_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
    // 读取二进制文件
    let data = std::fs::read(binary_path)?;
    
    // 解析二进制文件
    let object = ObjectLike::parse(&data)?;
    
    // 创建CFI缓存
    let cfi_cache = CfiCache::from_object(&object)?;
    
    // 遍历所有可执行段
    for segment in object.segments() {
        if segment.is_executable() {
            println!("分析可执行段: 0x{:x}-0x{:x}", segment.address(), segment.address() + segment.size());
            
            // 遍历段中的函数
            for function in object.functions_in_range(segment.address(), segment.size())? {
                println!("\n函数: {} @ 0x{:x}", function.name, function.address);
                
                // 获取函数的CFI信息
                if let Some(cfi_info) = cfi_cache.get(function.address) {
                    println!("  CFI信息:");
                    println!("    栈指针调整: {}", cfi_info.stack_pointer_adjustment);
                    println!("    返回地址寄存器: {}", cfi_info.return_address_register);
                    
                    println!("    寄存器规则:");
                    for rule in &cfi_info.rules {
                        println!("      {}: {}", rule.register, rule.expression);
                    }
                } else {
                    println!("  未找到CFI信息");
                }
            }
        }
    }
    
    Ok(())
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let binary_path = Path::new("example_binary");
    analyze_binary_cfi(binary_path)
}

特性

symbolic-cfi库提供以下功能:

  1. 控制流完整性(CFI)分析
  2. 二进制文件解析
  3. 调试信息提取
  4. 堆栈展开支持

所有权者

  • Sentry Bot

1 回复

Rust符号执行与CFI分析库symbolic-cfi使用指南

完整示例demo

下面是一个结合了二进制分析、CFI检查和符号执行的完整示例:

use symbolic_cfi::{
    analysis::{Binary, BinaryAnalysis, VulnerabilityType},
    cfi::{CFIAnalysis, CFIConfig, CFIRule},
    symbolic_execution::{SymbolicExecutor, ExecutionState}
};

fn main() {
    // 1. 加载二进制文件并分析基本信息
    let binary_path = "target_binary";
    let binary = Binary::from_path(binary_path)
        .expect("Failed to load binary file");
    
    let analysis = BinaryAnalysis::new(&binary);
    println!("Analyzing binary: {}", binary_path);
    println!("Architecture: {:?}", analysis.architecture());
    println!("Entry point: 0x{:x}", analysis.entry_point());
    println!("Section count: {}", analysis.sections().len());

    // 2. 执行CFI分析
    println!("\nRunning CFI analysis...");
    let mut cfi_config = CFIConfig::default();
    cfi_config.add_rule(CFIRule::DirectCallOnly); // 只允许直接调用
    cfi_config.add_rule(CFIRule::NoIndirectJumps); // 禁止间接跳转
    
    let cfi_results = CFIAnalysis::new(&binary, cfi_config)
        .analyze()
        .expect("CFI analysis failed");
    
    println!("Found {} CFI violations", cfi_results.violations.len());
    for violation in &cfi_results.violations {
        println!("Violation at 0x{:x}: {}", violation.address, violation.description);
    }

    // 3. 执行符号执行分析
    println!("\nRunning symbolic execution...");
    let mut executor = SymbolicExecutor::new(&binary)
        .with_max_depth(1000); // 限制执行深度
    
    let exec_results = executor.execute(ExecutionState::new())
        .expect("Symbolic execution failed");
    
    println!("Explored {} paths", exec_results.paths.len());
    for (i, path) in exec_results.paths.iter().enumerate() {
        println!("Path {}: {} steps", i, path.steps.len());
        if let Some(vuln) = &path.vulnerability {
            println!("  Vulnerability: {:?}", vuln);
        }
    }

    // 4. 特定漏洞扫描
    println!("\nScanning for specific vulnerabilities...");
    let vulnerabilities = analysis.find_vulnerabilities(&[
        VulnerabilityType::BufferOverflow,
        VulnerabilityType::UseAfterFree,
    ]).expect("Vulnerability scan failed");
    
    println!("Found {} potential vulnerabilities", vulnerabilities.len());
    for vuln in vulnerabilities {
        println!("{:#?}", vuln);
    }
}

示例代码说明

  1. 二进制加载与分析

    • 加载目标二进制文件并解析基本信息
    • 输出架构、入口点和段信息
  2. CFI分析

    • 使用自定义规则配置(只允许直接调用/禁止间接跳转)
    • 检测并报告CFI违规情况
  3. 符号执行

    • 限制最大执行深度防止路径爆炸
    • 记录所有探索路径及其发现的漏洞
  4. 漏洞扫描

    • 针对特定漏洞类型(缓冲区溢出、释放后使用)进行扫描
    • 输出发现的潜在漏洞

运行输出示例

Analyzing binary: target_binary
Architecture: X86_64
Entry point: 0x401000
Section count: 12

Running CFI analysis...
Found 3 CFI violations
Violation at 0x401234: Indirect call to unprotected location
Violation at 0x4012ab: Unexpected return target
Violation at 0x4013cd: Invalid jump table entry

Running symbolic execution...
Explored 42 paths
Path 0: 128 steps
  Vulnerability: BufferOverflow { size: 256, offset: 8 }
Path 1: 97 steps
Path 2: 213 steps
  Vulnerability: UseAfterFree { ptr: 0x7ffd1234 }

Scanning for specific vulnerabilities...
Found 5 potential vulnerabilities
BufferOverflow {
    location: 0x401234,
    size: 256,
    input_source: "argv[1]"
}
...

实际应用建议

  1. 对于大型二进制,建议分模块分析
  2. 将CFI分析和符号执行结果交叉验证
  3. 重点关注重复出现的安全问题模式
  4. 可以保存分析结果供后续深入调查
回到顶部