use crate::errors::*;
use crate::utils;
use std::collections::HashMap;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Rules {
map: HashMap<String, String>,
}
impl Rules {
pub fn load_yaml<F: fmt::Debug>(&mut self, name: F, buf: &[u8]) -> Result<String> {
let sha256 = utils::sha256(buf);
let list = stalkerware_indicators::parse_from_buf(buf)
.context("Failed to load stalkerware-indicators yaml")?;
let num_of_rules = list.len();
for rule in list {
for package in rule.packages {
self.map.insert(package, rule.name.to_string());
}
}
info!("Loaded {num_of_rules} rules from {name:?} (sha256={sha256})",);
Ok(sha256)
}
pub fn get(&self, pkg_id: &str) -> Option<&String> {
self.map.get(pkg_id)
}
}
#[cfg(test)]
mod tests {
use super::*;
use maplit::hashmap;
#[test]
fn test_parse_ioc_yaml() {
let mut rules = Rules::default();
rules
.load_yaml(
"unit-test",
b"
- name: Reptilicus
names:
- Reptilicus
- CyberNanny
- Vkur
type: stalkerware
packages:
- com.brot.storage.work
- com.cycle.start.mess
- com.thecybernanny.andapp
- net.androidcoreapp.androidbackup
- net.delphiboardlayer.androidcoreapp
- net.reptilicus.clientapp
- net.system_updater_abs341
- net.vkurhandler
- se.vkur.clientapp
- yc.sysupd.client
certificates:
- 230E35A26E471352DF5DBDBCF9834E0711500CB0
- 2C08279BCC8EB16B2B31ACFBD7E1D4BB28E49A87
- 2FD8BEF4081F126D4DA655B40E9FC63F116DD857
- 9256E291823DA741B64CB23F7E371D0940E5272E
- 9BD494107EFED96F630D29D6E18AE4DCC47149E2
- 6D0FF787BF4534F1077D1E4BF2E18BA381D97061
- D3A7E0E542A3E1112741806AC31F341C4200FBA1
- B61326887306E5A65726AE6BFD1D720D2760CEFF
websites:
- reptilicus.net
- thecybernanny.com
c2:
ips:
- 176.9.42.16
domains:
- cabinet.ecohouse-eg.com
- cabinet.gps-monitor.uz
- cabinet.kfnm.ru
- cabinet.vegosm.ru
- cabinet.vkur.se
- cabinet.vkur1.se
- data.reptilicus.net
- e2c64.firebaseio.com
- mob.eurotrans.kz
- phonecontrolapp-e2c64.firebaseio.com
- proxy.reptilicus.net
- reptilicus.net
- rp.apollospy.com
- vkur1.se
- www.reptilicus.net
- name: Snoopza
names:
- Snoopza
type: stalkerware
packages:
- com.android.core.mngi
- com.android.core.mngj
- com.android.core.mngk
- com.android.core.mngl
- com.android.core.mngn
- com.android.core.mngo
- com.android.core.mngp
certificates: []
websites:
- snoopza.com
c2:
ips:
- 217.182.250.165
- 46.105.57.148
domains:
- snoopza.com
- my.snoopza.com
- my2.snoopza.com
- api.snoopza.com
",
)
.unwrap();
assert_eq!(
rules.map,
hashmap![
"com.brot.storage.work".to_string() => "Reptilicus".to_string(),
"com.cycle.start.mess".to_string() => "Reptilicus".to_string(),
"com.thecybernanny.andapp".to_string() => "Reptilicus".to_string(),
"net.androidcoreapp.androidbackup".to_string() => "Reptilicus".to_string(),
"net.delphiboardlayer.androidcoreapp".to_string() => "Reptilicus".to_string(),
"net.reptilicus.clientapp".to_string() => "Reptilicus".to_string(),
"net.system_updater_abs341".to_string() => "Reptilicus".to_string(),
"net.vkurhandler".to_string() => "Reptilicus".to_string(),
"se.vkur.clientapp".to_string() => "Reptilicus".to_string(),
"yc.sysupd.client".to_string() => "Reptilicus".to_string(),
"com.android.core.mngi".to_string() => "Snoopza".to_string(),
"com.android.core.mngj".to_string() => "Snoopza".to_string(),
"com.android.core.mngk".to_string() => "Snoopza".to_string(),
"com.android.core.mngl".to_string() => "Snoopza".to_string(),
"com.android.core.mngn".to_string() => "Snoopza".to_string(),
"com.android.core.mngo".to_string() => "Snoopza".to_string(),
"com.android.core.mngp".to_string() => "Snoopza".to_string(),
]
);
}
}