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)]
133#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
134pub enum Endianness {
135 Little,
136 Big,
137}
138
139#[derive(Debug, Clone, Default)]
141#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
142pub struct SecurityFeatures {
143 pub nx_bit: bool,
145 pub aslr: bool,
147 pub stack_canary: bool,
149 pub cfi: bool,
151 pub fortify: bool,
153 pub pie: bool,
155 pub relro: bool,
157 pub signed: bool,
159}
160
161#[derive(Debug, Clone)]
163#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
164pub struct Section {
165 pub name: String,
167 pub address: u64,
169 pub size: u64,
171 pub offset: u64,
173 pub permissions: SectionPermissions,
175 pub section_type: SectionType,
177 pub data: Option<Vec<u8>>,
179}
180
181#[derive(Debug, Clone, Default)]
183#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
184pub struct SectionPermissions {
185 pub read: bool,
186 pub write: bool,
187 pub execute: bool,
188}
189
190#[derive(Debug, Clone, PartialEq, Eq)]
192#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
193pub enum SectionType {
194 Code,
195 Data,
196 ReadOnlyData,
197 Bss,
198 Debug,
199 Symbol,
200 String,
201 Relocation,
202 Dynamic,
203 Note,
204 Other(String),
205}
206
207#[derive(Debug, Clone)]
209#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
210pub struct Symbol {
211 pub name: String,
213 pub demangled_name: Option<String>,
215 pub address: u64,
217 pub size: u64,
219 pub symbol_type: SymbolType,
221 pub binding: SymbolBinding,
223 pub visibility: SymbolVisibility,
225 pub section_index: Option<usize>,
227}
228
229#[derive(Debug, Clone, PartialEq, Eq)]
231#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
232pub enum SymbolType {
233 Function,
234 Object,
235 Section,
236 File,
237 Common,
238 Thread,
239 Other(String),
240}
241
242#[derive(Debug, Clone, PartialEq, Eq)]
244#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
245pub enum SymbolBinding {
246 Local,
247 Global,
248 Weak,
249 Other(String),
250}
251
252#[derive(Debug, Clone, PartialEq, Eq)]
254#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
255pub enum SymbolVisibility {
256 Default,
257 Internal,
258 Hidden,
259 Protected,
260}
261
262#[derive(Debug, Clone)]
264#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
265pub struct Import {
266 pub name: String,
268 pub library: Option<String>,
270 pub address: Option<u64>,
272 pub ordinal: Option<u16>,
274}
275
276#[derive(Debug, Clone)]
278#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
279pub struct Export {
280 pub name: String,
282 pub address: u64,
284 pub ordinal: Option<u16>,
286 pub forwarded_name: Option<String>,
288}
289
290#[derive(Debug, Clone)]
292#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
293pub struct Instruction {
294 pub address: u64,
296 pub bytes: Vec<u8>,
298 pub mnemonic: String,
300 pub operands: String,
302 pub category: InstructionCategory,
304 pub flow: ControlFlow,
306 pub size: usize,
308}
309
310#[derive(Debug, Clone, PartialEq, Eq, Hash)]
312#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
313pub enum InstructionCategory {
314 Arithmetic,
315 Logic,
316 Memory,
317 Control,
318 System,
319 Crypto,
320 Vector,
321 Float,
322 Unknown,
323}
324
325#[derive(Debug, Clone, PartialEq, Eq)]
327#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
328pub enum ControlFlow {
329 Sequential,
331 Jump(u64),
333 ConditionalJump(u64),
335 Call(u64),
337 Return,
339 Interrupt,
341 Unknown,
343}
344
345#[derive(Debug, Clone)]
347#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
348pub struct BasicBlock {
349 pub id: usize,
351 pub start_address: u64,
353 pub end_address: u64,
355 pub instructions: Vec<Instruction>,
357 pub successors: Vec<usize>,
359 pub predecessors: Vec<usize>,
361 pub block_type: BlockType,
363 pub dominator: Option<usize>,
365 pub dominance_frontier: Vec<usize>,
367}
368
369#[derive(Debug, Clone)]
371#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
372pub struct ControlFlowGraph {
373 pub function: Function,
375 pub basic_blocks: Vec<BasicBlock>,
377 pub complexity: ComplexityMetrics,
379 pub loops: Vec<Loop>,
381}
382
383#[derive(Debug, Clone)]
385#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
386pub struct Function {
387 pub name: String,
389 pub start_address: u64,
391 pub end_address: u64,
393 pub size: u64,
395 pub function_type: FunctionType,
397 pub calling_convention: Option<String>,
399 pub parameters: Vec<Parameter>,
401 pub return_type: Option<String>,
403}
404
405#[derive(Debug, Clone, PartialEq, Eq)]
407#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
408pub enum FunctionType {
409 Normal,
410 Constructor,
411 Destructor,
412 Operator,
413 Main,
414 Entrypoint,
415 Import,
416 Export,
417 Thunk,
418 Unknown,
419}
420
421#[derive(Debug, Clone)]
423#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
424pub struct Parameter {
425 pub name: Option<String>,
427 pub param_type: String,
429 pub location: ParameterLocation,
431}
432
433#[derive(Debug, Clone, PartialEq)]
435#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
436pub enum ParameterLocation {
437 Register(String),
438 Stack(i64),
439 Unknown,
440}
441
442#[derive(Debug, Clone, Default)]
444#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
445pub struct ComplexityMetrics {
446 pub cyclomatic_complexity: u32,
448 pub basic_block_count: u32,
450 pub edge_count: u32,
452 pub nesting_depth: u32,
454 pub loop_count: u32,
456 pub cognitive_complexity: u32,
458 pub halstead_metrics: Option<HalsteadMetrics>,
460 pub maintainability_index: Option<f64>,
462}
463
464#[derive(Debug, Clone)]
466#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
467pub struct HalsteadMetrics {
468 pub n1: u32,
470 pub n2: u32,
472 pub capital_n1: u32,
474 pub capital_n2: u32,
476 pub vocabulary: u32,
478 pub length: u32,
480 pub calculated_length: f64,
482 pub volume: f64,
484 pub difficulty: f64,
486 pub effort: f64,
488 pub time: f64,
490 pub bugs: f64,
492}
493
494#[derive(Debug, Clone, PartialEq, Eq, Hash)]
496#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
497pub enum LoopType {
498 Natural,
500 Irreducible,
502 DoWhile,
504 While,
506 For,
508 Infinite,
510 Unknown,
512}
513
514#[derive(Debug, Clone)]
516#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
517pub struct Loop {
518 pub header_block: usize,
520 pub body_blocks: Vec<usize>,
522 pub exit_blocks: Vec<usize>,
524 pub loop_type: LoopType,
526 pub induction_variables: Vec<String>,
528 pub is_natural: bool,
530 pub nesting_level: u32,
532}
533
534#[derive(Debug, Clone, PartialEq, Eq)]
536#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
537pub enum BlockType {
538 Entry,
539 Exit,
540 Normal,
541 LoopHeader,
542 LoopBody,
543 LoopExit,
544 Conditional,
545 Call,
546 Return,
547 Exception,
548}
549
550#[derive(Debug, Clone)]
552#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
553pub struct EntropyAnalysis {
554 pub overall_entropy: f64,
556 pub section_entropy: HashMap<String, f64>,
558 pub high_entropy_regions: Vec<EntropyRegion>,
560 pub packing_indicators: PackingIndicators,
562}
563
564#[derive(Debug, Clone)]
566#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
567pub struct EntropyRegion {
568 pub start: u64,
570 pub end: u64,
572 pub entropy: f64,
574 pub description: String,
576}
577
578#[derive(Debug, Clone, Default)]
580#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
581pub struct PackingIndicators {
582 pub is_packed: bool,
584 pub packer_name: Option<String>,
586 pub compression_ratio: Option<f64>,
588 pub obfuscation_level: ObfuscationLevel,
590}
591
592#[derive(Debug, Clone, PartialEq, Eq, Default)]
594#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
595pub enum ObfuscationLevel {
596 #[default]
597 None,
598 Low,
599 Medium,
600 High,
601 Extreme,
602}
603
604#[derive(Debug, Clone, Default)]
606#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
607pub struct SecurityIndicators {
608 pub suspicious_apis: Vec<String>,
610 pub anti_debug: Vec<String>,
612 pub anti_vm: Vec<String>,
614 pub crypto_indicators: Vec<String>,
616 pub network_indicators: Vec<String>,
618 pub filesystem_indicators: Vec<String>,
620 pub registry_indicators: Vec<String>,
622}
623
624#[derive(Debug, Clone)]
626#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
627pub struct CallGraph {
628 pub nodes: Vec<CallGraphNode>,
630 pub edges: Vec<CallGraphEdge>,
632 pub entry_points: Vec<u64>,
634 pub unreachable_functions: Vec<u64>,
636 pub statistics: CallGraphStatistics,
638}
639
640#[derive(Debug, Clone)]
642#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
643pub struct CallGraphNode {
644 pub function_address: u64,
646 pub function_name: String,
648 pub node_type: NodeType,
650 pub complexity: u32,
652 pub in_degree: u32,
654 pub out_degree: u32,
656 pub is_recursive: bool,
658 pub call_depth: Option<u32>,
660}
661
662#[derive(Debug, Clone, PartialEq, Eq)]
664#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
665pub enum NodeType {
666 EntryPoint,
668 Library,
670 Internal,
672 External,
674 Indirect,
676 Virtual,
678 Unknown,
680}
681
682#[derive(Debug, Clone)]
684#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
685pub struct CallGraphEdge {
686 pub caller: u64,
688 pub callee: u64,
690 pub call_type: CallType,
692 pub call_sites: Vec<CallSite>,
694}
695
696#[derive(Debug, Clone, PartialEq, Eq)]
698#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
699pub enum CallType {
700 Direct,
702 Indirect,
704 TailCall,
706 Virtual,
708 Recursive,
710 Conditional,
712}
713
714#[derive(Debug, Clone)]
716#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
717pub struct CallSite {
718 pub address: u64,
720 pub instruction_bytes: Vec<u8>,
722 pub context: CallContext,
724}
725
726#[derive(Debug, Clone, PartialEq, Eq)]
728#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
729pub enum CallContext {
730 Normal,
731 Exception,
732 Loop,
733 Conditional,
734}
735
736#[derive(Debug, Clone, Default)]
738#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
739pub struct CallGraphStatistics {
740 pub total_functions: usize,
742 pub total_calls: usize,
744 pub direct_calls: usize,
746 pub indirect_calls: usize,
748 pub recursive_functions: usize,
750 pub leaf_functions: usize,
752 pub entry_points: usize,
754 pub unreachable_functions: usize,
756 pub max_call_depth: u32,
758 pub average_call_depth: f64,
760 pub cyclic_dependencies: usize,
762}
763
764#[derive(Debug, Clone)]
766#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
767pub struct CallGraphConfig {
768 pub analyze_indirect_calls: bool,
770 pub detect_tail_calls: bool,
772 pub resolve_virtual_calls: bool,
774 pub follow_import_thunks: bool,
776 pub max_call_depth: Option<u32>,
778 pub include_library_calls: bool,
780}
781
782impl Default for CallGraphConfig {
783 fn default() -> Self {
784 Self {
785 analyze_indirect_calls: true,
786 detect_tail_calls: true,
787 resolve_virtual_calls: false,
788 follow_import_thunks: true,
789 max_call_depth: Some(50),
790 include_library_calls: false,
791 }
792 }
793}
794
795#[derive(Debug, Clone, Default)]
797#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
798pub struct AnalysisResult {
799 pub format: BinaryFormat,
801 pub architecture: Architecture,
803 pub entry_point: Option<u64>,
805 pub metadata: BinaryMetadata,
807 pub sections: Vec<Section>,
809 pub symbols: Vec<Symbol>,
811 pub imports: Vec<Import>,
813 pub exports: Vec<Export>,
815 pub disassembly: Option<Vec<Instruction>>,
817 pub control_flow: Option<Vec<ControlFlowGraph>>,
819 pub entropy: Option<EntropyAnalysis>,
821 pub security: Option<SecurityIndicators>,
823 pub call_graph: Option<CallGraph>,
825 pub enhanced_control_flow: Option<EnhancedControlFlowAnalysis>,
827}
828
829#[derive(Debug, Clone)]
831#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
832pub struct EnhancedControlFlowAnalysis {
833 pub control_flow_graphs: Vec<ControlFlowGraph>,
835 pub cognitive_complexity_summary: CognitiveComplexityStats,
837 pub loop_analysis_summary: LoopAnalysisStats,
839}
840
841#[derive(Debug, Clone, Default)]
843#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
844pub struct CognitiveComplexityStats {
845 pub total_cognitive_complexity: u32,
847 pub average_cognitive_complexity: f64,
849 pub max_cognitive_complexity: u32,
851 pub most_complex_function: Option<String>,
853 pub functions_analyzed: usize,
855}
856
857#[derive(Debug, Clone, Default)]
859#[cfg_attr(feature = "serde-support", derive(Serialize, Deserialize))]
860pub struct LoopAnalysisStats {
861 pub total_loops: usize,
863 pub natural_loops: usize,
865 pub irreducible_loops: usize,
867 pub nested_loops: usize,
869 pub max_nesting_depth: u32,
871 pub loops_by_type: HashMap<LoopType, usize>,
873}
874
875impl Default for BinaryMetadata {
876 fn default() -> Self {
877 Self {
878 size: 0,
879 format: BinaryFormat::Unknown,
880 architecture: Architecture::Unknown,
881 entry_point: None,
882 base_address: None,
883 timestamp: None,
884 compiler_info: None,
885 endian: Endianness::Little,
886 security_features: SecurityFeatures::default(),
887 }
888 }
889}
890
891pub trait BinaryFormatParser {
893 fn parse(data: &[u8]) -> ParseResult;
895
896 fn can_parse(data: &[u8]) -> bool;
898}
899
900pub trait BinaryFormatTrait: Send + Sync {
902 fn format_type(&self) -> BinaryFormat;
904
905 fn architecture(&self) -> Architecture;
907
908 fn entry_point(&self) -> Option<u64>;
910
911 fn sections(&self) -> &[Section];
913
914 fn symbols(&self) -> &[Symbol];
916
917 fn imports(&self) -> &[Import];
919
920 fn exports(&self) -> &[Export];
922
923 fn metadata(&self) -> &BinaryMetadata;
925}