myph-v2.git


myph-v2

~ rust shellcode loader with evasive capabilities
git clone https://github.com/djnnvx/myph-v2.git
log | files | refs | archive | README

capabilities.rs (14144B)

      1 use std::collections::HashSet;
      2 
      3 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
      4 pub enum Capability {
      5     RequiresAdmin,
      6     SupportsRemoteProcess,
      7     SupportsDynamicResolver,
      8     SupportsAMSIPatch,
      9     RequiresNtdll,
     10     LocalExecutionOnly,
     11     RequiresProcessInjection,
     12 }
     13 
     14 impl Capability {
     15     pub fn description(&self) -> &'static str {
     16         match self {
     17             Capability::RequiresAdmin => "Requires administrator privileges to execute",
     18             Capability::SupportsRemoteProcess => "Supports injection into remote process",
     19             Capability::SupportsDynamicResolver => "Supports dynamic function resolution",
     20             Capability::SupportsAMSIPatch => "Compatible with AMSI patching",
     21             Capability::RequiresNtdll => "Requires ntdll.dll functions",
     22             Capability::LocalExecutionOnly => "Executes shellcode locally (no process injection)",
     23             Capability::RequiresProcessInjection => {
     24                 "Requires target process for shellcode injection"
     25             }
     26         }
     27     }
     28 }
     29 
     30 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
     31 pub enum DetectionDifficulty {
     32     Low,
     33     Medium,
     34     MediumHigh,
     35     High,
     36     VeryHigh,
     37 }
     38 
     39 impl DetectionDifficulty {
     40     pub fn as_str(&self) -> &'static str {
     41         match self {
     42             DetectionDifficulty::Low => "Low",
     43             DetectionDifficulty::Medium => "Medium",
     44             DetectionDifficulty::MediumHigh => "Medium-High",
     45             DetectionDifficulty::High => "High",
     46             DetectionDifficulty::VeryHigh => "Very High",
     47         }
     48     }
     49 }
     50 
     51 #[derive(Debug, Clone)]
     52 pub struct TechniqueMetadata {
     53     pub name: &'static str,
     54     pub capabilities: HashSet<Capability>,
     55     pub detection_difficulty: DetectionDifficulty,
     56     pub description: &'static str,
     57 }
     58 
     59 impl TechniqueMetadata {
     60     pub fn has_capability(&self, cap: Capability) -> bool {
     61         self.capabilities.contains(&cap)
     62     }
     63 
     64     pub fn requires_process(&self) -> bool {
     65         self.has_capability(Capability::RequiresProcessInjection)
     66     }
     67 
     68     pub fn supports_dynamic_resolver(&self) -> bool {
     69         self.has_capability(Capability::SupportsDynamicResolver)
     70     }
     71 }
     72 
     73 pub fn get_technique_metadata(technique_name: &str) -> Option<TechniqueMetadata> {
     74     get_technique_registry().iter().find_map(|meta| {
     75         if meta.name.eq_ignore_ascii_case(technique_name) {
     76             Some(meta.clone())
     77         } else {
     78             None
     79         }
     80     })
     81 }
     82 
     83 pub fn list_all_techniques() -> Vec<TechniqueMetadata> {
     84     get_technique_registry()
     85 }
     86 
     87 fn get_technique_registry() -> Vec<TechniqueMetadata> {
     88     vec![
     89         TechniqueMetadata {
     90             name: "crt",
     91             capabilities: [
     92                 Capability::SupportsRemoteProcess,
     93                 Capability::SupportsDynamicResolver,
     94                 Capability::SupportsAMSIPatch,
     95                 Capability::RequiresProcessInjection,
     96             ]
     97             .iter()
     98             .copied()
     99             .collect(),
    100             detection_difficulty: DetectionDifficulty::Medium,
    101             description: "CreateRemoteThread - Classic remote thread injection",
    102         },
    103         TechniqueMetadata {
    104             name: "crtx",
    105             capabilities: [
    106                 Capability::SupportsRemoteProcess,
    107                 Capability::SupportsDynamicResolver,
    108                 Capability::SupportsAMSIPatch,
    109                 Capability::RequiresProcessInjection,
    110             ]
    111             .iter()
    112             .copied()
    113             .collect(),
    114             detection_difficulty: DetectionDifficulty::Medium,
    115             description: "CreateRemoteThreadEx - Extended remote thread injection",
    116         },
    117         TechniqueMetadata {
    118             name: "create-fiber",
    119             capabilities: [
    120                 Capability::LocalExecutionOnly,
    121                 Capability::SupportsDynamicResolver,
    122                 Capability::SupportsAMSIPatch,
    123             ]
    124             .iter()
    125             .copied()
    126             .collect(),
    127             detection_difficulty: DetectionDifficulty::MediumHigh,
    128             description: "CreateFiber - Fiber-based local execution",
    129         },
    130         TechniqueMetadata {
    131             name: "process-hollowing",
    132             capabilities: [
    133                 Capability::SupportsRemoteProcess,
    134                 Capability::SupportsDynamicResolver,
    135                 Capability::SupportsAMSIPatch,
    136                 Capability::RequiresNtdll,
    137                 Capability::RequiresProcessInjection,
    138             ]
    139             .iter()
    140             .copied()
    141             .collect(),
    142             detection_difficulty: DetectionDifficulty::High,
    143             description: "Process Hollowing - Memory replacement technique",
    144         },
    145         TechniqueMetadata {
    146             name: "nt-create-thread-ex",
    147             capabilities: [
    148                 Capability::SupportsRemoteProcess,
    149                 Capability::SupportsDynamicResolver,
    150                 Capability::SupportsAMSIPatch,
    151                 Capability::RequiresNtdll,
    152                 Capability::RequiresProcessInjection,
    153             ]
    154             .iter()
    155             .copied()
    156             .collect(),
    157             detection_difficulty: DetectionDifficulty::MediumHigh,
    158             description: "NtCreateThreadEx - Native NT API thread creation",
    159         },
    160         TechniqueMetadata {
    161             name: "syscall",
    162             capabilities: [
    163                 Capability::LocalExecutionOnly,
    164                 Capability::SupportsDynamicResolver,
    165                 Capability::SupportsAMSIPatch,
    166                 Capability::RequiresNtdll,
    167             ]
    168             .iter()
    169             .copied()
    170             .collect(),
    171             detection_difficulty: DetectionDifficulty::Medium,
    172             description: "Syscall - Direct system call execution",
    173         },
    174         TechniqueMetadata {
    175             name: "etwp",
    176             capabilities: [
    177                 Capability::LocalExecutionOnly,
    178                 Capability::SupportsDynamicResolver,
    179                 Capability::SupportsAMSIPatch,
    180             ]
    181             .iter()
    182             .copied()
    183             .collect(),
    184             detection_difficulty: DetectionDifficulty::High,
    185             description: "Etwp - ETW thread pool-based execution",
    186         },
    187         TechniqueMetadata {
    188             name: "set-timer",
    189             capabilities: [
    190                 Capability::LocalExecutionOnly,
    191                 Capability::SupportsDynamicResolver,
    192                 Capability::SupportsAMSIPatch,
    193             ]
    194             .iter()
    195             .copied()
    196             .collect(),
    197             detection_difficulty: DetectionDifficulty::High,
    198             description: "SetTimer - Timer callback-based execution",
    199         },
    200         TechniqueMetadata {
    201             name: "enum-calendar",
    202             capabilities: [
    203                 Capability::LocalExecutionOnly,
    204                 Capability::SupportsDynamicResolver,
    205                 Capability::SupportsAMSIPatch,
    206             ]
    207             .iter()
    208             .copied()
    209             .collect(),
    210             detection_difficulty: DetectionDifficulty::High,
    211             description: "EnumCalendar - Callback-based via EnumCalendarInfoW",
    212         },
    213         TechniqueMetadata {
    214             name: "enum-windows",
    215             capabilities: [
    216                 Capability::LocalExecutionOnly,
    217                 Capability::SupportsDynamicResolver,
    218                 Capability::SupportsAMSIPatch,
    219             ]
    220             .iter()
    221             .copied()
    222             .collect(),
    223             detection_difficulty: DetectionDifficulty::High,
    224             description: "EnumWindows - Window enumeration callback-based execution",
    225         },
    226         TechniqueMetadata {
    227             name: "enum-system-locales",
    228             capabilities: [
    229                 Capability::LocalExecutionOnly,
    230                 Capability::SupportsDynamicResolver,
    231                 Capability::SupportsAMSIPatch,
    232             ]
    233             .iter()
    234             .copied()
    235             .collect(),
    236             detection_difficulty: DetectionDifficulty::High,
    237             description: "EnumSystemLocales - Locale enumeration callback-based execution",
    238         },
    239         TechniqueMetadata {
    240             name: "image-get-digest-stream",
    241             capabilities: [
    242                 Capability::LocalExecutionOnly,
    243                 Capability::SupportsDynamicResolver,
    244                 Capability::SupportsAMSIPatch,
    245             ]
    246             .iter()
    247             .copied()
    248             .collect(),
    249             detection_difficulty: DetectionDifficulty::High,
    250             description: "ImageGetDigestStream - Imagehlp callback-based execution",
    251         },
    252         TechniqueMetadata {
    253             name: "queue-user-apc",
    254             capabilities: [
    255                 Capability::LocalExecutionOnly,
    256                 Capability::SupportsDynamicResolver,
    257                 Capability::SupportsAMSIPatch,
    258             ]
    259             .iter()
    260             .copied()
    261             .collect(),
    262             detection_difficulty: DetectionDifficulty::High,
    263             description: "QueueUserAPC - APC-based local execution",
    264         },
    265         TechniqueMetadata {
    266             name: "fairy-law",
    267             capabilities: [
    268                 Capability::RequiresAdmin,
    269                 Capability::LocalExecutionOnly,
    270                 Capability::SupportsDynamicResolver,
    271                 Capability::SupportsAMSIPatch,
    272             ]
    273             .iter()
    274             .copied()
    275             .collect(),
    276             detection_difficulty: DetectionDifficulty::VeryHigh,
    277             description: "Fairy-Law - Privilege escalation via policy manipulation",
    278         },
    279         TechniqueMetadata {
    280             name: "module-stomping",
    281             capabilities: [
    282                 Capability::LocalExecutionOnly,
    283                 Capability::SupportsDynamicResolver,
    284                 Capability::SupportsAMSIPatch,
    285             ]
    286             .iter()
    287             .copied()
    288             .collect(),
    289             detection_difficulty: DetectionDifficulty::VeryHigh,
    290             description: "Module Stomping - DLL overwrite technique",
    291         },
    292         TechniqueMetadata {
    293             name: "thread-hijacking",
    294             capabilities: [
    295                 Capability::SupportsRemoteProcess,
    296                 Capability::SupportsDynamicResolver,
    297                 Capability::SupportsAMSIPatch,
    298                 Capability::RequiresProcessInjection,
    299             ]
    300             .iter()
    301             .copied()
    302             .collect(),
    303             detection_difficulty: DetectionDifficulty::VeryHigh,
    304             description: "Thread Hijacking - Context manipulation technique",
    305         },
    306         TechniqueMetadata {
    307             name: "early-bird",
    308             capabilities: [
    309                 Capability::SupportsRemoteProcess,
    310                 Capability::SupportsDynamicResolver,
    311                 Capability::SupportsAMSIPatch,
    312                 Capability::RequiresProcessInjection,
    313             ]
    314             .iter()
    315             .copied()
    316             .collect(),
    317             detection_difficulty: DetectionDifficulty::VeryHigh,
    318             description: "Early Bird - APC injection before main thread starts",
    319         },
    320     ]
    321 }
    322 
    323 #[cfg(test)]
    324 mod tests {
    325     use super::*;
    326 
    327     #[test]
    328     fn test_all_techniques_registered() {
    329         assert_eq!(get_technique_registry().len(), 17);
    330     }
    331 
    332     #[test]
    333     fn test_get_technique_metadata_crt() {
    334         let meta = get_technique_metadata("crt").unwrap();
    335         assert_eq!(meta.name, "crt");
    336         assert!(meta.has_capability(Capability::SupportsRemoteProcess));
    337         assert!(meta.has_capability(Capability::SupportsDynamicResolver));
    338         assert!(meta.requires_process());
    339     }
    340 
    341     #[test]
    342     fn test_get_technique_metadata_fairy_law() {
    343         let meta = get_technique_metadata("fairy-law").unwrap();
    344         assert_eq!(meta.name, "fairy-law");
    345         assert!(meta.has_capability(Capability::RequiresAdmin));
    346         assert!(!meta.requires_process());
    347     }
    348 
    349     #[test]
    350     fn test_get_technique_metadata_case_insensitive() {
    351         let meta1 = get_technique_metadata("CRT");
    352         let meta2 = get_technique_metadata("crt");
    353         let meta3 = get_technique_metadata("CrT");
    354         assert!(meta1.is_some());
    355         assert!(meta2.is_some());
    356         assert!(meta3.is_some());
    357     }
    358 
    359     #[test]
    360     fn test_get_technique_metadata_unknown() {
    361         let meta = get_technique_metadata("unknown-technique");
    362         assert!(meta.is_none());
    363     }
    364 
    365     #[test]
    366     fn test_list_all_techniques() {
    367         let techniques = list_all_techniques();
    368         assert_eq!(techniques.len(), 17);
    369     }
    370 
    371     #[test]
    372     fn test_local_execution_techniques_dont_require_process() {
    373         for meta in get_technique_registry() {
    374             if meta.has_capability(Capability::LocalExecutionOnly) {
    375                 assert!(!meta.requires_process());
    376             }
    377         }
    378     }
    379 
    380     #[test]
    381     fn test_process_injection_techniques_require_process() {
    382         for meta in get_technique_registry() {
    383             if meta.has_capability(Capability::RequiresProcessInjection) {
    384                 assert!(meta.requires_process());
    385             }
    386         }
    387     }
    388 
    389     #[test]
    390     fn test_all_techniques_support_dynamic_resolver() {
    391         for meta in get_technique_registry() {
    392             assert!(meta.supports_dynamic_resolver());
    393         }
    394     }
    395 
    396     #[test]
    397     fn test_all_techniques_support_amsi_patch() {
    398         for meta in get_technique_registry() {
    399             assert!(meta.has_capability(Capability::SupportsAMSIPatch));
    400         }
    401     }
    402 
    403     #[test]
    404     fn test_capability_descriptions() {
    405         assert!(!Capability::RequiresAdmin.description().is_empty());
    406         assert!(!Capability::SupportsRemoteProcess.description().is_empty());
    407         assert!(!Capability::SupportsDynamicResolver.description().is_empty());
    408     }
    409 
    410     #[test]
    411     fn test_detection_difficulty_ordering() {
    412         assert!(DetectionDifficulty::Low < DetectionDifficulty::Medium);
    413         assert!(DetectionDifficulty::Medium < DetectionDifficulty::MediumHigh);
    414         assert!(DetectionDifficulty::MediumHigh < DetectionDifficulty::High);
    415         assert!(DetectionDifficulty::High < DetectionDifficulty::VeryHigh);
    416     }
    417 }