1use std::collections::HashMap;
4
5#[cfg(feature = "serde-support")]
6use serde::{Deserialize, Serialize};
7
8pub type BinaryResult<T> = crate::Result<T>;
10pub type ParsedBinary = Box<dyn BinaryFormatTrait>;
11pub type ParseResult = BinaryResult<ParsedBinary>;
12pub type ImportExportResult = BinaryResult<(Vec<Import>, Vec<Export>)>;
13pub type ByteSliceResult<'a> = BinaryResult<&'a [u8]>;
14pub type PatternMatchMap =
15 HashMap<crate::utils::patterns::PatternCategory, Vec<crate::utils::patterns::PatternMatch>>;
16pub type HexPatternResult = BinaryResult<Vec<Option<u8>>>;
17pub type HexPattern = Vec<Option<u8>>;
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
21#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
22pub enum BinaryFormat {
23 Elf,
25 Pe,
27 MachO,
29 Java,
31 Wasm,
33 Raw,
35 #[default]
37 Unknown,
38}
39
40impl std::fmt::Display for BinaryFormat {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 match self {
43 BinaryFormat::Elf => write!(f, "ELF"),
44 BinaryFormat::Pe => write!(f, "PE"),
45 BinaryFormat::MachO => write!(f, "Mach-O"),
46 BinaryFormat::Java => write!(f, "Java"),
47 BinaryFormat::Wasm => write!(f, "WebAssembly"),
48 BinaryFormat::Raw => write!(f, "Raw"),
49 BinaryFormat::Unknown => write!(f, "Unknown"),
50 }
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
56#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
57pub enum Architecture {
58 X86,
60 X86_64,
62 Arm,
64 Arm64,
66 Mips,
68 Mips64,
70 PowerPC,
72 PowerPC64,
74 RiscV,
76 RiscV64,
78 Wasm,
80 Jvm,
82 #[default]
84 Unknown,
85}
86
87impl std::fmt::Display for Architecture {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 match self {
90 Architecture::X86 => write!(f, "x86"),
91 Architecture::X86_64 => write!(f, "x86-64"),
92 Architecture::Arm => write!(f, "ARM"),
93 Architecture::Arm64 => write!(f, "ARM64"),
94 Architecture::Mips => write!(f, "MIPS"),
95 Architecture::Mips64 => write!(f, "MIPS64"),
96 Architecture::PowerPC => write!(f, "PowerPC"),
97 Architecture::PowerPC64 => write!(f, "PowerPC64"),
98 Architecture::RiscV => write!(f, "RISC-V"),
99 Architecture::RiscV64 => write!(f, "RISC-V64"),
100 Architecture::Wasm => write!(f, "WebAssembly"),
101 Architecture::Jvm => write!(f, "JVM"),
102 Architecture::Unknown => write!(f, "Unknown"),
103 }
104 }
105}
106
107#[derive(Debug, Clone)]
109#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
110pub struct BinaryMetadata {
111 pub size: usize,
113 pub format: BinaryFormat,
115 pub architecture: Architecture,
117 pub entry_point: Option<u64>,
119 pub base_address: Option<u64>,
121 pub timestamp: Option<u64>,
123 pub compiler_info: Option<String>,
125 pub endian: Endianness,
127 pub security_features: SecurityFeatures,
129}
130
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
133#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
134pub enum Endianness {
135 Little,
136 Big,
137 #[default]
139 Unknown,
140}
141
142#[derive(Debug, Clone, Default)]
144#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
145pub struct SecurityFeatures {
146 pub nx_bit: bool,
148 pub aslr: bool,
150 pub stack_canary: bool,
152 pub cfi: bool,
154 pub fortify: bool,
156 pub pie: bool,
158 pub relro: bool,
160 pub signed: bool,
165}
166
167#[derive(Debug, Clone)]
169#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
170pub struct Section {
171 pub name: String,
173 pub address: u64,
175 pub size: u64,
177 pub offset: u64,
179 pub file_size: u64,
181 pub permissions: SectionPermissions,
183 pub section_type: SectionType,
185 pub data: Option<Vec<u8>>,
187}
188
189#[derive(Debug, Clone, Default)]
191#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
192pub struct SectionPermissions {
193 pub read: bool,
194 pub write: bool,
195 pub execute: bool,
196}
197
198#[derive(Debug, Clone, PartialEq, Eq)]
200#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
201pub enum SectionType {
202 Code,
203 Data,
204 ReadOnlyData,
205 Bss,
206 Debug,
207 Symbol,
208 String,
209 Relocation,
210 Dynamic,
211 Note,
212 Other(String),
213}
214
215#[derive(Debug, Clone)]
217#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
218pub struct Symbol {
219 pub name: String,
221 pub demangled_name: Option<String>,
223 pub address: u64,
225 pub size: u64,
227 pub symbol_type: SymbolType,
229 pub binding: SymbolBinding,
231 pub visibility: SymbolVisibility,
233 pub section_index: Option<usize>,
235}
236
237#[derive(Debug, Clone, PartialEq, Eq)]
239#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
240pub enum SymbolType {
241 Function,
242 Object,
243 Section,
244 File,
245 Common,
246 Thread,
247 Other(String),
248}
249
250#[derive(Debug, Clone, PartialEq, Eq)]
252#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
253pub enum SymbolBinding {
254 Local,
255 Global,
256 Weak,
257 Other(String),
258}
259
260#[derive(Debug, Clone, PartialEq, Eq)]
262#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
263pub enum SymbolVisibility {
264 Default,
265 Internal,
266 Hidden,
267 Protected,
268}
269
270#[derive(Debug, Clone)]
272#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
273pub struct Import {
274 pub name: String,
276 pub library: Option<String>,
278 pub address: Option<u64>,
280 pub ordinal: Option<u16>,
282}
283
284#[derive(Debug, Clone)]
286#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
287pub struct Export {
288 pub name: String,
290 pub address: u64,
292 pub ordinal: Option<u16>,
294 pub forwarded_name: Option<String>,
296}
297
298#[derive(Debug, Clone)]
300#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
301pub struct Instruction {
302 pub address: u64,
304 pub bytes: Vec<u8>,
306 pub mnemonic: String,
308 pub operands: String,
310 pub category: InstructionCategory,
312 pub flow: ControlFlow,
314 pub size: usize,
316}
317
318#[derive(Debug, Clone, PartialEq, Eq, Hash)]
320#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
321pub enum InstructionCategory {
322 Arithmetic,
323 Logic,
324 Memory,
325 Control,
326 System,
327 Crypto,
328 Vector,
329 Float,
330 Unknown,
331}
332
333#[derive(Debug, Clone, PartialEq, Eq)]
335#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
336pub enum ControlFlow {
337 Sequential,
339 Jump(u64),
341 ConditionalJump(u64),
343 Call(u64),
345 Return,
347 Interrupt,
349 Unknown,
351}
352
353#[derive(Debug, Clone)]
355#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
356pub struct BasicBlock {
357 pub id: usize,
359 pub start_address: u64,
361 pub end_address: u64,
363 pub instructions: Vec<Instruction>,
365 pub successors: Vec<usize>,
367 pub predecessors: Vec<usize>,
369 pub block_type: BlockType,
371 pub dominator: Option<usize>,
373 pub dominance_frontier: Vec<usize>,
375}
376
377#[derive(Debug, Clone)]
379#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
380pub struct ControlFlowGraph {
381 pub function: Function,
383 pub basic_blocks: Vec<BasicBlock>,
385 pub complexity: ComplexityMetrics,
387 pub loops: Vec<Loop>,
389}
390
391#[derive(Debug, Clone)]
393#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
394pub struct Function {
395 pub name: String,
397 pub start_address: u64,
399 pub end_address: u64,
401 pub size: u64,
403 pub function_type: FunctionType,
405 pub calling_convention: Option<String>,
407 pub parameters: Vec<Parameter>,
409 pub return_type: Option<String>,
411}
412
413#[derive(Debug, Clone, PartialEq, Eq)]
415#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
416pub enum FunctionType {
417 Normal,
418 Constructor,
419 Destructor,
420 Operator,
421 Main,
422 Entrypoint,
423 Import,
424 Export,
425 Thunk,
426 Unknown,
427}
428
429#[derive(Debug, Clone)]
431#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
432pub struct Parameter {
433 pub name: Option<String>,
435 pub param_type: String,
437 pub location: ParameterLocation,
439}
440
441#[derive(Debug, Clone, PartialEq)]
443#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
444pub enum ParameterLocation {
445 Register(String),
446 Stack(i64),
447 Unknown,
448}
449
450#[derive(Debug, Clone, Default)]
452#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
453pub struct ComplexityMetrics {
454 pub cyclomatic_complexity: u32,
456 pub basic_block_count: u32,
458 pub edge_count: u32,
460 pub nesting_depth: u32,
462 pub loop_count: u32,
464 pub cognitive_complexity: u32,
466 pub halstead_metrics: Option<HalsteadMetrics>,
468 pub maintainability_index: Option<f64>,
470}
471
472#[derive(Debug, Clone)]
474#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
475pub struct HalsteadMetrics {
476 pub n1: u32,
478 pub n2: u32,
480 pub capital_n1: u32,
482 pub capital_n2: u32,
484 pub vocabulary: u32,
486 pub length: u32,
488 pub calculated_length: f64,
490 pub volume: f64,
492 pub difficulty: f64,
494 pub effort: f64,
496 pub time: f64,
498 pub bugs: f64,
500}
501
502#[derive(Debug, Clone, PartialEq, Eq, Hash)]
504#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
505pub enum LoopType {
506 Natural,
508 Irreducible,
510 DoWhile,
512 While,
514 For,
516 Infinite,
518 Unknown,
520}
521
522#[derive(Debug, Clone)]
524#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
525pub struct Loop {
526 pub header_block: usize,
528 pub body_blocks: Vec<usize>,
530 pub exit_blocks: Vec<usize>,
532 pub loop_type: LoopType,
534 pub induction_variables: Vec<String>,
536 pub is_natural: bool,
538 pub nesting_level: u32,
540}
541
542#[derive(Debug, Clone, PartialEq, Eq)]
544#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
545pub enum BlockType {
546 Entry,
547 Exit,
548 Normal,
549 LoopHeader,
550 LoopBody,
551 LoopExit,
552 Conditional,
553 Call,
554 Return,
555 Exception,
556}
557
558#[derive(Debug, Clone)]
560#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
561pub struct EntropyAnalysis {
562 pub overall_entropy: f64,
564 pub section_entropy: HashMap<String, f64>,
566 pub high_entropy_regions: Vec<EntropyRegion>,
568 pub packing_indicators: PackingIndicators,
570}
571
572#[derive(Debug, Clone)]
574#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
575pub struct EntropyRegion {
576 pub start: u64,
578 pub end: u64,
580 pub entropy: f64,
582 pub description: String,
584}
585
586#[derive(Debug, Clone, Default)]
588#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
589pub struct PackingIndicators {
590 pub is_packed: bool,
592 pub packer_name: Option<String>,
594 pub compression_ratio: Option<f64>,
596 pub obfuscation_level: ObfuscationLevel,
598}
599
600#[derive(Debug, Clone, PartialEq, Eq, Default)]
602#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
603pub enum ObfuscationLevel {
604 #[default]
605 None,
606 Low,
607 Medium,
608 High,
609 Extreme,
610}
611
612#[derive(Debug, Clone, Default)]
614#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
615pub struct SecurityIndicators {
616 pub suspicious_apis: Vec<String>,
618 pub anti_debug: Vec<String>,
620 pub anti_vm: Vec<String>,
622 pub crypto_indicators: Vec<String>,
624 pub network_indicators: Vec<String>,
626 pub filesystem_indicators: Vec<String>,
628 pub registry_indicators: Vec<String>,
630}
631
632#[derive(Debug, Clone)]
634#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
635pub struct CallGraph {
636 pub nodes: Vec<CallGraphNode>,
638 pub edges: Vec<CallGraphEdge>,
640 pub entry_points: Vec<u64>,
642 pub unreachable_functions: Vec<u64>,
644 pub statistics: CallGraphStatistics,
646}
647
648#[derive(Debug, Clone)]
650#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
651pub struct CallGraphNode {
652 pub function_address: u64,
654 pub function_name: String,
656 pub node_type: NodeType,
658 pub complexity: u32,
660 pub in_degree: u32,
662 pub out_degree: u32,
664 pub is_recursive: bool,
666 pub call_depth: Option<u32>,
668}
669
670#[derive(Debug, Clone, PartialEq, Eq)]
672#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
673pub enum NodeType {
674 EntryPoint,
676 Library,
678 Internal,
680 External,
682 Indirect,
684 Virtual,
686 Unknown,
688}
689
690#[derive(Debug, Clone)]
692#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
693pub struct CallGraphEdge {
694 pub caller: u64,
696 pub callee: Option<u64>,
698 pub call_type: CallType,
700 pub call_sites: Vec<CallSite>,
702}
703
704#[derive(Debug, Clone, PartialEq, Eq)]
706#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
707pub enum CallType {
708 Direct,
710 Indirect,
712 TailCall,
714 Virtual,
716 Recursive,
718 Conditional,
720}
721
722#[derive(Debug, Clone)]
724#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
725pub struct CallSite {
726 pub address: u64,
728 pub instruction_bytes: Vec<u8>,
730 pub context: CallContext,
732}
733
734#[derive(Debug, Clone, PartialEq, Eq)]
736#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
737pub enum CallContext {
738 Normal,
739 Exception,
740 Loop,
741 Conditional,
742}
743
744#[derive(Debug, Clone, Default)]
746#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
747pub struct CallGraphStatistics {
748 pub total_functions: usize,
750 pub total_calls: usize,
752 pub direct_calls: usize,
754 pub indirect_calls: usize,
756 pub recursive_functions: usize,
758 pub leaf_functions: usize,
760 pub entry_points: usize,
762 pub unreachable_functions: usize,
764 pub max_call_depth: u32,
766 pub average_call_depth: f64,
768 pub cyclic_dependencies: usize,
770}
771
772#[derive(Debug, Clone)]
774#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
775pub struct CallGraphConfig {
776 pub analyze_indirect_calls: bool,
778 pub detect_tail_calls: bool,
780 pub max_functions: usize,
782 pub max_total_instructions: usize,
784 pub max_labeled_call_depth: Option<u32>,
788 pub include_library_calls: bool,
790}
791
792impl Default for CallGraphConfig {
793 fn default() -> Self {
794 Self {
795 analyze_indirect_calls: true,
796 detect_tail_calls: true,
797 max_functions: 10_000,
798 max_total_instructions: 1_000_000,
799 max_labeled_call_depth: Some(50),
800 include_library_calls: false,
801 }
802 }
803}
804
805#[derive(Debug, Clone, Default)]
807#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
808pub struct AnalysisResult {
809 pub format: BinaryFormat,
811 pub architecture: Architecture,
813 pub entry_point: Option<u64>,
815 pub metadata: BinaryMetadata,
817 pub sections: Vec<Section>,
819 pub symbols: Vec<Symbol>,
821 pub imports: Vec<Import>,
823 pub exports: Vec<Export>,
825 pub disassembly: Option<Vec<Instruction>>,
827 pub control_flow: Option<Vec<ControlFlowGraph>>,
829 pub entropy: Option<EntropyAnalysis>,
831 pub security: Option<SecurityIndicators>,
833 pub call_graph: Option<CallGraph>,
835 pub enhanced_control_flow: Option<EnhancedControlFlowAnalysis>,
837}
838
839#[derive(Debug, Clone)]
841#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
842pub struct EnhancedControlFlowAnalysis {
843 pub control_flow_graphs: Vec<ControlFlowGraph>,
845 pub cognitive_complexity_summary: CognitiveComplexityStats,
847 pub loop_analysis_summary: LoopAnalysisStats,
849}
850
851#[derive(Debug, Clone, Default)]
853#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
854pub struct CognitiveComplexityStats {
855 pub total_cognitive_complexity: u32,
857 pub average_cognitive_complexity: f64,
859 pub max_cognitive_complexity: u32,
861 pub most_complex_function: Option<String>,
863 pub functions_analyzed: usize,
865}
866
867#[derive(Debug, Clone, Default)]
869#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
870pub struct LoopAnalysisStats {
871 pub total_loops: usize,
873 pub natural_loops: usize,
875 pub irreducible_loops: usize,
877 pub nested_loops: usize,
879 pub max_nesting_depth: u32,
881 pub loops_by_type: HashMap<LoopType, usize>,
883}
884
885impl Default for BinaryMetadata {
886 fn default() -> Self {
887 Self {
888 size: 0,
889 format: BinaryFormat::Unknown,
890 architecture: Architecture::Unknown,
891 entry_point: None,
892 base_address: None,
893 timestamp: None,
894 compiler_info: None,
895 endian: Endianness::Unknown,
896 security_features: SecurityFeatures::default(),
897 }
898 }
899}
900
901pub trait BinaryFormatParser {
903 fn parse(data: &[u8]) -> ParseResult;
905
906 fn can_parse(data: &[u8]) -> bool;
908}
909
910pub trait BinaryFormatTrait: Send + Sync {
912 fn format_type(&self) -> BinaryFormat;
914
915 fn architecture(&self) -> Architecture;
917
918 fn entry_point(&self) -> Option<u64>;
920
921 fn sections(&self) -> &[Section];
923
924 fn symbols(&self) -> &[Symbol];
926
927 fn imports(&self) -> &[Import];
929
930 fn exports(&self) -> &[Export];
932
933 fn metadata(&self) -> &BinaryMetadata;
935}