pub mod analysis;
pub mod cfg;
pub mod cfg_analyzer;
pub mod disasm;
pub mod lifting;
pub mod patcher;
pub mod types;
pub use types::*;
use anyhow::Result;
use nabla_scanner::binary::analysis::BinaryAnalysis;
use serde::{Deserialize, Serialize};
pub struct Decompiler {
binary_analysis: BinaryAnalysis,
}
impl Decompiler {
pub fn new(binary_analysis: BinaryAnalysis) -> Self {
Self { binary_analysis }
}
pub fn analyze(&self) -> Result<DecompilerAnalysis> {
let disasm = disasm::disassemble_binary(&self.binary_analysis)?;
let arch = self.binary_analysis.architecture.as_str();
let format = self.binary_analysis.format.as_str();
let functions = analysis::identify_functions_with_yara(&disasm, arch, format)?;
let call_graph = cfg::build_call_graph(&functions)?;
let function_cfgs = cfg::build_function_cfgs(&functions, &disasm, arch, format)?;
let pseudocode = lifting::generate_pseudocode(&functions, &disasm)?;
Ok(DecompilerAnalysis {
binary: self.binary_analysis.clone(),
disassembly: disasm,
functions,
call_graph,
function_cfgs,
pseudocode,
analysis_timestamp: chrono::Utc::now(),
})
}
pub fn analyze_function(&self, address: u64) -> Result<FunctionAnalysis> {
let disasm = disasm::disassemble_from_address(&self.binary_analysis, address)?;
let arch = self.binary_analysis.architecture.as_str();
let format = self.binary_analysis.format.as_str();
let function = analysis::analyze_single_function_with_arch(&disasm, address, arch, format)?;
let cfg = cfg::build_function_cfg_with_arch(&function, &disasm, arch, format)?;
let pseudocode = lifting::lift_function_to_pseudocode(&function, &disasm)?;
Ok(FunctionAnalysis {
function,
cfg,
pseudocode,
disassembly: disasm,
})
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DecompileRequest {
pub binary_path: String,
pub function_address: Option<u64>,
pub output_format: String,
}
pub struct DecompilerEngine {
}
impl DecompilerEngine {
pub async fn new() -> Result<Self> {
Ok(Self {})
}
pub async fn decompile(&mut self, request: DecompileRequest, binary_analysis: &BinaryAnalysis) -> Result<DecompilerResult> {
let decompiler = Decompiler::new(binary_analysis.clone());
match request.function_address {
Some(address) => {
let func_analysis = decompiler.analyze_function(address)?;
Ok(DecompilerResult::FunctionAnalysis(func_analysis))
}
None => {
let full_analysis = decompiler.analyze()?;
Ok(DecompilerResult::FullAnalysis(full_analysis))
}
}
}
}
#[derive(Debug, Clone)]
pub enum DecompilerResult {
FullAnalysis(DecompilerAnalysis),
FunctionAnalysis(FunctionAnalysis),
}
#[cfg(test)]
mod tests {
include!("lifting_tests.rs");
}