pub mod doc;
pub mod exec;
pub mod utils;
use crate::exec::ExecutableFile;
use anyhow::Result;
use chrono::{DateTime, Utc};
pub const MDB_VERSION: &str = env!("CARGO_PKG_VERSION");
pub trait TypeMagic {
const MAGIC: &'static [&'static [u8]];
}
#[allow(clippy::large_enum_variant)]
pub enum KnownType<'a> {
#[cfg(feature = "elf")]
ELF(exec::elf::Elf<'a>),
#[cfg(feature = "pe32")]
EXE(exec::pe32::EXE<'a>),
#[cfg(feature = "macho")]
MachO(exec::macho::Macho<'a>),
#[cfg(feature = "macho")]
FatMachO(exec::macho::fat::FatMacho<'a>),
#[cfg(feature = "pef")]
PEF(exec::pef::Pef<'a>),
#[cfg(feature = "pdf")]
PDF(doc::pdf::PDF<'a>),
Unknown,
}
impl<'a> KnownType<'a> {
pub fn new(data: &'a [u8]) -> Result<Self> {
#[cfg(feature = "elf")]
if data.starts_with(exec::elf::Elf::MAGIC[0]) {
return Ok(Self::ELF(exec::elf::Elf::from(data)?));
}
#[cfg(feature = "pe32")]
if data.starts_with(exec::pe32::EXE::MAGIC[0])
|| data.starts_with(exec::pe32::EXE::MAGIC[1])
{
return Ok(Self::EXE(exec::pe32::EXE::from(data)?));
}
#[cfg(feature = "macho")]
for mach_magic in exec::macho::Macho::MAGIC {
if data.starts_with(mach_magic) {
return Ok(Self::MachO(exec::macho::Macho::from(data)?));
}
}
#[cfg(feature = "macho")]
for mach_magic in exec::macho::fat::FatMacho::MAGIC {
if data.starts_with(mach_magic) {
return Ok(Self::FatMachO(exec::macho::fat::FatMacho::from(data)?));
}
}
#[cfg(feature = "pdf")]
if data.starts_with(doc::pdf::PDF::MAGIC[0]) {
return Ok(Self::PDF(doc::pdf::PDF::from(data)?));
}
#[cfg(feature = "pef")]
if data.starts_with(exec::pef::Pef::MAGIC[0]) {
return Ok(Self::PEF(exec::pef::Pef::from(data)?));
}
Ok(Self::Unknown)
}
pub fn is_exec(&self) -> bool {
match self {
#[cfg(feature = "elf")]
KnownType::ELF(_) => true,
#[cfg(feature = "pe32")]
KnownType::EXE(_) => true,
#[cfg(feature = "macho")]
KnownType::MachO(_) => true,
#[cfg(feature = "macho")]
KnownType::FatMachO(_) => true,
#[cfg(feature = "pef")]
KnownType::PEF(_) => true,
_ => false,
}
}
pub fn is_doc(&self) -> bool {
match self {
#[cfg(feature = "pdf")]
KnownType::PDF(_) => true,
_ => false,
}
}
pub fn created(&self) -> Option<DateTime<Utc>> {
match self {
#[cfg(feature = "pe32")]
KnownType::EXE(e) => e.compiled_timestamp(),
#[cfg(feature = "pef")]
KnownType::PEF(p) => p.compiled_timestamp(),
#[cfg(feature = "pdf")]
KnownType::PDF(p) => p.creation_date,
_ => None,
}
}
pub fn exec(self) -> Option<Box<dyn ExecutableFile + Send + 'a>> {
match self {
#[cfg(feature = "elf")]
KnownType::ELF(e) => Some(Box::new(e)),
#[cfg(feature = "pe32")]
KnownType::EXE(e) => Some(Box::new(e)),
#[cfg(feature = "macho")]
KnownType::MachO(m) => Some(Box::new(m)),
#[cfg(feature = "macho")]
KnownType::FatMachO(m) => Some(Box::new(m)),
#[cfg(feature = "pef")]
KnownType::PEF(p) => Some(Box::new(p)),
_ => None,
}
}
pub fn doc(self) -> Option<Box<doc::pdf::PDF<'a>>> {
match self {
KnownType::PDF(p) => Some(Box::new(p)),
_ => None,
}
}
}